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 #ifndef lint
00039 static const char RCSanim[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_anim.c,v 14.11 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00040 #endif
00041
00042 #include "common.h"
00043
00044 #include <stdlib.h>
00045 #include <stdio.h>
00046 #ifdef HAVE_STRING_H
00047 # include <string.h>
00048 #else
00049 # include <strings.h>
00050 #endif
00051 #include <math.h>
00052
00053 #include "machine.h"
00054 #include "vmath.h"
00055 #include "bu.h"
00056 #include "raytrace.h"
00057 #include "./debug.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 int
00073 db_add_anim(struct db_i *dbip, register struct animate *anp, int root)
00074 {
00075 register struct animate **headp;
00076 struct directory *dp;
00077
00078
00079
00080 RT_CK_ANIMATE(anp);
00081 anp->an_forw = ANIM_NULL;
00082 if( root ) {
00083 if( RT_G_DEBUG&DEBUG_ANIM )
00084 bu_log("db_add_anim(x%x) root\n", anp);
00085 headp = &(dbip->dbi_anroot);
00086 } else {
00087 dp = DB_FULL_PATH_CUR_DIR(&anp->an_path);
00088 if( RT_G_DEBUG&DEBUG_ANIM )
00089 bu_log("db_add_anim(x%x) arc %s\n", anp,
00090 dp->d_namep);
00091 headp = &(dp->d_animate);
00092 }
00093
00094
00095 while( *headp != ANIM_NULL ) {
00096 RT_CK_ANIMATE(*headp);
00097 headp = &((*headp)->an_forw);
00098 }
00099 *headp = anp;
00100 return(0);
00101 }
00102
00103 static char *db_anim_matrix_strings[] = {
00104 "(nope)",
00105 "ANM_RSTACK",
00106 "ANM_RARC",
00107 "ANM_LMUL",
00108 "ANM_RMUL",
00109 "ANM_RBOTH",
00110 "eh?"
00111 };
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 int
00123 db_do_anim(register struct animate *anp, mat_t stack, mat_t arc, struct mater_info *materp)
00124 {
00125 mat_t temp;
00126
00127 if( RT_G_DEBUG&DEBUG_ANIM )
00128 bu_log("db_do_anim(x%x) ", anp);
00129 if( RT_G_DEBUG&DEBUG_ANIM && !materp ) bu_log("(null materp) ");
00130 RT_CK_ANIMATE(anp);
00131 switch( anp->an_type ) {
00132 case RT_AN_MATRIX:
00133 if( RT_G_DEBUG&DEBUG_ANIM ) {
00134 int op = anp->an_u.anu_m.anm_op;
00135 if( op < 0 ) op = 0;
00136 bu_log("matrix, op=%s (%d)\n",
00137 db_anim_matrix_strings[op], op);
00138 if( RT_G_DEBUG&DEBUG_ANIM_FULL ) {
00139 bn_mat_print("on original arc", arc);
00140 bn_mat_print("on original stack", stack);
00141 }
00142 }
00143 switch( anp->an_u.anu_m.anm_op ) {
00144 case ANM_RSTACK:
00145 MAT_COPY( stack, anp->an_u.anu_m.anm_mat );
00146 break;
00147 case ANM_RARC:
00148 MAT_COPY( arc, anp->an_u.anu_m.anm_mat );
00149 break;
00150 case ANM_RBOTH:
00151 MAT_COPY( stack, anp->an_u.anu_m.anm_mat );
00152 MAT_IDN( arc );
00153 break;
00154 case ANM_LMUL:
00155
00156 bn_mat_mul( temp, anp->an_u.anu_m.anm_mat, arc );
00157 MAT_COPY( arc, temp );
00158 break;
00159 case ANM_RMUL:
00160
00161 bn_mat_mul( temp, arc, anp->an_u.anu_m.anm_mat );
00162 MAT_COPY( arc, temp );
00163 break;
00164 default:
00165 return(-1);
00166 }
00167 if( RT_G_DEBUG&DEBUG_ANIM_FULL ) {
00168 bn_mat_print("arc result", arc);
00169 bn_mat_print("stack result", stack);
00170 }
00171 break;
00172 case RT_AN_MATERIAL:
00173 if( RT_G_DEBUG&DEBUG_ANIM )
00174 bu_log("property\n");
00175
00176
00177
00178
00179 if (!materp) {
00180 char *sofar = db_path_to_string(&anp->an_path);
00181 bu_log("ERROR db_do_anim(%s) property animation below region, ignored\n", sofar);
00182 bu_free(sofar, "path string");
00183 break;
00184 }
00185 if (anp->an_u.anu_p.anp_op == RT_ANP_REPLACE) {
00186 if( materp->ma_shader ) bu_free( (genptr_t)materp->ma_shader, "ma_shader" );
00187 materp->ma_shader = bu_vls_strdup(&anp->an_u.anu_p.anp_shader);
00188 } else if (anp->an_u.anu_p.anp_op == RT_ANP_APPEND) {
00189 struct bu_vls str;
00190
00191 bu_vls_init(&str);
00192 bu_vls_strcpy( &str, materp->ma_shader );
00193 bu_vls_putc( &str, ' ' );
00194 bu_vls_vlscat( &str, &anp->an_u.anu_p.anp_shader );
00195 if( materp->ma_shader ) bu_free( (genptr_t)materp->ma_shader, "ma_shader" );
00196 materp->ma_shader = bu_vls_strgrab( &str );
00197
00198 } else
00199 bu_log("Unknown anp_op=%d\n", anp->an_u.anu_p.anp_op);
00200 break;
00201 case RT_AN_COLOR:
00202 if( RT_G_DEBUG&DEBUG_ANIM )
00203 bu_log("color\n");
00204
00205
00206
00207
00208 if (!materp) {
00209 char *sofar = db_path_to_string(&anp->an_path);
00210 bu_log("ERROR db_do_anim(%s) color animation below region, ignored\n", sofar);
00211 bu_free(sofar, "path string");
00212 break;
00213 }
00214 materp->ma_color_valid = 1;
00215 materp->ma_color[0] =
00216 (((float)anp->an_u.anu_c.anc_rgb[0])+0.5)*bn_inv255;
00217 materp->ma_color[1] =
00218 (((float)anp->an_u.anu_c.anc_rgb[1])+0.5)*bn_inv255;
00219 materp->ma_color[2] =
00220 (((float)anp->an_u.anu_c.anc_rgb[2])+0.5)*bn_inv255;
00221 break;
00222 case RT_AN_TEMPERATURE:
00223 if( RT_G_DEBUG&DEBUG_ANIM )
00224 bu_log("temperature = %g\n", anp->an_u.anu_t);
00225 if (!materp) {
00226 char *sofar = db_path_to_string(&anp->an_path);
00227 bu_log("ERROR db_do_anim(%s) temperature animation below region, ignored\n", sofar);
00228 bu_free(sofar, "path string");
00229 break;
00230 }
00231 materp->ma_temperature = anp->an_u.anu_t;
00232 break;
00233 default:
00234 if( RT_G_DEBUG&DEBUG_ANIM )
00235 bu_log("unknown op\n");
00236
00237 return(-1);
00238 }
00239 return(0);
00240 }
00241
00242
00243
00244
00245
00246
00247 void
00248 db_free_1anim( struct animate *anp )
00249 {
00250 RT_CK_ANIMATE( anp );
00251
00252 switch( anp->an_type ) {
00253 case RT_AN_MATERIAL:
00254 bu_vls_free( &anp->an_u.anu_p.anp_shader );
00255 break;
00256 }
00257
00258 db_free_full_path( &anp->an_path );
00259 bu_free( (char *)anp, "animate");
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 void
00270 db_free_anim(register struct db_i *dbip)
00271 {
00272 register struct animate *anp;
00273 register struct directory *dp;
00274 register int i;
00275
00276
00277 for( anp = dbip->dbi_anroot; anp != ANIM_NULL; ) {
00278 register struct animate *nextanp;
00279 RT_CK_ANIMATE(anp);
00280 nextanp = anp->an_forw;
00281
00282 db_free_1anim( anp );
00283 anp = nextanp;
00284 }
00285 dbip->dbi_anroot = ANIM_NULL;
00286
00287
00288 for( i=0; i < RT_DBNHASH; i++ ) {
00289 dp = dbip->dbi_Head[i];
00290 for( ; dp != DIR_NULL; dp = dp->d_forw ) {
00291 for( anp = dp->d_animate; anp != ANIM_NULL; ) {
00292 register struct animate *nextanp;
00293 RT_CK_ANIMATE(anp);
00294 nextanp = anp->an_forw;
00295
00296 db_free_1anim( anp );
00297 anp = nextanp;
00298 }
00299 dp->d_animate = ANIM_NULL;
00300 }
00301 }
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311 struct animate *
00312 db_parse_1anim(struct db_i *dbip, int argc, const char *argv[])
00313 {
00314 struct db_tree_state ts;
00315 struct animate *anp;
00316 int i;
00317
00318 BU_GETSTRUCT( anp, animate );
00319 anp->magic = ANIMATE_MAGIC;
00320
00321 db_init_db_tree_state( &ts, dbip, &rt_uniresource );
00322 db_full_path_init( &anp->an_path );
00323 if( db_follow_path_for_state( &ts, &(anp->an_path), argv[1], LOOKUP_NOISY ) < 0 )
00324 goto bad;
00325
00326 if( strcmp( argv[2], "matrix" ) == 0 ) {
00327 anp->an_type = RT_AN_MATRIX;
00328 if( strcmp( argv[3], "rstack" ) == 0 )
00329 anp->an_u.anu_m.anm_op = ANM_RSTACK;
00330 else if( strcmp( argv[3], "rarc" ) == 0 )
00331 anp->an_u.anu_m.anm_op = ANM_RARC;
00332 else if( strcmp( argv[3], "lmul" ) == 0 )
00333 anp->an_u.anu_m.anm_op = ANM_LMUL;
00334 else if( strcmp( argv[3], "rmul" ) == 0 )
00335 anp->an_u.anu_m.anm_op = ANM_RMUL;
00336 else if( strcmp( argv[3], "rboth" ) == 0 )
00337 anp->an_u.anu_m.anm_op = ANM_RBOTH;
00338 else {
00339 bu_log("db_parse_1anim: Matrix op '%s' unknown\n",
00340 argv[3]);
00341 goto bad;
00342 }
00343
00344 if( strcmp( argv[4], "translate" ) == 0 ||
00345 strcmp( argv[4], "xlate" ) == 0 ) {
00346 if( argc < 5+2 ) {
00347 bu_log("db_parse_1anim: matrix %s translate does not have enough arguments, only %d\n",
00348 argv[3], argc );
00349 goto bad;
00350 }
00351 MAT_IDN( anp->an_u.anu_m.anm_mat );
00352 MAT_DELTAS( anp->an_u.anu_m.anm_mat,
00353 atof( argv[5+0] ),
00354 atof( argv[5+1] ),
00355 atof( argv[5+2] ) );
00356 } else if( strcmp( argv[4], "rot" ) == 0 ) {
00357 if( argc < 5+2 ) {
00358 bu_log("db_parse_1anim: matrix %s rot does not have enough arguments, only %d\n",
00359 argv[3], argc );
00360 goto bad;
00361 }
00362 MAT_IDN( anp->an_u.anu_m.anm_mat );
00363 bn_mat_angles( anp->an_u.anu_m.anm_mat,
00364 atof( argv[5+0] ),
00365 atof( argv[5+1] ),
00366 atof( argv[5+2] ) );
00367 } else if( strcmp( argv[4], "scale" ) == 0 ) {
00368 fastf_t scale;
00369 if( argc < 5+0 ) {
00370 bu_log("db_parse_1anim: matrix %s scale does not have enough arguments, only %d\n",
00371 argv[3], argc );
00372 goto bad;
00373 }
00374 scale = atof( argv[5+3] );
00375 if( NEAR_ZERO( scale, SMALL ) ) {
00376 bu_log("db_parse_1anim: matrix %s scale factor is zero\n",
00377 argv[3] );
00378 goto bad;
00379 }
00380 MAT_IDN( anp->an_u.anu_m.anm_mat );
00381 anp->an_u.anu_m.anm_mat[15] = 1/scale;
00382 } else if( strcmp( argv[4], "scale_about" ) == 0 ) {
00383 point_t pt;
00384 fastf_t scale;
00385 if( argc < 5+3 ) {
00386 bu_log("db_parse_1anim: matrix %s scale_about does not have enough arguments, only %d\n",
00387 argv[3], argc );
00388 goto bad;
00389 }
00390 VSET( pt,
00391 atof( argv[5+0] ),
00392 atof( argv[5+1] ),
00393 atof( argv[5+2] ) );
00394 scale = atof( argv[5+3] );
00395 if( bn_mat_scale_about_pt( anp->an_u.anu_m.anm_mat,
00396 pt, scale ) < 0 ) {
00397 bu_log("db_parse_1anim: matrix %s scale_about (%g, %g, %g) scale=%g failed\n",
00398 argv[3], V3ARGS(pt), scale );
00399 goto bad;
00400 }
00401 } else {
00402
00403 for( i=0; i<16; i++ )
00404 anp->an_u.anu_m.anm_mat[i] = atof( argv[i+4] );
00405 }
00406 } else if( strcmp( argv[2], "material" ) == 0 ) {
00407 anp->an_type = RT_AN_MATERIAL;
00408 bu_vls_init( &anp->an_u.anu_p.anp_shader );
00409 if( (strcmp( argv[3], "replace" ) == 0) ||
00410 (strcmp( argv[3], "rboth" ) == 0) ) {
00411 bu_vls_from_argv( &anp->an_u.anu_p.anp_shader,
00412 argc-4, (const char **)&argv[4] );
00413 anp->an_u.anu_p.anp_op = RT_ANP_REPLACE;
00414 } else if( strcmp( argv[3], "append" ) == 0 ) {
00415 bu_vls_from_argv( &anp->an_u.anu_p.anp_shader,
00416 argc-4, (const char **)&argv[4] );
00417 anp->an_u.anu_p.anp_op = RT_ANP_APPEND;
00418 } else {
00419 bu_log("db_parse_1anim: material animation '%s' unknown\n",
00420 argv[3]);
00421 goto bad;
00422 }
00423 } else if( strcmp( argv[2], "color" ) == 0 ) {
00424 anp->an_type = RT_AN_COLOR;
00425 anp->an_u.anu_c.anc_rgb[0] = atoi( argv[3+0] );
00426 anp->an_u.anu_c.anc_rgb[1] = atoi( argv[3+1] );
00427 anp->an_u.anu_c.anc_rgb[2] = atoi( argv[3+2] );
00428 } else if( strcmp( argv[2], "temperature" ) == 0 ||
00429 strcmp( argv[2], "temp" ) == 0 ) {
00430 anp->an_type = RT_AN_TEMPERATURE;
00431 anp->an_u.anu_t = atof( argv[3] );
00432 } else {
00433 bu_log("db_parse_1anim: animation type '%s' unknown\n", argv[2]);
00434 goto bad;
00435 }
00436 db_free_db_tree_state( &ts );
00437 return anp;
00438 bad:
00439 db_free_db_tree_state( &ts );
00440 db_free_1anim( anp );
00441 return (struct animate *)NULL;
00442 }
00443
00444
00445
00446
00447
00448
00449
00450
00451 int db_parse_anim(struct db_i *dbip,
00452 int argc,
00453 const char **argv)
00454 {
00455 struct animate *anp;
00456 int at_root = 0;
00457
00458 if( !(anp = db_parse_1anim( dbip, argc, argv )) )
00459 return -1;
00460
00461 if( argv[1][0] == '/' )
00462 at_root = 1;
00463
00464 if( anp->an_path.fp_len > 1 )
00465 at_root = 0;
00466
00467 if( db_add_anim( dbip, anp, at_root ) < 0 ) {
00468 return -1;
00469 }
00470 return 0;
00471 }
00472 void
00473 db_write_anim(FILE *fop, struct animate *anp)
00474 {
00475 char *thepath;
00476 int i;
00477
00478 RT_CK_ANIMATE(anp);
00479
00480 thepath = db_path_to_string(&(anp->an_path));
00481 if ( RT_G_DEBUG&DEBUG_ANIM) {
00482 bu_log("db_write_anim: Writing %s\n", thepath);
00483 }
00484
00485 fprintf(fop,"anim %s ", thepath);
00486 bu_free(thepath, "path string");
00487
00488 switch (anp->an_type) {
00489 case RT_AN_MATRIX:
00490 fputs("matrix ",fop);
00491 switch (anp->an_u.anu_m.anm_op) {
00492 case ANM_RSTACK:
00493 fputs("rstack\n", fop);
00494 break;
00495 case ANM_RARC:
00496 fputs("rarc\n", fop);
00497 break;
00498 case ANM_LMUL:
00499 fputs("lmul\n", fop);
00500 break;
00501 case ANM_RMUL:
00502 fputs("rmul\n", fop);
00503 break;
00504 case ANM_RBOTH:
00505 fputs("rboth\n", fop);
00506 break;
00507 default:
00508 fputs("unknown\n",fop);
00509 bu_log("db_write_anim: unknown matrix operation\n");
00510 }
00511 for (i=0; i<16; i++) {
00512 fprintf(fop, " %.15e", anp->an_u.anu_m.anm_mat[i]);
00513 if ((i == 15) || ((i&3) == 3)) {
00514 fputs("\n",fop);
00515 }
00516 }
00517 break;
00518 case RT_AN_MATERIAL:
00519 fputs("material ",fop);
00520 switch (anp->an_u.anu_p.anp_op) {
00521 case RT_ANP_REPLACE:
00522 fputs("replace ", fop);
00523 break;
00524 case RT_ANP_APPEND:
00525 fputs("append ", fop);
00526 break;
00527 default:
00528 bu_log("db_write_anim: unknown property operation.\n");
00529 break;
00530 }
00531 break;
00532 case RT_AN_COLOR:
00533 fprintf(fop,"color %d %d %d", anp->an_u.anu_c.anc_rgb[0],
00534 anp->an_u.anu_c.anc_rgb[1], anp->an_u.anu_c.anc_rgb[2]);
00535 break;
00536 case RT_AN_SOLID:
00537 break;
00538 default:
00539 bu_log("db_write_anim: Unknown animate type.\n");
00540 }
00541 fputs(";\n", fop);
00542 return;
00543 }
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554