00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef lint
00037 static const char RCSbot[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_bot.c,v 14.16 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00038 #endif
00039
00040 #include "common.h"
00041
00042 #include <stdlib.h>
00043 #include <stdio.h>
00044 #ifdef HAVE_STRING_H
00045 # include <string.h>
00046 #else
00047 # include <strings.h>
00048 #endif
00049 #include <math.h>
00050 #include <ctype.h>
00051
00052 #include "tcl.h"
00053 #include "machine.h"
00054 #include "vmath.h"
00055 #include "db.h"
00056 #include "nmg.h"
00057 #include "rtgeom.h"
00058 #include "raytrace.h"
00059 #include "./debug.h"
00060 #include "./plane.h"
00061 #include "./bot.h"
00062
00063 #define GLUE(_a, _b) _a ## _b
00064 #define XGLUE(_a,_b) GLUE(_a,_b)
00065
00066
00067 int rt_bot_minpieces = RT_DEFAULT_MINPIECES;
00068 int rt_bot_tri_per_piece = RT_DEFAULT_TRIS_PER_PIECE;
00069
00070 #define MAXHITS 128
00071
00072 #define BOT_MIN_DN 1.0e-9
00073
00074 #define RT_BOT_UNORIENTED_NORM( _hitp, _in_or_out) { \
00075 if( _in_or_out < 0 ) { \
00076 if( (_hitp)->hit_vpriv[X] < 0.0 ) { \
00077 VREVERSE( (_hitp)->hit_normal, trip->tri_N ); \
00078 } else { \
00079 VMOVE( (_hitp)->hit_normal, trip->tri_N ); \
00080 } \
00081 } else { \
00082 if( (_hitp)->hit_vpriv[X] > 0.0 ) { \
00083 VREVERSE( (_hitp)->hit_normal, trip->tri_N ); \
00084 } else { \
00085 VMOVE( (_hitp)->hit_normal, trip->tri_N ); \
00086 } \
00087 } \
00088 }
00089
00090
00091 HIDDEN int
00092 rt_bot_makesegs(
00093 struct hit *hits,
00094 int nhits,
00095 struct soltab *stp,
00096 struct xray *rp,
00097 struct application *ap,
00098 struct seg *seghead,
00099 struct rt_piecestate *psp);
00100
00101 static int
00102 rt_bot_unoriented_segs(struct hit *hits,
00103 int nhits,
00104 struct soltab *stp,
00105 struct xray *rp,
00106 struct application *ap,
00107 struct seg *seghead,
00108 struct bot_specific *bot);
00109
00110 int
00111 rt_botface_w_normals(struct soltab *stp,
00112 struct bot_specific *bot,
00113 fastf_t *ap,
00114 fastf_t *bp,
00115 fastf_t *cp,
00116 fastf_t *vertex_normals,
00117 int face_no,
00118 const struct bn_tol *tol);
00119
00120
00121 #define TRI_TYPE float
00122 #define NORM_TYPE signed char
00123 #define NORMAL_SCALE 127.0
00124 #define ONE_OVER_SCALE (1.0/127.0)
00125 #include "./g_bot_include.c"
00126 #undef TRI_TYPE
00127 #undef NORM_TYPE
00128 #undef NORMAL_SCALE
00129 #undef ONE_OVER_SCALE
00130 #define TRI_TYPE double
00131 #define NORM_TYPE fastf_t
00132 #define NORMAL_SCALE 1.0
00133 #define ONE_OVER_SCALE 1.0
00134 #include "./g_bot_include.c"
00135 #undef TRI_TYPE
00136 #undef NORM_TYPE
00137 #undef NORMAL_SCALE
00138 #undef ONE_OVER_SCALE
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 int
00153 rt_botface_w_normals(struct soltab *stp,
00154 struct bot_specific *bot,
00155 fastf_t *ap,
00156 fastf_t *bp,
00157 fastf_t *cp,
00158 fastf_t *vertex_normals,
00159 int face_no,
00160 const struct bn_tol *tol)
00161 {
00162
00163 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00164 return rt_botface_w_normals_float( stp, bot, ap, bp, cp,
00165 vertex_normals, face_no, tol );
00166 } else {
00167 return rt_botface_w_normals_double( stp, bot, ap, bp, cp,
00168 vertex_normals, face_no, tol );
00169 }
00170 }
00171
00172 int
00173 rt_botface(struct soltab *stp,
00174 struct bot_specific *bot,
00175 fastf_t *ap,
00176 fastf_t *bp,
00177 fastf_t *cp,
00178 int face_no,
00179 const struct bn_tol *tol)
00180 {
00181 return( rt_botface_w_normals( stp, bot, ap, bp, cp, NULL, face_no, tol ) );
00182 }
00183
00184
00185
00186
00187
00188 void
00189 rt_bot_prep_pieces(struct bot_specific *bot,
00190 struct soltab *stp,
00191 int ntri,
00192 const struct bn_tol *tol)
00193 {
00194 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00195 rt_bot_prep_pieces_float( bot, stp, ntri, tol );
00196 } else {
00197 rt_bot_prep_pieces_double( bot, stp, ntri, tol );
00198 }
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int
00217 rt_bot_prep(struct soltab *stp, struct rt_db_internal *ip, struct rt_i *rtip)
00218 {
00219 struct rt_bot_internal *bot_ip;
00220
00221
00222 RT_CK_DB_INTERNAL(ip);
00223 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00224 RT_BOT_CK_MAGIC(bot_ip);
00225
00226 if( bot_ip->bot_flags & RT_BOT_USE_FLOATS ) {
00227 return (rt_bot_prep_float( stp, bot_ip, rtip ));
00228 } else {
00229 return( rt_bot_prep_double( stp, bot_ip, rtip ));
00230 }
00231 }
00232
00233
00234
00235
00236 void
00237 rt_bot_print(register const struct soltab *stp)
00238 {
00239 }
00240
00241 static int
00242 rt_bot_plate_segs(struct hit *hits,
00243 int nhits,
00244 struct soltab *stp,
00245 struct xray *rp,
00246 struct application *ap,
00247 struct seg *seghead,
00248 struct bot_specific *bot)
00249 {
00250 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00251 return (rt_bot_plate_segs_float( hits, nhits, stp, rp, ap, seghead, bot ));
00252 } else {
00253 return (rt_bot_plate_segs_double( hits, nhits, stp, rp, ap, seghead, bot ));
00254 }
00255 }
00256
00257 static int
00258 rt_bot_unoriented_segs(struct hit *hits,
00259 int nhits,
00260 struct soltab *stp,
00261 struct xray *rp,
00262 struct application *ap,
00263 struct seg *seghead,
00264 struct bot_specific *bot)
00265 {
00266 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00267 return (rt_bot_unoriented_segs_float( hits, nhits, stp, rp, ap, seghead, bot ));
00268 } else {
00269 return (rt_bot_unoriented_segs_double( hits, nhits, stp, rp, ap, seghead, bot ));
00270 }
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 HIDDEN int
00282 rt_bot_makesegs(struct hit *hits, int nhits, struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead, struct rt_piecestate *psp)
00283 {
00284 struct bot_specific *bot = (struct bot_specific *)stp->st_specific;
00285
00286 if(bot->bot_mode == RT_BOT_PLATE ||
00287 bot->bot_mode == RT_BOT_PLATE_NOCOS) {
00288 return rt_bot_plate_segs(hits, nhits, stp, rp, ap, seghead, bot);
00289 }
00290
00291 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00292 return( rt_bot_makesegs_float( hits, nhits, stp, rp, ap, seghead, psp ) );
00293 } else {
00294 return( rt_bot_makesegs_double( hits, nhits, stp, rp, ap, seghead, psp ) );
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 int
00314 rt_bot_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead)
00315 {
00316 struct bot_specific *bot = (struct bot_specific *)stp->st_specific;
00317
00318 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00319 return( rt_bot_shot_float( stp, rp, ap, seghead ) );
00320 } else {
00321 return( rt_bot_shot_double( stp, rp, ap, seghead ) );
00322 }
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 int
00338 rt_bot_piece_shot(struct rt_piecestate *psp, struct rt_piecelist *plp, double dist_corr, register struct xray *rp, struct application *ap, struct seg *seghead)
00339 {
00340 struct soltab *stp;
00341 struct bot_specific *bot;
00342
00343 RT_CK_PIECELIST(plp);
00344 stp = plp->stp;
00345 RT_CK_SOLTAB(stp);
00346 bot = (struct bot_specific *)stp->st_specific;
00347
00348 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00349 return( rt_bot_piece_shot_float( psp, plp, dist_corr, rp, ap, seghead ) );
00350 } else {
00351 return( rt_bot_piece_shot_double( psp, plp, dist_corr, rp, ap, seghead ) );
00352 }
00353 }
00354
00355
00356
00357
00358 void
00359 rt_bot_piece_hitsegs(struct rt_piecestate *psp, struct seg *seghead, struct application *ap)
00360 {
00361 RT_CK_PIECESTATE(psp);
00362 RT_CK_AP(ap);
00363 RT_CK_HTBL(&psp->htab);
00364
00365
00366 rt_hitsort( psp->htab.hits, psp->htab.end );
00367
00368
00369 (void)rt_bot_makesegs( psp->htab.hits, psp->htab.end, psp->stp, &ap->a_ray, ap, seghead, psp );
00370 }
00371
00372 #define RT_BOT_SEG_MISS(SEG) (SEG).seg_stp=RT_SOLTAB_NULL
00373
00374
00375
00376
00377
00378
00379 void
00380 rt_bot_vshot(struct soltab **stp, struct xray **rp, struct seg *segp, int n, struct application *ap)
00381
00382
00383
00384
00385
00386 {
00387 rt_vstub( stp, rp, segp, n, ap );
00388 }
00389
00390
00391
00392
00393
00394
00395 void
00396 rt_bot_norm(register struct hit *hitp, struct soltab *stp, register struct xray *rp)
00397 {
00398 struct bot_specific *bot=(struct bot_specific *)stp->st_specific;
00399
00400 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00401 rt_bot_norm_float( bot, hitp, stp, rp );
00402 } else {
00403 rt_bot_norm_double( bot, hitp, stp, rp );
00404 }
00405 }
00406
00407
00408
00409
00410
00411
00412 void
00413 rt_bot_curve(register struct curvature *cvp, register struct hit *hitp, struct soltab *stp)
00414 {
00415 cvp->crv_c1 = cvp->crv_c2 = 0;
00416
00417
00418 bn_vec_ortho( cvp->crv_pdir, hitp->hit_normal );
00419 cvp->crv_c1 = cvp->crv_c2 = 0;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 void
00431 rt_bot_uv(struct application *ap, struct soltab *stp, register struct hit *hitp, register struct uvcoord *uvp)
00432 {
00433 }
00434
00435
00436
00437
00438 void
00439 rt_bot_free(register struct soltab *stp)
00440 {
00441 register struct bot_specific *bot =
00442 (struct bot_specific *)stp->st_specific;
00443
00444 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
00445 rt_bot_free_float( bot );
00446 } else {
00447 rt_bot_free_double( bot );
00448 }
00449 }
00450
00451
00452
00453
00454 int
00455 rt_bot_class(const struct soltab *stp, const fastf_t *min, const fastf_t *max, const struct bn_tol *tol)
00456 {
00457 return RT_CLASSIFY_UNIMPLEMENTED;
00458 }
00459
00460
00461
00462
00463 int
00464 rt_bot_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00465 {
00466 LOCAL struct rt_bot_internal *bot_ip;
00467 int i;
00468
00469 RT_CK_DB_INTERNAL(ip);
00470 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00471 RT_BOT_CK_MAGIC(bot_ip);
00472
00473 for( i=0 ; i<bot_ip->num_faces ; i++ )
00474 {
00475 RT_ADD_VLIST( vhead, &bot_ip->vertices[bot_ip->faces[i*3]*3], BN_VLIST_LINE_MOVE );
00476 RT_ADD_VLIST( vhead, &bot_ip->vertices[bot_ip->faces[i*3+1]*3], BN_VLIST_LINE_DRAW );
00477 RT_ADD_VLIST( vhead, &bot_ip->vertices[bot_ip->faces[i*3+2]*3], BN_VLIST_LINE_DRAW );
00478 RT_ADD_VLIST( vhead, &bot_ip->vertices[bot_ip->faces[i*3]*3], BN_VLIST_LINE_DRAW );
00479 }
00480
00481 return(0);
00482 }
00483
00484
00485
00486
00487 int
00488 rt_bot_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00489 {
00490 LOCAL struct rt_bot_internal *bot_ip;
00491 int i;
00492
00493 RT_CK_DB_INTERNAL(ip);
00494 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00495 RT_BOT_CK_MAGIC(bot_ip);
00496
00497
00498 for( i=0 ; i<bot_ip->num_faces ; i++ )
00499 {
00500 point_t aa, bb, cc;
00501 vect_t ab, ac;
00502 vect_t norm;
00503
00504 VMOVE( aa, &bot_ip->vertices[bot_ip->faces[i*3+0]*3] );
00505 VMOVE( bb, &bot_ip->vertices[bot_ip->faces[i*3+1]*3] );
00506 VMOVE( cc, &bot_ip->vertices[bot_ip->faces[i*3+2]*3] );
00507
00508 VSUB2( ab, aa, bb );
00509 VSUB2( ac, aa, cc );
00510 VCROSS( norm, ab, ac );
00511 VUNITIZE(norm);
00512 RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START);
00513
00514 if( (bot_ip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) &&
00515 (bot_ip->bot_flags & RT_BOT_USE_NORMALS) ) {
00516 vect_t na, nb, nc;
00517
00518 VMOVE( na, &bot_ip->normals[bot_ip->face_normals[i*3+0]*3] );
00519 VMOVE( nb, &bot_ip->normals[bot_ip->face_normals[i*3+1]*3] );
00520 VMOVE( nc, &bot_ip->normals[bot_ip->face_normals[i*3+2]*3] );
00521 RT_ADD_VLIST( vhead, na, BN_VLIST_POLY_VERTNORM );
00522 RT_ADD_VLIST( vhead, aa, BN_VLIST_POLY_MOVE );
00523 RT_ADD_VLIST( vhead, nb, BN_VLIST_POLY_VERTNORM );
00524 RT_ADD_VLIST( vhead, bb, BN_VLIST_POLY_DRAW );
00525 RT_ADD_VLIST( vhead, nc, BN_VLIST_POLY_VERTNORM );
00526 RT_ADD_VLIST( vhead, cc, BN_VLIST_POLY_DRAW );
00527 RT_ADD_VLIST( vhead, aa, BN_VLIST_POLY_END );
00528 } else {
00529 RT_ADD_VLIST( vhead, aa, BN_VLIST_POLY_MOVE );
00530 RT_ADD_VLIST( vhead, bb, BN_VLIST_POLY_DRAW );
00531 RT_ADD_VLIST( vhead, cc, BN_VLIST_POLY_DRAW );
00532 RT_ADD_VLIST( vhead, aa, BN_VLIST_POLY_END );
00533 }
00534 }
00535
00536 return(0);
00537 }
00538
00539
00540
00541
00542
00543
00544
00545
00546 int
00547 rt_bot_tess(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *tol)
00548 {
00549 LOCAL struct rt_bot_internal *bot_ip;
00550 struct shell *s;
00551 struct vertex **verts;
00552 point_t pt[3];
00553 int i;
00554
00555 RT_CK_DB_INTERNAL(ip);
00556 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00557 RT_BOT_CK_MAGIC(bot_ip);
00558 #if 0
00559 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
00560 return( -1 );
00561 #endif
00562 *r = nmg_mrsv( m );
00563 s = BU_LIST_FIRST(shell, &(*r)->s_hd);
00564
00565 verts = (struct vertex **)bu_calloc( bot_ip->num_vertices, sizeof( struct vertex *),
00566 "rt_bot_tess: *verts[]" );
00567
00568 for( i=0 ; i<bot_ip->num_faces ; i++ )
00569 {
00570 struct faceuse *fu;
00571 struct vertex **corners[3];
00572
00573 if( bot_ip->orientation == RT_BOT_CW )
00574 {
00575 VMOVE( pt[2], &bot_ip->vertices[bot_ip->faces[i*3]*3] );
00576 VMOVE( pt[1], &bot_ip->vertices[bot_ip->faces[i*3+1]*3] );
00577 VMOVE( pt[0], &bot_ip->vertices[bot_ip->faces[i*3+2]*3] );
00578 corners[2] = &verts[bot_ip->faces[i*3]];
00579 corners[1] = &verts[bot_ip->faces[i*3+1]];
00580 corners[0] = &verts[bot_ip->faces[i*3+2]];
00581 }
00582 else
00583 {
00584 VMOVE( pt[0], &bot_ip->vertices[bot_ip->faces[i*3]*3] );
00585 VMOVE( pt[1], &bot_ip->vertices[bot_ip->faces[i*3+1]*3] );
00586 VMOVE( pt[2], &bot_ip->vertices[bot_ip->faces[i*3+2]*3] );
00587 corners[0] = &verts[bot_ip->faces[i*3]];
00588 corners[1] = &verts[bot_ip->faces[i*3+1]];
00589 corners[2] = &verts[bot_ip->faces[i*3+2]];
00590 }
00591
00592 if( !bn_3pts_distinct( pt[0], pt[1], pt[2], tol )
00593 || bn_3pts_collinear( pt[0], pt[1], pt[2], tol ) )
00594 continue;
00595
00596 if( (fu=nmg_cmface( s, corners, 3 )) == (struct faceuse *)NULL )
00597 {
00598 bu_log( "rt_bot_tess() nmg_cmface() failed for face #%d\n", i );
00599 continue;
00600 }
00601
00602 if( !(*corners[0])->vg_p )
00603 nmg_vertex_gv( *(corners[0]), pt[0] );
00604 if( !(*corners[1])->vg_p )
00605 nmg_vertex_gv( *(corners[1]), pt[1] );
00606 if( !(*corners[2])->vg_p )
00607 nmg_vertex_gv( *(corners[2]), pt[2] );
00608
00609 if( nmg_calc_face_g( fu ) )
00610 nmg_kfu( fu );
00611 else if( bot_ip->mode == RT_BOT_SURFACE )
00612 {
00613 struct vertex **tmp;
00614
00615 tmp = corners[0];
00616 corners[0] = corners[2];
00617 corners[2] = tmp;
00618 if( (fu=nmg_cmface( s, corners, 3 )) == (struct faceuse *)NULL )
00619 bu_log( "rt_bot_tess() nmg_cmface() failed for face #%d\n", i );
00620 else
00621 nmg_calc_face_g( fu );
00622 }
00623 }
00624
00625 bu_free( (char *)verts, "rt_bot_tess *verts[]" );
00626
00627 nmg_mark_edges_real( &s->l.magic );
00628
00629 nmg_region_a( *r, tol );
00630
00631 if( bot_ip->mode == RT_BOT_SOLID && bot_ip->orientation == RT_BOT_UNORIENTED )
00632 nmg_fix_normals( s, tol );
00633
00634 return( 0 );
00635 }
00636
00637
00638
00639
00640
00641
00642
00643 int
00644 rt_bot_import(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00645 {
00646 LOCAL struct rt_bot_internal *bot_ip;
00647 union record *rp;
00648 int i;
00649 int chars_used;
00650
00651 BU_CK_EXTERNAL( ep );
00652 rp = (union record *)ep->ext_buf;
00653
00654 if( rp->u_id != DBID_BOT ) {
00655 bu_log("rt_bot_import: defective record\n");
00656 return(-1);
00657 }
00658
00659 RT_CK_DB_INTERNAL( ip );
00660 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00661 ip->idb_type = ID_BOT;
00662 ip->idb_meth = &rt_functab[ID_BOT];
00663 ip->idb_ptr = bu_malloc( sizeof(struct rt_bot_internal), "rt_bot_internal");
00664 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00665 bot_ip->magic = RT_BOT_INTERNAL_MAGIC;
00666
00667 bot_ip->num_vertices = bu_glong( rp->bot.bot_num_verts );
00668 bot_ip->num_faces = bu_glong( rp->bot.bot_num_triangles );
00669 bot_ip->orientation = rp->bot.bot_orientation;
00670 bot_ip->mode = rp->bot.bot_mode;
00671 bot_ip->bot_flags = 0;
00672
00673 bot_ip->vertices = (fastf_t *)bu_calloc( bot_ip->num_vertices * 3, sizeof( fastf_t ), "Bot vertices" );
00674 bot_ip->faces = (int *)bu_calloc( bot_ip->num_faces * 3, sizeof( int ), "Bot faces" );
00675
00676 for( i=0 ; i<bot_ip->num_vertices ; i++ )
00677 {
00678 point_t tmp;
00679
00680 ntohd( (unsigned char *)tmp, (const unsigned char *)(&rp->bot.bot_data[i*24]), 3 );
00681 MAT4X3PNT( &(bot_ip->vertices[i*3]), mat, tmp );
00682 }
00683
00684 chars_used = bot_ip->num_vertices * 3 * 8;
00685
00686 for( i=0 ; i<bot_ip->num_faces ; i++ )
00687 {
00688 int index=chars_used + i * 12;
00689
00690 bot_ip->faces[i*3] = bu_glong( (const unsigned char *)&rp->bot.bot_data[index] );
00691 bot_ip->faces[i*3 + 1] = bu_glong( (const unsigned char *)&rp->bot.bot_data[index + 4] );
00692 bot_ip->faces[i*3 + 2] = bu_glong( (const unsigned char *)&rp->bot.bot_data[index + 8] );
00693 }
00694
00695 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
00696 {
00697 chars_used = bot_ip->num_vertices * 3 * 8 + bot_ip->num_faces * 12;
00698
00699 bot_ip->thickness = (fastf_t *)bu_calloc( bot_ip->num_faces, sizeof( fastf_t ), "BOT thickness" );
00700 for( i=0 ; i<bot_ip->num_faces ; i++ )
00701 ntohd( (unsigned char *)&(bot_ip->thickness[i]),
00702 (const unsigned char *)(&rp->bot.bot_data[chars_used + i*8]), 1 );
00703 bot_ip->face_mode = bu_hex_to_bitv( (const char *)(&rp->bot.bot_data[chars_used + bot_ip->num_faces * 8]) );
00704 }
00705 else
00706 {
00707 bot_ip->thickness = (fastf_t *)NULL;
00708 bot_ip->face_mode = (struct bu_bitv *)NULL;
00709 }
00710
00711 return(0);
00712 }
00713
00714
00715
00716
00717
00718
00719 int
00720 rt_bot_export(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00721 {
00722 struct rt_bot_internal *bot_ip;
00723 union record *rec;
00724 int i;
00725 int chars_used;
00726 int num_recs;
00727 struct bu_vls face_mode;
00728
00729
00730 RT_CK_DB_INTERNAL(ip);
00731 if( ip->idb_type != ID_BOT ) return(-1);
00732 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
00733 RT_BOT_CK_MAGIC(bot_ip);
00734
00735 if( bot_ip->num_normals > 0 ) {
00736 bu_log( "BOT surface normals not supported in older database formats, normals not saved\n" );
00737 bu_log( "\tPlease update to current database format using \"dbupgrade\"\n" );
00738 }
00739
00740 BU_CK_EXTERNAL(ep);
00741 ep->ext_nbytes = sizeof( struct bot_rec ) - 1 +
00742 bot_ip->num_vertices * 3 * 8 + bot_ip->num_faces * 3 * 4;
00743 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
00744 {
00745 if( !bot_ip->face_mode )
00746 {
00747 bot_ip->face_mode = bu_bitv_new( bot_ip->num_faces );
00748 bu_bitv_clear( bot_ip->face_mode );
00749 }
00750 if( !bot_ip->thickness )
00751 bot_ip->thickness = (fastf_t *)bu_calloc( bot_ip->num_faces, sizeof( fastf_t ), "BOT thickness" );
00752 bu_vls_init( &face_mode );
00753 bu_bitv_to_hex( &face_mode, bot_ip->face_mode );
00754 ep->ext_nbytes += bot_ip->num_faces * 8 + bu_vls_strlen( &face_mode ) + 1;
00755 }
00756
00757
00758 if( ep->ext_nbytes % (sizeof( union record ) ) )
00759 {
00760 ep->ext_nbytes += (sizeof( union record ) )
00761 - ep->ext_nbytes % (sizeof( union record ) );
00762 }
00763 num_recs = ep->ext_nbytes / sizeof( union record ) - 1;
00764 ep->ext_buf = (genptr_t)bu_calloc( 1, ep->ext_nbytes, "bot external");
00765 rec = (union record *)ep->ext_buf;
00766
00767 rec->bot.bot_id = DBID_BOT;
00768
00769 bu_plong( (unsigned char *)rec->bot.bot_nrec, num_recs );
00770 rec->bot.bot_orientation = bot_ip->orientation;
00771 rec->bot.bot_mode = bot_ip->mode;
00772 rec->bot.bot_err_mode = 0;
00773 bu_plong( (unsigned char *)rec->bot.bot_num_verts, bot_ip->num_vertices );
00774 bu_plong( (unsigned char *)rec->bot.bot_num_triangles, bot_ip->num_faces );
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 for( i=0 ; i<bot_ip->num_vertices ; i++ )
00786 {
00787 point_t tmp;
00788
00789 VSCALE( tmp, &bot_ip->vertices[i*3], local2mm );
00790 htond( (unsigned char *)&rec->bot.bot_data[i*24], (const unsigned char *)tmp, 3 );
00791 }
00792
00793 chars_used = bot_ip->num_vertices * 24;
00794
00795 for( i=0 ; i<bot_ip->num_faces ; i++ )
00796 {
00797 int index=chars_used + i * 12;
00798
00799 bu_plong( (unsigned char *)(&rec->bot.bot_data[index]), bot_ip->faces[i*3] );
00800 bu_plong( (unsigned char *)(&rec->bot.bot_data[index + 4]), bot_ip->faces[i*3+1] );
00801 bu_plong( (unsigned char *)(&rec->bot.bot_data[index + 8]), bot_ip->faces[i*3+2] );
00802 }
00803
00804 chars_used += bot_ip->num_faces * 12;
00805
00806 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
00807 {
00808 for( i=0 ; i<bot_ip->num_faces ; i++ )
00809 {
00810 fastf_t tmp;
00811 tmp = bot_ip->thickness[i] * local2mm;
00812 htond( (unsigned char *)&rec->bot.bot_data[chars_used], (const unsigned char *)&tmp, 1 );
00813 chars_used += 8;
00814 }
00815 strcpy( (char *)&rec->bot.bot_data[chars_used], bu_vls_addr( &face_mode ) );
00816 bu_vls_free( &face_mode );
00817 }
00818
00819 return(0);
00820 }
00821
00822
00823
00824
00825 int
00826 rt_bot_import5(struct rt_db_internal *ip, const struct bu_external *ep, register const fastf_t *mat, const struct db_i *dbip)
00827 {
00828 struct rt_bot_internal *bip;
00829 register unsigned char *cp;
00830 int i;
00831
00832 BU_CK_EXTERNAL( ep );
00833
00834 RT_CK_DB_INTERNAL( ip );
00835 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00836 ip->idb_type = ID_BOT;
00837 ip->idb_meth = &rt_functab[ID_BOT];
00838 ip->idb_ptr = bu_calloc( 1, sizeof(struct rt_bot_internal), "rt_bot_internal");
00839
00840 bip = (struct rt_bot_internal *)ip->idb_ptr;
00841 bip->magic = RT_BOT_INTERNAL_MAGIC;
00842
00843 cp = ep->ext_buf;
00844 bip->num_vertices = bu_glong( cp );
00845 cp += SIZEOF_NETWORK_LONG;
00846 bip->num_faces = bu_glong( cp );
00847 cp += SIZEOF_NETWORK_LONG;
00848 bip->orientation = *cp++;
00849 bip->mode = *cp++;
00850 bip->bot_flags = *cp++;
00851
00852 bip->vertices = (fastf_t *)bu_calloc( bip->num_vertices * 3, sizeof( fastf_t ), "BOT vertices" );
00853 bip->faces = (int *)bu_calloc( bip->num_faces * 3, sizeof( int ), "BOT faces" );
00854
00855 for( i=0 ; i<bip->num_vertices ; i++ )
00856 {
00857 point_t tmp;
00858
00859 ntohd( (unsigned char *)tmp, (const unsigned char *)cp, 3 );
00860 cp += SIZEOF_NETWORK_DOUBLE * 3;
00861 MAT4X3PNT( &(bip->vertices[i*3]), mat, tmp );
00862 }
00863
00864 for( i=0 ; i<bip->num_faces ; i++ )
00865 {
00866 bip->faces[i*3] = bu_glong( cp );
00867 cp += SIZEOF_NETWORK_LONG;
00868 bip->faces[i*3 + 1] = bu_glong( cp );
00869 cp += SIZEOF_NETWORK_LONG;
00870 bip->faces[i*3 + 2] = bu_glong( cp );
00871 cp += SIZEOF_NETWORK_LONG;
00872 }
00873
00874 if( bip->mode == RT_BOT_PLATE || bip->mode == RT_BOT_PLATE_NOCOS )
00875 {
00876 bip->thickness = (fastf_t *)bu_calloc( bip->num_faces, sizeof( fastf_t ), "BOT thickness" );
00877 for( i=0 ; i<bip->num_faces ; i++ )
00878 {
00879 ntohd( (unsigned char *)&(bip->thickness[i]), cp, 1 );
00880 cp += SIZEOF_NETWORK_DOUBLE;
00881 }
00882 bip->face_mode = bu_hex_to_bitv( (const char *)cp );
00883 while( *(cp++) != '\0' );
00884 }
00885 else
00886 {
00887 bip->thickness = (fastf_t *)NULL;
00888 bip->face_mode = (struct bu_bitv *)NULL;
00889 }
00890
00891 if( bip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
00892 vect_t tmp;
00893
00894 bip->num_normals = bu_glong( cp );
00895 cp += SIZEOF_NETWORK_LONG;
00896 bip->num_face_normals = bu_glong( cp );
00897 cp += SIZEOF_NETWORK_LONG;
00898
00899 if( bip->num_normals <= 0 ) {
00900 bip->normals = (fastf_t *)NULL;
00901 }
00902 if( bip->num_face_normals <= 0 ) {
00903 bip->face_normals = (int *)NULL;
00904 }
00905 if( bip->num_normals > 0 ) {
00906 bip->normals = (fastf_t *)bu_calloc( bip->num_normals * 3, sizeof( fastf_t ), "BOT normals" );
00907
00908 for( i=0 ; i<bip->num_normals ; i++ ) {
00909 ntohd( (unsigned char *)tmp, (const unsigned char *)cp, 3 );
00910 cp += SIZEOF_NETWORK_DOUBLE * 3;
00911 MAT4X3VEC( &(bip->normals[i*3]), mat, tmp );
00912 }
00913 }
00914 if( bip->num_face_normals > 0 ) {
00915 bip->face_normals = (int *)bu_calloc( bip->num_face_normals * 3, sizeof( int ), "BOT face normals" );
00916
00917 for( i=0 ; i<bip->num_face_normals ; i++ ) {
00918 bip->face_normals[i*3] = bu_glong( cp );
00919 cp += SIZEOF_NETWORK_LONG;
00920 bip->face_normals[i*3 + 1] = bu_glong( cp );
00921 cp += SIZEOF_NETWORK_LONG;
00922 bip->face_normals[i*3 + 2] = bu_glong( cp );
00923 cp += SIZEOF_NETWORK_LONG;
00924 }
00925 }
00926 } else {
00927 bip->normals = (fastf_t *)NULL;
00928 bip->face_normals = (int *)NULL;
00929 bip->num_normals = 0;
00930 }
00931
00932 return(0);
00933 }
00934
00935
00936
00937
00938 int
00939 rt_bot_export5(struct bu_external *ep, const struct rt_db_internal *ip, double local2mm, const struct db_i *dbip)
00940 {
00941 struct rt_bot_internal *bip;
00942 struct bu_vls vls;
00943 register unsigned char *cp;
00944 int i;
00945
00946 RT_CK_DB_INTERNAL( ip );
00947
00948 if( ip->idb_type != ID_BOT ) return -1;
00949 bip = (struct rt_bot_internal *)ip->idb_ptr;
00950 RT_BOT_CK_MAGIC( bip );
00951
00952 BU_CK_EXTERNAL( ep );
00953
00954 if( bip->mode == RT_BOT_PLATE || bip->mode == RT_BOT_PLATE_NOCOS )
00955 {
00956
00957 bu_vls_init( &vls );
00958 if( bip->face_mode )
00959 bu_bitv_to_hex( &vls, bip->face_mode );
00960 }
00961
00962 ep->ext_nbytes = 3
00963 + SIZEOF_NETWORK_LONG * (bip->num_faces * 3 + 2)
00964 + SIZEOF_NETWORK_DOUBLE * bip->num_vertices * 3;
00965
00966 if( bip->mode == RT_BOT_PLATE || bip->mode == RT_BOT_PLATE_NOCOS ) {
00967 ep->ext_nbytes += SIZEOF_NETWORK_DOUBLE * bip->num_faces
00968 + bu_vls_strlen( &vls ) + 1;
00969 }
00970
00971 if( bip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
00972 ep->ext_nbytes += SIZEOF_NETWORK_DOUBLE * bip->num_normals * 3
00973 + SIZEOF_NETWORK_LONG * (bip->num_face_normals * 3 + 2);
00974 }
00975
00976 ep->ext_buf = (genptr_t)bu_malloc( ep->ext_nbytes, "BOT external" );
00977
00978 cp = ep->ext_buf;
00979
00980 (void)bu_plong( cp, bip->num_vertices );
00981 cp += SIZEOF_NETWORK_LONG;
00982 (void)bu_plong( cp, bip->num_faces );
00983 cp += SIZEOF_NETWORK_LONG;
00984 *cp++ = bip->orientation;
00985 *cp++ = bip->mode;
00986 *cp++ = bip->bot_flags;
00987
00988 for( i=0 ; i<bip->num_vertices ; i++ )
00989 {
00990 point_t tmp;
00991
00992 VSCALE( tmp, &bip->vertices[i*3], local2mm );
00993 htond( cp, (unsigned char *)tmp, 3 );
00994 cp += SIZEOF_NETWORK_DOUBLE * 3;
00995 }
00996
00997 for( i=0 ; i<bip->num_faces ; i++ )
00998 {
00999 (void)bu_plong( cp, bip->faces[i*3] );
01000 cp += SIZEOF_NETWORK_LONG;
01001 (void)bu_plong( cp, bip->faces[i*3 + 1] );
01002 cp += SIZEOF_NETWORK_LONG;
01003 (void)bu_plong( cp, bip->faces[i*3 + 2] );
01004 cp += SIZEOF_NETWORK_LONG;
01005 }
01006
01007 if( bip->mode == RT_BOT_PLATE || bip->mode == RT_BOT_PLATE_NOCOS )
01008 {
01009 for( i=0 ; i<bip->num_faces ; i++ )
01010 {
01011 fastf_t tmp;
01012
01013 tmp = bip->thickness[i] * local2mm;
01014 htond( cp, (const unsigned char *)&tmp, 1 );
01015 cp += SIZEOF_NETWORK_DOUBLE;
01016 }
01017 strcpy( (char *)cp, bu_vls_addr( &vls ) );
01018 cp += bu_vls_strlen( &vls );
01019 *cp = '\0';
01020 cp++;
01021 bu_vls_free( &vls );
01022 }
01023
01024 if( bip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
01025 (void)bu_plong( cp, bip->num_normals );
01026 cp += SIZEOF_NETWORK_LONG;
01027 (void)bu_plong( cp, bip->num_face_normals );
01028 cp += SIZEOF_NETWORK_LONG;
01029 if( bip->num_normals > 0 ) {
01030 htond( cp, (unsigned char*)bip->normals, bip->num_normals*3 );
01031 cp += SIZEOF_NETWORK_DOUBLE * 3 * bip->num_normals;
01032 }
01033 if( bip->num_face_normals > 0 ) {
01034 for( i=0 ; i<bip->num_face_normals ; i++ ) {
01035 (void)bu_plong( cp, bip->face_normals[i*3] );
01036 cp += SIZEOF_NETWORK_LONG;
01037 (void)bu_plong( cp, bip->face_normals[i*3 + 1] );
01038 cp += SIZEOF_NETWORK_LONG;
01039 (void)bu_plong( cp, bip->face_normals[i*3 + 2] );
01040 cp += SIZEOF_NETWORK_LONG;
01041 }
01042 }
01043 }
01044
01045 return 0;
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055 static char *unoriented="unoriented";
01056 static char *ccw="counter-clockwise";
01057 static char *cw="clockwise";
01058 static char *unknown_orientation="unknown orientation";
01059 static char *surface="\tThis is a surface with no volume\n";
01060 static char *solid="\tThis is a solid object (not just a surface)\n";
01061 static char *plate="\tThis is a FASTGEN plate mode solid\n";
01062 static char *nocos="\tThis is a plate mode solid with no obliquity angle effect\n";
01063 static char *unknown_mode="\tunknown mode\n";
01064 int
01065 rt_bot_describe(struct bu_vls *str, const struct rt_db_internal *ip, int verbose, double mm2local)
01066 {
01067 register struct rt_bot_internal *bot_ip =
01068 (struct rt_bot_internal *)ip->idb_ptr;
01069 char buf[256];
01070 char *orientation,*mode;
01071 int i;
01072
01073 RT_BOT_CK_MAGIC(bot_ip);
01074 bu_vls_strcat( str, "Bag of triangles (BOT)\n");
01075
01076 switch( bot_ip->orientation )
01077 {
01078 case RT_BOT_UNORIENTED:
01079 orientation = unoriented;
01080 break;
01081 case RT_BOT_CCW:
01082 orientation = ccw;
01083 break;
01084 case RT_BOT_CW:
01085 orientation = cw;
01086 break;
01087 default:
01088 orientation = unknown_orientation;
01089 break;
01090 }
01091 switch( bot_ip->mode )
01092 {
01093 case RT_BOT_SURFACE:
01094 mode = surface;
01095 break;
01096 case RT_BOT_SOLID:
01097 mode = solid;
01098 break;
01099 case RT_BOT_PLATE:
01100 mode = plate;
01101 break;
01102 case RT_BOT_PLATE_NOCOS:
01103 mode = nocos;
01104 break;
01105 default:
01106 mode = unknown_mode;
01107 break;
01108 }
01109 sprintf(buf, "\t%d vertices, %d faces (%s)\n",
01110 bot_ip->num_vertices,
01111 bot_ip->num_faces,
01112 orientation );
01113 bu_vls_strcat( str, buf );
01114 bu_vls_strcat( str, mode );
01115 if( (bot_ip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) && bot_ip->num_normals > 0 ) {
01116 bu_vls_strcat( str, "\twith surface normals" );
01117 if( bot_ip->bot_flags & RT_BOT_USE_NORMALS ) {
01118 bu_vls_strcat( str, " (they will be used)\n" );
01119 } else {
01120 bu_vls_strcat( str, " (they will be ignored)\n" );
01121 }
01122 }
01123
01124 if( verbose )
01125 {
01126 for( i=0 ; i<bot_ip->num_faces ; i++ )
01127 {
01128 int j, k;
01129 point_t pt[3];
01130
01131 for( j=0 ; j<3 ; j++ )
01132 VSCALE( pt[j], &bot_ip->vertices[bot_ip->faces[i*3+j]*3], mm2local );
01133 if( (bot_ip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) && bot_ip->num_normals > 0 ) {
01134 sprintf( buf, "\tface %d: (%g %g %g), (%g %g %g), (%g %g %g) normals: ", i,
01135 V3INTCLAMPARGS( pt[0] ),
01136 V3INTCLAMPARGS( pt[1] ),
01137 V3INTCLAMPARGS( pt[2] ) );
01138 bu_vls_strcat( str, buf );
01139 for( k=0 ; k<3 ; k++ ) {
01140 int index;
01141
01142 index = i*3 + k;
01143 if( bot_ip->face_normals[index] < 0 || bot_ip->face_normals[index] >= bot_ip->num_normals ) {
01144 bu_vls_strcat( str, "none " );
01145 } else {
01146 sprintf( buf, "(%g %g %g) ", V3INTCLAMPARGS( &bot_ip->normals[bot_ip->face_normals[index]*3]));
01147 bu_vls_strcat( str, buf );
01148 }
01149 }
01150 bu_vls_strcat( str, "\n" );
01151 } else {
01152 sprintf( buf, "\tface %d: (%g %g %g), (%g %g %g), (%g %g %g)\n", i,
01153 V3INTCLAMPARGS( pt[0] ),
01154 V3INTCLAMPARGS( pt[1] ),
01155 V3INTCLAMPARGS( pt[2] ) );
01156 bu_vls_strcat( str, buf );
01157 }
01158 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
01159 {
01160 char *face_mode;
01161
01162 if( BU_BITTEST( bot_ip->face_mode, i ) )
01163 face_mode = "appended to hit point";
01164 else
01165 face_mode = "centered about hit point";
01166 sprintf( buf, "\t\tthickness = %g, %s\n", INTCLAMP(mm2local*bot_ip->thickness[i]), face_mode );
01167 bu_vls_strcat( str, buf );
01168 }
01169 }
01170 }
01171
01172 return(0);
01173 }
01174
01175
01176
01177
01178
01179
01180 void
01181 rt_bot_ifree(struct rt_db_internal *ip)
01182 {
01183 register struct rt_bot_internal *bot_ip;
01184
01185 RT_CK_DB_INTERNAL(ip);
01186 bot_ip = (struct rt_bot_internal *)ip->idb_ptr;
01187 RT_BOT_CK_MAGIC(bot_ip);
01188 bot_ip->magic = 0;
01189
01190 bu_free( (char *)bot_ip->vertices, "BOT vertices" );
01191 bu_free( (char *)bot_ip->faces, "BOT faces" );
01192
01193 if( bot_ip->mode == RT_BOT_PLATE || bot_ip->mode == RT_BOT_PLATE_NOCOS )
01194 {
01195 bu_free( (char *)bot_ip->thickness, "BOT thickness" );
01196 bu_free( (char *)bot_ip->face_mode, "BOT face_mode" );
01197 }
01198
01199 bu_free( (char *)bot_ip, "bot ifree" );
01200 ip->idb_ptr = GENPTR_NULL;
01201 }
01202
01203 int
01204 rt_bot_tnurb(struct nmgregion **r, struct model *m, struct rt_db_internal *ip, const struct bn_tol *tol)
01205 {
01206 return( 1 );
01207 }
01208
01209 int
01210 rt_bot_xform(struct rt_db_internal *op, const fastf_t *mat, struct rt_db_internal *ip, const int free, struct db_i *dbip)
01211 {
01212 struct rt_bot_internal *botip, *botop;
01213 register int i;
01214 point_t pt;
01215
01216 RT_CK_DB_INTERNAL( ip );
01217 botip = (struct rt_bot_internal *)ip->idb_ptr;
01218 RT_BOT_CK_MAGIC(botip);
01219
01220 if( op != ip && !free )
01221 {
01222 RT_INIT_DB_INTERNAL(op);
01223 BU_GETSTRUCT( botop, rt_bot_internal );
01224 botop->magic = RT_BOT_INTERNAL_MAGIC;
01225 botop->mode = botip->mode;
01226 botop->orientation = botip->orientation;
01227 botop->bot_flags = botip->bot_flags;
01228 botop->num_vertices = botip->num_vertices;
01229 botop->num_faces = botip->num_faces;
01230 if( botop->num_vertices > 0 ) {
01231 botop->vertices = (fastf_t *)bu_malloc( botip->num_vertices * 3 *
01232 sizeof( fastf_t ), "botop->vertices" );
01233 }
01234 if( botop->num_faces > 0 ) {
01235 botop->faces = (int *)bu_malloc( botip->num_faces * 3 *
01236 sizeof( int ), "botop->faces" );
01237 memcpy( botop->faces, botip->faces, botop->num_faces * 3 * sizeof( int ) );
01238 }
01239 if( botip->thickness )
01240 botop->thickness = (fastf_t *)bu_malloc( botip->num_faces *
01241 sizeof( fastf_t ), "botop->thickness" );
01242 if( botip->face_mode )
01243 botop->face_mode = bu_bitv_dup( botip->face_mode );
01244 if( botip->thickness )
01245 {
01246 for( i=0 ; i<botip->num_faces ; i++ )
01247 botop->thickness[i] = botip->thickness[i];
01248 }
01249
01250 if( botop->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
01251 botop->num_normals = botip->num_normals;
01252 botop->normals = (fastf_t *)bu_calloc( botop->num_normals * 3, sizeof( fastf_t ), "BOT normals" );
01253 botop->face_normals = (int *)bu_calloc( botop->num_faces * 3, sizeof( int ), "BOT face normals" );
01254 memcpy( botop->face_normals, botip->face_normals, botop->num_faces * 3 * sizeof( int ) );
01255 }
01256 op->idb_ptr = (genptr_t)botop;
01257 op->idb_major_type = DB5_MAJORTYPE_BRLCAD;
01258 op->idb_type = ID_BOT;
01259 op->idb_meth = &rt_functab[ID_BOT];
01260 }
01261 else
01262 botop = botip;
01263
01264 if( ip != op ) {
01265 if( ip->idb_avs.magic == BU_AVS_MAGIC ) {
01266 bu_avs_init( &op->idb_avs, ip->idb_avs.count, "avs" );
01267 bu_avs_merge( &op->idb_avs, &ip->idb_avs );
01268 }
01269 }
01270
01271 for( i=0 ; i<botip->num_vertices ; i++ )
01272 {
01273 MAT4X3PNT( pt, mat, &botip->vertices[i*3] );
01274 VMOVE( &botop->vertices[i*3], pt );
01275 }
01276
01277 for( i=0 ; i<botip->num_normals ; i++ ) {
01278 MAT4X3VEC( pt, mat, &botip->normals[i*3] );
01279 VMOVE( &botop->normals[i*3], pt );
01280 }
01281
01282 if( free && op != ip ) {
01283 rt_bot_ifree( ip );
01284 }
01285
01286 return( 0 );
01287 }
01288
01289 int
01290 rt_bot_find_v_nearest_pt2(
01291 const struct rt_bot_internal *bot,
01292 const point_t pt2,
01293 const mat_t mat)
01294 {
01295 point_t v;
01296 int index;
01297 fastf_t dist=MAX_FASTF;
01298 int closest=-1;
01299
01300 RT_BOT_CK_MAGIC( bot );
01301
01302 for( index=0 ; index < bot->num_vertices ; index++ )
01303 {
01304 fastf_t tmp_dist;
01305 fastf_t tmpx, tmpy;
01306
01307 MAT4X3PNT( v, mat, &bot->vertices[index*3] )
01308 tmpx = v[X] - pt2[X];
01309 tmpy = v[Y] - pt2[Y];
01310 tmp_dist = tmpx * tmpx + tmpy * tmpy;
01311 if( tmp_dist < dist )
01312 {
01313 dist = tmp_dist;
01314 closest = index;
01315 }
01316 }
01317
01318 return( closest );
01319 }
01320
01321 int
01322 rt_bot_edge_in_list( const int v1, const int v2, const int edge_list[], const int edge_count )
01323 {
01324 int i, ev1, ev2;
01325
01326 for( i=0 ; i<edge_count ; i++ )
01327 {
01328 ev1 = edge_list[i*2];
01329 ev2 = edge_list[i*2 + 1];
01330
01331 if( ev1 == v1 && ev2 == v2 )
01332 return( 1 );
01333
01334 if( ev1 == v2 && ev2 == v1 )
01335 return( 1 );
01336 }
01337
01338 return( 0 );
01339 }
01340
01341
01342
01343
01344
01345 int
01346 rt_bot_find_e_nearest_pt2(
01347 int *vert1,
01348 int *vert2,
01349 const struct rt_bot_internal *bot,
01350 const point_t pt2,
01351 const mat_t mat)
01352 {
01353 int i;
01354 int v1, v2, v3;
01355 fastf_t dist=MAX_FASTF, tmp_dist;
01356 int *edge_list;
01357 int edge_count=0;
01358 struct bn_tol tol;
01359
01360 RT_BOT_CK_MAGIC( bot );
01361
01362 if( bot->num_faces < 1 )
01363 return( -1 );
01364
01365
01366 edge_list = (int *)bu_calloc( bot->num_faces * 3 * 2, sizeof( int ), "bot edge list" );
01367
01368 for( i=0 ; i<bot->num_faces ; i++ )
01369 {
01370 v1 = bot->faces[i*3];
01371 v2 = bot->faces[i*3 + 1];
01372 v3 = bot->faces[i*3 + 2];
01373
01374 if( !rt_bot_edge_in_list( v1, v2, edge_list, edge_count ) )
01375 {
01376 edge_list[edge_count*2] = v1;
01377 edge_list[edge_count*2 + 1] = v2;
01378 edge_count++;
01379 }
01380 if( !rt_bot_edge_in_list( v3, v2, edge_list, edge_count ) )
01381 {
01382 edge_list[edge_count*2] = v3;
01383 edge_list[edge_count*2 + 1] = v2;
01384 edge_count++;
01385 }
01386 if( !rt_bot_edge_in_list( v1, v3, edge_list, edge_count ) )
01387 {
01388 edge_list[edge_count*2] = v1;
01389 edge_list[edge_count*2 + 1] = v3;
01390 edge_count++;
01391 }
01392 }
01393
01394
01395 tol.magic = BN_TOL_MAGIC;
01396 tol.dist = 0.0;
01397 tol.dist_sq = 0.0;
01398 tol.perp = 0.0;
01399 tol.para = 1.0;
01400
01401
01402 for( i=0 ; i<edge_count ; i++ )
01403 {
01404 point_t p1, p2, pca;
01405 vect_t p1_to_pca, p1_to_p2;
01406 int ret;
01407
01408 MAT4X3PNT( p1, mat, &bot->vertices[ edge_list[i*2]*3] )
01409 MAT4X3PNT( p2, mat, &bot->vertices[ edge_list[i*2+1]*3] )
01410
01411 ret = bn_dist_pt2_lseg2( &tmp_dist, pca, p1, p2, pt2, &tol );
01412
01413 if( ret < 3 || tmp_dist < dist )
01414 {
01415 switch( ret )
01416 {
01417 case 0:
01418 dist = 0.0;
01419 if( tmp_dist < 0.5 )
01420 {
01421 *vert1 = edge_list[i*2];
01422 *vert2 = edge_list[i*2+1];
01423 }
01424 else
01425 {
01426 *vert1 = edge_list[i*2+1];
01427 *vert2 = edge_list[i*2];
01428 }
01429 break;
01430 case 1:
01431 dist = 0.0;
01432 *vert1 = edge_list[i*2];
01433 *vert2 = edge_list[i*2+1];
01434 break;
01435 case 2:
01436 dist = 0.0;
01437 *vert1 = edge_list[i*2+1];
01438 *vert2 = edge_list[i*2];
01439 break;
01440 case 3:
01441 dist = tmp_dist;
01442 *vert1 = edge_list[i*2];
01443 *vert2 = edge_list[i*2+1];
01444 break;
01445 case 4:
01446 dist = tmp_dist;
01447 *vert1 = edge_list[i*2+1];
01448 *vert2 = edge_list[i*2];
01449 case 5:
01450 dist = tmp_dist;
01451 V2SUB2( p1_to_pca, pca, p1 );
01452 V2SUB2( p1_to_p2, p2, p1 );
01453 if( MAG2SQ( p1_to_pca ) / MAG2SQ( p1_to_p2 ) < 0.25 )
01454 {
01455 *vert1 = edge_list[i*2];
01456 *vert2 = edge_list[i*2+1];
01457 }
01458 else
01459 {
01460 *vert1 = edge_list[i*2+1];
01461 *vert2 = edge_list[i*2];
01462 }
01463 break;
01464 }
01465 }
01466 }
01467
01468 bu_free( (char *)edge_list, "bot edge list" );
01469
01470 return( 0 );
01471 }
01472
01473 static char *modes[]={
01474 "ERROR: Unrecognized mode",
01475 "surf",
01476 "volume",
01477 "plate",
01478 "plate_nocos"
01479 };
01480
01481 static char *orientation[]={
01482 "ERROR: Unrecognized orientation",
01483 "no",
01484 "rh",
01485 "lh"
01486 };
01487
01488 static char *los[]={
01489 "center",
01490 "append"
01491 };
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519 int
01520 rt_bot_tclget(Tcl_Interp *interp, const struct rt_db_internal *intern, const char *attr)
01521 {
01522 register struct rt_bot_internal *bot=(struct rt_bot_internal *)intern->idb_ptr;
01523 Tcl_DString ds;
01524 struct bu_vls vls;
01525 int status;
01526 int i;
01527
01528 RT_BOT_CK_MAGIC( bot );
01529
01530 Tcl_DStringInit( &ds );
01531 bu_vls_init( &vls );
01532
01533 if( attr == (char *)NULL )
01534 {
01535 bu_vls_strcpy( &vls, "bot" );
01536 bu_vls_printf( &vls, " mode %s orient %s",
01537 modes[bot->mode], orientation[bot->orientation] );
01538 bu_vls_printf( &vls, " flags {" );
01539 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
01540 bu_vls_printf( &vls, " has_normals" );
01541 }
01542 if( bot->bot_flags & RT_BOT_USE_NORMALS ) {
01543 bu_vls_printf( &vls, " use_normals" );
01544 }
01545 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
01546 bu_vls_printf( &vls, " use_floats" );
01547 }
01548 bu_vls_printf( &vls, "} V {" );
01549 for( i=0 ; i<bot->num_vertices ; i++ )
01550 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01551 V3ARGS( &bot->vertices[i*3] ) );
01552 bu_vls_strcat( &vls, "} F {" );
01553 for( i=0 ; i<bot->num_faces ; i++ )
01554 bu_vls_printf( &vls, " { %d %d %d }",
01555 V3ARGS( &bot->faces[i*3] ) );
01556 bu_vls_strcat( &vls, "}" );
01557 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
01558 {
01559 bu_vls_strcat( &vls, " T {" );
01560 for( i=0 ; i<bot->num_faces ; i++ )
01561 bu_vls_printf( &vls, " %.25G", bot->thickness[i] );
01562 bu_vls_strcat( &vls, "} fm " );
01563 bu_bitv_to_hex( &vls, bot->face_mode );
01564 }
01565 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
01566 bu_vls_printf( &vls, " N {" );
01567 for( i=0 ; i<bot->num_normals ; i++ ) {
01568 bu_vls_printf( &vls, " { %.25G %.25G %.25G }", V3ARGS( &bot->normals[i*3] ) );
01569 }
01570 bu_vls_printf( &vls, "} fn {" );
01571 for( i=0 ; i<bot->num_faces ; i++ ) {
01572 bu_vls_printf( &vls, " { %d %d %d }", V3ARGS( &bot->face_normals[i*3] ) );
01573 }
01574 bu_vls_printf( &vls, "}" );
01575 }
01576 status = TCL_OK;
01577 }
01578 else
01579 {
01580 if( attr[0] == 'N' )
01581 {
01582 if( attr[1] == '\0' ) {
01583 if( !(bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) || bot->num_normals < 1 ) {
01584 bu_vls_strcat( &vls, "{}" );
01585 } else {
01586 for( i=0 ; i<bot->num_normals ; i++ ) {
01587 bu_vls_printf( &vls, " { %.25G %.25G %.25G }", V3ARGS( &bot->normals[i*3] ) );
01588 }
01589 }
01590 status = TCL_OK;
01591 } else {
01592 i = atoi( &attr[1] );
01593 if( i < 0 || i >= bot->num_normals ) {
01594 bu_vls_strcat( &vls, "Specified normal index is out of range" );
01595 status = TCL_ERROR;
01596 } else {
01597 bu_vls_printf( &vls, "%.25G %.25G %.25G", V3ARGS( &bot->normals[i*3] ) );
01598 status = TCL_OK;
01599 }
01600 }
01601 }
01602 else if( !strncmp( attr, "fn", 2 ) )
01603 {
01604 if( attr[2] == '\0' ) {
01605 for( i=0 ; i<bot->num_faces ; i++ ) {
01606 bu_vls_printf( &vls, " { %d %d %d }", V3ARGS( &bot->face_normals[i*3] ) );
01607 }
01608 status = TCL_OK;
01609 } else {
01610 i = atoi( &attr[2] );
01611 if( i < 0 || i >= bot->num_faces ) {
01612 bu_vls_strcat( &vls, "Specified face index is out of range" );
01613 status = TCL_ERROR;
01614 } else {
01615 bu_vls_printf( &vls, "%d %d %d", V3ARGS( &bot->face_normals[i*3] ) );
01616 status = TCL_OK;
01617 }
01618 }
01619 }
01620 else if( !strcmp( attr, "nn" ) )
01621 {
01622 if( !(bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) || bot->num_normals < 1 ) {
01623 bu_vls_strcat( &vls, "0" );
01624 } else {
01625 bu_vls_printf( &vls, "%d", bot->num_normals );
01626 }
01627 status = TCL_OK;
01628 }
01629 else if( !strcmp( attr, "nfn" ) )
01630 {
01631 if( !(bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) || bot->num_face_normals < 1 ) {
01632 bu_vls_strcat( &vls, "0" );
01633 } else {
01634 bu_vls_printf( &vls, "%d", bot->num_face_normals );
01635 }
01636 status = TCL_OK;
01637 }
01638 else if( !strncmp( attr, "fm", 2 ) )
01639 {
01640 if( bot->mode != RT_BOT_PLATE && bot->mode != RT_BOT_PLATE_NOCOS )
01641 {
01642 bu_vls_strcat( &vls, "Only plate mode BOTs have face_modes" );
01643 status = TCL_ERROR;
01644 }
01645 else
01646 {
01647 if( attr[2] == '\0' )
01648 {
01649 bu_bitv_to_hex( &vls, bot->face_mode );
01650 status = TCL_OK;
01651 }
01652 else
01653 {
01654 i = atoi( &attr[2] );
01655 if( i < 0 || i >=bot->num_faces )
01656 {
01657 bu_vls_printf( &vls, "face number %d out of range (0..%d)", i, bot->num_faces-1 );
01658 status = TCL_ERROR;
01659 }
01660 else
01661 {
01662 bu_vls_printf( &vls, "%s",
01663 los[BU_BITTEST( bot->face_mode, i )?1:0] );
01664 status = TCL_OK;
01665 }
01666 }
01667 }
01668 }
01669 else if( attr[0] == 'V' )
01670 {
01671 if( attr[1] != '\0' )
01672 {
01673 i = atoi( &attr[1] );
01674 if( i < 0 || i >=bot->num_vertices )
01675 {
01676 bu_vls_printf( &vls, "vertex number %d out of range (0..%d)", i, bot->num_vertices-1 );
01677 status = TCL_ERROR;
01678 }
01679 else
01680 {
01681 bu_vls_printf( &vls, "%.25G %.25G %.25G",
01682 V3ARGS( &bot->vertices[i*3] ) );
01683 status = TCL_OK;
01684 }
01685 }
01686 else
01687 {
01688 for( i=0 ; i<bot->num_vertices ; i++ )
01689 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01690 V3ARGS( &bot->vertices[i*3] ) );
01691 status = TCL_OK;
01692 }
01693 }
01694 else if( attr[0] == 'F' )
01695 {
01696
01697 if( attr[1] == '\0' )
01698 {
01699 for( i=0 ; i<bot->num_faces ; i++ )
01700 bu_vls_printf( &vls, " { %d %d %d }",
01701 V3ARGS( &bot->faces[i*3] ) );
01702 status = TCL_OK;
01703 }
01704 else
01705 {
01706 i = atoi( &attr[1] );
01707 if( i < 0 || i >=bot->num_faces )
01708 {
01709 bu_vls_printf( &vls, "face number %d out of range (0..%d)", i, bot->num_faces-1 );
01710 status = TCL_ERROR;
01711 }
01712 else
01713 {
01714 bu_vls_printf( &vls, "%d %d %d",
01715 V3ARGS( &bot->faces[i*3] ) );
01716 status = TCL_OK;
01717 }
01718 }
01719 }
01720 else if( !strcmp( attr, "flags" ) )
01721 {
01722 bu_vls_printf( &vls, "{" );
01723 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
01724 bu_vls_printf( &vls, " has_normals" );
01725 }
01726 if( bot->bot_flags & RT_BOT_USE_NORMALS ) {
01727 bu_vls_printf( &vls, " use_normals" );
01728 }
01729 if( bot->bot_flags & RT_BOT_USE_FLOATS ) {
01730 bu_vls_printf( &vls, " use_floats" );
01731 }
01732 bu_vls_printf( &vls, "}" );
01733 status = TCL_OK;
01734 }
01735 else if( attr[0] == 'f' )
01736 {
01737 int indx;
01738
01739 if( attr[1] == '\0' )
01740 {
01741 for( i=0 ; i<bot->num_faces ; i++ ) {
01742 indx = bot->faces[i*3];
01743 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01744 bot->vertices[indx*3],
01745 bot->vertices[indx*3+1],
01746 bot->vertices[indx*3+2] );
01747 indx = bot->faces[i*3+1];
01748 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01749 bot->vertices[indx*3],
01750 bot->vertices[indx*3+1],
01751 bot->vertices[indx*3+2] );
01752 indx = bot->faces[i*3+2];
01753 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01754 bot->vertices[indx*3],
01755 bot->vertices[indx*3+1],
01756 bot->vertices[indx*3+2] );
01757 }
01758 status = TCL_OK;
01759 }
01760 else
01761 {
01762 i = atoi( &attr[1] );
01763 if( i < 0 || i >=bot->num_faces )
01764 {
01765 bu_vls_printf( &vls, "face number %d out of range (0..%d)", i, bot->num_faces-1 );
01766 status = TCL_ERROR;
01767 }
01768 else
01769 {
01770 indx = bot->faces[i*3];
01771 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01772 bot->vertices[indx*3],
01773 bot->vertices[indx*3+1],
01774 bot->vertices[indx*3+2] );
01775 indx = bot->faces[i*3+1];
01776 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01777 bot->vertices[indx*3],
01778 bot->vertices[indx*3+1],
01779 bot->vertices[indx*3+2] );
01780 indx = bot->faces[i*3+2];
01781 bu_vls_printf( &vls, " { %.25G %.25G %.25G }",
01782 bot->vertices[indx*3],
01783 bot->vertices[indx*3+1],
01784 bot->vertices[indx*3+2] );
01785 status = TCL_OK;
01786 }
01787 }
01788 }
01789 else if( attr[0] == 'T' )
01790 {
01791 if( bot->mode != RT_BOT_PLATE && bot->mode != RT_BOT_PLATE_NOCOS )
01792 {
01793 bu_vls_strcat( &vls, "Only plate mode BOTs have thicknesses" );
01794 status = TCL_ERROR;
01795 }
01796 else
01797 {
01798 if( attr[1] == '\0' )
01799 {
01800 for( i=0 ; i<bot->num_faces ; i++ )
01801 bu_vls_printf( &vls, " %.25G", bot->thickness[i] );
01802 status = TCL_OK;
01803 }
01804 else
01805 {
01806 i = atoi( &attr[1] );
01807 if( i < 0 || i >=bot->num_faces )
01808 {
01809 bu_vls_printf( &vls, "face number %d out of range (0..%d)", i, bot->num_faces-1 );
01810 status = TCL_ERROR;
01811 }
01812 else
01813 {
01814 bu_vls_printf( &vls, " %.25G", bot->thickness[i] );
01815 status = TCL_OK;
01816 }
01817 }
01818 }
01819 }
01820 else if( !strcmp( attr, "nv" ) )
01821 {
01822 bu_vls_printf( &vls, "%d", bot->num_vertices );
01823 status = TCL_OK;
01824 }
01825 else if( !strcmp( attr, "nt" ) )
01826 {
01827 bu_vls_printf( &vls, "%d", bot->num_faces );
01828 status = TCL_OK;
01829 }
01830 else if( !strcmp( attr, "mode" ) )
01831 {
01832 bu_vls_printf( &vls, "%s", modes[bot->mode] );
01833 status = TCL_OK;
01834 }
01835 else if( !strcmp( attr, "orient" ) )
01836 {
01837 bu_vls_printf( &vls, "%s", orientation[bot->orientation] );
01838 status = TCL_OK;
01839 }
01840 else
01841 {
01842 bu_vls_printf( &vls, "BoT has no attribute '%s'", attr );
01843 status = TCL_ERROR;
01844 }
01845 }
01846
01847 Tcl_DStringAppend( &ds, bu_vls_addr( &vls ), -1 );
01848 Tcl_DStringResult( interp, &ds );
01849 Tcl_DStringFree( &ds );
01850 bu_vls_free( &vls );
01851
01852 return( status );
01853 }
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876 int
01877 rt_bot_tcladjust(Tcl_Interp *interp, struct rt_db_internal *intern, int argc, char **argv)
01878 {
01879 struct rt_bot_internal *bot;
01880 Tcl_Obj *obj, *list, **obj_array;
01881 int len;
01882 int i;
01883
01884 RT_CK_DB_INTERNAL( intern );
01885 bot = (struct rt_bot_internal *)intern->idb_ptr;
01886 RT_BOT_CK_MAGIC( bot );
01887
01888 while( argc >= 2 )
01889 {
01890 obj = Tcl_NewStringObj( argv[1], -1 );
01891 list = Tcl_NewListObj( 0, NULL );
01892 Tcl_ListObjAppendList( interp, list, obj );
01893
01894 if( !strncmp( argv[0], "fm", 2 ) )
01895 {
01896 if( argv[0][2] == '\0' )
01897 {
01898 if( bot->face_mode )
01899 bu_free( (char *)bot->face_mode, "bot->face_mode" );
01900 bot->face_mode = bu_hex_to_bitv( argv[1] );
01901 }
01902 else
01903 {
01904 i = atoi( &(argv[0][2]) );
01905 if( i < 0 || i >= bot->num_faces )
01906 {
01907 Tcl_SetResult( interp, "Face number out of range", TCL_STATIC );
01908 Tcl_DecrRefCount( list );
01909 return( TCL_ERROR );
01910 }
01911
01912 if( isdigit( *argv[1] ) )
01913 {
01914 if( atoi( argv[1] ) == 0 )
01915 BU_BITCLR( bot->face_mode, i );
01916 else
01917 BU_BITSET( bot->face_mode, i );
01918 }
01919 else if( !strcmp( argv[1], "append" ) )
01920 BU_BITSET( bot->face_mode, i );
01921 else
01922 BU_BITCLR( bot->face_mode, i );
01923 }
01924 }
01925 else if( !strcmp( argv[0], "nn" ) )
01926 {
01927 int new_num=0;
01928 int old_num = bot->num_normals;
01929
01930 new_num = atoi( Tcl_GetStringFromObj( obj, NULL ) );
01931 if( new_num < 0 ) {
01932 Tcl_SetResult( interp, "Number of normals may not be less than 0", TCL_STATIC );
01933 Tcl_DecrRefCount( list );
01934 return( TCL_ERROR );
01935 }
01936
01937 if( new_num == 0 ) {
01938 bot->num_normals = 0;
01939 if( bot->normals ) {
01940 bu_free( (char *)bot->normals, "BOT normals" );
01941 }
01942 bot->normals = (fastf_t *)NULL;
01943 } else {
01944 if( new_num != old_num ) {
01945 bot->num_normals = new_num;
01946 if( bot->normals ) {
01947 bot->normals = (fastf_t *)bu_realloc( (char *)bot->normals,
01948 bot->num_normals * 3 * sizeof( fastf_t ), "BOT normals" );
01949 } else {
01950 bot->normals = (fastf_t *)bu_calloc( bot->num_normals * 3, sizeof( fastf_t ),
01951 "BOT normals" );
01952 }
01953
01954 if( new_num > old_num ) {
01955 for( i = old_num ; i<new_num ; i++ ) {
01956 VSET( &bot->normals[i*3], 0, 0, 0 );
01957 }
01958 }
01959 }
01960
01961 }
01962
01963 }
01964 else if( !strncmp( argv[0], "fn", 2 ) )
01965 {
01966 char *f_str;
01967
01968 if( argv[0][2] == '\0' )
01969 {
01970 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
01971 if( len != bot->num_faces || len <= 0 ) {
01972 Tcl_SetResult( interp, "Must provide normals for all faces!!!", TCL_STATIC );
01973 Tcl_DecrRefCount( list );
01974 return( TCL_ERROR );
01975 }
01976 if( bot->face_normals )
01977 bu_free( (char *)bot->face_normals, "BOT face_normals" );
01978 bot->face_normals = (int *)bu_calloc( len*3, sizeof( int ), "BOT face_normals" );
01979 bot->num_face_normals = len;
01980 for( i=0 ; i<len ; i++ ) {
01981 f_str = Tcl_GetStringFromObj( obj_array[i], NULL );
01982 while( isspace( *f_str ) ) f_str++;
01983
01984 if( *f_str == '\0' ) {
01985 Tcl_SetResult( interp, "incomplete list of face_normals", TCL_STATIC );
01986 Tcl_DecrRefCount( list );
01987 return( TCL_ERROR );
01988 }
01989 bot->face_normals[i*3] = atoi( f_str );
01990 f_str = bu_next_token( f_str );
01991 if( *f_str == '\0' ) {
01992 Tcl_SetResult( interp, "incomplete list of face_normals", TCL_STATIC );
01993 Tcl_DecrRefCount( list );
01994 return( TCL_ERROR );
01995 }
01996 bot->face_normals[i*3+1] = atoi( f_str );
01997 f_str = bu_next_token( f_str );
01998 if( *f_str == '\0' ) {
01999 Tcl_SetResult( interp, "incomplete list of face_normals", TCL_STATIC );
02000 Tcl_DecrRefCount( list );
02001 return( TCL_ERROR );
02002 }
02003 bot->face_normals[i*3+2] = atoi( f_str );
02004 }
02005 bot->bot_flags |= RT_BOT_HAS_SURFACE_NORMALS;
02006 }
02007 else
02008 {
02009 i = atoi( &argv[0][2] );
02010 if( i < 0 || i >= bot->num_faces )
02011 {
02012 Tcl_SetResult( interp, "face_normal number out of range!!!", TCL_STATIC );
02013 Tcl_DecrRefCount( list );
02014 return( TCL_ERROR );
02015 }
02016 f_str = Tcl_GetStringFromObj( list, NULL );
02017 while( isspace( *f_str ) ) f_str++;
02018 bot->face_normals[i*3] = atoi( f_str );
02019 f_str = bu_next_token( f_str );
02020 if( *f_str == '\0' )
02021 {
02022 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02023 Tcl_DecrRefCount( list );
02024 return( TCL_ERROR );
02025 }
02026 bot->face_normals[i*3+1] = atoi( f_str );
02027 f_str = bu_next_token( f_str );
02028 if( *f_str == '\0' )
02029 {
02030 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02031 Tcl_DecrRefCount( list );
02032 return( TCL_ERROR );
02033 }
02034 bot->face_normals[i*3+2] = atoi( f_str );
02035 }
02036 }
02037 else if( argv[0][0] == 'N' )
02038 {
02039 char *v_str;
02040
02041 if( argv[0][1] == '\0' )
02042 {
02043 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
02044 if( len <= 0 )
02045 {
02046 Tcl_SetResult( interp, "Must provide at least one normal!!!", TCL_STATIC );
02047 Tcl_DecrRefCount( list );
02048 return( TCL_ERROR );
02049 }
02050 bot->num_normals = len;
02051 if( bot->normals )
02052 bu_free( (char *)bot->normals, "BOT normals" );
02053 bot->normals = (fastf_t *)bu_calloc( len*3, sizeof( fastf_t ), "BOT normals" );
02054 for( i=0 ; i<len ; i++ )
02055 {
02056 v_str = Tcl_GetStringFromObj( obj_array[i], NULL );
02057 while( isspace( *v_str ) ) v_str++;
02058 if( *v_str == '\0' )
02059 {
02060 Tcl_SetResult( interp, "incomplete list of normals", TCL_STATIC );
02061 Tcl_DecrRefCount( list );
02062 return( TCL_ERROR );
02063 }
02064 bot->normals[i*3] = atof( v_str );
02065 v_str = bu_next_token( v_str );
02066 if( *v_str == '\0' )
02067 {
02068 Tcl_SetResult( interp, "incomplete list of normals", TCL_STATIC );
02069 Tcl_DecrRefCount( list );
02070 return( TCL_ERROR );
02071 }
02072 bot->normals[i*3+1] = atof( v_str );
02073 v_str = bu_next_token( v_str );
02074 if( *v_str == '\0' )
02075 {
02076 Tcl_SetResult( interp, "incomplete list of normals", TCL_STATIC );
02077 Tcl_DecrRefCount( list );
02078 return( TCL_ERROR );
02079 }
02080 bot->normals[i*3+2] = atof( v_str );
02081 Tcl_DecrRefCount( obj_array[i] );
02082 }
02083 bot->bot_flags |= RT_BOT_HAS_SURFACE_NORMALS;
02084 } else {
02085 i = atoi( &argv[0][1] );
02086 if( i < 0 || i >= bot->num_normals )
02087 {
02088 Tcl_SetResult( interp, "normal number out of range!!!", TCL_STATIC );
02089 Tcl_DecrRefCount( list );
02090 return( TCL_ERROR );
02091 }
02092 v_str = Tcl_GetStringFromObj( list, NULL );
02093 while( isspace( *v_str ) ) v_str++;
02094
02095 bot->normals[i*3] = atof( v_str );
02096 v_str = bu_next_token( v_str );
02097 if( *v_str == '\0' )
02098 {
02099 Tcl_SetResult( interp, "incomplete normal", TCL_STATIC );
02100 Tcl_DecrRefCount( list );
02101 return( TCL_ERROR );
02102 }
02103 bot->normals[i*3+1] = atof( v_str );
02104 v_str = bu_next_token( v_str );
02105 if( *v_str == '\0' )
02106 {
02107 Tcl_SetResult( interp, "incomplete normal", TCL_STATIC );
02108 Tcl_DecrRefCount( list );
02109 return( TCL_ERROR );
02110 }
02111 bot->normals[i*3+2] = atof( v_str );
02112 }
02113 }
02114 else if( argv[0][0] == 'V' )
02115 {
02116 char *v_str;
02117
02118 if( argv[0][1] == '\0' )
02119 {
02120 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
02121 if( len <= 0 )
02122 {
02123 Tcl_SetResult( interp, "Must provide at least one vertex!!!", TCL_STATIC );
02124 Tcl_DecrRefCount( list );
02125 return( TCL_ERROR );
02126 }
02127 bot->num_vertices = len;
02128 if( bot->vertices )
02129 bu_free( (char *)bot->vertices, "BOT vertices" );
02130 bot->vertices = (fastf_t *)bu_calloc( len*3, sizeof( fastf_t ), "BOT vertices" );
02131 for( i=0 ; i<len ; i++ )
02132 {
02133 v_str = Tcl_GetStringFromObj( obj_array[i], NULL );
02134 while( isspace( *v_str ) ) v_str++;
02135 if( *v_str == '\0' )
02136 {
02137 Tcl_SetResult( interp, "incomplete list of vertices", TCL_STATIC );
02138 Tcl_DecrRefCount( list );
02139 return( TCL_ERROR );
02140 }
02141 bot->vertices[i*3] = atof( v_str );
02142 v_str = bu_next_token( v_str );
02143 if( *v_str == '\0' )
02144 {
02145 Tcl_SetResult( interp, "incomplete list of vertices", TCL_STATIC );
02146 Tcl_DecrRefCount( list );
02147 return( TCL_ERROR );
02148 }
02149 bot->vertices[i*3+1] = atof( v_str );
02150 v_str = bu_next_token( v_str );
02151 if( *v_str == '\0' )
02152 {
02153 Tcl_SetResult( interp, "incomplete list of vertices", TCL_STATIC );
02154 Tcl_DecrRefCount( list );
02155 return( TCL_ERROR );
02156 }
02157 bot->vertices[i*3+2] = atof( v_str );
02158 Tcl_DecrRefCount( obj_array[i] );
02159 }
02160 }
02161 else
02162 {
02163 i = atoi( &argv[0][1] );
02164 if( i < 0 || i >= bot->num_vertices )
02165 {
02166 Tcl_SetResult( interp, "vertex number out of range!!!", TCL_STATIC );
02167 Tcl_DecrRefCount( list );
02168 return( TCL_ERROR );
02169 }
02170 v_str = Tcl_GetStringFromObj( list, NULL );
02171 while( isspace( *v_str ) ) v_str++;
02172
02173 bot->vertices[i*3] = atof( v_str );
02174 v_str = bu_next_token( v_str );
02175 if( *v_str == '\0' )
02176 {
02177 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02178 Tcl_DecrRefCount( list );
02179 return( TCL_ERROR );
02180 }
02181 bot->vertices[i*3+1] = atof( v_str );
02182 v_str = bu_next_token( v_str );
02183 if( *v_str == '\0' )
02184 {
02185 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02186 Tcl_DecrRefCount( list );
02187 return( TCL_ERROR );
02188 }
02189 bot->vertices[i*3+2] = atof( v_str );
02190 }
02191 }
02192 else if( argv[0][0] == 'F' )
02193 {
02194 char *f_str;
02195
02196 if( argv[0][1] == '\0' )
02197 {
02198 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
02199 if( len <= 0 )
02200 {
02201 Tcl_SetResult( interp, "Must provide at least one face!!!", TCL_STATIC );
02202 Tcl_DecrRefCount( list );
02203 return( TCL_ERROR );
02204 }
02205 bot->num_faces = len;
02206 if( bot->faces )
02207 bu_free( (char *)bot->faces, "BOT faces" );
02208 bot->faces = (int *)bu_calloc( len*3, sizeof( int ), "BOT faces" );
02209 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02210 if( !bot->face_normals ) {
02211 bot->face_normals = (int *)bu_malloc( bot->num_faces * 3 * sizeof( int ),
02212 "bot->face_normals" );
02213 bot->num_face_normals = bot->num_faces;
02214 for( i=0 ; i<bot->num_face_normals ; i++ ) {
02215 VSETALL( &bot->face_normals[i*3], -1 );
02216 }
02217 } else if( bot->num_face_normals < bot->num_faces ) {
02218 bot->face_normals = (int *)bu_realloc( bot->face_normals,
02219 bot->num_faces * 3 * sizeof( int ), "bot->face_normals" );
02220 for( i=bot->num_face_normals ; i<bot->num_faces ; i++ ) {
02221 VSETALL( &bot->face_normals[i*3], -1 );
02222 }
02223 bot->num_face_normals = bot->num_faces;
02224 }
02225 }
02226 for( i=0 ; i<len ; i++ )
02227 {
02228 f_str = Tcl_GetStringFromObj( obj_array[i], NULL );
02229 while( isspace( *f_str ) ) f_str++;
02230
02231 if( *f_str == '\0' )
02232 {
02233 Tcl_SetResult( interp, "incomplete list of faces", TCL_STATIC );
02234 Tcl_DecrRefCount( list );
02235 return( TCL_ERROR );
02236 }
02237 bot->faces[i*3] = atoi( f_str );
02238 f_str = bu_next_token( f_str );
02239 if( *f_str == '\0' )
02240 {
02241 Tcl_SetResult( interp, "incomplete list of faces", TCL_STATIC );
02242 Tcl_DecrRefCount( list );
02243 return( TCL_ERROR );
02244 }
02245 bot->faces[i*3+1] = atoi( f_str );
02246 f_str = bu_next_token( f_str );
02247 if( *f_str == '\0' )
02248 {
02249 Tcl_SetResult( interp, "incomplete list of faces", TCL_STATIC );
02250 Tcl_DecrRefCount( list );
02251 return( TCL_ERROR );
02252 }
02253 bot->faces[i*3+2] = atoi( f_str );
02254 }
02255 }
02256 else
02257 {
02258 i = atoi( &argv[0][1] );
02259 if( i < 0 || i >= bot->num_faces )
02260 {
02261 Tcl_SetResult( interp, "face number out of range!!!", TCL_STATIC );
02262 Tcl_DecrRefCount( list );
02263 return( TCL_ERROR );
02264 }
02265 f_str = Tcl_GetStringFromObj( list, NULL );
02266 while( isspace( *f_str ) ) f_str++;
02267 bot->faces[i*3] = atoi( f_str );
02268 f_str = bu_next_token( f_str );
02269 if( *f_str == '\0' )
02270 {
02271 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02272 Tcl_DecrRefCount( list );
02273 return( TCL_ERROR );
02274 }
02275 bot->faces[i*3+1] = atoi( f_str );
02276 f_str = bu_next_token( f_str );
02277 if( *f_str == '\0' )
02278 {
02279 Tcl_SetResult( interp, "incomplete vertex", TCL_STATIC );
02280 Tcl_DecrRefCount( list );
02281 return( TCL_ERROR );
02282 }
02283 bot->faces[i*3+2] = atoi( f_str );
02284 }
02285 }
02286 else if( argv[0][0] == 'T' )
02287 {
02288 char *t_str;
02289
02290 if( argv[0][1] == '\0' )
02291 {
02292 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
02293 if( len <= 0 )
02294 {
02295 Tcl_SetResult( interp, "Must provide at least one thickness!!!", TCL_STATIC );
02296 Tcl_DecrRefCount( list );
02297 return( TCL_ERROR );
02298 }
02299 if( len > bot->num_faces )
02300 {
02301 Tcl_SetResult( interp, "Too many thicknesses (there are not that many faces)!!!", TCL_STATIC );
02302 Tcl_DecrRefCount( list );
02303 return( TCL_ERROR );
02304 }
02305 if( !bot->thickness ) {
02306 bot->thickness = (fastf_t *)bu_calloc( bot->num_faces, sizeof( fastf_t ),
02307 "bot->thickness" );
02308 }
02309 for( i=0 ; i<len ; i++ )
02310 {
02311 bot->thickness[i] = atof( Tcl_GetStringFromObj( obj_array[i], NULL ) );
02312 Tcl_DecrRefCount( obj_array[i] );
02313 }
02314 }
02315 else
02316 {
02317 i = atoi( &argv[0][1] );
02318 if( i < 0 || i >= bot->num_faces )
02319 {
02320 Tcl_SetResult( interp, "face number out of range!!!", TCL_STATIC );
02321 Tcl_DecrRefCount( list );
02322 return( TCL_ERROR );
02323 }
02324 if( !bot->thickness ) {
02325 bot->thickness = (fastf_t *)bu_calloc( bot->num_faces, sizeof( fastf_t ),
02326 "bot->thickness" );
02327 }
02328 t_str = Tcl_GetStringFromObj( list, NULL );
02329 bot->thickness[i] = atof( t_str );
02330 }
02331 }
02332 else if( !strcmp( argv[0], "mode" ) )
02333 {
02334 char *m_str;
02335
02336 m_str = Tcl_GetStringFromObj( list, NULL );
02337 if( isdigit( *m_str ) )
02338 {
02339 int mode;
02340
02341 mode = atoi( m_str );
02342 if( mode < RT_BOT_SURFACE || mode > RT_BOT_PLATE_NOCOS )
02343 {
02344 Tcl_SetResult( interp, "unrecognized mode!!!", TCL_STATIC );
02345 Tcl_DecrRefCount( list );
02346 return( TCL_ERROR );
02347 }
02348 bot->mode = mode;
02349 }
02350 else
02351 {
02352 if( !strncmp( m_str, modes[RT_BOT_SURFACE], 4 ) )
02353 bot->mode = RT_BOT_SURFACE;
02354 else if( !strcmp( m_str, modes[RT_BOT_SOLID] ) )
02355 bot->mode = RT_BOT_SOLID;
02356 else if( !strcmp( m_str, modes[RT_BOT_PLATE] ) )
02357 bot->mode = RT_BOT_PLATE;
02358 else if( !strcmp( m_str, modes[RT_BOT_PLATE_NOCOS] ) )
02359 bot->mode = RT_BOT_PLATE_NOCOS;
02360 else
02361 {
02362 Tcl_SetResult( interp, "unrecognized mode!!!", TCL_STATIC );
02363 Tcl_DecrRefCount( list );
02364 return( TCL_ERROR );
02365 }
02366 }
02367 }
02368 else if( !strncmp( argv[0], "orient", 6 ) )
02369 {
02370 char *o_str;
02371
02372 o_str = Tcl_GetStringFromObj( list, NULL );
02373 if( isdigit( *o_str ) )
02374 {
02375 int orientation;
02376
02377 orientation = atoi( o_str );
02378 if( orientation < RT_BOT_UNORIENTED || orientation > RT_BOT_CW )
02379 {
02380 Tcl_SetResult( interp, "unrecognized orientation!!!", TCL_STATIC );
02381 Tcl_DecrRefCount( list );
02382 return( TCL_ERROR );
02383 }
02384 bot->orientation = orientation;
02385 }
02386 else
02387 {
02388 if( !strcmp( o_str, orientation[RT_BOT_UNORIENTED] ) )
02389 bot->orientation = RT_BOT_UNORIENTED;
02390 else if( !strcmp( o_str, orientation[RT_BOT_CCW] ) )
02391 bot->orientation = RT_BOT_CCW;
02392 else if( !strcmp( o_str, orientation[RT_BOT_CW] ) )
02393 bot->orientation = RT_BOT_CW;
02394 else
02395 {
02396 Tcl_SetResult( interp, "unrecognized orientation!!!", TCL_STATIC );
02397 Tcl_DecrRefCount( list );
02398 return( TCL_ERROR );
02399 }
02400 }
02401 }
02402 else if( !strcmp( argv[0], "flags" ) )
02403 {
02404 (void)Tcl_ListObjGetElements( interp, list, &len, &obj_array );
02405 bot->bot_flags = 0;
02406 for( i=0 ; i<len ; i++ ) {
02407 char *str;
02408
02409 str = Tcl_GetStringFromObj( obj_array[i], NULL );
02410 if( !strcmp( str, "has_normals" ) ) {
02411 bot->bot_flags |= RT_BOT_HAS_SURFACE_NORMALS;
02412 } else if( !strcmp( str, "use_normals" ) ) {
02413 bot->bot_flags |= RT_BOT_USE_NORMALS;
02414 } else if( !strcmp( str, "use_floats" ) ) {
02415 bot->bot_flags |= RT_BOT_USE_FLOATS;
02416 } else {
02417 Tcl_SetResult( interp, "unrecognized flag (must be \"has_normals\", \"use_normals\", or \"use_floats\"!!!", TCL_STATIC );
02418 Tcl_DecrRefCount( list );
02419 return( TCL_ERROR );
02420 }
02421 }
02422 }
02423
02424 Tcl_DecrRefCount( list );
02425
02426 argc -= 2;
02427 argv += 2;
02428 }
02429
02430 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
02431 {
02432 if( !bot->thickness )
02433 bot->thickness = (fastf_t *)bu_calloc( bot->num_faces, sizeof( fastf_t ), "BOT thickness" );
02434 if( !bot->face_mode )
02435 {
02436 bot->face_mode = bu_bitv_new( bot->num_faces );
02437 bu_bitv_clear( bot->face_mode );
02438 }
02439 }
02440 else
02441 {
02442 if( bot->thickness )
02443 {
02444 bu_free( (char *)bot->thickness, "BOT thickness" );
02445 bot->thickness = (fastf_t *)NULL;
02446 }
02447 if( bot->face_mode )
02448 {
02449 bu_free( (char *)bot->face_mode, "BOT facemode" );
02450 bot->face_mode = (bitv_t)NULL;
02451 }
02452 }
02453
02454 return( TCL_OK );
02455 }
02456
02457 int
02458 rt_bot_tclform( const struct rt_functab *ftp, Tcl_Interp *interp)
02459 {
02460 RT_CK_FUNCTAB(ftp);
02461
02462 Tcl_AppendResult( interp,
02463 "mode {%s} orient {%s} V { {%f %f %f} {%f %f %f} ...} F { {%d %d %d} {%d %d %d} ...} T { %f %f %f ... } fm %s", (char *)NULL );
02464
02465 return TCL_OK;
02466 }
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479 int
02480 rt_bot_vertex_fuse( struct rt_bot_internal *bot )
02481 {
02482 int i,j,k;
02483 int count=0;
02484
02485 RT_BOT_CK_MAGIC( bot );
02486
02487 for( i=0 ; i<bot->num_vertices ; i++ )
02488 {
02489 j = i + 1;
02490 while( j < bot->num_vertices ) {
02491
02492 if( VEQUAL( &bot->vertices[i*3], &bot->vertices[j*3] ) )
02493 {
02494 count++;
02495 bot->num_vertices--;
02496 for( k=j ; k<bot->num_vertices ; k++ )
02497 VMOVE( &bot->vertices[k*3] , &bot->vertices[(k+1)*3] );
02498 for( k=0 ; k<bot->num_faces*3 ; k++ )
02499 {
02500 if( bot->faces[k] == j )
02501 {
02502 bot->faces[k] = i;
02503 }
02504 else if ( bot->faces[k] > j )
02505 bot->faces[k]--;
02506 }
02507 } else {
02508 j++;
02509 }
02510 }
02511 }
02512
02513 return( count );
02514 }
02515
02516 int
02517 rt_bot_same_orientation( const int *a, const int *b )
02518 {
02519 int i;
02520
02521 for( i=0 ; i<3 ; i++ )
02522 {
02523 if( a[0] == b[i] )
02524 {
02525 i++;
02526 if( i == 3 )
02527 i = 0;
02528 if( a[1] == b[i] )
02529 return( 1 );
02530 else
02531 return( 0 );
02532 }
02533 }
02534
02535 return( 0 );
02536 }
02537
02538 int
02539 rt_bot_face_fuse( struct rt_bot_internal *bot )
02540 {
02541 int num_faces;
02542 int i,j,k,l;
02543 int count=0;
02544
02545 RT_BOT_CK_MAGIC( bot );
02546
02547 num_faces = bot->num_faces;
02548 for( i=0 ; i<num_faces ; i++ )
02549 {
02550 j = i+1;
02551 while( j<num_faces )
02552 {
02553
02554 int match=0;
02555 int elim;
02556
02557 for( k=i*3 ; k<(i+1)*3 ; k++ )
02558 {
02559 for( l=j*3 ; l<(j+1)*3 ; l++ )
02560 {
02561 if( bot->faces[k] == bot->faces[l] )
02562 {
02563 match++;
02564 break;
02565 }
02566 }
02567 }
02568
02569 if( match != 3 )
02570 {
02571 j++;
02572 continue;
02573 }
02574
02575
02576 elim = -1;
02577 switch( bot->mode )
02578 {
02579 case RT_BOT_PLATE:
02580 case RT_BOT_PLATE_NOCOS:
02581
02582 if( bot->thickness[i] != bot->thickness[j] ||
02583 (BU_BITTEST( bot->face_mode, i )?1:0) != (BU_BITTEST( bot->face_mode, j )?1:0) )
02584 break;
02585 case RT_BOT_SOLID:
02586 case RT_BOT_SURFACE:
02587 if( bot->orientation == RT_BOT_UNORIENTED )
02588 {
02589
02590 elim = j;
02591 }
02592 else
02593 {
02594
02595 if( rt_bot_same_orientation( &bot->faces[i*3], &bot->faces[j*3] ) )
02596 elim = j;
02597 }
02598 break;
02599 default:
02600 bu_bomb( "bot_face_condense: Unrecognized BOT mode!!!\n" );
02601 break;
02602 }
02603
02604 if( elim < 0 )
02605 {
02606 j++;
02607 continue;
02608 }
02609
02610
02611 for( l=elim ; l< num_faces-1 ; l++ )
02612 VMOVE( &bot->faces[l*3], &bot->faces[(l+1)*3] )
02613 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
02614 {
02615 for( l=elim ; l<num_faces-1 ; l++ )
02616 {
02617 bot->thickness[l] = bot->thickness[l+1];
02618 if( BU_BITTEST( bot->face_mode, l+1 ) )
02619 BU_BITSET( bot->face_mode, l );
02620 else
02621 BU_BITCLR( bot->face_mode, l );
02622 }
02623 }
02624 num_faces--;
02625 }
02626 }
02627
02628 count = bot->num_faces - num_faces;
02629
02630 if( count )
02631 {
02632 bot->num_faces = num_faces;
02633 bot->faces = (int *)bu_realloc( bot->faces, num_faces*3*sizeof( int ), "BOT faces realloc" );
02634 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_PLATE_NOCOS )
02635 {
02636 struct bu_bitv *new_mode;
02637
02638 bot->thickness = bu_realloc( bot->thickness, num_faces*sizeof( fastf_t ), "BOT thickness realloc" );
02639 new_mode = bu_bitv_new( num_faces );
02640 bu_bitv_clear( new_mode );
02641 for( l=0 ; l<num_faces ; l++ )
02642 {
02643 if( BU_BITTEST( bot->face_mode, l ) )
02644 BU_BITSET( new_mode, l );
02645 }
02646 bu_free( (char *)bot->face_mode, "BOT face_mode" );
02647 bot->face_mode = new_mode;
02648 }
02649 }
02650
02651 return( count );
02652 }
02653
02654
02655
02656
02657
02658
02659 int
02660 rt_bot_condense( struct rt_bot_internal *bot )
02661 {
02662 int i,j,k;
02663 int num_verts;
02664 int dead_verts=0;
02665 int *verts;
02666
02667 RT_BOT_CK_MAGIC( bot );
02668
02669 num_verts = bot->num_vertices;
02670 verts = (int *)bu_calloc( num_verts, sizeof( int ), "VERTEX LIST" );
02671
02672
02673
02674 for( i=0 ; i<bot->num_faces*3 ; i++ )
02675 {
02676 j = bot->faces[i];
02677 if( j >= num_verts || j < 0 )
02678 {
02679 bu_log( "Illegal vertex number %d, should be 0 through %d\n", j, num_verts-1 );
02680 bu_bomb( "Illegal vertex number\n" );
02681 }
02682 verts[j] = 1;
02683 }
02684
02685
02686
02687
02688 i = 0;
02689 while( i < num_verts-dead_verts )
02690 {
02691 while( !verts[i] && i < num_verts-dead_verts )
02692 {
02693 dead_verts++;
02694 for( j=i ; j<num_verts-dead_verts ; j++ )
02695 {
02696 k = j+1;
02697 VMOVE( &bot->vertices[j*3], &bot->vertices[k*3] );
02698 verts[j] = verts[k];
02699 }
02700 for( j=0 ; j<bot->num_faces*3 ; j++ )
02701 {
02702 if( bot->faces[j] >= i )
02703 bot->faces[j]--;
02704 }
02705 }
02706 i++;
02707 }
02708
02709 if( !dead_verts )
02710 return( 0 );
02711
02712
02713
02714
02715 bot->num_vertices -= dead_verts;
02716 bot->vertices = (fastf_t *)bu_realloc( bot->vertices, bot->num_vertices*3*sizeof( fastf_t ), "bot verts realloc" );
02717
02718 return( dead_verts );
02719 }
02720
02721 int
02722 find_closest_face( fastf_t **centers, int *piece, int *old_faces, int num_faces, fastf_t *vertices )
02723 {
02724 pointp_t v0, v1, v2;
02725 point_t center;
02726 int i;
02727 fastf_t one_third = 1.0/3.0;
02728 fastf_t min_dist;
02729 int min_face=-1;
02730
02731 if( (*centers) == NULL ) {
02732 int count_centers=0;
02733
02734
02735 (*centers) = (fastf_t *)bu_malloc( num_faces * 3 * sizeof( fastf_t ), "center" );
02736 for( i=0 ; i<num_faces ; i++ ) {
02737 if( old_faces[i*3] < 0 ) {
02738 continue;
02739 }
02740 count_centers++;
02741 v0 = &vertices[old_faces[i*3]*3];
02742 v1 = &vertices[old_faces[i*3+1]*3];
02743 v2 = &vertices[old_faces[i*3+2]*3];
02744 VADD3( center, v0 , v1, v2 );
02745 VSCALE( &(*centers)[i*3], center, one_third );
02746 }
02747 }
02748
02749 v0 = &vertices[piece[0]*3];
02750 v1 = &vertices[piece[1]*3];
02751 v2 = &vertices[piece[2]*3];
02752
02753 VADD3( center, v0, v1, v2 );
02754 VSCALE( center, center, one_third );
02755
02756 min_dist = MAX_FASTF;
02757
02758 for( i=0 ; i<num_faces ; i++ ) {
02759 vect_t diff;
02760 fastf_t dist;
02761
02762 if( old_faces[i*3] < 0 ) {
02763 continue;
02764 }
02765
02766 VSUB2( diff, center, &(*centers)[i*3] );
02767 dist = MAGSQ( diff );
02768 if( dist < min_dist ) {
02769 min_dist = dist;
02770 min_face = i;
02771 }
02772 }
02773
02774 return( min_face );
02775 }
02776
02777 void
02778 Add_unique_verts( int *piece_verts, int *v )
02779 {
02780 int i, j;
02781 int *ptr=v;
02782
02783 for( j=0 ; j<3 ; j++ ) {
02784 i = -1;
02785 while( piece_verts[++i] > -1 ) {
02786 if( piece_verts[i] == (*ptr) ) {
02787 break;
02788 }
02789 }
02790 if( piece_verts[i] == -1 ) {
02791 piece_verts[i] = (*ptr);
02792 }
02793 ptr++;
02794 }
02795 }
02796
02797
02798
02799
02800
02801
02802 int
02803 rt_bot_sort_faces( struct rt_bot_internal *bot, int tris_per_piece )
02804 {
02805 int *new_faces;
02806 int new_face_count=0;
02807 int *new_norms = (int*)NULL;
02808 int *old_faces;
02809 int *piece;
02810 int *piece_norms = (int*)NULL;
02811 int *piece_verts;
02812 unsigned char *vert_count;
02813 int faces_left;
02814 int piece_len;
02815 int max_verts;
02816 fastf_t *centers;
02817 int i, j;
02818
02819 RT_BOT_CK_MAGIC( bot );
02820
02821
02822 new_faces = (int *)bu_calloc( bot->num_faces * 3, sizeof( int ), "new_faces" );
02823 old_faces = (int *)bu_calloc( bot->num_faces * 3, sizeof( int ), "old_faces" );
02824 piece = (int *)bu_calloc( tris_per_piece * 3, sizeof( int ), "piece" );
02825 vert_count = (unsigned char *)bu_malloc( bot->num_faces * sizeof( unsigned char ), "vert_count" );
02826 piece_verts = (int *)bu_malloc( (tris_per_piece * 3 + 1) * sizeof( int ), "piece_verts" );
02827 centers = (fastf_t *)NULL;
02828
02829 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02830 new_norms = (int *)bu_calloc( bot->num_faces * 3, sizeof( int ), "new_norms" );
02831 piece_norms = (int *)bu_calloc( tris_per_piece * 3, sizeof( int ), "piece_norms" );
02832 }
02833
02834
02835 for( i=0 ; i<bot->num_faces*3 ; i++) {
02836 old_faces[i] = bot->faces[i];
02837 }
02838
02839
02840 faces_left = bot->num_faces;
02841 while( faces_left ) {
02842 int cur_face;
02843 int done_with_piece;
02844
02845
02846 for( i=0 ; i<tris_per_piece*3+1 ; i++ ) {
02847 piece_verts[i] = -1;
02848 }
02849
02850
02851 cur_face = 0;
02852 while( cur_face < bot->num_faces && old_faces[cur_face*3] < 0 ) {
02853 cur_face++;
02854 }
02855
02856 if( cur_face >= bot->num_faces ) {
02857
02858 break;
02859 }
02860
02861
02862 VMOVE( piece, &old_faces[cur_face*3] );
02863 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02864 VMOVE( piece_norms, &bot->face_normals[cur_face*3] );
02865 }
02866
02867
02868 VMOVE( piece_verts, piece );
02869
02870
02871 VSETALL( &old_faces[cur_face*3], -1 );
02872
02873
02874 piece_len = 1;
02875 faces_left--;
02876
02877 if( faces_left == 0 ) {
02878
02879 for( j=0 ; j<piece_len ; j++ ) {
02880 VMOVE( &new_faces[new_face_count*3], &piece[j*3] );
02881 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02882 VMOVE( &new_norms[new_face_count*3], &piece_norms[j*3] );
02883 }
02884 new_face_count++;
02885 }
02886 piece_len = 0;
02887 max_verts = 0;
02888
02889
02890 done_with_piece = 1;
02891 } else {
02892 done_with_piece = 0;
02893 }
02894
02895 while( !done_with_piece ) {
02896 int max_verts_min;
02897
02898
02899 (void)memset( vert_count, '\0', bot->num_faces );
02900 max_verts = 0;
02901 for( i=0 ; i<bot->num_faces ; i++) {
02902 int vert_num;
02903 int v0, v1, v2;
02904
02905 vert_num = i*3;
02906 if( old_faces[vert_num] < 0 ) {
02907 continue;
02908 }
02909 v0 = old_faces[vert_num];
02910 v1 = old_faces[vert_num+1];
02911 v2 = old_faces[vert_num+2];
02912
02913 j = -1;
02914 while( piece_verts[ ++j ] > -1 ) {
02915 if( v0 == piece_verts[j] ||
02916 v1 == piece_verts[j] ||
02917 v2 == piece_verts[j] ) {
02918 vert_count[i]++;
02919 }
02920 }
02921
02922 if( vert_count[i] > 1 ) {
02923
02924 VMOVE( &piece[piece_len*3], &old_faces[i*3] );
02925 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02926 VMOVE( &piece_norms[piece_len*3], &bot->face_normals[i*3] );
02927 }
02928
02929
02930 Add_unique_verts( piece_verts, &old_faces[i*3] );
02931
02932
02933 VSETALL( &old_faces[i*3], -1 );
02934
02935
02936 piece_len++;
02937 faces_left--;
02938 vert_count[i] = 0;
02939
02940
02941 if( piece_len == tris_per_piece || faces_left == 0 ) {
02942
02943 for( j=0 ; j<piece_len ; j++ ) {
02944 VMOVE( &new_faces[new_face_count*3], &piece[j*3] );
02945 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02946 VMOVE( &new_norms[new_face_count*3], &piece_norms[j*3] );
02947 }
02948 new_face_count++;
02949 }
02950 piece_len = 0;
02951 max_verts = 0;
02952 done_with_piece = 1;
02953 break;
02954 }
02955 }
02956 if( vert_count[i] > max_verts ) {
02957 max_verts = vert_count[i];
02958 }
02959 }
02960
02961
02962 max_verts_min = 2;
02963
02964 if( max_verts == 0 && !done_with_piece ) {
02965
02966 int face_to_add;
02967
02968
02969
02970
02971 face_to_add = find_closest_face( ¢ers, piece, old_faces, bot->num_faces, bot->vertices );
02972
02973
02974 VMOVE( &piece[piece_len*3], &old_faces[face_to_add*3] );
02975 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02976 VMOVE( &piece_norms[piece_len*3], &bot->face_normals[face_to_add*3] );
02977 }
02978
02979
02980 Add_unique_verts( piece_verts, &old_faces[face_to_add*3] );
02981
02982
02983 VSETALL( &old_faces[face_to_add*3], -1 );
02984
02985
02986 piece_len++;
02987 faces_left--;
02988
02989
02990 if( piece_len == tris_per_piece || faces_left == 0 ) {
02991
02992 for( j=0 ; j<piece_len ; j++ ) {
02993 VMOVE( &new_faces[new_face_count*3], &piece[j*3] );
02994 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
02995 VMOVE( &new_norms[new_face_count*3], &piece_norms[j*3] );
02996 }
02997 new_face_count++;
02998 }
02999 piece_len = 0;
03000 max_verts = 0;
03001 done_with_piece = 1;
03002 }
03003 } else if( max_verts == 1 && !done_with_piece ) {
03004
03005 max_verts_min = 1;
03006 } else if( !done_with_piece ) {
03007
03008 max_verts_min = 2;
03009 }
03010
03011
03012
03013
03014
03015 while( max_verts >= max_verts_min && !done_with_piece ) {
03016
03017 for( i=0 ; i<bot->num_faces ; i++ ) {
03018
03019
03020
03021 if( vert_count[i] == max_verts ) {
03022 VMOVE( &piece[piece_len*3], &old_faces[i*3] );
03023 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
03024 VMOVE( &piece_norms[piece_len*3], &bot->face_normals[i*3] );
03025 }
03026 Add_unique_verts( piece_verts, &old_faces[i*3] );
03027 VSETALL( &old_faces[i*3], -1 );
03028
03029 piece_len++;
03030 faces_left--;
03031
03032
03033 if( piece_len == tris_per_piece || faces_left == 0 ) {
03034
03035 for( j=0 ; j<piece_len ; j++ ) {
03036 VMOVE( &new_faces[new_face_count*3], &piece[j*3] );
03037 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
03038 VMOVE( &new_norms[new_face_count*3], &piece_norms[j*3] );
03039 }
03040 new_face_count++;
03041 }
03042 piece_len = 0;
03043 max_verts = 0;
03044 done_with_piece = 1;
03045 break;
03046 }
03047 }
03048 }
03049 max_verts--;
03050 }
03051 }
03052 }
03053
03054 bu_free( (char *)old_faces, "old_faces" );
03055 bu_free( (char *)piece, "piece" );
03056 bu_free( (char *)vert_count, "vert_count" );
03057 bu_free( (char *)piece_verts, "piece_verts" );
03058 if( centers ) {
03059 bu_free( (char *)centers, "centers" );
03060 }
03061
03062
03063 if( new_face_count != bot->num_faces ) {
03064 bu_log( "new_face_count = %d, should be %d\n", new_face_count, bot->num_faces );
03065 bu_free( (char *)new_faces, "new_faces" );
03066 return( 1 );
03067 }
03068
03069 bu_free( (char *)bot->faces, "bot->faces" );
03070
03071 bot->faces = new_faces;
03072
03073 if( bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS ) {
03074 bu_free( (char *)piece_norms, "piece_norms" );
03075 bu_free( (char *)bot->face_normals, "bot->face_normals" );
03076 bot->face_normals = new_norms;
03077 }
03078
03079 return( 0 );
03080 }
03081
03082 struct bot_edge {
03083 int v;
03084 int use_count;
03085 struct bot_edge *next;
03086 };
03087
03088 static void
03089 delete_edge( int v1, int v2, struct bot_edge **edges )
03090 {
03091 struct bot_edge *edg, *prev=NULL;
03092
03093 if( v1 < v2 ) {
03094 edg = edges[v1];
03095 while( edg ) {
03096 if( edg->v == v2 ) {
03097 edg->use_count--;
03098 if( edg->use_count < 1 ) {
03099 if( prev ) {
03100 prev->next = edg->next;
03101 } else {
03102 edges[v1] = edg->next;
03103 }
03104 edg->v = -1;
03105 edg->next = NULL;
03106 bu_free( (char *)edg, "bot_edge" );
03107 return;
03108 }
03109 }
03110 prev = edg;
03111 edg = edg->next;
03112 }
03113 } else {
03114 edg = edges[v2];
03115 while( edg ) {
03116 if( edg->v == v1 ) {
03117 edg->use_count--;
03118 if( edg->use_count < 1 ) {
03119 if( prev ) {
03120 prev->next = edg->next;
03121 } else {
03122 edges[v2] = edg->next;
03123 }
03124 edg->v = -1;
03125 edg->next = NULL;
03126 bu_free( (char *)edg, "bot_edge" );
03127 return;
03128 }
03129 }
03130 prev = edg;
03131 edg = edg->next;
03132 }
03133 }
03134 }
03135
03136
03137
03138
03139
03140
03141
03142
03143
03144
03145 static int
03146 decimate_edge( int v1, int v2, struct bot_edge **edges, int num_edges, int *faces, int num_faces, int face_del1, int face_del2 )
03147 {
03148 int i;
03149 struct bot_edge *edg;
03150
03151
03152 delete_edge( faces[face_del1*3 + 0], faces[face_del1*3 + 1], edges );
03153 delete_edge( faces[face_del1*3 + 1], faces[face_del1*3 + 2], edges );
03154 delete_edge( faces[face_del1*3 + 2], faces[face_del1*3 + 0], edges );
03155 delete_edge( faces[face_del2*3 + 0], faces[face_del2*3 + 1], edges );
03156 delete_edge( faces[face_del2*3 + 1], faces[face_del2*3 + 2], edges );
03157 delete_edge( faces[face_del2*3 + 2], faces[face_del2*3 + 0], edges );
03158
03159
03160 for( i=0 ; i<3 ; i++ ) {
03161 faces[face_del1*3 + i] = -1;
03162 faces[face_del2*3 + i] = -1;
03163 }
03164 for( i=0 ; i<num_faces*3 ; i++ ) {
03165 if( faces[i] == v1 ) {
03166 faces[i] = v2;
03167 }
03168 }
03169
03170
03171
03172 edg = edges[v1];
03173 while( edg ) {
03174 struct bot_edge *ptr;
03175 struct bot_edge *next;
03176
03177 next = edg->next;
03178
03179 if( edg->v < v2 ) {
03180 ptr = edges[edg->v];
03181 while( ptr ) {
03182 if( ptr->v == v2 ) {
03183 ptr->use_count++;
03184 edg->v = -1;
03185 edg->next = NULL;
03186 bu_free( (char *)edg, "bot edge" );
03187 break;
03188 }
03189 ptr = ptr->next;
03190 }
03191 if( !ptr ) {
03192 edg->next = edges[edg->v];
03193 edges[edg->v] = edg;
03194 edg->v = v2;
03195 }
03196 } else {
03197 ptr = edges[v2];
03198 while( ptr ) {
03199 if( ptr->v == edg->v ) {
03200 ptr->use_count++;
03201 edg->v = -1;
03202 edg->next = NULL;
03203 bu_free( (char *)edg, "bot edge" );
03204 break;
03205 }
03206 ptr = ptr->next;
03207 }
03208 if( !ptr ) {
03209 edg->next = edges[v2];
03210 edges[v2] = edg;
03211 }
03212 }
03213
03214 edg = next;
03215 }
03216 edges[v1] = NULL;
03217
03218
03219 for( i=0 ; i<num_edges ; i++ ) {
03220 struct bot_edge *next, *prev, *ptr;
03221
03222 prev = NULL;
03223 edg = edges[i];
03224
03225 while( edg ) {
03226 next = edg->next;
03227
03228 if( edg->v == v1 ) {
03229
03230 edg->v = v2;
03231 if( v2 < i ) {
03232
03233 if( prev ) {
03234 prev->next = next;
03235 } else {
03236 edges[i] = next;
03237 }
03238
03239
03240 ptr = edges[v2];
03241 while( ptr ) {
03242 if( ptr->v == i ) {
03243
03244
03245
03246 ptr->use_count++;
03247
03248
03249 edg->v = -1;
03250 edg->next = NULL;
03251 bu_free( (char *)edg, "bot edge" );
03252 break;
03253 }
03254 ptr = ptr->next;
03255 }
03256 if( !ptr ) {
03257
03258 edg->next = edges[v2];
03259 edges[v2] = edg;
03260 }
03261 edg = next;
03262 } else {
03263
03264
03265
03266 ptr = edges[i];
03267 while( ptr ) {
03268 if( ptr->v == v2 && ptr != edg ) {
03269
03270
03271 ptr->use_count++;
03272
03273
03274 if( prev ) {
03275 prev->next = next;
03276 } else {
03277 edges[i] = next;
03278 }
03279
03280
03281 edg->v = -1;
03282 edg->next = NULL;
03283 bu_free( (char *)edg, "bot edge" );
03284
03285 break;
03286 }
03287 ptr = ptr->next;
03288 }
03289 if( !ptr ) {
03290 prev = edg;
03291 }
03292 edg = next;
03293 }
03294 } else {
03295
03296 edg = next;
03297 }
03298 }
03299 }
03300
03301 return 2;
03302 }
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319 #define MAX_AFFECTED_FACES 128
03320
03321 static int
03322 edge_can_be_decimated( struct rt_bot_internal *bot,
03323 int *faces,
03324 struct bot_edge **edges,
03325 int v1,
03326 int v2,
03327 int *face_del1,
03328 int *face_del2,
03329 fastf_t max_chord_error,
03330 fastf_t max_normal_error,
03331 fastf_t min_edge_length_sq )
03332 {
03333 int i, j, k;
03334 int num_faces=bot->num_faces;
03335 int num_edges=bot->num_vertices;
03336 int count, v1_count;
03337 int affected_count=0;
03338 vect_t v01, v02, v12;
03339 fastf_t *vertices=bot->vertices;
03340 int faces_affected[MAX_AFFECTED_FACES];
03341
03342 if( v1 < 0 || v2 < 0 ) {
03343 return 0;
03344 }
03345
03346
03347 *face_del1 = -1;
03348 *face_del2 = -1;
03349 for( i=0 ; i<num_faces*3 ; i += 3 ) {
03350 count = 0;
03351 v1_count = 0;
03352 for( j=0 ; j<3 ; j++ ) {
03353 k = i + j;
03354 if( faces[k] == v1 ) {
03355
03356 count++;
03357 v1_count++;
03358 } else if( faces[k] == v2 ) {
03359
03360 count++;
03361 }
03362 }
03363 if( count > 1 ) {
03364
03365 if( *face_del1 > -1 ) {
03366 *face_del2 = i/3;
03367 } else {
03368 *face_del1 = i/3;
03369 }
03370 } else if( v1_count ) {
03371
03372 faces_affected[affected_count] = i;
03373 affected_count++;
03374 if( affected_count >= MAX_AFFECTED_FACES ) {
03375 return 0;
03376 }
03377 }
03378 }
03379
03380
03381
03382
03383 if( *face_del2 < 0 ) {
03384 return 0;
03385 }
03386
03387
03388 if( affected_count < 1 ) {
03389 return 0;
03390 }
03391
03392
03393 if( bot->mode == RT_BOT_PLATE || bot->mode == RT_BOT_SURFACE ) {
03394 struct bot_edge *edg;
03395
03396
03397 for( i=0 ; i<num_edges ; i++ ) {
03398 edg = edges[i];
03399 while( edg ) {
03400 if( (i == v1 || edg->v == v1) && edg->use_count < 2 ) {
03401 return 0;
03402 }
03403 edg = edg->next;
03404 }
03405 }
03406 }
03407
03408
03409 VSUB2( v12, &vertices[v1*3], &vertices[v2*3] );
03410
03411 if( min_edge_length_sq > SMALL_FASTF ) {
03412 if( MAGSQ( v12 ) > min_edge_length_sq ) {
03413 return 0;
03414 }
03415 }
03416
03417 if( max_chord_error > -1.0 || max_normal_error > -1.0 ) {
03418
03419
03420 for( i=0 ; i<affected_count ; i++ ) {
03421 fastf_t dist;
03422 fastf_t dot;
03423 plane_t pla, plb;
03424 int va, vb, vc;
03425
03426
03427
03428
03429
03430
03431 va = bot->faces[faces_affected[i]];
03432 vb = bot->faces[faces_affected[i]+1];
03433 vc = bot->faces[faces_affected[i]+2];
03434 VSUB2( v01, &vertices[vb*3], &vertices[va*3] );
03435 VSUB2( v02, &vertices[vc*3], &vertices[va*3] );
03436 VCROSS( plb, v01, v02 );
03437 VUNITIZE( plb );
03438 plb[3] = VDOT( &vertices[va*3], plb );
03439
03440
03441 va = faces[faces_affected[i]];
03442 vb = faces[faces_affected[i]+1];
03443 vc = faces[faces_affected[i]+2];
03444
03445 if( va == v1 ) {
03446 va = v2;
03447 } else if( vb == v1 ) {
03448 vb = v2;
03449 } else if( vc == v1 ) {
03450 vc = v2;
03451 }
03452 VSUB2( v01, &vertices[vb*3], &vertices[va*3] );
03453 VSUB2( v02, &vertices[vc*3], &vertices[va*3] );
03454 VCROSS( pla, v01, v02 );
03455 VUNITIZE( pla );
03456 pla[3] = VDOT( &vertices[va*3], pla );
03457
03458
03459 dot = VDOT( pla, plb );
03460 if( max_normal_error > -1.0 && dot < max_normal_error ) {
03461 return 0;
03462 }
03463
03464
03465 dist = fabs( DIST_PT_PLANE( &vertices[v1*3], pla ) );
03466 if( max_chord_error > -1.0 && dist > max_chord_error ) {
03467 return 0;
03468 }
03469 }
03470 }
03471
03472 return 1;
03473 }
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490 int
03491 rt_bot_decimate( struct rt_bot_internal *bot,
03492 fastf_t max_chord_error,
03493 fastf_t max_normal_error,
03494 fastf_t min_edge_length )
03495 {
03496 int *faces;
03497 struct bot_edge **edges;
03498 fastf_t min_edge_length_sq;
03499 int edges_deleted=0;
03500 int edge_count=0;
03501 int face_count;
03502 int actual_count;
03503 int deleted;
03504 int v1, v2;
03505 int i, j;
03506 int done;
03507
03508 RT_BOT_CK_MAGIC( bot );
03509
03510 #if 0
03511 if( max_chord_error <= SMALL_FASTF &&
03512 max_normal_error <= SMALL_FASTF &&
03513 min_edge_length <= SMALL_FASTF )
03514 return 0;
03515 #endif
03516
03517 if( max_normal_error > -1.0 ) {
03518 max_normal_error = cos( max_normal_error * M_PI / 180.0 );
03519 }
03520
03521 if( min_edge_length > SMALL_FASTF ) {
03522 min_edge_length_sq = min_edge_length * min_edge_length;
03523 } else {
03524 min_edge_length_sq = min_edge_length;
03525 }
03526
03527
03528 faces = (int *)bu_malloc( sizeof( int ) * bot->num_faces * 3, "faces" );
03529 for( i=0 ; i<bot->num_faces*3 ; i++ ) {
03530 faces[i] = bot->faces[i];
03531 }
03532 face_count = bot->num_faces;
03533
03534
03535
03536
03537 edges = (struct bot_edge **)bu_calloc( bot->num_vertices,
03538 sizeof( struct bot_edge *), "edges" );
03539
03540
03541 for( i=0 ; i<bot->num_faces*3 ; i += 3 ) {
03542 for( j=0 ; j<3 ; j++ ) {
03543 struct bot_edge *ptr;
03544 int k;
03545
03546 k = j + 1;
03547 if( k > 2 ) {
03548 k = 0;
03549 }
03550
03551
03552
03553 v1 = faces[i+j];
03554 v2 = faces[i+k];
03555
03556
03557 if( v2 < v1 ) {
03558 int tmp;
03559
03560 tmp = v1;
03561 v1 = v2;
03562 v2 = tmp;
03563 }
03564
03565
03566 ptr = edges[v1];
03567 if( !ptr ) {
03568 ptr = bu_calloc( 1, sizeof( struct bot_edge ), "edges[v1]" );
03569 edges[v1] = ptr;
03570 } else {
03571 while( ptr->next && ptr->v != v2 ) ptr = ptr->next;
03572 if( ptr->v == v2 ) {
03573 ptr->use_count++;
03574 continue;
03575 }
03576 ptr->next = bu_calloc( 1, sizeof( struct bot_edge ), "ptr->next" );
03577 ptr = ptr->next;
03578 }
03579 edge_count++;
03580 ptr->v = v2;
03581 ptr->use_count++;
03582 ptr->next = NULL;
03583 }
03584 }
03585
03586
03587 done = 0;
03588 while( !done ) {
03589 done = 1;
03590
03591
03592 for( i=0 ; i<bot->num_vertices ; i++ ) {
03593 struct bot_edge *ptr;
03594 int face_del1, face_del2;
03595
03596 ptr = edges[i];
03597 while( ptr ) {
03598
03599
03600 if( face_count < 5 )
03601 break;
03602
03603
03604 if( edge_can_be_decimated( bot, faces, edges, i, ptr->v,
03605 &face_del1, &face_del2,
03606 max_chord_error,
03607 max_normal_error,
03608 min_edge_length_sq )) {
03609 face_count -= decimate_edge( i, ptr->v, edges, bot->num_vertices,
03610 faces, bot->num_faces,
03611 face_del1, face_del2 );
03612 edges_deleted++;
03613 done = 0;
03614 break;
03615 } else if( edge_can_be_decimated( bot, faces, edges, ptr->v, i,
03616 &face_del1, &face_del2,
03617 max_chord_error,
03618 max_normal_error,
03619 min_edge_length_sq )) {
03620 face_count -= decimate_edge( ptr->v, i, edges, bot->num_vertices,
03621 faces, bot->num_faces,
03622 face_del1, face_del2 );
03623 edges_deleted++;
03624 done = 0;
03625 break;
03626 } else {
03627 ptr = ptr->next;
03628 }
03629 }
03630 }
03631 }
03632
03633
03634 for( i=0 ; i<bot->num_vertices ; i++ ) {
03635 struct bot_edge *ptr, *ptr2;
03636
03637 ptr = edges[i];
03638 while( ptr ) {
03639 ptr2 = ptr;
03640 ptr = ptr->next;
03641 bu_free( (char *)ptr2, "ptr->edges" );
03642 }
03643 }
03644 bu_free( (char *)edges, "edges" );
03645
03646
03647 actual_count = 0;
03648 deleted = 0;
03649 for( i=0 ; i<bot->num_faces*3 ; i++ ) {
03650 if( faces[i] < 0 ) {
03651 deleted++;
03652 continue;
03653 }
03654 if( deleted ) {
03655 faces[i-deleted] = faces[i];
03656 }
03657 actual_count++;
03658 }
03659
03660 if( actual_count % 3 ) {
03661 bu_log( "rt_bot_decimate: face vertices count is not a multilple of 3!!\n" );
03662 bu_free( ( char *)faces, "faces" );
03663 return -1;
03664 }
03665
03666 bu_log( "original face count = %d, edge count = %d\n",
03667 bot->num_faces, edge_count );
03668 bu_log( "\tedges deleted = %d\n", edges_deleted );
03669 bu_log( "\tnew face_count = %d\n", face_count );
03670
03671 actual_count /= 3;
03672
03673 if( face_count != actual_count ) {
03674 bu_log( "rt_bot_decimate: Face count is confused!!\n" );
03675 bu_free( ( char *)faces, "faces" );
03676 return -2;
03677 }
03678
03679 bu_free( (char *)bot->faces, "bot->faces" );
03680 bot->faces = (int *)bu_realloc( faces, sizeof( int ) * face_count * 3, "bot->faces" );
03681 bot->num_faces = face_count;
03682
03683
03684 (void)rt_bot_condense( bot );
03685
03686 return edges_deleted;
03687 }
03688
03689 static int
03690 smooth_bot_miss( struct application *ap )
03691 {
03692 return 0;
03693 }
03694
03695 static int
03696 smooth_bot_hit( struct application *ap, struct partition *PartHeadp, struct seg *seg )
03697 {
03698 struct partition *pp;
03699 struct soltab *stp;
03700 vect_t inormal, onormal;
03701 vect_t *normals=(vect_t *)ap->a_uptr;
03702
03703 for( pp=PartHeadp->pt_forw ; pp != PartHeadp; pp = pp->pt_forw ) {
03704 stp = pp->pt_inseg->seg_stp;
03705 RT_HIT_NORMAL( inormal, pp->pt_inhit, stp, &(ap->a_ray), pp->pt_inflip );
03706
03707 stp = pp->pt_outseg->seg_stp;
03708 RT_HIT_NORMAL( onormal, pp->pt_outhit, stp, &(ap->a_ray), pp->pt_outflip );
03709 if( pp->pt_inhit->hit_surfno == ap->a_user ) {
03710 VMOVE( normals[pp->pt_inhit->hit_surfno], inormal );
03711 break;
03712 }
03713 if( pp->pt_outhit->hit_surfno == ap->a_user ) {
03714 VMOVE( normals[pp->pt_outhit->hit_surfno], onormal );
03715 break;
03716 }
03717 }
03718
03719 return 1;
03720 }
03721
03722 int
03723 rt_smooth_bot( struct rt_bot_internal *bot, char *bot_name, struct db_i *dbip, fastf_t norm_tol_angle )
03724 {
03725 int vert_no;
03726 int i,j,k;
03727 struct rt_i *rtip;
03728 struct application ap;
03729 fastf_t normal_dot_tol=0.0;
03730 vect_t *normals;
03731
03732 RT_BOT_CK_MAGIC( bot );
03733
03734 if( norm_tol_angle < 0.0 || norm_tol_angle > M_PI ) {
03735 bu_log( "normal tolerance angle must be from 0 to Pi\n" );
03736 return( -2 );
03737 }
03738
03739 if( (bot->orientation == RT_BOT_UNORIENTED) && (bot->mode != RT_BOT_SOLID) ) {
03740 bu_log( "Cannot smooth unoriented BOT primitives unless they are solid objects\n" );
03741 return( -3 );
03742 }
03743
03744 normal_dot_tol = cos( norm_tol_angle );
03745
03746 if( bot->normals ) {
03747 bu_free( (char *)bot->normals, "bot->normals" );
03748 bot->normals = NULL;
03749 }
03750
03751 if( bot->face_normals ) {
03752 bu_free( (char *)bot->face_normals, "bot->face_normals" );
03753 bot->face_normals = NULL;
03754 }
03755
03756 bot->bot_flags &= !(RT_BOT_HAS_SURFACE_NORMALS | RT_BOT_USE_NORMALS);
03757 bot->num_normals = 0;
03758 bot->num_face_normals = 0;
03759
03760
03761 normals = (vect_t *)bu_calloc( bot->num_faces , sizeof( vect_t ), "normals" );
03762
03763 if( bot->orientation == RT_BOT_UNORIENTED ) {
03764
03765 rtip = rt_new_rti( dbip );
03766
03767 RT_APPLICATION_INIT(&ap);
03768 ap.a_rt_i = rtip;
03769 ap.a_hit = smooth_bot_hit;
03770 ap.a_miss = smooth_bot_miss;
03771 ap.a_uptr = (genptr_t)normals;
03772 if( rt_gettree( rtip, bot_name ) ) {
03773 bu_log( "rt_gettree failed for %s\n", bot_name );
03774 return( -1 );
03775 }
03776 rt_prep( rtip );
03777
03778
03779 for( i=0 ; i<bot->num_faces ; i++ ) {
03780 vect_t a, b;
03781 vect_t inv_dir;
03782
03783 VSUB2( a, &bot->vertices[bot->faces[i*3+1]*3], &bot->vertices[bot->faces[i*3]*3] );
03784 VSUB2( b, &bot->vertices[bot->faces[i*3+2]*3], &bot->vertices[bot->faces[i*3]*3] );
03785 VCROSS( ap.a_ray.r_dir, a, b );
03786 VUNITIZE( ap.a_ray.r_dir );
03787
03788
03789 VADD3( ap.a_ray.r_pt, &bot->vertices[bot->faces[i*3]*3],
03790 &bot->vertices[bot->faces[i*3+1]*3],
03791 &bot->vertices[bot->faces[i*3+2]*3] );
03792 VSCALE( ap.a_ray.r_pt, ap.a_ray.r_pt, 0.333333333333 );
03793
03794
03795
03796
03797 if( ap.a_ray.r_dir[X] < -SQRT_SMALL_FASTF ) {
03798 inv_dir[X]=1.0/ap.a_ray.r_dir[X];
03799 } else if( ap.a_ray.r_dir[X] > SQRT_SMALL_FASTF ) {
03800 inv_dir[X]=1.0/ap.a_ray.r_dir[X];
03801 } else {
03802 ap.a_ray.r_dir[X] = 0.0;
03803 inv_dir[X] = INFINITY;
03804 }
03805 if( ap.a_ray.r_dir[Y] < -SQRT_SMALL_FASTF ) {
03806 inv_dir[Y]=1.0/ap.a_ray.r_dir[Y];
03807 } else if( ap.a_ray.r_dir[Y] > SQRT_SMALL_FASTF ) {
03808 inv_dir[Y]=1.0/ap.a_ray.r_dir[Y];
03809 } else {
03810 ap.a_ray.r_dir[Y] = 0.0;
03811 inv_dir[Y] = INFINITY;
03812 }
03813 if( ap.a_ray.r_dir[Z] < -SQRT_SMALL_FASTF ) {
03814 inv_dir[Z]=1.0/ap.a_ray.r_dir[Z];
03815 } else if( ap.a_ray.r_dir[Z] > SQRT_SMALL_FASTF ) {
03816 inv_dir[Z]=1.0/ap.a_ray.r_dir[Z];
03817 } else {
03818 ap.a_ray.r_dir[Z] = 0.0;
03819 inv_dir[Z] = INFINITY;
03820 }
03821
03822 if( !rt_in_rpp( &ap.a_ray, inv_dir, rtip->mdl_min, rtip->mdl_max ) ) {
03823
03824 bu_log( "ERROR: Ray missed target!!!!\n" );
03825 }
03826 VJOIN1( ap.a_ray.r_pt, ap.a_ray.r_pt, ap.a_ray.r_min, ap.a_ray.r_dir );
03827 ap.a_user = i;
03828 (void) rt_shootray( &ap );
03829 }
03830 rt_free_rti( rtip );
03831 } else {
03832
03833 for( i=0 ; i<bot->num_faces ; i++ ) {
03834 vect_t a, b;
03835
03836 VSUB2( a, &bot->vertices[bot->faces[i*3+1]*3], &bot->vertices[bot->faces[i*3]*3] );
03837 VSUB2( b, &bot->vertices[bot->faces[i*3+2]*3], &bot->vertices[bot->faces[i*3]*3] );
03838 VCROSS( normals[i], a, b );
03839 VUNITIZE( normals[i] );
03840 if( bot->orientation == RT_BOT_CW ) {
03841 VREVERSE( normals[i], normals[i] );
03842 }
03843 }
03844 }
03845
03846 bot->num_normals = bot->num_faces * 3;
03847 bot->num_face_normals = bot->num_faces;
03848
03849 bot->normals = (fastf_t *)bu_calloc( bot->num_normals * 3, sizeof( fastf_t ), "bot->normals" );
03850 bot->face_normals = (int *)bu_calloc( bot->num_face_normals * 3, sizeof( int ), "bot->face_normals" );
03851
03852
03853 for( i=0 ; i<bot->num_faces ; i++ ) {
03854 vect_t def_norm;
03855
03856 VMOVE( def_norm, normals[i] );
03857
03858
03859 for( k=0 ; k<3 ; k++ ) {
03860 vect_t ave_norm;
03861
03862
03863 vert_no = bot->faces[i*3+k];
03864 VSETALL( ave_norm, 0.0 );
03865
03866
03867 for( j=0 ; j<bot->num_faces*3 ; j++ ) {
03868 if( bot->faces[j] == vert_no ) {
03869 int the_face;
03870
03871 the_face = j / 3;
03872
03873
03874
03875
03876 if( VDOT( normals[the_face], def_norm ) >= normal_dot_tol ) {
03877 VADD2( ave_norm, ave_norm, normals[the_face] );
03878 }
03879 }
03880 }
03881 VUNITIZE( ave_norm );
03882 VMOVE( &bot->normals[(i*3+k)*3], ave_norm );
03883 bot->face_normals[i*3+k] = i*3+k;
03884 }
03885 }
03886
03887 bu_free( (char *)normals, "normals" );
03888
03889 bot->bot_flags |= RT_BOT_HAS_SURFACE_NORMALS;
03890 bot->bot_flags |= RT_BOT_USE_NORMALS;
03891
03892 return( 0 );
03893 }
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904