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
00043
00044
00045
00046 #ifndef lint
00047 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_comb.c,v 14.14 2006/09/16 02:04:24 lbutler Exp $ (ARL)";
00048 #endif
00049
00050 #include "common.h"
00051
00052
00053
00054 #include <stdio.h>
00055 #include <math.h>
00056 #ifdef HAVE_STRING_H
00057 #include <string.h>
00058 #else
00059 #include <strings.h>
00060 #endif
00061
00062 #include "machine.h"
00063 #include "bu.h"
00064 #include "vmath.h"
00065 #include "bn.h"
00066 #include "db.h"
00067 #include "raytrace.h"
00068
00069 #include "./debug.h"
00070
00071 #define STAT_ROT 1
00072 #define STAT_XLATE 2
00073 #define STAT_PERSP 4
00074 #define STAT_SCALE 8
00075
00076
00077
00078
00079
00080
00081
00082 static int
00083 mat_categorize(const fastf_t *matp)
00084 {
00085 int status = 0;
00086
00087 if( !matp ) return 0;
00088
00089 if( matp[0] != 1.0 || matp[5] != 1.0 || matp[10] != 1.0 )
00090 status |= STAT_ROT;
00091
00092 if( matp[MDX] != 0.0 ||
00093 matp[MDY] != 0.0 ||
00094 matp[MDZ] != 0.0 )
00095 status |= STAT_XLATE;
00096
00097 if( matp[12] != 0.0 ||
00098 matp[13] != 0.0 ||
00099 matp[14] != 0.0 )
00100 status |= STAT_PERSP;
00101
00102 if( matp[15] != 1.0 ) status |= STAT_SCALE;
00103
00104 return status;
00105 }
00106
00107
00108
00109
00110
00111
00112 int
00113 db_tree_nleaves( const union tree *tp )
00114 {
00115 if( tp == TREE_NULL ) return 0;
00116
00117 RT_CK_TREE(tp);
00118
00119 switch( tp->tr_op ) {
00120 case OP_NOP:
00121 return 0;
00122 case OP_DB_LEAF:
00123 return 1;
00124 case OP_SOLID:
00125 return 1;
00126 case OP_REGION:
00127 return 1;
00128
00129 case OP_NOT:
00130 case OP_GUARD:
00131 case OP_XNOP:
00132
00133 return db_tree_nleaves( tp->tr_b.tb_left );
00134
00135 case OP_UNION:
00136 case OP_INTERSECT:
00137 case OP_SUBTRACT:
00138 case OP_XOR:
00139
00140 return db_tree_nleaves( tp->tr_b.tb_left ) +
00141 db_tree_nleaves( tp->tr_b.tb_right );
00142
00143 default:
00144 bu_log("db_tree_nleaves: bad op %d\n", tp->tr_op);
00145 rt_bomb("db_tree_nleaves\n");
00146 }
00147 return( -1 );
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 struct rt_tree_array *
00166 db_flatten_tree(
00167 struct rt_tree_array *rt_tree_array,
00168 union tree *tp,
00169 int op,
00170 int free,
00171 struct resource *resp)
00172 {
00173
00174 RT_CK_TREE(tp);
00175 RT_CK_RESOURCE(resp);
00176
00177 switch( tp->tr_op ) {
00178 case OP_DB_LEAF:
00179 rt_tree_array->tl_op = op;
00180 rt_tree_array->tl_tree = tp;
00181 return rt_tree_array+1;
00182
00183 case OP_UNION:
00184 case OP_INTERSECT:
00185 case OP_SUBTRACT:
00186
00187 rt_tree_array = db_flatten_tree( rt_tree_array, tp->tr_b.tb_left, op, free, resp );
00188 rt_tree_array = db_flatten_tree( rt_tree_array, tp->tr_b.tb_right, tp->tr_op, free, resp );
00189 if(free) {
00190
00191 tp->tr_b.tb_left = TREE_NULL;
00192 tp->tr_b.tb_right = TREE_NULL;
00193 RT_FREE_TREE( tp, resp )
00194 }
00195 return rt_tree_array;
00196
00197 default:
00198 bu_log("db_flatten_tree: bad op %d\n", tp->tr_op);
00199 bu_bomb("db_flatten_tree\n");
00200 }
00201
00202 return( (struct rt_tree_array *)NULL );
00203 }
00204
00205
00206
00207
00208
00209
00210 int
00211 rt_comb_import4(
00212 struct rt_db_internal *ip,
00213 const struct bu_external *ep,
00214 const mat_t matrix,
00215 const struct db_i *dbip,
00216 struct resource *resp)
00217 {
00218 union record *rp;
00219 struct rt_tree_array *rt_tree_array;
00220 union tree *tree;
00221 struct rt_comb_internal *comb;
00222 int j;
00223 int node_count;
00224
00225 BU_CK_EXTERNAL( ep );
00226 rp = (union record *)ep->ext_buf;
00227
00228 if( rp[0].u_id != ID_COMB )
00229 {
00230 bu_log( "rt_comb_import4: Attempt to import a non-combination\n" );
00231 return( -1 );
00232 }
00233
00234
00235 node_count = ep->ext_nbytes/sizeof( union record ) - 1;
00236
00237 if( node_count )
00238 rt_tree_array = (struct rt_tree_array *)bu_calloc( node_count , sizeof( struct rt_tree_array ) , "rt_tree_array" );
00239 else
00240 rt_tree_array = (struct rt_tree_array *)NULL;
00241
00242 for( j=0 ; j<node_count ; j++ )
00243 {
00244 if( rp[j+1].u_id != ID_MEMB )
00245 {
00246 bu_free( (genptr_t)rt_tree_array , "rt_comb_import4: rt_tree_array" );
00247 bu_log( "rt_comb_import4(): granule in external buffer is not ID_MEMB, id=%d\n", rp[j+1].u_id );
00248 return( -1 );
00249 }
00250
00251 switch( rp[j+1].M.m_relation )
00252 {
00253 case '+':
00254 rt_tree_array[j].tl_op = OP_INTERSECT;
00255 break;
00256 case '-':
00257 rt_tree_array[j].tl_op = OP_SUBTRACT;
00258 break;
00259 default:
00260 bu_log("rt_comb_import4() unknown op=x%x, assuming UNION\n", rp[j+1].M.m_relation );
00261
00262 case 'u':
00263 rt_tree_array[j].tl_op = OP_UNION;
00264 break;
00265 }
00266
00267 {
00268 union tree *tp;
00269 mat_t diskmat;
00270 char namebuf[NAMESIZE+2];
00271
00272 RT_GET_TREE( tp, resp );
00273 rt_tree_array[j].tl_tree = tp;
00274 tp->tr_l.magic = RT_TREE_MAGIC;
00275 tp->tr_l.tl_op = OP_DB_LEAF;
00276 strncpy( namebuf, rp[j+1].M.m_instname, NAMESIZE );
00277 namebuf[NAMESIZE] = '\0';
00278 tp->tr_l.tl_name = bu_strdup( namebuf );
00279
00280 rt_mat_dbmat( diskmat, rp[j+1].M.m_mat );
00281
00282
00283 if( fabs(diskmat[0]) > 1 || fabs(diskmat[1]) > 1 ||
00284 fabs(diskmat[2]) > 1 ||
00285 fabs(diskmat[4]) > 1 || fabs(diskmat[5]) > 1 ||
00286 fabs(diskmat[6]) > 1 ||
00287 fabs(diskmat[8]) > 1 || fabs(diskmat[9]) > 1 ||
00288 fabs(diskmat[10]) > 1 ) {
00289 bu_log("ERROR: %s/%s improper scaling, rotation matrix elements > 1\n",
00290 rp[0].c.c_name, namebuf );
00291 }
00292
00293
00294 if( diskmat[12] != 0 || diskmat[13] != 0 || diskmat[14] != 0 ) {
00295 bu_log("ERROR: %s/%s has perspective transform\n",
00296 rp[0].c.c_name, namebuf );
00297 }
00298
00299
00300 if( bn_mat_is_identity( diskmat ) ) {
00301 if( matrix == NULL ) {
00302 tp->tr_l.tl_mat = NULL;
00303 } else {
00304 tp->tr_l.tl_mat = bn_mat_dup( matrix );
00305 }
00306 } else {
00307 if( matrix == NULL ) {
00308 tp->tr_l.tl_mat = bn_mat_dup( diskmat );
00309 } else {
00310 mat_t prod;
00311 bn_mat_mul( prod, matrix, diskmat );
00312 tp->tr_l.tl_mat = bn_mat_dup( prod );
00313 }
00314 }
00315
00316 }
00317 }
00318 if( node_count )
00319 tree = db_mkgift_tree( rt_tree_array, node_count, &rt_uniresource );
00320 else
00321 tree = (union tree *)NULL;
00322
00323 RT_INIT_DB_INTERNAL( ip );
00324 ip->idb_major_type = DB5_MAJORTYPE_BRLCAD;
00325 ip->idb_type = ID_COMBINATION;
00326 ip->idb_meth = &rt_functab[ID_COMBINATION];
00327 comb = (struct rt_comb_internal *)bu_malloc( sizeof( struct rt_comb_internal ) , "rt_comb_import4: rt_comb_internal" );
00328 ip->idb_ptr = (genptr_t)comb;
00329 comb->magic = RT_COMB_MAGIC;
00330 bu_vls_init( &comb->shader );
00331 bu_vls_init( &comb->material );
00332 comb->tree = tree;
00333 comb->temperature = -1;
00334 switch( rp[0].c.c_flags ) {
00335 case DBV4_NON_REGION_NULL:
00336 case DBV4_NON_REGION:
00337 comb->region_flag = 0;
00338 break;
00339 case DBV4_REGION:
00340 comb->region_flag = 1;
00341 comb->is_fastgen = REGION_NON_FASTGEN;
00342 break;
00343 case DBV4_REGION_FASTGEN_PLATE:
00344 comb->region_flag = 1;
00345 comb->is_fastgen = REGION_FASTGEN_PLATE;
00346 break;
00347 case DBV4_REGION_FASTGEN_VOLUME:
00348 comb->region_flag = 1;
00349 comb->is_fastgen = REGION_FASTGEN_VOLUME;
00350 break;
00351 default:
00352 bu_log("WARNING: combination %s has illegal c_flag=x%x\n",
00353 rp[0].c.c_name, rp[0].c.c_flags );
00354 break;
00355 }
00356
00357 if( comb->region_flag ) {
00358 comb->region_id = rp[0].c.c_regionid;
00359 comb->aircode = rp[0].c.c_aircode;
00360 comb->GIFTmater = rp[0].c.c_material;
00361 comb->los = rp[0].c.c_los;
00362 #if 0
00363 if( comb->region_id && comb->aircode )
00364 {
00365 bu_log( "NOTICE: region %s has both id=%d and aircode=%d, ignoring aircode!!!\n",
00366 rp[0].c.c_name, comb->region_id, comb->aircode );
00367 comb->aircode = 0;
00368 }
00369 #endif
00370 }
00371 else {
00372 comb->region_id = 0;
00373 comb->aircode = 0;
00374 comb->GIFTmater = 0;
00375 comb->los = 0;
00376 }
00377
00378 comb->rgb_valid = rp[0].c.c_override;
00379 if ( comb->rgb_valid ) {
00380 comb->rgb[0] = rp[0].c.c_rgb[0];
00381 comb->rgb[1] = rp[0].c.c_rgb[1];
00382 comb->rgb[2] = rp[0].c.c_rgb[2];
00383 }
00384 if( rp[0].c.c_matname[0] != '\0' )
00385 {
00386 char shader_str[94];
00387
00388
00389 strncpy( shader_str, rp[0].c.c_matname, 32 );
00390 shader_str[33] = '\0';
00391 strcat( shader_str, " " );
00392 strncat( shader_str, rp[0].c.c_matparm, 60 );
00393 shader_str[93] = '\0';
00394
00395
00396 if( bu_shader_to_tcl_list( shader_str, &comb->shader ) )
00397 {
00398 bu_log( "rt_comb_import4: Error: Cannot convert following shader to TCL format:\n" );
00399 bu_log( "\t%s\n", shader_str );
00400 bu_vls_free( &comb->shader );
00401 return -1;
00402 }
00403 }
00404
00405
00406
00407 comb->inherit = (rp[0].c.c_inherit == DB_INH_HIGHER) ? 1 : 0;
00408
00409 if( comb->region_flag )
00410 bu_vls_printf( &comb->material, "gift%d", comb->GIFTmater );
00411
00412 if( rt_tree_array ) bu_free( (genptr_t)rt_tree_array, "rt_tree_array" );
00413
00414 return( 0 );
00415 }
00416
00417
00418
00419
00420 int
00421 rt_comb_export4(
00422 struct bu_external *ep,
00423 const struct rt_db_internal *ip,
00424 double local2mm,
00425 const struct db_i *dbip,
00426 struct resource *resp)
00427 {
00428 struct rt_comb_internal *comb;
00429 int node_count;
00430 int actual_count;
00431 struct rt_tree_array *rt_tree_array;
00432 union tree *tp;
00433 union record *rp;
00434 int j;
00435 char *endp;
00436 struct bu_vls tmp_vls;
00437
00438 RT_CK_DB_INTERNAL( ip );
00439 RT_CK_RESOURCE(resp);
00440 if( ip->idb_type != ID_COMBINATION ) bu_bomb("rt_comb_export4() type not ID_COMBINATION");
00441 comb = (struct rt_comb_internal *)ip->idb_ptr;
00442 RT_CK_COMB(comb);
00443
00444 if( comb->tree && db_ck_v4gift_tree( comb->tree ) < 0 ) {
00445 db_non_union_push( comb->tree, resp );
00446 if( db_ck_v4gift_tree( comb->tree ) < 0 ) {
00447
00448 bu_log("rt_comb_export4() Unable to V4-ify tree, aborting.\n");
00449 rt_pr_tree( comb->tree, 0 );
00450 return -1;
00451 }
00452 }
00453
00454
00455 node_count = db_tree_nleaves( comb->tree );
00456 if( node_count > 0 ) {
00457 rt_tree_array = (struct rt_tree_array *)bu_calloc( node_count , sizeof( struct rt_tree_array ) , "rt_tree_array" );
00458
00459
00460 actual_count = db_flatten_tree( rt_tree_array, comb->tree,
00461 OP_UNION, 1, resp ) - rt_tree_array;
00462 BU_ASSERT_LONG( actual_count, ==, node_count );
00463 comb->tree = TREE_NULL;
00464 } else {
00465 rt_tree_array = (struct rt_tree_array *)NULL;
00466 actual_count = 0;
00467 }
00468
00469
00470 BU_INIT_EXTERNAL(ep);
00471 ep->ext_nbytes = sizeof(union record) * ( 1 + node_count );
00472 ep->ext_buf = bu_calloc( 1, ep->ext_nbytes, "v4 comb external" );
00473 rp = (union record *)ep->ext_buf;
00474
00475
00476 for( j = 0; j < node_count; j++ ) {
00477 tp = rt_tree_array[j].tl_tree;
00478 RT_CK_TREE(tp);
00479 if( tp->tr_op != OP_DB_LEAF ) bu_bomb("rt_comb_export4() tree not OP_DB_LEAF");
00480
00481 rp[j+1].u_id = ID_MEMB;
00482 switch( rt_tree_array[j].tl_op ) {
00483 case OP_INTERSECT:
00484 rp[j+1].M.m_relation = '+';
00485 break;
00486 case OP_SUBTRACT:
00487 rp[j+1].M.m_relation = '-';
00488 break;
00489 case OP_UNION:
00490 rp[j+1].M.m_relation = 'u';
00491 break;
00492 default:
00493 bu_bomb("rt_comb_export4() corrupt rt_tree_array");
00494 }
00495 strncpy( rp[j+1].M.m_instname, tp->tr_l.tl_name, NAMESIZE );
00496 if( tp->tr_l.tl_mat ) {
00497 rt_dbmat_mat( rp[j+1].M.m_mat, tp->tr_l.tl_mat );
00498 } else {
00499 rt_dbmat_mat( rp[j+1].M.m_mat, bn_mat_identity );
00500 }
00501 db_free_tree( tp, resp );
00502 }
00503
00504
00505 rp[0].u_id = ID_COMB;
00506
00507 if( comb->region_flag ) {
00508 rp[0].c.c_regionid = (short)comb->region_id;
00509 rp[0].c.c_aircode = (short)comb->aircode;
00510 rp[0].c.c_material = (short)comb->GIFTmater;
00511 rp[0].c.c_los = (short)comb->los;
00512 switch( comb->is_fastgen ) {
00513 case REGION_FASTGEN_PLATE:
00514 rp[0].c.c_flags = DBV4_REGION_FASTGEN_PLATE;
00515 break;
00516 case REGION_FASTGEN_VOLUME:
00517 rp[0].c.c_flags = DBV4_REGION_FASTGEN_VOLUME;
00518 break;
00519 default:
00520 case REGION_NON_FASTGEN:
00521 rp[0].c.c_flags = DBV4_REGION;
00522 break;
00523 }
00524 } else {
00525 rp[0].c.c_flags = DBV4_NON_REGION;
00526 }
00527 if( comb->rgb_valid ) {
00528 rp[0].c.c_override = 1;
00529 rp[0].c.c_rgb[0] = comb->rgb[0];
00530 rp[0].c.c_rgb[1] = comb->rgb[1];
00531 rp[0].c.c_rgb[2] = comb->rgb[2];
00532 }
00533
00534 bu_vls_init( &tmp_vls );
00535
00536
00537 if( bu_shader_to_key_eq( bu_vls_addr(&comb->shader), &tmp_vls ) )
00538 {
00539
00540 bu_log( "rt_comb_export4: Cannot convert following shader string to keyword=value format:\n" );
00541 bu_log( "\t%s\n", bu_vls_addr(&comb->shader) );
00542 rp[0].c.c_matparm[0] = '\0';
00543 rp[0].c.c_matname[0] = '\0';
00544 return -1;
00545 }
00546 else
00547 {
00548 endp = strchr( bu_vls_addr(&tmp_vls), ' ' );
00549 if( endp ) {
00550 int len;
00551 len = endp - bu_vls_addr(&tmp_vls);
00552 if( len <= 0 && bu_vls_strlen(&tmp_vls) > 0 ) {
00553 bu_log("WARNING: leading spaces on shader '%s' implies NULL shader\n",
00554 bu_vls_addr(&tmp_vls) );
00555 }
00556
00557 if( len >= sizeof(rp[0].c.c_matname) ) {
00558 bu_log("ERROR: Shader name '%s' exceeds v4 database field, aborting.\n",
00559 bu_vls_addr(&tmp_vls) );
00560 return -1;
00561 }
00562 if( strlen(endp+1) >= sizeof(rp[0].c.c_matparm) ) {
00563 bu_log("ERROR: Shader parameters '%s' exceed database field, aborting.\nUse \"dbupgrade\" to enable unlimited length strings.\n",
00564 endp+1);
00565 return -1;
00566 }
00567 strncpy( rp[0].c.c_matname, bu_vls_addr(&tmp_vls), len );
00568 strncpy( rp[0].c.c_matparm, endp+1, sizeof(rp[0].c.c_matparm) );
00569 } else {
00570 if( bu_vls_strlen(&tmp_vls) >= sizeof(rp[0].c.c_matname) ) {
00571 bu_log("ERROR: Shader name '%s' exceeds v4 database field, aborting.\n",
00572 bu_vls_addr(&tmp_vls) );
00573 return -1;
00574 }
00575 strncpy( rp[0].c.c_matname, bu_vls_addr(&tmp_vls), sizeof(rp[0].c.c_matname) );
00576 rp[0].c.c_matparm[0] = '\0';
00577 }
00578 }
00579 bu_vls_free( &tmp_vls );
00580
00581 rp[0].c.c_inherit = comb->inherit;
00582
00583 if( rt_tree_array ) bu_free( (char *)rt_tree_array, "rt_tree_array" );
00584
00585 return 0;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void
00595 db_tree_flatten_describe(
00596 struct bu_vls *vls,
00597 const union tree *tp,
00598 int indented,
00599 int lvl,
00600 double mm2local,
00601 struct resource *resp)
00602 {
00603 int node_count;
00604 struct rt_tree_array *rt_tree_array;
00605 int i;
00606 char op = OP_NOP;
00607 int status;
00608 union tree *ntp;
00609
00610 BU_CK_VLS(vls);
00611 RT_CK_RESOURCE(resp);
00612
00613 if( !tp )
00614 {
00615
00616 bu_vls_strcat( vls, "-empty-\n" );
00617 return;
00618 }
00619 RT_CK_TREE(tp);
00620
00621 node_count = db_tree_nleaves( tp );
00622 if( node_count <= 0 ) {
00623 if( !indented ) bu_vls_spaces( vls, 2*lvl );
00624 bu_vls_strcat( vls, "-empty-\n" );
00625 return;
00626 }
00627
00628
00629
00630
00631
00632
00633 ntp = db_dup_subtree( tp, resp );
00634 RT_CK_TREE(ntp);
00635
00636
00637 if( db_ck_v4gift_tree( ntp ) < 0 )
00638 db_non_union_push( ntp, resp );
00639 RT_CK_TREE(ntp);
00640
00641 node_count = db_tree_nleaves( ntp );
00642 rt_tree_array = (struct rt_tree_array *)bu_calloc( node_count , sizeof( struct rt_tree_array ) , "rt_tree_array" );
00643
00644
00645
00646
00647 (void)db_flatten_tree( rt_tree_array, ntp, OP_UNION, 0, resp );
00648
00649 for( i=0 ; i<node_count ; i++ )
00650 {
00651 union tree *itp = rt_tree_array[i].tl_tree;
00652
00653 RT_CK_TREE(itp);
00654 BU_ASSERT_LONG( itp->tr_op, ==, OP_DB_LEAF );
00655 BU_ASSERT_PTR( itp->tr_l.tl_name, !=, NULL );
00656
00657 switch (rt_tree_array[i].tl_op)
00658 {
00659 case OP_INTERSECT:
00660 op = '+';
00661 break;
00662 case OP_SUBTRACT:
00663 op = '-';
00664 break;
00665 case OP_UNION:
00666 op = 'u';
00667 break;
00668 default:
00669 bu_bomb("db_tree_flatten_describe() corrupt rt_tree_array");
00670 }
00671
00672 status = mat_categorize( itp->tr_l.tl_mat );
00673 if( !indented ) bu_vls_spaces( vls, 2*lvl );
00674 bu_vls_printf( vls, " %c %s", op, itp->tr_l.tl_name );
00675 if( status & STAT_ROT ) {
00676 fastf_t az, el;
00677 bn_ae_vec( &az, &el, itp->tr_l.tl_mat ?
00678 itp->tr_l.tl_mat : bn_mat_identity );
00679 bu_vls_printf( vls,
00680 " az=%g, el=%g, ",
00681 az, el );
00682 }
00683 if( status & STAT_XLATE ) {
00684 bu_vls_printf( vls, " [%g,%g,%g]",
00685 itp->tr_l.tl_mat[MDX]*mm2local,
00686 itp->tr_l.tl_mat[MDY]*mm2local,
00687 itp->tr_l.tl_mat[MDZ]*mm2local);
00688 }
00689 if( status & STAT_SCALE ) {
00690 bu_vls_printf( vls, " scale %g",
00691 1.0/itp->tr_l.tl_mat[15] );
00692 }
00693 if( status & STAT_PERSP ) {
00694 bu_vls_printf( vls,
00695 " Perspective=[%g,%g,%g]??",
00696 itp->tr_l.tl_mat[12],
00697 itp->tr_l.tl_mat[13],
00698 itp->tr_l.tl_mat[14] );
00699 }
00700 bu_vls_printf( vls, "\n" );
00701 }
00702
00703 if( rt_tree_array ) bu_free( (genptr_t)rt_tree_array, "rt_tree_array" );
00704 db_free_tree( ntp, resp );
00705 }
00706
00707
00708
00709
00710 void
00711 db_tree_describe(
00712 struct bu_vls *vls,
00713 const union tree *tp,
00714 int indented,
00715 int lvl,
00716 double mm2local)
00717 {
00718 int status;
00719
00720 BU_CK_VLS(vls);
00721
00722 if( !tp )
00723 {
00724
00725 bu_vls_strcat( vls, "-empty-\n" );
00726 return;
00727 }
00728 RT_CK_TREE(tp);
00729 switch( tp->tr_op ) {
00730
00731 case OP_DB_LEAF:
00732 status = mat_categorize( tp->tr_l.tl_mat );
00733
00734
00735 if( !indented ) bu_vls_spaces( vls, 2*lvl );
00736 bu_vls_strcat( vls, tp->tr_l.tl_name );
00737 if( status & STAT_ROT ) {
00738 fastf_t az, el;
00739 bn_ae_vec( &az, &el, tp->tr_l.tl_mat ?
00740 tp->tr_l.tl_mat : bn_mat_identity );
00741 bu_vls_printf( vls,
00742 " az=%g, el=%g, ",
00743 az, el );
00744 }
00745 if( status & STAT_XLATE ) {
00746 bu_vls_printf( vls, " [%g,%g,%g]",
00747 tp->tr_l.tl_mat[MDX]*mm2local,
00748 tp->tr_l.tl_mat[MDY]*mm2local,
00749 tp->tr_l.tl_mat[MDZ]*mm2local);
00750 }
00751 if( status & STAT_SCALE ) {
00752 bu_vls_printf( vls, " scale %g",
00753 1.0/tp->tr_l.tl_mat[15] );
00754 }
00755 if( status & STAT_PERSP ) {
00756 bu_vls_printf( vls,
00757 " Perspective=[%g,%g,%g]??",
00758 tp->tr_l.tl_mat[12],
00759 tp->tr_l.tl_mat[13],
00760 tp->tr_l.tl_mat[14] );
00761 }
00762 bu_vls_printf( vls, "\n" );
00763 return;
00764
00765
00766 case OP_UNION:
00767 if(!indented) bu_vls_spaces( vls, 2*lvl );
00768 bu_vls_strcat( vls, "u " );
00769 goto bin;
00770 case OP_INTERSECT:
00771 if(!indented) bu_vls_spaces( vls, 2*lvl );
00772 bu_vls_strcat( vls, "+ " );
00773 goto bin;
00774 case OP_SUBTRACT:
00775 if(!indented) bu_vls_spaces( vls, 2*lvl );
00776 bu_vls_strcat( vls, "- " );
00777 goto bin;
00778 case OP_XOR:
00779 if(!indented) bu_vls_spaces( vls, 2*lvl );
00780 bu_vls_strcat( vls, "^ " );
00781 bin:
00782 db_tree_describe( vls, tp->tr_b.tb_left, 1, lvl+1, mm2local );
00783 db_tree_describe( vls, tp->tr_b.tb_right, 0, lvl+1, mm2local );
00784 return;
00785
00786
00787 case OP_NOT:
00788 if(!indented) bu_vls_spaces( vls, 2*lvl );
00789 bu_vls_strcat( vls, "! " );
00790 goto unary;
00791 case OP_GUARD:
00792 if(!indented) bu_vls_spaces( vls, 2*lvl );
00793 bu_vls_strcat( vls, "G " );
00794 goto unary;
00795 case OP_XNOP:
00796 if(!indented) bu_vls_spaces( vls, 2*lvl );
00797 bu_vls_strcat( vls, "X " );
00798 unary:
00799 db_tree_describe( vls, tp->tr_b.tb_left, 1, lvl+1, mm2local );
00800 return;
00801
00802 case OP_NOP:
00803 if(!indented) bu_vls_spaces( vls, 2*lvl );
00804 bu_vls_strcat( vls, "NOP\n" );
00805 return;
00806
00807 default:
00808 bu_log("db_tree_describe: bad op %d\n", tp->tr_op);
00809 bu_bomb("db_tree_describe\n");
00810 }
00811 }
00812
00813
00814
00815
00816 void
00817 db_comb_describe(
00818 struct bu_vls *str,
00819 const struct rt_comb_internal *comb,
00820 int verbose,
00821 double mm2local,
00822 struct resource *resp)
00823 {
00824 RT_CK_COMB(comb);
00825 RT_CK_RESOURCE(resp);
00826
00827 if( comb->region_flag ) {
00828 bu_vls_printf( str,
00829 "REGION id=%d (air=%d, los=%d, GIFTmater=%d) ",
00830 comb->region_id,
00831 comb->aircode,
00832 comb->los,
00833 comb->GIFTmater );
00834
00835 if( comb->is_fastgen == REGION_FASTGEN_PLATE )
00836 bu_vls_printf( str, "(FASTGEN plate mode) " );
00837 else if( comb->is_fastgen == REGION_FASTGEN_VOLUME )
00838 bu_vls_printf( str, "(FASTGEN volume mode) " );
00839 }
00840
00841
00842 bu_vls_strcat( str, "--\n" );
00843 if( bu_vls_strlen(&comb->shader) > 0 ) {
00844 bu_vls_printf( str,
00845 "Shader '%s'\n",
00846 bu_vls_addr(&comb->shader) );
00847 }
00848
00849 if( comb->rgb_valid ) {
00850 bu_vls_printf( str,
00851 "Color %d %d %d\n",
00852 comb->rgb[0],
00853 comb->rgb[1],
00854 comb->rgb[2]);
00855 }
00856
00857 if( bu_vls_strlen(&comb->shader) > 0 || comb->rgb_valid ) {
00858 if( comb->inherit ) {
00859 bu_vls_strcat( str,
00860 "(These material properties override all lower ones in the tree)\n");
00861 }
00862 }
00863
00864 if( comb->tree ) {
00865 if( verbose ) {
00866 db_tree_flatten_describe( str, comb->tree, 0, 1, mm2local, resp );
00867 } else {
00868 rt_pr_tree_vls( str, comb->tree );
00869 }
00870 } else {
00871 bu_vls_strcat( str, "(empty tree)\n");
00872 }
00873 }
00874
00875
00876
00877
00878
00879
00880 void
00881 rt_comb_ifree( struct rt_db_internal *ip, struct resource *resp )
00882 {
00883 register struct rt_comb_internal *comb;
00884
00885 RT_CK_DB_INTERNAL(ip);
00886 RT_CK_RESOURCE(resp);
00887 comb = (struct rt_comb_internal *)ip->idb_ptr;
00888
00889 if (comb) {
00890
00891 if(comb->tree) db_free_tree( comb->tree, resp );
00892 comb->tree = NULL;
00893
00894 bu_vls_free( &comb->shader );
00895 bu_vls_free( &comb->material );
00896
00897 comb->magic = 0;
00898 bu_free( (genptr_t)comb, "comb ifree" );
00899 }
00900 ip->idb_ptr = GENPTR_NULL;
00901 }
00902
00903
00904
00905
00906
00907
00908
00909 int
00910 rt_comb_describe(
00911 struct bu_vls *str,
00912 const struct rt_db_internal *ip,
00913 int verbose,
00914 double mm2local,
00915 struct resource *resp,
00916 struct db_i *db_i)
00917 {
00918 const struct rt_comb_internal *comb;
00919
00920 RT_CK_DB_INTERNAL(ip);
00921 RT_CK_RESOURCE(resp);
00922
00923 comb = (struct rt_comb_internal *)ip->idb_ptr;
00924 RT_CK_COMB(comb);
00925
00926 db_comb_describe( str, comb, verbose, mm2local, resp );
00927 return 0;
00928 }
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 void
00940 db_wrap_v4_external( struct bu_external *op, const char *name )
00941 {
00942 union record *rec;
00943
00944 BU_CK_EXTERNAL(op);
00945
00946 rec = (union record *)op->ext_buf;
00947 NAMEMOVE( name, rec->s.s_name );
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963 int
00964 db_ck_left_heavy_tree(
00965 const union tree *tp,
00966 int no_unions)
00967 {
00968 RT_CK_TREE(tp);
00969 switch( tp->tr_op ) {
00970
00971 case OP_DB_LEAF:
00972 break;
00973
00974 case OP_UNION:
00975 if( no_unions ) return -1;
00976
00977 case OP_INTERSECT:
00978 case OP_SUBTRACT:
00979 case OP_XOR:
00980 if( db_ck_left_heavy_tree( tp->tr_b.tb_right, no_unions ) < 0 )
00981 return -1;
00982 return db_ck_left_heavy_tree( tp->tr_b.tb_left, no_unions );
00983
00984 default:
00985 bu_log("db_ck_left_heavy_tree: bad op %d\n", tp->tr_op);
00986 bu_bomb("db_ck_left_heavy_tree\n");
00987 }
00988 return 0;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 int
01008 db_ck_v4gift_tree( const union tree *tp )
01009 {
01010 RT_CK_TREE(tp);
01011 switch( tp->tr_op ) {
01012
01013 case OP_DB_LEAF:
01014 break;
01015
01016 case OP_UNION:
01017 if( db_ck_v4gift_tree( tp->tr_b.tb_left ) < 0 )
01018 return -1;
01019 return db_ck_v4gift_tree( tp->tr_b.tb_right );
01020
01021 case OP_INTERSECT:
01022 case OP_SUBTRACT:
01023 case OP_XOR:
01024 return db_ck_left_heavy_tree( tp, 1 );
01025
01026 default:
01027 bu_log("db_ck_v4gift_tree: bad op %d\n", tp->tr_op);
01028 bu_bomb("db_ck_v4gift_tree\n");
01029 }
01030 return 0;
01031 }
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 union tree *
01044 db_mkbool_tree(
01045 struct rt_tree_array *rt_tree_array,
01046 int howfar,
01047 struct resource *resp)
01048 {
01049 register struct rt_tree_array *tlp;
01050 register int i;
01051 register struct rt_tree_array *first_tlp = (struct rt_tree_array *)0;
01052 register union tree *xtp;
01053 register union tree *curtree;
01054 register int inuse;
01055
01056 RT_CK_RESOURCE(resp);
01057
01058 if( howfar <= 0 )
01059 return(TREE_NULL);
01060
01061
01062 for( i=howfar, inuse=0, tlp=rt_tree_array; i>0; i--, tlp++ ) {
01063 if( tlp->tl_tree == TREE_NULL )
01064 continue;
01065 if( inuse++ == 0 )
01066 first_tlp = tlp;
01067 }
01068
01069
01070 if( inuse <= 0 )
01071 return(TREE_NULL);
01072 if( inuse == 1 ) {
01073 curtree = first_tlp->tl_tree;
01074 first_tlp->tl_tree = TREE_NULL;
01075 return( curtree );
01076 }
01077
01078 if( first_tlp->tl_op != OP_UNION ) {
01079 first_tlp->tl_op = OP_UNION;
01080 if( RT_G_DEBUG & DEBUG_TREEWALK ) {
01081 bu_log("db_mkbool_tree() WARNING: non-union (%c) first operation ignored\n",
01082 first_tlp->tl_op );
01083 }
01084 }
01085
01086 curtree = first_tlp->tl_tree;
01087 first_tlp->tl_tree = TREE_NULL;
01088 tlp=first_tlp+1;
01089 for( i=howfar-(tlp-rt_tree_array); i>0; i--, tlp++ ) {
01090 if( tlp->tl_tree == TREE_NULL )
01091 continue;
01092
01093 RT_GET_TREE( xtp, resp );
01094 xtp->magic = RT_TREE_MAGIC;
01095 xtp->tr_b.tb_left = curtree;
01096 xtp->tr_b.tb_right = tlp->tl_tree;
01097 xtp->tr_b.tb_regionp = (struct region *)0;
01098 xtp->tr_op = tlp->tl_op;
01099 curtree = xtp;
01100 tlp->tl_tree = TREE_NULL;
01101 }
01102 return(curtree);
01103 }
01104
01105
01106
01107
01108 union tree *
01109 db_mkgift_tree(
01110 struct rt_tree_array *trees,
01111 int subtreecount,
01112 struct resource *resp)
01113 {
01114 register struct rt_tree_array *tstart;
01115 register struct rt_tree_array *tnext;
01116 union tree *curtree;
01117 int i;
01118 int j;
01119
01120 RT_CK_RESOURCE(resp);
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131 tstart = trees;
01132 tnext = trees+1;
01133 for( i=subtreecount-1; i>=0; i--, tnext++ ) {
01134
01135 if( i>0 && tnext->tl_op != OP_UNION )
01136 continue;
01137 if( (j = tnext-tstart) <= 0 )
01138 continue;
01139 curtree = db_mkbool_tree( tstart, j, resp );
01140
01141
01142
01143 tstart->tl_op = OP_UNION;
01144 tstart->tl_tree = curtree;
01145
01146 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01147 bu_log("db_mkgift_tree() intermediate term:\n");
01148 rt_pr_tree(tstart->tl_tree, 0);
01149 }
01150
01151
01152 tstart = tnext;
01153 }
01154
01155 curtree = db_mkbool_tree( trees, subtreecount, resp );
01156 if(RT_G_DEBUG&DEBUG_TREEWALK) {
01157 bu_log("db_mkgift_tree() returns:\n");
01158 rt_pr_tree(curtree, 0);
01159 }
01160 return( curtree );
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172