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
00037
00038
00039
00040
00041
00042 #ifndef lint
00043 static const char XGLUE(RCSbot_inc_,TRI_TYPE)[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/g_bot_include.c,v 14.14 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00044 #endif
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 int
00058 XGLUE(rt_botface_w_normals_,TRI_TYPE)(struct soltab *stp,
00059 struct bot_specific *bot,
00060 fastf_t *ap,
00061 fastf_t *bp,
00062 fastf_t *cp,
00063 fastf_t *vertex_normals,
00064 int face_no,
00065 const struct bn_tol *tol)
00066 {
00067 register XGLUE(tri_specific_,TRI_TYPE) *trip;
00068 vect_t work;
00069 LOCAL fastf_t m1, m2, m3, m4;
00070 int i;
00071
00072 BU_GETTYPE( trip, XGLUE(tri_specific_,TRI_TYPE) );
00073 VMOVE( trip->tri_A, ap );
00074 VSUB2( trip->tri_BA, bp, ap );
00075 VSUB2( trip->tri_CA, cp, ap );
00076 VCROSS( trip->tri_wn, trip->tri_BA, trip->tri_CA );
00077 trip->tri_surfno = face_no;
00078
00079
00080 m1 = MAGNITUDE( trip->tri_BA );
00081 m2 = MAGNITUDE( trip->tri_CA );
00082 VSUB2( work, bp, cp );
00083 m3 = MAGNITUDE( work );
00084 m4 = MAGNITUDE( trip->tri_wn );
00085 if( m1 < 0.00001 || m2 < 0.00001 ||
00086 m3 < 0.00001 || m4 < 0.00001 ) {
00087 bu_free( (char *)trip, "getstruct tri_specific");
00088
00089 if( RT_G_DEBUG & DEBUG_SHOOT ) {
00090 bu_log("%s: degenerate facet #%d\n",
00091 stp->st_name, face_no);
00092 bu_log( "\t(%g %g %g) (%g %g %g) (%g %g %g)\n",
00093 V3ARGS( ap ), V3ARGS( bp ), V3ARGS( cp ) );
00094 }
00095 return(0);
00096 }
00097
00098 if( (bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) && (bot->bot_flags & RT_BOT_USE_NORMALS) && vertex_normals ) {
00099 trip->tri_normals = (NORM_TYPE *)bu_malloc( 9 * sizeof( NORM_TYPE ), "trip->tri_normals" );
00100 for( i=0 ; i<3 ; i++ ) {
00101 int j;
00102
00103 for( j=0 ; j<3 ; j++ ) {
00104 trip->tri_normals[i*3+j] = vertex_normals[i*3+j] * NORMAL_SCALE;
00105 }
00106 }
00107 } else {
00108 trip->tri_normals = (NORM_TYPE *)NULL;
00109 }
00110
00111
00112
00113
00114
00115 VMOVE( trip->tri_N, trip->tri_wn );
00116 VUNITIZE( trip->tri_N );
00117 if( bot->bot_mode == RT_BOT_CW )
00118 VREVERSE( trip->tri_N, trip->tri_N );
00119
00120
00121 trip->tri_forw = (XGLUE(tri_specific_,TRI_TYPE) *)bot->bot_facelist;
00122 bot->bot_facelist = (genptr_t)trip;
00123 return(3);
00124 }
00125
00126
00127
00128
00129
00130 void
00131 XGLUE(rt_bot_prep_pieces_,TRI_TYPE)(struct bot_specific *bot,
00132 struct soltab *stp,
00133 int ntri,
00134 const struct bn_tol *tol)
00135 {
00136 struct bound_rpp *minmax = (struct bound_rpp *)NULL;
00137 XGLUE(tri_specific_,TRI_TYPE) **fap;
00138 register XGLUE(tri_specific_,TRI_TYPE) *trip;
00139 point_t b,c;
00140 point_t d,e,f;
00141 vect_t offset;
00142 fastf_t los;
00143 int surfno;
00144 long num_rpps;
00145 int tri_per_piece, tpp_m1;
00146
00147 tri_per_piece = bot->bot_tri_per_piece = rt_bot_tri_per_piece;
00148
00149 num_rpps = ntri / tri_per_piece;
00150 if (ntri % tri_per_piece) num_rpps++;
00151
00152 stp->st_npieces = num_rpps;
00153
00154 fap = (XGLUE(tri_specific_,TRI_TYPE) **)
00155 bu_malloc( sizeof(XGLUE(tri_specific_,TRI_TYPE) *) * ntri,
00156 "bot_facearray" );
00157 bot->bot_facearray = (genptr_t *)fap;
00158
00159 stp->st_piece_rpps = (struct bound_rpp *)
00160 bu_malloc( sizeof(struct bound_rpp) * num_rpps,
00161 "st_piece_rpps" );
00162
00163
00164 tpp_m1 = tri_per_piece - 1;
00165 trip = bot->bot_facelist;
00166 minmax = &stp->st_piece_rpps[num_rpps-1];
00167 minmax->min[X] = minmax->max[X] = trip->tri_A[X];
00168 minmax->min[Y] = minmax->max[Y] = trip->tri_A[Y];
00169 minmax->min[Z] = minmax->max[Z] = trip->tri_A[Z];
00170 for (surfno=ntri-1 ; trip; trip = trip->tri_forw, surfno-- ) {
00171
00172 if ( (surfno % tri_per_piece) == tpp_m1) {
00173
00174
00175 minmax = &stp->st_piece_rpps[surfno / tri_per_piece];
00176
00177 minmax->min[X] = minmax->max[X] = trip->tri_A[X];
00178 minmax->min[Y] = minmax->max[Y] = trip->tri_A[Y];
00179 minmax->min[Z] = minmax->max[Z] = trip->tri_A[Z];
00180 } else {
00181 VMINMAX( minmax->min, minmax->max, trip->tri_A);
00182 }
00183
00184 fap[surfno] = trip;
00185
00186 if (bot->bot_mode == RT_BOT_PLATE ||
00187 bot->bot_mode == RT_BOT_PLATE_NOCOS ) {
00188 if( BU_BITTEST( bot->bot_facemode, surfno ) ) {
00189
00190 los = bot->bot_thickness[surfno];
00191 } else {
00192
00193 los = bot->bot_thickness[surfno] * 0.51;
00194 }
00195 } else {
00196
00197 los = tol->dist;
00198 }
00199
00200 VADD2( b, trip->tri_BA, trip->tri_A );
00201 VADD2( c, trip->tri_CA, trip->tri_A );
00202 VMINMAX( minmax->min, minmax->max, b );
00203 VMINMAX( minmax->min, minmax->max, c );
00204
00205
00206 VSCALE( offset, trip->tri_N, los );
00207 VADD2( d, trip->tri_A, offset );
00208 VADD2( e, b, offset );
00209 VADD2( f, c, offset );
00210 VMINMAX( minmax->min, minmax->max, d );
00211 VMINMAX( minmax->min, minmax->max, e );
00212 VMINMAX( minmax->min, minmax->max, f );
00213
00214
00215 VSCALE( offset, trip->tri_N, -los );
00216 VADD2( d, trip->tri_A, offset );
00217 VADD2( e, b, offset );
00218 VADD2( f, c, offset );
00219 VMINMAX( minmax->min, minmax->max, d );
00220 VMINMAX( minmax->min, minmax->max, e );
00221 VMINMAX( minmax->min, minmax->max, f );
00222
00223 VMINMAX( stp->st_min, stp->st_max, minmax->min );
00224 VMINMAX( stp->st_min, stp->st_max, minmax->max );
00225
00226 }
00227
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 int
00246 XGLUE(rt_bot_prep_,TRI_TYPE)( stp, bot_ip, rtip )
00247 struct soltab *stp;
00248 struct rt_bot_internal *bot_ip;
00249 struct rt_i *rtip;
00250 {
00251 register struct bot_specific *bot;
00252 const struct bn_tol *tol = &rtip->rti_tol;
00253 int tri_index, i;
00254 LOCAL fastf_t dx, dy, dz;
00255 LOCAL fastf_t f;
00256 int ntri = 0;
00257
00258 RT_BOT_CK_MAGIC(bot_ip);
00259
00260 BU_GETSTRUCT( bot, bot_specific );
00261 stp->st_specific = (genptr_t)bot;
00262 bot->bot_mode = bot_ip->mode;
00263 bot->bot_orientation = bot_ip->orientation;
00264 bot->bot_flags = bot_ip->bot_flags;
00265 if( bot_ip->thickness )
00266 {
00267 bot->bot_thickness = (fastf_t *)bu_calloc( bot_ip->num_faces, sizeof( fastf_t ), "bot_thickness" );
00268 for( tri_index=0 ; tri_index < bot_ip->num_faces ; tri_index++ )
00269 bot->bot_thickness[tri_index] = bot_ip->thickness[tri_index];
00270 }
00271 if( bot_ip->face_mode )
00272 bot->bot_facemode = bu_bitv_dup( bot_ip->face_mode );
00273 bot->bot_facelist = (XGLUE(tri_specific_,TRI_TYPE) *)NULL;
00274
00275 VSETALL( stp->st_min, MAX_FASTF );
00276 VREVERSE( stp->st_max, stp->st_min );
00277 for( tri_index=0 ; tri_index < bot_ip->num_faces ; tri_index++ )
00278 {
00279 point_t p1, p2, p3;
00280 int default_normal=-1;
00281
00282 VMOVE( p1, &bot_ip->vertices[bot_ip->faces[tri_index*3]*3] );
00283 VMOVE( p2, &bot_ip->vertices[bot_ip->faces[tri_index*3 + 1]*3] );
00284 VMOVE( p3, &bot_ip->vertices[bot_ip->faces[tri_index*3 + 2]*3] );
00285
00286 if( rt_bot_minpieces <= 0 || bot_ip->num_faces <= rt_bot_minpieces ) {
00287 VMINMAX( stp->st_min, stp->st_max, p1 );
00288 VMINMAX( stp->st_min, stp->st_max, p2 );
00289 VMINMAX( stp->st_min, stp->st_max, p3 );
00290 }
00291
00292 if( (bot_ip->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) && (bot_ip->bot_flags & RT_BOT_USE_NORMALS)
00293 && (bot_ip->num_normals > 0) && (bot_ip->num_face_normals > tri_index) ) {
00294 for( i=0 ; i<3 ; i++ ) {
00295 int index;
00296
00297 index = bot_ip->face_normals[tri_index*3 + i];
00298 if( index >= 0 && index < bot_ip->num_normals ) {
00299 default_normal = index;
00300 }
00301 }
00302 if( default_normal < 0 ) {
00303 if( rt_botface( stp, bot, p1, p2, p3, tri_index, tol ) > 0 )
00304 ntri++;
00305 } else {
00306 fastf_t normals[9];
00307
00308 for( i=0 ; i<3 ; i++ ) {
00309 int index;
00310
00311 index = bot_ip->face_normals[tri_index*3 + i];
00312 if( index < 0 || index > bot_ip->num_normals ) {
00313 VMOVE( &normals[i*3], &bot_ip->normals[default_normal*3] );
00314 } else {
00315 VMOVE( &normals[i*3], &bot_ip->normals[index*3] );
00316 }
00317 }
00318 if( rt_botface_w_normals( stp, bot, p1, p2, p3, normals, tri_index, tol ) > 0 )
00319 ntri++;
00320 }
00321 } else {
00322 if( rt_botface( stp, bot, p1, p2, p3, tri_index, tol ) > 0 )
00323 ntri++;
00324 }
00325 }
00326
00327 if( bot->bot_facelist == (XGLUE(tri_specific_,TRI_TYPE) *)0 ) {
00328 bu_log("bot(%s): no faces\n", stp->st_name);
00329 return(-1);
00330 }
00331
00332 bot->bot_ntri = ntri;
00333
00334 if( rt_bot_minpieces > 0 && bot_ip->num_faces > rt_bot_minpieces ) {
00335 rt_bot_prep_pieces( bot, stp, ntri, tol );
00336 }
00337
00338
00339 for( i=0 ; i<3 ; i++ )
00340 {
00341 if( NEAR_ZERO( stp->st_min[i] - stp->st_max[i], 1.0 ) )
00342 {
00343 stp->st_min[i] -= 0.000001;
00344 stp->st_max[i] += 0.000001;
00345 }
00346 }
00347
00348 VADD2SCALE( stp->st_center, stp->st_max, stp->st_min, 0.5 );
00349
00350 dx = (stp->st_max[X] - stp->st_min[X])/2;
00351 f = dx;
00352 dy = (stp->st_max[Y] - stp->st_min[Y])/2;
00353 if( dy > f ) f = dy;
00354 dz = (stp->st_max[Z] - stp->st_min[Z])/2;
00355 if( dz > f ) f = dz;
00356 stp->st_aradius = f;
00357 stp->st_bradius = sqrt(dx*dx + dy*dy + dz*dz);
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 return 0;
00376 }
00377
00378 static int
00379 XGLUE(rt_bot_plate_segs_,TRI_TYPE)(struct hit *hits,
00380 int nhits,
00381 struct soltab *stp,
00382 struct xray *rp,
00383 struct application *ap,
00384 struct seg *seghead,
00385 struct bot_specific *bot)
00386 {
00387 register struct seg *segp;
00388 register int i;
00389 register fastf_t los;
00390 int surfno;
00391
00392
00393 for( i=0; i < nhits; i++ ) {
00394 XGLUE(tri_specific_,TRI_TYPE) *trip=(XGLUE(tri_specific_,TRI_TYPE) *)hits[i].hit_private;
00395
00396 surfno = hits[i].hit_surfno;
00397
00398 if( bot->bot_mode == RT_BOT_PLATE_NOCOS )
00399 los = bot->bot_thickness[surfno];
00400 else {
00401 los = bot->bot_thickness[surfno] / hits[i].hit_vpriv[X];
00402 if( los < 0.0 )
00403 los = -los;
00404 }
00405 if( BU_BITTEST( bot->bot_facemode, hits[i].hit_surfno ) ) {
00406
00407
00408 RT_GET_SEG( segp, ap->a_resource);
00409 segp->seg_stp = stp;
00410
00411
00412 segp->seg_in = hits[i];
00413 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00414
00415
00416 segp->seg_out.hit_surfno = surfno;
00417 segp->seg_out.hit_dist = segp->seg_in.hit_dist + los;
00418 VMOVE( segp->seg_out.hit_vpriv, hits[i].hit_vpriv );
00419 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00420 segp->seg_out.hit_private = segp->seg_in.hit_private;
00421 segp->seg_out.hit_rayp = &ap->a_ray;
00422
00423 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00424 } else {
00425
00426 RT_GET_SEG( segp, ap->a_resource);
00427 segp->seg_stp = stp;
00428
00429
00430 segp->seg_in.hit_surfno = surfno;
00431 VMOVE( segp->seg_in.hit_vpriv, hits[i].hit_vpriv );
00432 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00433 segp->seg_in.hit_private = hits[i].hit_private;
00434 segp->seg_in.hit_dist = hits[i].hit_dist - (los*0.5 );
00435 segp->seg_in.hit_rayp = &ap->a_ray;
00436
00437
00438 segp->seg_out.hit_surfno = surfno;
00439 segp->seg_out.hit_dist = segp->seg_in.hit_dist + los;
00440 VMOVE( segp->seg_out.hit_vpriv, hits[i].hit_vpriv );
00441 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00442 segp->seg_out.hit_private = hits[i].hit_private;
00443 segp->seg_out.hit_rayp = &ap->a_ray;
00444
00445 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00446 }
00447 }
00448
00449 return( nhits*2 );
00450
00451 }
00452
00453 static int
00454 XGLUE(rt_bot_unoriented_segs_,TRI_TYPE)(struct hit *hits,
00455 int nhits,
00456 struct soltab *stp,
00457 struct xray *rp,
00458 struct application *ap,
00459 struct seg *seghead,
00460 struct bot_specific *bot)
00461 {
00462 register struct seg *segp;
00463 register int i, j;
00464
00465
00466
00467
00468 fastf_t rm_dist=0.0;
00469 int removed=0;
00470
00471 if( nhits == 1 ) {
00472 XGLUE(tri_specific_,TRI_TYPE) *trip=(XGLUE(tri_specific_,TRI_TYPE) *)hits[0].hit_private;
00473
00474
00475 RT_GET_SEG( segp, ap->a_resource );
00476 segp->seg_stp = stp;
00477
00478
00479 segp->seg_in = hits[0];
00480 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00481
00482
00483 segp->seg_out = hits[0];
00484 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00485
00486 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00487 return( 1 );
00488 }
00489
00490
00491 for( i=0 ; i<nhits-1 ; i++ ) {
00492 fastf_t dist;
00493
00494 dist = hits[i].hit_dist - hits[i+1].hit_dist;
00495 if( NEAR_ZERO( dist, ap->a_rt_i->rti_tol.dist ) ) {
00496 removed++;
00497 rm_dist = hits[i+1].hit_dist;
00498 for( j=i ; j<nhits-1 ; j++ )
00499 hits[j] = hits[j+1];
00500 nhits--;
00501 i--;
00502 }
00503 }
00504
00505
00506 if( nhits == 1 )
00507 return( 0 );
00508
00509 if( nhits&1 && removed ) {
00510
00511
00512
00513
00514 register int j;
00515
00516 for( i=0 ; i<nhits ; i++ ) {
00517 if( hits[i].hit_dist == rm_dist ) {
00518 for( j=i ; j<nhits-1 ; j++ )
00519 hits[j] = hits[j+1];
00520 nhits--;
00521 i--;
00522 break;
00523 }
00524 }
00525 }
00526
00527 for( i=0 ; i<(nhits&~1) ; i += 2 ) {
00528 XGLUE(tri_specific_,TRI_TYPE) *trip;
00529
00530 RT_GET_SEG( segp, ap->a_resource );
00531 segp->seg_stp = stp;
00532
00533
00534 segp->seg_in = hits[i];
00535 trip = (XGLUE(tri_specific_,TRI_TYPE) *)hits[i].hit_private;
00536 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00537
00538
00539 segp->seg_out = hits[i+1];
00540 trip = (XGLUE(tri_specific_,TRI_TYPE) *)hits[i+1].hit_private;
00541 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00542
00543 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00544 }
00545 if( nhits&1 ) {
00546 if( RT_G_DEBUG & DEBUG_SHOOT ) {
00547 bu_log( "rt_bot_unoriented_segs(%s): WARNING: odd number of hits (%d), last hit ignored\n",
00548 stp->st_name, nhits );
00549 bu_log( "\tray = -p %g %g %g -d %g %g %g\n",
00550 V3ARGS( rp->r_pt ), V3ARGS( rp->r_dir ) );
00551 }
00552 nhits--;
00553 }
00554 return( nhits );
00555 }
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 HIDDEN int
00566 XGLUE(rt_bot_makesegs_,TRI_TYPE)( struct hit *hits, int nhits, struct soltab *stp,
00567 struct xray *rp, struct application *ap,
00568 struct seg *seghead, struct rt_piecestate *psp )
00569 {
00570 struct bot_specific *bot = (struct bot_specific *)stp->st_specific;
00571 register struct seg *segp;
00572 register int i;
00573
00574 RT_CK_SOLTAB(stp);
00575
00576 if( bot->bot_mode == RT_BOT_SURFACE ) {
00577 for( i=0 ; i<nhits ; i++ )
00578 {
00579 XGLUE(tri_specific_,TRI_TYPE) *trip=(XGLUE(tri_specific_,TRI_TYPE) *)hits[i].hit_private;
00580
00581 RT_GET_SEG( segp, ap->a_resource );
00582 segp->seg_stp = stp;
00583
00584
00585 segp->seg_in = hits[i];
00586 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00587
00588
00589 segp->seg_out = hits[i];
00590 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00591 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00592 }
00593
00594 return( nhits*2 );
00595 }
00596
00597 BU_ASSERT( bot->bot_mode == RT_BOT_SOLID );
00598
00599 if( bot->bot_orientation == RT_BOT_UNORIENTED ) {
00600 return rt_bot_unoriented_segs(hits, nhits, stp, rp, ap,
00601 seghead, bot);
00602 }
00603
00604
00605
00606
00607
00608
00609
00610
00611 {
00612 register int j,k,l;
00613
00614 for( i=0 ; i<nhits-1 ; i++ )
00615 {
00616 FAST fastf_t dist;
00617 FAST fastf_t dn;
00618
00619 dn = hits[i].hit_vpriv[X];
00620
00621 k = i + 1;
00622 dist = hits[i].hit_dist - hits[k].hit_dist;
00623
00624
00625 while( NEAR_ZERO( dist, ap->a_rt_i->rti_tol.dist ) ) {
00626 k++;
00627 if( k > nhits - 1 )
00628 break;
00629 dist = hits[i].hit_dist - hits[k].hit_dist;
00630 }
00631
00632 if( (k - i) == 2 && dn * hits[i+1].hit_vpriv[X] > 0) {
00633
00634
00635 for( j=i ; j<nhits-1 ; j++ )
00636 hits[j] = hits[j+1];
00637 if( psp ) {
00638 psp->htab.end--;
00639 }
00640 nhits--;
00641 i--;
00642 continue;
00643 } else if( (k - i) > 2 ) {
00644 int keep1=-1, keep2=-1;
00645 int enters=0, exits=0;
00646 int reorder=0;
00647 int reorder_failed=0;
00648
00649
00650
00651
00652
00653
00654 for( j=0 ; j<k ; j++ ) {
00655 if( hits[j].hit_vpriv[X] > 0 )
00656 exits++;
00657 else
00658 enters++;
00659 }
00660
00661 if( k%2 ) {
00662 if( exits == (enters - 1) ) {
00663 reorder = 1;
00664 }
00665 } else {
00666 if( exits == enters ) {
00667 reorder = 1;
00668 }
00669 }
00670
00671 if( reorder ) {
00672 struct hit tmp_hit;
00673 int changed=0;
00674
00675 for( j=i ; j<k ; j++ ) {
00676 int l;
00677
00678 if( j%2 ) {
00679 if( hits[j].hit_vpriv[X] > 0 ) {
00680 continue;
00681 }
00682
00683 l = j+1;
00684 while( l < k ) {
00685 if( hits[l].hit_vpriv[X] > 0 ) {
00686
00687 tmp_hit = hits[j];
00688 hits[j] = hits[l];
00689 hits[l] = tmp_hit;
00690 changed = 1;
00691 break;
00692 }
00693 l++;
00694 }
00695 if( hits[j].hit_vpriv[X] < 0 ) {
00696 reorder_failed = 1;
00697 break;
00698 }
00699 } else {
00700 if( hits[j].hit_vpriv[X] < 0 ) {
00701 continue;
00702 }
00703
00704 l = j+1;
00705 while( l < k ) {
00706 if( hits[l].hit_vpriv[X] < 0 ) {
00707
00708 tmp_hit = hits[j];
00709 hits[j] = hits[l];
00710 hits[l] = tmp_hit;
00711 changed = 1;
00712 break;
00713 }
00714 l++;
00715 }
00716 if( hits[j].hit_vpriv[X] > 0 ) {
00717 reorder_failed = 1;
00718 break;
00719 }
00720 }
00721 }
00722 if( changed ) {
00723
00724
00725
00726 for( j=i+1 ; j<k ; j++ ) {
00727 hits[j].hit_dist = hits[i].hit_dist;
00728 }
00729 }
00730 }
00731 if( !reorder || reorder_failed ) {
00732
00733 exits = 0;
00734 enters = 0;
00735 if( i == 0 ) {
00736 dn = 1.0;
00737 } else {
00738 dn = hits[i-1].hit_vpriv[X];
00739 }
00740 for( j=i ; j<k ; j++ ) {
00741 if( hits[j].hit_vpriv[X] > 0 )
00742 exits++;
00743 else
00744 enters++;
00745 if( dn * hits[j].hit_vpriv[X] < 0 ) {
00746 if( keep1 < 0 ) {
00747 keep1 = j;
00748 dn = hits[j].hit_vpriv[X];
00749 } else if( keep2 < 0 ) {
00750 keep2 = j;
00751 dn = hits[j].hit_vpriv[X];
00752 break;
00753 }
00754 }
00755 }
00756
00757 if( keep2 == -1 ) {
00758
00759 if( exits == k - i || enters == k - i ) {
00760
00761 for( j=k-1 ; j>i ; j-- ) {
00762
00763 for( l=j ; l<nhits-1 ; l++ )
00764 hits[l] = hits[l+1];
00765 if( psp ) {
00766 psp->htab.end--;
00767 }
00768 nhits--;
00769 }
00770 i--;
00771 }
00772 } else if( keep2 >= 0 ) {
00773
00774 for( j=k-1 ; j>=i ; j-- ) {
00775 if( j != keep1 && j != keep2 ) {
00776
00777 for( l=j ; l<nhits-1 ; l++ )
00778 hits[l] = hits[l+1];
00779 if( psp ) {
00780 psp->htab.end--;
00781 }
00782 nhits--;
00783 }
00784 }
00785 i--;
00786 }
00787 }
00788 }
00789 }
00790 }
00791 #if 0
00792 bu_log( "nhits = %d\n", nhits );
00793 for( i=0 ; i<nhits ; i++ ) {
00794 rt_bot_norm( &hits[i], stp, rp );
00795 bu_log( "dist=%g, normal = (%g %g %g), %s\n", hits[i].hit_dist, V3ARGS( hits[i].hit_normal), hits[i].hit_vpriv[X] > 0 ? "exit" : "entrance" );
00796 }
00797 #endif
00798
00799
00800
00801
00802 while( nhits > 0 && hits[0].hit_vpriv[X] > 0.0 ) {
00803 int j;
00804
00805 for( j=1 ; j<nhits ; j++ ) {
00806 hits[j-1] = hits[j];
00807 }
00808 nhits--;
00809 }
00810
00811
00812 while( nhits > 0 && hits[nhits-1].hit_vpriv[X] < 0.0 ) {
00813 nhits--;
00814 }
00815
00816 if( (nhits&1) ) {
00817 register int i;
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 if( nhits > 2 )
00828 {
00829 fastf_t dot1,dot2;
00830 int j;
00831
00832
00833
00834
00835 dot2 = 1.0;
00836 i = 0;
00837 while( i<nhits )
00838 {
00839 dot1 = dot2;
00840 dot2 = hits[i].hit_vpriv[X];
00841 if( dot1 > 0.0 && dot2 > 0.0 )
00842 {
00843
00844
00845
00846
00847
00848 if( psp ) {
00849
00850 (void)rt_htbl_get(&psp->htab);
00851 hits = psp->htab.hits;
00852 } else if( nhits + 1 >= MAXHITS ) {
00853
00854 bu_log( "rt_bot_makesegs: too many hits on %s\n", stp->st_dp->d_namep );
00855 i++;
00856 continue;
00857 }
00858 for( j=nhits ; j>i ; j-- )
00859 hits[j] = hits[j-1];
00860
00861 hits[i].hit_vpriv[X] = -hits[i].hit_vpriv[X];
00862 dot2 = hits[i].hit_vpriv[X];
00863 nhits++;
00864 bu_log( "\t\tadding fictitious entry at %f (%s)\n", hits[i].hit_dist, stp->st_name );
00865 bu_log( "\t\t\tray = (%g %g %g) -> (%g %g %g)\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) );
00866 }
00867 else if( dot1 < 0.0 && dot2 < 0.0 )
00868 {
00869
00870
00871
00872
00873
00874 if( psp ) {
00875
00876 (void)rt_htbl_get(&psp->htab);
00877 hits = psp->htab.hits;
00878 } else if( nhits + 1 >= MAXHITS ) {
00879
00880 bu_log( "rt_bot_makesegs: too many hits on %s\n", stp->st_dp->d_namep );
00881 i++;
00882 continue;
00883 }
00884 for( j=nhits ; j>i ; j-- )
00885 hits[j] = hits[j-1];
00886
00887 hits[i] = hits[i-1];
00888 hits[i].hit_vpriv[X] = -hits[i].hit_vpriv[X];
00889 dot2 = hits[i].hit_vpriv[X];
00890 nhits++;
00891 bu_log( "\t\tadding fictitious exit at %f (%s)\n", hits[i].hit_dist, stp->st_name );
00892 bu_log( "\t\t\tray = (%g %g %g) -> (%g %g %g)\n", V3ARGS( ap->a_ray.r_pt ), V3ARGS( ap->a_ray.r_dir ) );
00893 }
00894 i++;
00895 }
00896 }
00897 }
00898
00899 if( (nhits&1) ) {
00900 #if 1
00901
00902 if( psp ) {
00903 (void)rt_htbl_get(&psp->htab);
00904 hits = psp->htab.hits;
00905 }
00906 if( !psp && (nhits + 1 >= MAXHITS) ) {
00907 bu_log( "rt_bot_makesegs: too many hits on %s\n", stp->st_dp->d_namep );
00908 nhits--;
00909 } else {
00910 hits[nhits] = hits[nhits-1];
00911 hits[nhits].hit_vpriv[X] = -hits[nhits].hit_vpriv[X];
00912 nhits++;
00913 }
00914 #else
00915 nhits--;
00916 #endif
00917 }
00918
00919
00920 for( i=0; i < nhits; i += 2 ) {
00921 XGLUE(tri_specific_,TRI_TYPE) *trip;
00922
00923 RT_GET_SEG(segp, ap->a_resource);
00924 segp->seg_stp = stp;
00925 segp->seg_in = hits[i];
00926 trip = (XGLUE(tri_specific_,TRI_TYPE) *)hits[i].hit_private;
00927 RT_BOT_UNORIENTED_NORM( &segp->seg_in, 1 );
00928 segp->seg_out = hits[i+1];
00929 trip = (XGLUE(tri_specific_,TRI_TYPE) *)hits[i+1].hit_private;
00930 RT_BOT_UNORIENTED_NORM( &segp->seg_out, -1 );
00931 BU_LIST_INSERT( &(seghead->l), &(segp->l) );
00932 }
00933
00934 return(nhits);
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952 int
00953 XGLUE(rt_bot_shot_,TRI_TYPE)( struct soltab *stp, struct xray *rp, struct application *ap, struct seg *seghead )
00954 {
00955 struct bot_specific *bot = (struct bot_specific *)stp->st_specific;
00956 register XGLUE(tri_specific_,TRI_TYPE) *trip = bot->bot_facelist;
00957 LOCAL struct hit hits[MAXHITS];
00958 register struct hit *hp;
00959 LOCAL int nhits;
00960 fastf_t toldist, dn_plus_tol;
00961
00962 nhits = 0;
00963 hp = &hits[0];
00964 if( bot->bot_orientation != RT_BOT_UNORIENTED && bot->bot_mode == RT_BOT_SOLID ) {
00965 toldist = stp->st_aradius / 10.0e+6;
00966 } else {
00967 toldist = 0.0;
00968 }
00969
00970
00971 for( ; trip; trip = trip->tri_forw ) {
00972 FAST fastf_t dn;
00973 LOCAL fastf_t abs_dn;
00974 FAST fastf_t k;
00975 LOCAL fastf_t alpha, beta;
00976 LOCAL vect_t wxb;
00977 LOCAL vect_t xp;
00978
00979
00980
00981
00982
00983 dn = VDOT( trip->tri_wn, rp->r_dir );
00984
00985
00986
00987
00988
00989 abs_dn = dn >= 0.0 ? dn : (-dn);
00990 if( abs_dn < BOT_MIN_DN ) {
00991 continue;
00992 }
00993 VSUB2( wxb, trip->tri_A, rp->r_pt );
00994 VCROSS( xp, wxb, rp->r_dir );
00995
00996 dn_plus_tol = toldist + abs_dn;
00997
00998
00999 alpha = VDOT( trip->tri_CA, xp );
01000 if( dn < 0.0 ) alpha = -alpha;
01001 if( alpha < -toldist || alpha > dn_plus_tol ) {
01002 continue;
01003 }
01004
01005
01006 beta = VDOT( trip->tri_BA, xp );
01007 if( dn > 0.0 ) beta = -beta;
01008 if( beta < -toldist || beta > dn_plus_tol ) {
01009 continue;
01010 }
01011 if( alpha+beta > dn_plus_tol ) {
01012 continue;
01013 }
01014 k = VDOT( wxb, trip->tri_wn ) / dn;
01015
01016 hp->hit_magic = RT_HIT_MAGIC;
01017 hp->hit_dist = k;
01018 hp->hit_private = (genptr_t)trip;
01019 hp->hit_vpriv[X] = VDOT( trip->tri_N, rp->r_dir );
01020 hp->hit_vpriv[Y] = alpha / abs_dn;
01021 hp->hit_vpriv[Z] = beta / abs_dn;
01022 hp->hit_surfno = trip->tri_surfno;
01023 hp->hit_rayp = &ap->a_ray;
01024 if( ++nhits >= MAXHITS ) {
01025 bu_log("rt_bot_shot(%s): too many hits (%d)\n", stp->st_name, nhits);
01026 break;
01027 }
01028 hp++;
01029 }
01030 if( nhits == 0 )
01031 return(0);
01032
01033
01034 rt_hitsort( hits, nhits );
01035
01036
01037 return rt_bot_makesegs( hits, nhits, stp, rp, ap, seghead, NULL );
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052 int
01053 XGLUE(rt_bot_piece_shot_,TRI_TYPE)( struct rt_piecestate *psp, struct rt_piecelist *plp,
01054 double dist_corr, struct xray *rp, struct application *ap, struct seg *seghead )
01055 {
01056 struct resource *resp;
01057 long *sol_piece_subscr_p;
01058 struct soltab *stp;
01059 long piecenum;
01060 register struct hit *hp;
01061 struct bot_specific *bot;
01062 const int debug_shoot = RT_G_DEBUG & DEBUG_SHOOT;
01063 int starting_hits;
01064 fastf_t toldist, dn_plus_tol;
01065 int trinum;
01066
01067 RT_CK_PIECELIST(plp);
01068 stp = plp->stp;
01069
01070 RT_CK_APPLICATION(ap);
01071 resp = ap->a_resource;
01072 RT_CK_RESOURCE(resp);
01073
01074 RT_CK_SOLTAB(stp);
01075 bot = (struct bot_specific *)stp->st_specific;
01076
01077 RT_CK_PIECESTATE(psp);
01078 starting_hits = psp->htab.end;
01079
01080 if( bot->bot_orientation != RT_BOT_UNORIENTED &&
01081 bot->bot_mode == RT_BOT_SOLID ) {
01082
01083 toldist = psp->stp->st_aradius / 10.0e+6;
01084 } else {
01085 toldist = 0.0;
01086 }
01087
01088 if( debug_shoot ) {
01089 bu_log( "In rt_bot_piece_shot(), looking at %d pieces\n", plp->npieces );
01090 }
01091 sol_piece_subscr_p = &(plp->pieces[plp->npieces-1]);
01092 for( ; sol_piece_subscr_p >= plp->pieces; sol_piece_subscr_p-- ) {
01093 FAST fastf_t dn;
01094 LOCAL fastf_t abs_dn;
01095 FAST fastf_t k;
01096 LOCAL fastf_t alpha, beta;
01097 LOCAL vect_t wxb;
01098 LOCAL vect_t xp;
01099 LOCAL int face_array_index;
01100 LOCAL int tris_in_piece;
01101
01102 piecenum = *sol_piece_subscr_p;
01103
01104 if( BU_BITTEST( psp->shot, piecenum ) ) {
01105 if(debug_shoot)
01106 bu_log("%s piece %d already shot\n",
01107 stp->st_name, piecenum);
01108
01109 resp->re_piece_ndup++;
01110 continue;
01111 }
01112
01113
01114 BU_BITSET( psp->shot, piecenum );
01115 if(debug_shoot)
01116 bu_log("%s piece %d ...\n", stp->st_name, piecenum);
01117
01118
01119
01120
01121
01122 face_array_index = piecenum*bot->bot_tri_per_piece;
01123 tris_in_piece = bot->bot_ntri - face_array_index;
01124 if( tris_in_piece > bot->bot_tri_per_piece ) {
01125 tris_in_piece = bot->bot_tri_per_piece;
01126 }
01127 for( trinum=0; trinum<tris_in_piece; trinum++ ) {
01128 register XGLUE(tri_specific_,TRI_TYPE) *trip = bot->bot_facearray[face_array_index+trinum];
01129 fastf_t dN, abs_dN;
01130
01131
01132
01133
01134
01135 dn = VDOT( trip->tri_wn, rp->r_dir );
01136 dN = VDOT( trip->tri_N, rp->r_dir );
01137
01138
01139
01140
01141
01142 abs_dN = dN >= 0.0 ? dN : (-dN);
01143 abs_dn = dn >= 0.0 ? dn : (-dn);
01144 if( abs_dN < BOT_MIN_DN ) {
01145 continue;
01146 }
01147 VSUB2( wxb, trip->tri_A, rp->r_pt );
01148 VCROSS( xp, wxb, rp->r_dir );
01149
01150 dn_plus_tol = toldist + abs_dn;
01151
01152
01153 alpha = VDOT( trip->tri_CA, xp );
01154 if( dn < 0.0 ) alpha = -alpha;
01155 if( alpha < -toldist || alpha > dn_plus_tol ) {
01156 continue;
01157 }
01158
01159
01160 beta = VDOT( trip->tri_BA, xp );
01161 if( dn > 0.0 ) beta = -beta;
01162 if( beta < -toldist || beta > dn_plus_tol ) {
01163 continue;
01164 }
01165 if( alpha+beta > dn_plus_tol ) {
01166 continue;
01167 }
01168 k = VDOT( wxb, trip->tri_wn ) / dn;
01169
01170
01171 hp = rt_htbl_get( &psp->htab );
01172 hp->hit_magic = RT_HIT_MAGIC;
01173 hp->hit_dist = k + dist_corr;
01174 hp->hit_private = (genptr_t)trip;
01175 hp->hit_vpriv[X] = VDOT( trip->tri_N, rp->r_dir );
01176 hp->hit_vpriv[Y] = alpha / abs_dn;
01177 hp->hit_vpriv[Z] = beta / abs_dn;
01178 hp->hit_surfno = trip->tri_surfno;
01179 hp->hit_rayp = &ap->a_ray;
01180 if(debug_shoot)
01181 bu_log("%s piece %d surfno %d ... HIT %g\n",
01182 stp->st_name, piecenum, trip->tri_surfno, hp->hit_dist);
01183 }
01184 }
01185
01186 if( psp->htab.end > 0 &&
01187 (bot->bot_mode == RT_BOT_PLATE ||
01188 bot->bot_mode == RT_BOT_PLATE_NOCOS) ) {
01189
01190
01191
01192
01193
01194 rt_hitsort( psp->htab.hits, psp->htab.end );
01195 return rt_bot_makesegs( psp->htab.hits, psp->htab.end,
01196 stp, rp, ap, seghead, psp );
01197 }
01198 return psp->htab.end - starting_hits;
01199 }
01200
01201
01202
01203
01204
01205
01206 void
01207 XGLUE(rt_bot_norm_,TRI_TYPE)( bot, hitp, stp, rp )
01208 struct bot_specific *bot;
01209 register struct hit *hitp;
01210 struct soltab *stp;
01211 register struct xray *rp;
01212 {
01213 XGLUE(tri_specific_,TRI_TYPE) *trip=(XGLUE(tri_specific_,TRI_TYPE) *)hitp->hit_private;
01214 vect_t old_norm;
01215
01216 VJOIN1( hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir );
01217 VMOVE( old_norm, hitp->hit_normal );
01218
01219 if( (bot->bot_flags & RT_BOT_HAS_SURFACE_NORMALS) && (bot->bot_flags & RT_BOT_USE_NORMALS) && trip->tri_normals ) {
01220 fastf_t old_ray_dot_norm, new_ray_dot_norm;
01221 fastf_t u, v, w;
01222 int i;
01223
01224 old_ray_dot_norm = VDOT( hitp->hit_normal, rp->r_dir );
01225
01226 v = hitp->hit_vpriv[Y];
01227 if( v < 0.0 ) v = 0.0;
01228 if( v > 1.0 ) v = 1.0;
01229
01230 w = hitp->hit_vpriv[Z];
01231 if( w < 0.0 ) w = 0.0;
01232 if( w > 1.0 ) w = 1.0;
01233
01234 u = 1.0 - v - w;
01235 if( u < 0.0 ) u = 0.0;
01236 VSETALL( hitp->hit_normal, 0.0 );
01237
01238 for( i=X ; i<=Z ; i++ ) {
01239 hitp->hit_normal[i] = u*trip->tri_normals[i]*ONE_OVER_SCALE + v*trip->tri_normals[i+3]*ONE_OVER_SCALE + w*trip->tri_normals[i+6]*ONE_OVER_SCALE;
01240 }
01241 VUNITIZE( hitp->hit_normal );
01242
01243 if( bot->bot_mode == RT_BOT_PLATE || bot->bot_mode == RT_BOT_PLATE_NOCOS ) {
01244 if( VDOT( old_norm, hitp->hit_normal ) < 0.0 ) {
01245 VREVERSE( hitp->hit_normal, hitp->hit_normal );
01246 }
01247 }
01248
01249 new_ray_dot_norm = VDOT( hitp->hit_normal, rp->r_dir );
01250
01251 if( (old_ray_dot_norm < 0.0 && new_ray_dot_norm > 0.0) ||
01252 (old_ray_dot_norm > 0.0 && new_ray_dot_norm < 0.0) ) {
01253
01254
01255
01256
01257 vect_t tmp;
01258
01259 VCROSS( tmp, rp->r_dir, hitp->hit_normal );
01260 VCROSS( hitp->hit_normal, tmp, rp->r_dir );
01261 }
01262
01263 VUNITIZE( hitp->hit_normal );
01264 }
01265 }
01266
01267
01268
01269
01270 void
01271 XGLUE(rt_bot_free_,TRI_TYPE)( bot )
01272 register struct bot_specific *bot;
01273 {
01274 register XGLUE(tri_specific_,TRI_TYPE) *tri, *ptr;
01275
01276 if( bot->bot_facearray ) {
01277 bu_free( (char *)bot->bot_facearray, "bot_facearray" );
01278 bot->bot_facearray = NULL;
01279 }
01280
01281 if( bot->bot_thickness ) {
01282 bu_free( (char *)bot->bot_thickness, "bot_thickness" );
01283 bot->bot_thickness = NULL;
01284 }
01285 if( bot->bot_facemode ) {
01286 bu_free( (char *)bot->bot_facemode, "bot_facemode" );
01287 bot->bot_facemode = NULL;
01288 }
01289 ptr = bot->bot_facelist;
01290 while( ptr )
01291 {
01292 tri = ptr->tri_forw;
01293 if( ptr ) {
01294 if( ptr->tri_normals ) {
01295 bu_free( (char *)ptr->tri_normals, "bot tri_specific normals" );
01296 }
01297 bu_free( (char *)ptr, "bot tri_specific" );
01298 }
01299 ptr = tri;
01300 }
01301 bot->bot_facelist = NULL;
01302 bu_free( (char *)bot, "bot_specific" );
01303 }
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315