Panda3D
|
00001 // Filename: soft2Egg.c 00002 // Created by: masad (26Sep03) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 //////////////////////////////////////////////////////////////////// 00016 // Includes 00017 //////////////////////////////////////////////////////////////////// 00018 00019 #include <SAA.h> 00020 00021 #ifdef __cplusplus 00022 extern "C" { 00023 #endif 00024 00025 #include "pandatoolbase.h" 00026 00027 int init_soft2egg(int, char **); 00028 00029 #if 0 00030 // DWD includes 00031 #include "eggBase.h" 00032 #include <eggParametrics.h> 00033 #include <animTable.h> 00034 #include <linMathOutput.h> 00035 00036 // system includes 00037 #include <fstream.h> 00038 #include <strstream.h> 00039 #include <math.h> 00040 #include <assert.h> 00041 #include <unistd.h> 00042 #include <ieeefp.h> 00043 00044 // Performer includes 00045 #include <Performer/pr/pfLinMath.h> 00046 00047 // SoftImage includes 00048 #include <SAA.h> 00049 #include <SI_macros.h> 00050 00051 static const int TEX_PER_MAT = 1; 00052 static FILE *outStream = stdout; 00053 //static FILE *outStream = stderr; 00054 00055 class soft2egg : public EggBase 00056 { 00057 public: 00058 00059 soft2egg() : EggBase("r:d:s:m:t:P:b:e:f:T:S:M:A:N:v:o:FhknpaxiucCD") 00060 { 00061 rsrc_path = "/ful/ufs/soft371_mips2/3D/rsrc"; 00062 database_name = NULL; 00063 scene_name = NULL; 00064 model_name = NULL; 00065 animFileName = NULL; 00066 eggFileName = NULL; 00067 tex_path = NULL; 00068 eggGroupName = NULL; 00069 tex_filename = NULL; 00070 search_prefix = NULL; 00071 result = SI_SUCCESS; 00072 00073 skeleton = new EggGroup(); 00074 foundRoot = FALSE; 00075 animRoot = NULL; 00076 morphRoot = NULL; 00077 geom_as_joint = 0; 00078 make_anim = 0; 00079 make_nurbs = 0; 00080 make_poly = 0; 00081 make_soft = 0; 00082 make_morph = 1; 00083 make_duv = 1; 00084 make_dart = TRUE; 00085 has_morph = 0; 00086 make_pose = 0; 00087 animData.is_z_up = FALSE; 00088 nurbs_step = 1; 00089 anim_start = -1000; 00090 anim_end = -1000; 00091 anim_rate = 24; 00092 pose_frame = -1; 00093 verbose = 0; 00094 flatten = 0; 00095 shift_textures = 0; 00096 ignore_tex_offsets = 0; 00097 use_prefix = 0; 00098 } 00099 00100 virtual void Help(); 00101 virtual void Usage(); 00102 virtual void ShowOpts(); 00103 00104 virtual boolean UseOutputSwitch() const { 00105 return false; 00106 } 00107 00108 virtual boolean 00109 HandleGetopts(char flag, char *optarg, int &optind, int argc, char **argv); 00110 00111 int isNum( float ); 00112 char *GetRootName( const char * ); 00113 char *RemovePathName( const char * ); 00114 char *GetSliderName( const char * ); 00115 char *GetFullName( SAA_Scene *, SAA_Elem * ); 00116 char *GetName( SAA_Scene *, SAA_Elem * ); 00117 char *GetModelNoteInfo( SAA_Scene *, SAA_Elem * ); 00118 char *MakeTableName( const char *, int ); 00119 char *DepointellizeName( char * ); 00120 SAA_Elem *FindModelByName( char *, SAA_Scene *, SAA_Elem *, int ); 00121 char *ConvertTexture( SAA_Scene *, SAA_Elem * ); 00122 int *FindClosestTriVert( EggVertexPool *, SAA_DVector *, int ); 00123 int *MakeIndexMap( int *, int, int ); 00124 int findShapeVert( SAA_DVector, SAA_DVector *, int ); 00125 void LoadSoft(); 00126 void MakeEgg( EggGroup *, EggJoint *, AnimGroup *, SAA_Scene *, SAA_Elem * ); 00127 void MakeSurfaceCurve( SAA_Scene *, SAA_Elem *, EggGroup *, 00128 EggNurbsSurface *&, int , SAA_SubElem *, bool ); 00129 00130 EggNurbsCurve *MakeUVNurbsCurve( int, long *, double *, double *, 00131 EggGroup *, char * ); 00132 00133 EggNurbsCurve *MakeNurbsCurve( SAA_Scene *, SAA_Elem *, EggGroup *, 00134 float [4][4], char * ); 00135 00136 void AddKnots( perf_vector<double> &, double *, int, SAA_Boolean, int ); 00137 void MakeJoint( SAA_Scene *, EggJoint *&, AnimGroup *&, SAA_Elem *, char * ); 00138 void MakeSoftSkin( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, char * ); 00139 void CleanUpSoftSkin( SAA_Scene *, SAA_Elem *, char * ); 00140 void MakeAnimTable( SAA_Scene *, SAA_Elem *, char * ); 00141 void MakeVertexOffsets( SAA_Scene *, SAA_Elem *, SAA_ModelType type, 00142 int, int, SAA_DVector *, float (*)[4], char * ); 00143 void MakeMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, char *, 00144 float ); 00145 void MakeLinearMorphTable( SAA_Scene *, SAA_Elem *, int, char *, float ); 00146 void MakeWeightedMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, 00147 int, char *, float ); 00148 void MakeExpressionMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, 00149 int, char *, float ); 00150 void MakeTexAnim( SAA_Scene *, SAA_Elem *, char * ); 00151 00152 private: 00153 00154 char *rsrc_path; 00155 char *database_name; 00156 char *scene_name; 00157 char *model_name; 00158 char *eggFileName; 00159 char *animFileName; 00160 char *eggGroupName; 00161 char *tex_path; 00162 char *tex_filename; 00163 char *search_prefix; 00164 00165 SI_Error result; 00166 SAA_Scene scene; 00167 SAA_Elem model; 00168 SAA_Database database; 00169 EggGroup *dart; 00170 EggGroup *skeleton; 00171 AnimGroup *rootAnim; 00172 EggJoint *rootJnt; 00173 AnimGroup *animRoot; 00174 AnimGroup *morphRoot; 00175 EggData animData; 00176 00177 int nurbs_step; 00178 int anim_start; 00179 int anim_end; 00180 int anim_rate; 00181 int pose_frame; 00182 int verbose; 00183 int flatten; 00184 int shift_textures; 00185 int ignore_tex_offsets; 00186 int use_prefix; 00187 00188 bool foundRoot; 00189 bool geom_as_joint; 00190 bool make_anim; 00191 bool make_nurbs; 00192 bool make_poly; 00193 bool make_soft; 00194 bool make_morph; 00195 bool make_duv; 00196 bool make_dart; 00197 bool has_morph; 00198 bool make_pose; 00199 00200 ofstream eggFile; 00201 ofstream animFile; 00202 ofstream texFile; 00203 00204 }; 00205 00206 00207 //////////////////////////////////////////////////////////////////// 00208 // Function: Help 00209 // Access: Public, Virtual 00210 // Description: Displays the "what is this program" message, along 00211 // with the usage message. Should be overridden in base 00212 // classes to describe the current program. 00213 //////////////////////////////////////////////////////////////////// 00214 void soft2egg:: 00215 Help() 00216 { 00217 cerr << 00218 "soft2egg takes a SoftImage scene or model\n" 00219 "and outputs its contents as an egg file\n"; 00220 00221 Usage(); 00222 } 00223 00224 //////////////////////////////////////////////////////////////////// 00225 // Function: Usage 00226 // Access: Public, Virtual 00227 // Description: Displays the usage message. 00228 //////////////////////////////////////////////////////////////////// 00229 void soft2egg:: 00230 Usage() { 00231 cerr << "\nUsage:\n" 00232 << _commandName << " [opts] (must specify -m or -s)\n\n" 00233 << "Options:\n"; 00234 00235 ShowOpts(); 00236 cerr << "\n"; 00237 } 00238 00239 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: ShowOpts 00243 // Access: Public, Virtual 00244 // Description: Displays the valid options. Should be extended in 00245 // base classes to show additional options relevant to 00246 // the current program. 00247 //////////////////////////////////////////////////////////////////// 00248 void soft2egg:: 00249 ShowOpts() 00250 { 00251 cerr << 00252 " -r <path> - Used to provide soft with the resource\n" 00253 " Defaults to 'c:/Softimage/SOFT_3.9.2/3D/test'.\n" 00254 // " Defaults to '/ful/ufs/soft371_mips2/3D/rsrc'.\n" 00255 " -d <path> - Database path.\n" 00256 " -s <scene> - Indicates that a scene will be converted.\n" 00257 " -m <model> - Indicates that a model will be converted.\n" 00258 " -t <path> - Specify path to place converted textures.\n" 00259 " -T <name> - Specify filename for texture map listing.\n" 00260 " -S <step> - Specify step for nurbs surface triangulation.\n" 00261 " -M <name> - Specify model output filename. Defaults to scene name.\n" 00262 " -A <name> - Specify anim output filename. Defaults to scene name.\n" 00263 " -N <name> - Specify egg group name.\n" 00264 " -k - Enable soft assignment for geometry.\n" 00265 " -n - Specify egg NURBS representation instead of poly's.\n" 00266 " -p - Specify egg polygon output for geometry.\n" 00267 " -P <frame> - Specify frame number for static pose.\n" 00268 " -b <frame> - Specify starting frame for animation (default = first).\n" 00269 " -e <frame> - Specify ending frame for animation (default = last).\n" 00270 " -f <fps> - Specify frame rate for animation playback.\n" 00271 " -a - Compile animation tables if animation present.\n" 00272 " -F - Ignore hierarchy and build a completely flat skeleton.\n" 00273 " -v <level> - Set debug level.\n" 00274 " -x - Shift NURBS parameters to preserve Alias textures.\n" 00275 " -i - Ignore Soft texture uv offsets.\n" 00276 " -u - Use Soft prefix in model names.\n" 00277 " -c - Cancel morph conversion.\n" 00278 " -C - Cancel duv conversion.\n" 00279 " -D - Don't make the output model a character.\n" 00280 " -o <prefix>- Convert only models with given prefix.\n"; 00281 00282 EggBase::ShowOpts(); 00283 } 00284 00285 00286 //////////////////////////////////////////////////////////////////// 00287 // Function: HandleGetopts 00288 // Access: Public, Virtual 00289 // Description: 00290 //////////////////////////////////////////////////////////////////// 00291 boolean soft2egg:: 00292 HandleGetopts(char flag, char *optarg, int &optind, int argc, char **argv) 00293 { 00294 boolean okflag = true; 00295 00296 switch (flag) 00297 { 00298 case 'r': // Set the resource path for soft. 00299 if ( strcmp( optarg, "" ) ) 00300 { 00301 // Get the path. 00302 rsrc_path = optarg; 00303 fprintf( outStream, "using rsrc path %s\n", rsrc_path ); 00304 } 00305 break; 00306 00307 case 'd': // Set the database path. 00308 if ( strcmp( optarg, "" ) ) 00309 { 00310 // Get the path. 00311 database_name = optarg; 00312 fprintf( outStream, "using database %s\n", database_name ); 00313 } 00314 break; 00315 00316 case 's': // Check if its a scene. 00317 if ( strcmp( optarg, "" ) ) 00318 { 00319 // Get scene name. 00320 scene_name = optarg; 00321 fprintf( outStream, "loading scene %s\n", scene_name ); 00322 } 00323 break; 00324 00325 case 'm': // Check if its a model. 00326 if ( strcmp( optarg, "" ) ) 00327 { 00328 // Get model name. 00329 model_name = optarg; 00330 fprintf( outStream, "loading model %s\n", model_name ); 00331 } 00332 break; 00333 00334 case 't': // Get converted texture path. 00335 if ( strcmp( optarg, "" ) ) 00336 { 00337 // Get tex path name. 00338 tex_path = optarg; 00339 fprintf( outStream, "texture path: %s\n", tex_path ); 00340 } 00341 break; 00342 00343 case 'T': // Specify texture list filename. 00344 if ( strcmp( optarg, "") ) 00345 { 00346 // Get the name. 00347 tex_filename = optarg; 00348 fprintf( outStream, "creating texture list file: %s\n", 00349 tex_filename ); 00350 } 00351 break; 00352 case 'S': // Set NURBS step. 00353 if ( strcmp( optarg, "" ) ) 00354 { 00355 nurbs_step = atoi(optarg); 00356 fprintf( outStream, "NURBS step: %d\n", nurbs_step ); 00357 } 00358 break; 00359 00360 case 'M': // Set model output file name. 00361 if ( strcmp( optarg, "" ) ) 00362 { 00363 eggFileName = optarg; 00364 fprintf( outStream, "Model output filename: %s\n", eggFileName ); 00365 } 00366 break; 00367 00368 case 'A': // Set anim output file name. 00369 if ( strcmp( optarg, "" ) ) 00370 { 00371 animFileName = optarg; 00372 fprintf( outStream, "Anim output filename: %s\n", animFileName ); 00373 } 00374 break; 00375 00376 case 'N': // Set egg model name. 00377 if ( strcmp( optarg, "" ) ) 00378 { 00379 eggGroupName = optarg; 00380 fprintf( outStream, "Egg group name: %s\n", eggGroupName ); 00381 } 00382 break; 00383 00384 case 'o': // Set search_prefix. 00385 if ( strcmp( optarg, "" ) ) 00386 { 00387 search_prefix = optarg; 00388 fprintf( outStream, "Only converting models with prefix: %s\n", 00389 search_prefix ); 00390 } 00391 break; 00392 00393 case 'h': // print help message 00394 Help(); 00395 exit(1); 00396 break; 00397 00398 case 'c': // Cancel morph animation conversion 00399 make_morph = FALSE; 00400 fprintf( outStream, "canceling morph conversion\n" ); 00401 break; 00402 00403 case 'C': // Cancel uv animation conversion 00404 make_duv = FALSE; 00405 fprintf( outStream, "canceling uv animation conversion\n" ); 00406 break; 00407 00408 case 'D': // Omit the Dart flag 00409 make_dart = FALSE; 00410 fprintf( outStream, "making a non-character model\n" ); 00411 break; 00412 00413 case 'k': // Enable soft skinning 00414 //make_soft = TRUE; 00415 //fprintf( outStream, "enabling soft skinning\n" ); 00416 fprintf( outStream, "-k flag no longer necessary\n" ); 00417 break; 00418 00419 case 'n': // Generate egg NURBS output 00420 make_nurbs = TRUE; 00421 fprintf( outStream, "outputting egg NURBS info\n" ); 00422 break; 00423 00424 case 'p': // Generate egg polygon output 00425 make_poly = TRUE; 00426 fprintf( outStream, "outputting egg polygon info\n" ); 00427 break; 00428 00429 case 'P': // Generate static pose from given frame 00430 if ( strcmp( optarg, "" ) ) 00431 { 00432 make_pose = TRUE; 00433 pose_frame = atoi(optarg); 00434 fprintf( outStream, "generating static pose from frame %d\n", 00435 pose_frame ); 00436 } 00437 break; 00438 00439 case 'a': // Compile animation tables. 00440 make_anim = TRUE; 00441 fprintf( outStream, "attempting to compile anim tables\n" ); 00442 break; 00443 00444 case 'F': // Build a flat skeleton. 00445 flatten = TRUE; 00446 fprintf( outStream, "building a flat skeleton!!!\n" ); 00447 break; 00448 00449 case 'x': // Shift NURBS parameters to preserve Alias textures. 00450 shift_textures = TRUE; 00451 fprintf( outStream, "shifting NURBS parameters...\n" ); 00452 break; 00453 00454 case 'i': // Ignore Soft uv texture offsets 00455 ignore_tex_offsets = TRUE; 00456 fprintf( outStream, "ignoring texture offsets...\n" ); 00457 break; 00458 00459 case 'u': // Use Soft prefix in model names 00460 use_prefix = TRUE; 00461 fprintf( outStream, "using prefix in model names...\n" ); 00462 break; 00463 00464 00465 case 'v': // print debug messages. 00466 if ( strcmp( optarg, "" ) ) 00467 { 00468 verbose = atoi(optarg); 00469 fprintf( outStream, "using debug level %d\n", verbose ); 00470 } 00471 break; 00472 00473 case 'b': // Set animation start frame. 00474 if ( strcmp( optarg, "" ) ) 00475 { 00476 anim_start = atoi(optarg); 00477 fprintf( outStream, "animation starting at frame: %d\n", 00478 anim_start ); 00479 } 00480 break; 00481 00482 case 'e': /// Set animation end frame. 00483 if ( strcmp( optarg, "" ) ) 00484 { 00485 anim_end = atoi(optarg); 00486 fprintf( outStream, "animation ending at frame: %d\n", anim_end ); 00487 } 00488 break; 00489 00490 case 'f': /// Set animation frame rate. 00491 if ( strcmp( optarg, "" ) ) 00492 { 00493 anim_rate = atoi(optarg); 00494 fprintf( outStream, "animation frame rate: %d\n", anim_rate ); 00495 } 00496 break; 00497 00498 default: 00499 okflag = EggBase::HandleGetopts(flag, optarg, optind, argc, argv); 00500 } 00501 00502 return (okflag); 00503 } 00504 00505 00506 00507 //////////////////////////////////////////////////////////////////// 00508 // Function: isNum 00509 // Access: Public, Virtual 00510 // Description: Take a float and make sure it is of the body. 00511 //////////////////////////////////////////////////////////////////// 00512 int soft2egg:: 00513 isNum( float num ) 00514 { 00515 return( ( num < HUGE_VAL ) && finite( num ) ); 00516 } 00517 00518 00519 //////////////////////////////////////////////////////////////////// 00520 // Function: GetRootName 00521 // Access: Public 00522 // Description: Given a string, return a copy of the string up to 00523 // the first occurence of '-'. 00524 //////////////////////////////////////////////////////////////////// 00525 char *soft2egg:: 00526 GetRootName( const char *name ) 00527 { 00528 char *hyphen; 00529 char *root; 00530 int len; 00531 00532 hyphen = strchr( name, '-' ); 00533 len = hyphen-name; 00534 00535 if ( (hyphen != NULL) && len ) 00536 { 00537 root = (char *)malloc(sizeof(char)*(len+1)); 00538 strncpy( root, name, len ); 00539 root[sizeof(char)*(len)] = '\0'; 00540 } 00541 else 00542 { 00543 root = (char *)malloc( sizeof(char)*(strlen(name)+1)); 00544 strcpy( root, name ); 00545 } 00546 00547 return( root ); 00548 } 00549 00550 00551 //////////////////////////////////////////////////////////////////// 00552 // Function: RemovePathName 00553 // Access: Public 00554 // Description: Given a string, return a copy of the string after 00555 // the last occurence of '/ 00556 //////////////////////////////////////////////////////////////////// 00557 char *soft2egg:: 00558 RemovePathName( const char *name ) 00559 { 00560 char *slash; 00561 char *root; 00562 00563 if ( *name != NULL ) 00564 { 00565 slash = strrchr( name, '/' ); 00566 00567 root = (char *)malloc( sizeof(char)*(strlen(name)+1)); 00568 00569 if ( slash != NULL ) 00570 strcpy( root, ++slash ); 00571 else 00572 strcpy( root, name ); 00573 00574 return( root ); 00575 } 00576 00577 fprintf( stderr, "Error: RemovePathName received NULL string!\n" ); 00578 return ( (char *)name ); 00579 } 00580 00581 //////////////////////////////////////////////////////////////////// 00582 // Function: GetSliderName 00583 // Access: Public 00584 // Description: Given a string, return that part of the string after 00585 // the first occurence of '-' and before the last 00586 // occurance of '.' 00587 //////////////////////////////////////////////////////////////////// 00588 char *soft2egg:: 00589 GetSliderName( const char *name ) 00590 { 00591 if ( name != NULL ) 00592 { 00593 strstream newStr; 00594 char *hyphen; 00595 char *end; 00596 00597 hyphen = strchr( name, '-' ); 00598 00599 // pull off stuff before first hyphen 00600 if (hyphen != NULL) 00601 { 00602 newStr << ++hyphen; 00603 end = newStr.str(); 00604 } 00605 00606 char *lastPeriod; 00607 00608 lastPeriod = strrchr( end, '.' ); 00609 00610 // ignore stuff after last period 00611 if ( lastPeriod != NULL ) 00612 { 00613 *lastPeriod = '\0'; 00614 } 00615 00616 if ( verbose >= 1 ) 00617 fprintf( stdout, "slider name: '%s'\n", end ); 00618 00619 return( end ); 00620 } 00621 00622 return( (char *)name ); 00623 } 00624 00625 //////////////////////////////////////////////////////////////////// 00626 // Function: GetName 00627 // Access: Public 00628 // Description: Given an element, return a copy of the element's 00629 // name WITHOUT prefix. 00630 //////////////////////////////////////////////////////////////////// 00631 char *soft2egg:: 00632 GetName( SAA_Scene *scene, SAA_Elem *element ) 00633 { 00634 int nameLen; 00635 char *name; 00636 00637 // get the name 00638 SAA_elementGetNameLength( scene, element, &nameLen ); 00639 name = (char *)malloc(sizeof(char)*++nameLen); 00640 SAA_elementGetName( scene, element, nameLen, name ); 00641 00642 return name; 00643 } 00644 00645 //////////////////////////////////////////////////////////////////// 00646 // Function: GetFullName 00647 // Access: Public 00648 // Description: Given an element, return a copy of the element's 00649 // name complete with prefix. 00650 //////////////////////////////////////////////////////////////////// 00651 char *soft2egg:: 00652 GetFullName( SAA_Scene *scene, SAA_Elem *element ) 00653 { 00654 int nameLen; 00655 char *name; 00656 00657 // get the name 00658 SAA_elementGetNameLength( scene, element, &nameLen ); 00659 name = (char *)malloc(sizeof(char)*++nameLen); 00660 SAA_elementGetName( scene, element, nameLen, name ); 00661 00662 int prefixLen; 00663 char *prefix; 00664 00665 // get the prefix 00666 SAA_elementGetPrefixLength( scene, element, &prefixLen ); 00667 prefix = (char *)malloc(sizeof(char)*++prefixLen); 00668 SAA_elementGetPrefix( scene, element, prefixLen, prefix ); 00669 00670 strstream fullNameStrm; 00671 00672 // add 'em together 00673 fullNameStrm << prefix << "-" << name << ends; 00674 00675 //free( name ); 00676 //free( prefix ); 00677 00678 return fullNameStrm.str(); 00679 } 00680 00681 //////////////////////////////////////////////////////////////////// 00682 // Function: GetModelNoteInfo 00683 // Access: Public 00684 // Description: Given an element, return a string containing the 00685 // contents of its MODEL NOTE entry 00686 //////////////////////////////////////////////////////////////////// 00687 char *soft2egg:: 00688 GetModelNoteInfo( SAA_Scene *scene, SAA_Elem *model ) 00689 { 00690 00691 int size; 00692 char *modelNote = NULL; 00693 SAA_Boolean bigEndian; 00694 00695 00696 SAA_elementGetUserDataSize( scene, model, "MNOT", &size ); 00697 00698 if ( size != 0 ) 00699 { 00700 // allocate modelNote string 00701 modelNote = (char *)malloc(sizeof(char)*(size + 1)); 00702 00703 // get ModelNote data from this model 00704 SAA_elementGetUserData( scene, model, "MNOT", size, 00705 &bigEndian, (void *)modelNote ); 00706 00707 //strip off newline, if present 00708 char *eol = strchr( modelNote, '\n' ); 00709 if ( eol != NULL) 00710 *eol = '\0'; 00711 else 00712 modelNote[size] = '\0'; 00713 00714 if ( verbose >= 1 ) 00715 fprintf( outStream, "\nmodelNote = %s\n", 00716 modelNote ); 00717 } 00718 00719 return modelNote; 00720 } 00721 00722 00723 //////////////////////////////////////////////////////////////////// 00724 // Function: MakeTableName 00725 // Access: Public 00726 // Description: Given a string, and a number, return a new string 00727 // consisting of "string.number". 00728 //////////////////////////////////////////////////////////////////// 00729 char *soft2egg:: 00730 MakeTableName( const char *name, int number ) 00731 { 00732 strstream namestrm; 00733 00734 namestrm << name << "." << number << ends; 00735 return namestrm.str(); 00736 } 00737 00738 //////////////////////////////////////////////////////////////////// 00739 // Function: FindModelByName 00740 // Access: Public 00741 // Description: Given a string, find the model in the scene 00742 // whose name corresponds to the given string. 00743 //////////////////////////////////////////////////////////////////// 00744 SAA_Elem *soft2egg:: 00745 FindModelByName( char *name, SAA_Scene *scene, SAA_Elem *models, 00746 int numModels ) 00747 { 00748 char *foundName; 00749 SAA_Elem *foundModel = NULL; 00750 00751 for ( int model = 0; model < numModels; model++ ) 00752 { 00753 foundName = GetName( scene, &models[model] ); 00754 00755 if ( !strcmp( name, foundName ) ) 00756 { 00757 if ( verbose >= 1 ) 00758 fprintf( outStream, "foundModel: '%s' = '%s'\n", 00759 name, foundName ); 00760 00761 foundModel = &models[model]; 00762 return( foundModel ); 00763 } 00764 } 00765 00766 fprintf( outStream, "findModelByName: failed to find model named: '%s'\n", 00767 name ); 00768 00769 return ( foundModel ); 00770 } 00771 00772 00773 //////////////////////////////////////////////////////////////////// 00774 // Function: DepointellizeName 00775 // Access: Public 00776 // Description: Given a string, return the string up to the first 00777 // period. 00778 //////////////////////////////////////////////////////////////////// 00779 char *soft2egg:: 00780 DepointellizeName( char *name ) 00781 { 00782 char *endPtr; 00783 char *newName; 00784 00785 newName = (char *)malloc(sizeof(char)*(strlen(name)+1)); 00786 sprintf( newName, "%s", name ); 00787 00788 endPtr = strchr( newName, '.' ); 00789 if ( endPtr != NULL ) 00790 *endPtr = '\0'; 00791 00792 return ( newName ); 00793 } 00794 00795 00796 //////////////////////////////////////////////////////////////////// 00797 // Function: ConvertTexture 00798 // Access: Public 00799 // Description: Given a string, return a copy of the string without 00800 // the leading file path, and make an rgb file of the 00801 // same name in the tex_path directory. 00802 //////////////////////////////////////////////////////////////////// 00803 char *soft2egg:: 00804 ConvertTexture( SAA_Scene *scene, SAA_Elem *texture ) 00805 { 00806 char *fileName = NULL; 00807 int fileNameLen = 0; 00808 00809 // get the texture's name 00810 SAA_texture2DGetPicNameLength( scene, texture, &fileNameLen); 00811 00812 if ( fileNameLen ) 00813 { 00814 fileName = (char *)malloc(sizeof(char)*++fileNameLen); 00815 SAA_texture2DGetPicName( scene, texture, fileNameLen, fileName ); 00816 } 00817 00818 // make sure we are not being passed a NULL image, an empty image 00819 // string or the default image created by egg2soft 00820 if ( (fileName != NULL) && strlen( fileName ) && strcmp( fileName, 00821 "/fat/people/gregw/new_test/PICTURES/default") && 00822 ( strstr( fileName, "noIcon" ) == NULL) ) 00823 { 00824 char *texName = NULL; 00825 char *texNamePath = NULL; 00826 char *tmpName = NULL; 00827 char *fileNameExt = NULL; 00828 00829 // strip off path and add .rgb 00830 tmpName = strrchr( fileName, '/' ); 00831 00832 if ( tmpName == NULL ) 00833 tmpName = fileName; 00834 else 00835 tmpName++; 00836 00837 float transp; 00838 00839 // check for alpha 00840 SAA_texture2DGetTransparency( scene, texture, &transp ); 00841 00842 if ( transp != 0.0f ) { 00843 texName = (char *)malloc(sizeof(char)*(strlen(tmpName)+6)); 00844 sprintf( texName, "%s.rgba", tmpName ); 00845 } else { 00846 texName = (char *)malloc(sizeof(char)*(strlen(tmpName)+5)); 00847 sprintf( texName, "%s.rgb", tmpName ); 00848 } 00849 00850 fileNameExt = (char *)malloc(sizeof(char)*(strlen(fileName)+5)); 00851 sprintf( fileNameExt, "%s.pic", fileName ); 00852 00853 if ( verbose >= 1 ) 00854 fprintf( outStream, "Looking for texture file: '%s'\n", fileNameExt ); 00855 00856 // try to make conversion of file 00857 int found_file = ( access( fileNameExt, F_OK ) == 0); 00858 00859 if ( found_file ) 00860 { 00861 if ( tex_path ) 00862 { 00863 texNamePath = (char *)malloc(sizeof(char)*(strlen(tex_path) + 00864 strlen(texName) + 2)); 00865 00866 sprintf( texNamePath, "%s/%s", tex_path, texName ); 00867 00868 if ( texFile ) 00869 texFile << texNamePath << ": " << fileNameExt << "\n"; 00870 00871 // make sure conversion doesn't already exist 00872 if ( (access( texNamePath, F_OK ) != 0) && !texFile ) 00873 { 00874 char *command = (char *)malloc(sizeof(char)* 00875 (strlen(fileNameExt) + strlen(texNamePath) + 20)); 00876 00877 sprintf( command, "image-resize -1 %s %s", 00878 fileNameExt, texNamePath ); 00879 00880 if ( verbose >=1 ) 00881 fprintf( outStream, "executing %s\n", command ); 00882 00883 system( command ); 00884 00885 //free( command ); 00886 } 00887 else 00888 if ( verbose >=1 ) 00889 fprintf( outStream, "%s already exists!\n", texNamePath ); 00890 } 00891 else 00892 { 00893 if ( verbose >= 1 ) 00894 { 00895 fprintf( outStream, "Warning: No texture path defined" ); 00896 fprintf( outStream, " - No automatic conversion performed\n" ); 00897 } 00898 } 00899 } 00900 else 00901 { 00902 fprintf( outStream, "Warning: Couldn't find texture file: %s\n", 00903 fileNameExt ); 00904 } 00905 00906 //free( fileNameExt ); 00907 00908 if (tex_path) 00909 return( texNamePath ); 00910 else 00911 return( texName ); 00912 } 00913 else 00914 { 00915 fprintf( outStream, "Warning: ConvertTexture received NULL fileName\n" ); 00916 return( NULL ); 00917 } 00918 } 00919 00920 //////////////////////////////////////////////////////////////////// 00921 // Function: FindClosestTriVert 00922 // Access: Public 00923 // Description: Given an egg vertex pool, map each vertex therein to 00924 // a vertex within an array of SAA model vertices of 00925 // size numVert. Mapping is done by closest proximity. 00926 //////////////////////////////////////////////////////////////////// 00927 int *soft2egg:: 00928 FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert ) 00929 { 00930 int *vertMap = NULL; 00931 int vpoolSize = vpool->NumVertices(); 00932 int i,j; 00933 float thisDist; 00934 float closestDist; 00935 int closest; 00936 00937 00938 vertMap = (int *)malloc(sizeof(int)*vpoolSize); 00939 00940 // for each vertex in vpool 00941 for ( i = 0; i < vpoolSize; i++ ) 00942 { 00943 // find closest model vertex 00944 for ( j = 0; j < numVert-1; j++ ) 00945 { 00946 // calculate distance 00947 thisDist = sqrtf( 00948 powf( vpool->Vertex(i)->position[0] - vertices[j].x , 2 ) + 00949 powf( vpool->Vertex(i)->position[1] - vertices[j].y , 2 ) + 00950 powf( vpool->Vertex(i)->position[2] - vertices[j].z , 2 ) ); 00951 00952 // remember this if its the closest so far 00953 if ( !j || ( thisDist < closestDist ) ) 00954 { 00955 closest = j; 00956 closestDist = thisDist; 00957 } 00958 } 00959 vertMap[i] = closest; 00960 00961 if ( verbose >= 2 ) 00962 { 00963 fprintf( outStream, "mapping v %d of %d:( %f, %f, %f )\n", i, 00964 vpoolSize, vpool->Vertex(i)->position[0], 00965 vpool->Vertex(i)->position[1], 00966 vpool->Vertex(i)->position[2] ); 00967 fprintf( outStream, "to cv %d of %d:( %f, %f, %f )\tdelta = %f\n", 00968 closest, numVert-1, vertices[closest].x, vertices[closest].y, 00969 vertices[closest].z, closestDist ); 00970 } 00971 } 00972 00973 return( vertMap ); 00974 } 00975 00976 00977 //////////////////////////////////////////////////////////////////// 00978 // Function: MakeIndexMap 00979 // Access: Public 00980 // Description: Given an array of indices that is a map from one 00981 // set of vertices to another, return an array that 00982 // performs the reverse mapping of the indices array 00983 //////////////////////////////////////////////////////////////////// 00984 int *soft2egg:: 00985 MakeIndexMap( int *indices, int numIndices, int mapSize ) 00986 { 00987 int i, j; 00988 00989 // allocate map array 00990 int *map = (int *)malloc(sizeof(int)*mapSize); 00991 00992 if ( map != NULL ) 00993 { 00994 for ( i = 0; i < mapSize; i++ ) 00995 { 00996 j = 0; 00997 int found = 0; 00998 while( j < numIndices ) 00999 { 01000 if ( indices[j] == i ) 01001 { 01002 map[i] = j; 01003 if ( verbose >= 2 ) 01004 fprintf( outStream, "map[%d] = %d\n", i, map[i] ); 01005 found = 1; 01006 break; 01007 } 01008 j++; 01009 } 01010 if ( !found) 01011 { 01012 if ( verbose >= 2 ) 01013 fprintf( outStream, "Warning: orphan vertex (%d)\n", i ); 01014 // default to -1 for now 01015 map[i] = -1; 01016 } 01017 } 01018 } 01019 else 01020 fprintf( outStream, "Not enough Memory for index Map...\n"); 01021 01022 01023 return( map ); 01024 } 01025 01026 01027 //////////////////////////////////////////////////////////////////// 01028 // Function: findShapeVert 01029 // Access: Public 01030 // Description: given a vertex, find its corresponding shape vertex 01031 // and return its index. 01032 //////////////////////////////////////////////////////////////////// 01033 int soft2egg:: 01034 findShapeVert( SAA_DVector vertex, SAA_DVector *vertices, int numVert ) 01035 { 01036 int i; 01037 int found = 0; 01038 01039 for ( i = 0; i < numVert && !found ; i++ ) 01040 { 01041 if ( ( vertex.x == vertices[i].x ) && 01042 ( vertex.y == vertices[i].y ) && 01043 ( vertex.z == vertices[i].z ) ) 01044 { 01045 found = 1; 01046 01047 if ( verbose >= 2) 01048 fprintf( outStream, "found shape vert at index %d\n", i ); 01049 } 01050 01051 } 01052 01053 if (!found ) 01054 i = -1; 01055 else 01056 i--; 01057 01058 return( i ); 01059 } 01060 01061 01062 //////////////////////////////////////////////////////////////////// 01063 // Function: LoadSoft 01064 // Access: Public 01065 // Description: Open the SI database and grab the scene & model info 01066 //////////////////////////////////////////////////////////////////// 01067 void soft2egg:: 01068 LoadSoft() 01069 { 01070 int i; 01071 01072 if ( (scene_name == NULL && model_name == NULL) || database_name == NULL ) 01073 { 01074 Usage(); 01075 exit( 1 ); 01076 } 01077 01078 if ((result = SAA_Init(rsrc_path, FALSE)) != SI_SUCCESS) 01079 { 01080 fprintf( outStream, "Error: Couldn't get resource path!\n"); 01081 exit( 1 ); 01082 } 01083 01084 if ((result = SAA_databaseLoad(database_name, &database)) != SI_SUCCESS) 01085 { 01086 fprintf( outStream, "Error: Couldn't load database!\n"); 01087 exit( 1 ); 01088 } 01089 01090 if ((result = SAA_sceneGetCurrent(&scene)) == SI_SUCCESS) 01091 { 01092 // load scene if present 01093 if ( scene_name != NULL ) 01094 { 01095 SAA_sceneLoad( &database, scene_name, &scene ); 01096 01097 // if no egg filename specified, make up a name 01098 if ( eggFileName == NULL ) 01099 { 01100 eggFileName = (char *)malloc(sizeof(char)* 01101 (strlen( scene_name ) + 14 )); 01102 sprintf( eggFileName, "%s", DepointellizeName(scene_name) ); 01103 if ( make_nurbs ) 01104 strcat( eggFileName, "-nurb" ); 01105 strcat( eggFileName, "-mod.egg" ); 01106 } 01107 01108 // open an output file for the geometry if necessary 01109 if ( make_poly || make_nurbs ) 01110 { 01111 unlink( eggFileName ); 01112 eggFile.open( eggFileName, ios::out, 0666 ); 01113 01114 if ( !eggFile ) 01115 { 01116 fprintf( outStream, "Couldn't open output file: %s\n", 01117 eggFileName ); 01118 exit( 1 ); 01119 } 01120 } 01121 01122 // open an output file for texture list if specified 01123 if ( tex_filename != NULL ) 01124 { 01125 unlink( tex_filename ); 01126 texFile.open( tex_filename, ios::out, 0666 ); 01127 01128 if ( !texFile ) 01129 { 01130 fprintf( outStream, "Couldn't open output file: %s\n", 01131 tex_filename ); 01132 exit( 1 ); 01133 } 01134 } 01135 01136 if ( SAA_updatelistGet( &scene ) == SI_SUCCESS ) 01137 { 01138 float time; 01139 01140 fprintf( outStream, "setting Scene to frame %d...\n", pose_frame ); 01141 //SAA_sceneSetPlayCtrlCurrentFrame( &scene, pose_frame ); 01142 SAA_frame2Seconds( &scene, pose_frame, &time ); 01143 SAA_updatelistEvalScene( &scene, time ); 01144 sginap( 100 ); 01145 SAA_updatelistEvalScene( &scene, time ); 01146 if ( make_pose ) 01147 SAA_sceneFreeze( &scene ); 01148 } 01149 01150 int numModels; 01151 SAA_Elem *models; 01152 01153 SAA_sceneGetNbModels( &scene, &numModels ); 01154 fprintf( outStream, "Scene has %d model(s)...\n", numModels ); 01155 01156 if ( numModels ) 01157 { 01158 // allocate array of models 01159 models = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numModels); 01160 01161 if ( models != NULL ) 01162 { 01163 char *rootName = GetRootName( eggFileName ); 01164 01165 01166 if ( eggGroupName == NULL ) 01167 dart = _data.CreateGroup( NULL, rootName ); 01168 else 01169 dart = _data.CreateGroup( NULL, eggGroupName ); 01170 01171 if (make_dart) 01172 dart->flags |= EF_DART; 01173 01174 AnimGroup *rootTable; 01175 01176 rootTable = animData.CreateTable( NULL, eggFileName ); 01177 01178 if ( eggGroupName == NULL ) 01179 animRoot = animData.CreateBundle( rootTable, rootName ); 01180 else 01181 animRoot = animData.CreateBundle( rootTable, 01182 eggGroupName ); 01183 01184 // propagate commet to anim data 01185 animData.root_group.children.push_front( 01186 new EggComment( _commandLine ) ); 01187 01188 if ( verbose >= 1 ) 01189 fprintf( outStream, "made animRoot: %s\n", rootName ); 01190 01191 SAA_sceneGetModels( &scene, numModels, models ); 01192 01193 for ( i = 0; i < numModels; i++ ) 01194 { 01195 int level; 01196 01197 SAA_elementGetHierarchyLevel( &scene, &models[i], &level ); 01198 if ( !level ) 01199 { 01200 if ( verbose >= 1 ) 01201 fprintf( outStream, 01202 "\negging scene model[%d]\n", i ); 01203 01204 MakeEgg( dart, NULL, NULL, &scene, &models[i] ); 01205 } 01206 } 01207 01208 if ( make_poly || make_nurbs ) 01209 { 01210 // generate soft skinning assignments if desired 01211 // 01212 //disabled 1/1/99 to streamline joint assignments. 01213 // all joint assignments now done here. Hard & Soft. 01214 //if ( make_soft) 01215 { 01216 char *name; 01217 char *fullname; 01218 SAA_Boolean isSkeleton; 01219 01220 // search through models and look for skeleton parts 01221 for ( i = 0; i < numModels; i++ ) 01222 { 01223 SAA_modelIsSkeleton( &scene, &models[i], &isSkeleton ); 01224 01225 // get fullname for splitting files, but 01226 // only use it in file if requested 01227 fullname = GetFullName( &scene, &models[i] ); 01228 if ( use_prefix ) 01229 name = fullname; 01230 else 01231 name = GetName( &scene, &models[i] ); 01232 01233 // split 01234 if ( strstr( fullname, search_prefix ) != NULL ) 01235 { 01236 // for every skel part: get soft skin info 01237 if ( isSkeleton ) 01238 MakeSoftSkin( &scene, &models[i], models, 01239 numModels, name ); 01240 } 01241 01242 //free( name ); 01243 } 01244 01245 // make sure all vertices were assigned 01246 // via soft skinning - if not hard assign them 01247 for ( i = 0; i < numModels; i++ ) 01248 { 01249 // get fullname for splitting files, but 01250 // only use it in file if requested 01251 fullname = GetFullName( &scene, &models[i] ); 01252 if ( use_prefix ) 01253 name = fullname; 01254 else 01255 name = GetName( &scene, &models[i] ); 01256 01257 // split 01258 if ( strstr( fullname, search_prefix ) != NULL ) 01259 CleanUpSoftSkin( &scene, &models[i], name ); 01260 01261 //free( name ); 01262 } 01263 01264 } 01265 01266 01267 // put the skeleton data into the egg data 01268 dart->StealChildren( *skeleton ); 01269 01270 // make sure all elements have unique names 01271 _data.UniquifyNames(); 01272 01273 // write out the geometry data if requested 01274 //if ( make_poly || make_nurbs ) 01275 //{ 01276 eggFile << _data << "\n"; 01277 fprintf( outStream, "\nwriting out %s...\n", eggFileName ); 01278 eggFile.close(); 01279 } 01280 01281 // close texture list file if opened 01282 if ( texFile ) 01283 texFile.close(); 01284 01285 // generate animation data if desired 01286 if ( make_anim ) 01287 { 01288 if ( animFileName == NULL ) 01289 { 01290 animFileName = (char *)malloc(sizeof(char)* 01291 (strlen(scene_name)+ 10 )); 01292 sprintf( animFileName, "%s", DepointellizeName(scene_name) ); 01293 strcat( animFileName, "-chan.egg" ); 01294 } 01295 01296 unlink( animFileName ); 01297 animFile.open( animFileName, ios::out, 0666 ); 01298 01299 if ( !animFile ) 01300 { 01301 fprintf( outStream, "Couldn't open output file: %s\n", 01302 animFileName ); 01303 exit( 1 ); 01304 } 01305 01306 int frame; 01307 //int frameStep; 01308 float time; 01309 01310 // get all the animation frame info if not specified 01311 // on the command line 01312 if (anim_start == -1000) 01313 SAA_sceneGetPlayCtrlStartFrame( &scene, &anim_start ); 01314 01315 if (anim_end == -1000) 01316 SAA_sceneGetPlayCtrlEndFrame( &scene, &anim_end ); 01317 01318 //SAA_sceneGetPlayCtrlFrameStep( &scene, &frameStep ); 01319 01320 fprintf( outStream, "\nframeStart = %d\n", anim_start ); 01321 fprintf( outStream, "frameEnd = %d\n", anim_end ); 01322 //fprintf( outStream, "frameStep = %d\n", frameStep ); 01323 01324 // start at first frame and go to last 01325 for ( frame = anim_start; frame <= anim_end; 01326 frame += 1) 01327 { 01328 SAA_frame2Seconds( &scene, frame, &time ); 01329 SAA_updatelistEvalScene( &scene, time ); 01330 sginap( 100 ); 01331 SAA_updatelistEvalScene( &scene, time ); 01332 fprintf( outStream, "\n> animating frame %d\n", frame ); 01333 01334 // for each model 01335 for ( i = 0; i < numModels; i++ ) 01336 { 01337 char *name; 01338 char *fullname; 01339 SAA_Boolean isSkeleton; 01340 SAA_ModelType type; 01341 01342 SAA_modelIsSkeleton( &scene, &models[i], &isSkeleton ); 01343 01344 // get fullname for splitting files, but 01345 // only use it in file if requested 01346 fullname = GetFullName( &scene, &models[i] ); 01347 if ( use_prefix ) 01348 name = fullname; 01349 else 01350 name = GetName( &scene, &models[i] ); 01351 01352 // split 01353 if ( strstr( fullname, search_prefix ) != NULL ) 01354 { 01355 // make the morph table for this critter 01356 if ( make_morph ) 01357 { 01358 MakeMorphTable( &scene, &models[i], models, 01359 numModels, name, time ); 01360 } 01361 } 01362 01363 // find out what type of node we're dealing with 01364 result = SAA_modelGetType( &scene, &models[i], &type ); 01365 01366 int size; 01367 01368 // check for uv texture animation 01369 SAA_elementGetUserDataSize( &scene, &models[i], 01370 "TEX_OFFSETS", &size ); 01371 01372 // if so, update for this frame if desired 01373 if ( ( size != 0 ) && make_duv ) 01374 MakeTexAnim( &scene, &models[i], name ); 01375 01376 // if we have a skeleton or something that acts 01377 // like one - build anim tables 01378 if ( isSkeleton || 01379 ( strstr( name, "joint") != NULL ) ) 01380 MakeAnimTable( &scene, &models[i], name ); 01381 01382 //free( name ); 01383 } 01384 01385 if ( verbose >= 1 ) 01386 fprintf( outStream, "\n" ); 01387 } 01388 01389 animFile << animData << "\n"; 01390 fprintf( outStream, "\nwriting out %s...\n", animFileName ); 01391 animFile.close(); 01392 } 01393 01394 //free( models ); 01395 01396 } 01397 else 01398 fprintf( outStream, "Error: Not enough Memory for models...\n"); 01399 } 01400 } 01401 // otherwise try to load a model 01402 else if ( model_name != NULL ) 01403 { 01404 01405 if ( eggFileName == NULL ) 01406 { 01407 eggFileName = 01408 (char *)malloc(sizeof(char)*(strlen( model_name )+13)); 01409 sprintf( eggFileName, "%s", DepointellizeName( model_name ) ); 01410 01411 if ( make_nurbs ) 01412 strcat( eggFileName, "-nurb" ); 01413 strcat( eggFileName, "-mod.egg" ); 01414 } 01415 01416 eggFile.open( eggFileName ); 01417 01418 if ( !eggFile ) 01419 { 01420 fprintf( outStream, "Couldn't open output file: %s\n", 01421 eggFileName ); 01422 exit( 1 ); 01423 } 01424 01425 if ((result = 01426 SAA_elementLoad(&database, &scene, model_name, &model)) 01427 == SI_SUCCESS) 01428 { 01429 fprintf( outStream, "Loading single model...\n"); 01430 MakeEgg( NULL, NULL, NULL, &scene, &model ); 01431 } 01432 01433 eggFile << _data << "\n"; 01434 } 01435 } 01436 01437 } 01438 01439 //////////////////////////////////////////////////////////////////// 01440 // Function: MakeEgg 01441 // Access: Public 01442 // Description: Make egg geometry from a given model. This include 01443 // textures, tex coords, colors, normals, and joints. 01444 //////////////////////////////////////////////////////////////////// 01445 void soft2egg:: 01446 MakeEgg( EggGroup *parent, EggJoint *lastJoint, AnimGroup *lastAnim, 01447 SAA_Scene *scene, SAA_Elem *model ) 01448 { 01449 char *name; 01450 char *fullname; 01451 SAA_ModelType type; 01452 int id = 0; 01453 int numShapes; 01454 int numTri; 01455 int numVert; 01456 int numTexLoc = 0; 01457 int numTexGlb = 0; 01458 int i, j; 01459 float matrix[4][4]; 01460 float *uScale = NULL; 01461 float *vScale = NULL; 01462 float *uOffset = NULL; 01463 float *vOffset = NULL; 01464 SAA_Boolean uv_swap = FALSE; 01465 void *relinfo; 01466 SAA_SubElem *triangles = NULL; 01467 SAA_Elem *materials = NULL; 01468 SAA_SubElem *cvertices = NULL; 01469 SAA_DVector *cvertPos = NULL; 01470 SAA_DVector *vertices = NULL; 01471 SAA_DVector *normals = NULL; 01472 int *indices = NULL; 01473 int *indexMap = NULL; 01474 int *numTexTri = NULL; 01475 SAA_Elem *textures = NULL; 01476 char **texNameArray; 01477 float *uCoords = NULL; 01478 float *vCoords = NULL; 01479 SAA_GeomType gtype = SAA_GEOM_ORIGINAL; 01480 SAA_Boolean visible; 01481 01482 ///////////////////////////////////////////////// 01483 // find out what type of node we're dealing with 01484 ///////////////////////////////////////////////// 01485 result = SAA_modelGetType( scene, model, &type ); 01486 01487 if ( verbose >= 1 ) 01488 { 01489 if ( type == SAA_MNILL ) 01490 fprintf( outStream, "encountered null\n"); 01491 else if ( type == SAA_MPTCH ) 01492 fprintf( outStream, "encountered patch\n" ); 01493 else if ( type == SAA_MFACE ) 01494 fprintf( outStream, "encountered face\n" ); 01495 else if ( type == SAA_MSMSH ) 01496 fprintf( outStream, "encountered mesh\n" ); 01497 else if ( type == SAA_MJNT ) 01498 fprintf( outStream, "encountered joint\n" ); 01499 else if ( type == SAA_MSPLN ) 01500 fprintf( outStream, "encountered spline\n" ); 01501 else if ( type == SAA_MMETA ) 01502 fprintf( outStream, "encountered meta element\n" ); 01503 else if ( type == SAA_MBALL ) 01504 fprintf( outStream, "encountered metaball\n" ); 01505 else if ( type == SAA_MNCRV ) 01506 fprintf( outStream, "encountered nurb curve\n" ); 01507 else if ( type == SAA_MNSRF ) 01508 fprintf( outStream, "encountered nurbs surf\n" ); 01509 else 01510 fprintf( outStream, "encountered unknown type: %d\n", type ); 01511 } 01512 01513 ///////////////////////////// 01514 // Get the name of the model 01515 ///////////////////////////// 01516 01517 // Get the FULL name of the model 01518 fullname = GetFullName( scene, model ); 01519 01520 if ( use_prefix ) 01521 { 01522 // Get the FULL name of the trim curve 01523 name = fullname; 01524 } 01525 else 01526 { 01527 // Get the name of the trim curve 01528 name = GetName( scene, model ); 01529 } 01530 01531 if ( verbose >= 1 ) 01532 fprintf( outStream, "element name <%s>\n", name ); 01533 01534 fflush( outStream ); 01535 01536 // get the model's matrix 01537 SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix ); 01538 01539 if ( verbose >= 2 ) 01540 { 01541 fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[0][0], 01542 matrix[0][1], matrix[0][2], matrix[0][3] ); 01543 fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[1][0], 01544 matrix[1][1], matrix[1][2], matrix[1][3] ); 01545 fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[2][0], 01546 matrix[2][1], matrix[2][2], matrix[2][3] ); 01547 fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[3][0], 01548 matrix[3][1], matrix[3][2], matrix[3][3] ); 01549 } 01550 01551 /////////////////////////////////////////////////////////////////////// 01552 // check to see if this is a branch we don't want to descend - this 01553 // will prevent creating geometry for animation control structures 01554 /////////////////////////////////////////////////////////////////////// 01555 if ( (strstr( name, "con-" ) == NULL) && 01556 (strstr( name, "con_" ) == NULL) && 01557 (strstr( name, "fly_" ) == NULL) && 01558 (strstr( name, "fly-" ) == NULL) && 01559 (strstr( name, "camRIG" ) == NULL) && 01560 (strstr( name, "bars" ) == NULL) && 01561 // split 01562 (strstr( fullname, search_prefix ) != NULL) ) 01563 { 01564 01565 // if making a pose - get deformed geometry 01566 if ( make_pose ) 01567 gtype = SAA_GEOM_DEFORMED; 01568 01569 // Get the number of key shapes 01570 SAA_modelGetNbShapes( scene, model, &numShapes ); 01571 if ( verbose >= 1 ) 01572 fprintf( outStream, "MakeEgg: num shapes: %d\n", numShapes); 01573 01574 /////////////////////////////////////////////////////////////////////// 01575 // if multiple key shapes exist create table entries for each 01576 /////////////////////////////////////////////////////////////////////// 01577 if ( (numShapes > 0) && make_morph ) 01578 { 01579 has_morph = 1; 01580 01581 // make sure root morph table exists 01582 if ( morphRoot == NULL ) 01583 morphRoot = animData.CreateTable( animRoot, "morph" ); 01584 01585 char *tableName; 01586 01587 // create morph table entry for each key shape 01588 // (start at second shape - as first is the original geometry) 01589 for ( i = 1; i < numShapes; i++ ) 01590 { 01591 tableName = MakeTableName( name, i ); 01592 SAnimTable *table = new SAnimTable( ); 01593 table->name = tableName; 01594 table->fps = anim_rate; 01595 morphRoot->children.push_back( table ); 01596 if ( verbose >= 1 ) 01597 fprintf( outStream, "created table named: '%s'\n", tableName ); 01598 } 01599 01600 //free( tableName ); 01601 } 01602 01603 SAA_modelGetNodeVisibility( scene, model, &visible ); 01604 if ( verbose >= 1 ) 01605 fprintf( outStream, "model visibility: %d\n", visible ); 01606 01607 /////////////////////////////////////////////////////////////////////// 01608 // Only create egg polygon data if: the node is visible, and its not 01609 // a NULL or a Joint, and we're outputing polys (or if we are outputing 01610 // NURBS and the model is a poly mesh or a face) 01611 /////////////////////////////////////////////////////////////////////// 01612 if ( visible && 01613 (type != SAA_MNILL) && 01614 (type != SAA_MJNT) && 01615 ((make_poly || 01616 (make_nurbs && ((type == SAA_MSMSH) || (type == SAA_MFACE )) )) 01617 || (!make_poly && !make_nurbs && make_duv && 01618 ((type == SAA_MSMSH) || (type == SAA_MFACE )) )) 01619 ) 01620 { 01621 // If the model is a NURBS in soft, set its step before tesselating 01622 if ( type == SAA_MNSRF ) 01623 SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step ); 01624 01625 // If the model is a PATCH in soft, set its step before tesselating 01626 else if ( type == SAA_MPTCH ) 01627 SAA_patchSetStep( scene, model, nurbs_step, nurbs_step ); 01628 01629 // Get the number of triangles 01630 result = SAA_modelGetNbTriangles( scene, model, gtype, id, &numTri); 01631 if ( verbose >= 1 ) 01632 fprintf( outStream, "triangles: %d\n", numTri); 01633 01634 if ( result != SI_SUCCESS ) 01635 { 01636 if ( verbose >= 1 ) { 01637 fprintf( outStream, 01638 "Error: couldn't get number of triangles!\n" ); 01639 fprintf( outStream, "\tbailing on model: '%s'\n", name ); 01640 } 01641 return; 01642 } 01643 01644 // check to see if surface is also skeleton... 01645 SAA_Boolean isSkeleton = FALSE; 01646 01647 SAA_modelIsSkeleton( scene, model, &isSkeleton ); 01648 01649 // check to see if this surface is used as a skeleton 01650 // or is animated via constraint only ( these nodes are 01651 // tagged by the animator with the keyword "joint" 01652 // somewhere in the nodes name) 01653 if ( isSkeleton || (strstr( name, "joint" ) != NULL) ) 01654 { 01655 if ( verbose >= 1 ) 01656 fprintf( outStream, "animating Polys as joint!!!\n" ); 01657 01658 MakeJoint( scene, lastJoint, lastAnim, model, name ); 01659 } 01660 01661 // model is not a null and has no triangles! 01662 if ( !numTri ) 01663 { 01664 if ( verbose >= 1 ) 01665 fprintf( outStream, "no triangles!\n"); 01666 } 01667 else 01668 { 01669 // allocate array of triangles 01670 triangles = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTri); 01671 if ( triangles != NULL ) 01672 { 01673 // triangulate model and read the triangles into array 01674 SAA_modelGetTriangles( scene, model, gtype, id, numTri, triangles ); 01675 } 01676 else 01677 fprintf( outStream, "Not enough Memory for triangles...\n"); 01678 01679 // allocate array of materials 01680 materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTri); 01681 if ( materials != NULL ) 01682 { 01683 // read each triangle's material into array 01684 SAA_triangleGetMaterials( scene, model, numTri, triangles, 01685 materials ); 01686 } 01687 else 01688 fprintf( outStream, "Not enough Memory for materials...\n"); 01689 01690 // allocate array of textures per triangle 01691 numTexTri = (int *)malloc(sizeof(int)*numTri); 01692 01693 // find out how many local textures per triangle 01694 for ( i = 0; i < numTri; i++ ) 01695 { 01696 result = SAA_materialRelationGetT2DLocNbElements( scene, 01697 &materials[i], FALSE, &relinfo, &numTexTri[i] ); 01698 01699 // polytex 01700 if ( result == SI_SUCCESS ) 01701 numTexLoc += numTexTri[i]; 01702 } 01703 01704 // don't need this anymore... 01705 //free( numTexTri ); 01706 01707 // get local textures if present 01708 if ( numTexLoc ) 01709 { 01710 // ASSUME only one texture per material 01711 textures = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTri); 01712 01713 for ( i = 0; i < numTri; i++ ) 01714 { 01715 // and read all referenced local textures into array 01716 SAA_materialRelationGetT2DLocElements( scene, &materials[i], 01717 TEX_PER_MAT , &textures[i] ); 01718 } 01719 01720 if ( verbose >= 1 ) 01721 fprintf( outStream, "numTexLoc = %d\n", numTexLoc); 01722 } 01723 // if no local textures, try to get global textures 01724 else 01725 { 01726 SAA_modelRelationGetT2DGlbNbElements( scene, model, 01727 FALSE, &relinfo, &numTexGlb ); 01728 01729 if ( numTexGlb ) 01730 { 01731 // ASSUME only one texture per model 01732 textures = (SAA_Elem *)malloc(sizeof(SAA_Elem)); 01733 01734 // get the referenced texture 01735 SAA_modelRelationGetT2DGlbElements( scene, model, 01736 TEX_PER_MAT, textures ); 01737 01738 if ( verbose >= 1 ) 01739 fprintf( outStream, "numTexGlb = %d\n", numTexGlb); 01740 } 01741 } 01742 01743 // allocate array of control vertices 01744 cvertices = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTri*3); 01745 if ( cvertices != NULL ) 01746 { 01747 // read each triangle's control vertices into array 01748 SAA_triangleGetCtrlVertices( scene, model, gtype, id, 01749 numTri, triangles, cvertices ); 01750 01751 if ( verbose >= 2 ) 01752 { 01753 cvertPos = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numTri*3); 01754 SAA_ctrlVertexGetPositions( scene, model, numTri*3, 01755 cvertices, cvertPos); 01756 01757 for ( i=0; i < numTri*3; i++ ) 01758 { 01759 fprintf( outStream, "cvert[%d] = %f %f %f %f\n", i, 01760 cvertPos[i].x, cvertPos[i].y, cvertPos[i].z, 01761 cvertPos[i].w ); 01762 } 01763 } 01764 } 01765 else 01766 fprintf( outStream, "Not enough Memory for control vertices...\n"); 01767 01768 // allocate array of control vertex indices 01769 // this array maps from the redundant cvertices array into 01770 // the unique vertices array (cvertices->vertices) 01771 indices = (int *)malloc(sizeof(int)*numTri*3); 01772 if ( indices != NULL ) 01773 { 01774 for ( i=0; i < numTri*3; i++ ) 01775 indices[i] = 0; 01776 01777 SAA_ctrlVertexGetIndices( scene, model, numTri*3, 01778 cvertices, indices ); 01779 01780 if ( verbose >= 2 ) 01781 for ( i=0; i < numTri*3; i++ ) 01782 fprintf( outStream, "indices[%d] = %d\n", i, indices[i] ); 01783 } 01784 else 01785 fprintf( outStream, "Not enough Memory for indices...\n"); 01786 01787 // get number of UNIQUE vertices in model 01788 SAA_modelGetNbTriVertices( scene, model, &numVert ); 01789 01790 if ( verbose >= 2 ) 01791 fprintf( outStream, "num unique verts = %d\n", numVert ); 01792 01793 //allocate array of vertices 01794 vertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numVert); 01795 01796 // get the UNIQUE vertices of all triangles in model 01797 SAA_modelGetTriVertices( scene, model, numVert, vertices ); 01798 01799 if ( verbose >= 2 ) 01800 { 01801 for ( i=0; i < numVert; i++ ) 01802 { 01803 fprintf( outStream, "vertices[%d] = %f ", i, vertices[i].x ); 01804 fprintf( outStream, "%f %f %f\n", vertices[i].y, 01805 vertices[i].z, vertices[i].w ); 01806 } 01807 } 01808 01809 // allocate indexMap array 01810 // we contruct this array to map from the unique vertices 01811 // array to the redundant cvertices array - it will save 01812 // us from doing repetitive searches later 01813 indexMap = MakeIndexMap( indices, numTri*3, numVert ); 01814 01815 // allocate array of normals 01816 normals = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numTri*3); 01817 if ( normals != NULL ) 01818 { 01819 // read each control vertex's normals into an array 01820 SAA_ctrlVertexGetNormals( scene, model, numTri*3, 01821 cvertices, normals ); 01822 } 01823 else 01824 fprintf( outStream, "Not enough Memory for normals...\n"); 01825 01826 if ( verbose >= 2 ) 01827 { 01828 for ( i=0; i<numTri*3; i++ ) 01829 fprintf( outStream, "normals[%d] = %f %f %f %f\n", i, 01830 normals[i].x, normals[i].y, normals[i].z, normals[i].w ); 01831 } 01832 01833 int uRepeat, vRepeat; 01834 01835 // make sure we have textures before we get t-coords 01836 if ( numTexLoc ) 01837 { 01838 // allocate arrays for u & v coords 01839 uCoords = (float *)malloc(sizeof(float)*numTri*numTexLoc*3); 01840 vCoords = (float *)malloc(sizeof(float)*numTri*numTexLoc*3); 01841 01842 // read the u & v coords into the arrays 01843 if ( uCoords != NULL && vCoords != NULL) 01844 { 01845 for ( i = 0; i < numTri*numTexLoc*3; i++ ) 01846 uCoords[i] = vCoords[i] = 0.0f; 01847 01848 SAA_ctrlVertexGetUVTxtCoords( scene, model, numTri*3, 01849 cvertices, numTexLoc*3, uCoords, vCoords ); 01850 } 01851 else 01852 fprintf( outStream, "Not enough Memory for texture coords...\n"); 01853 01854 if ( verbose >= 2 ) 01855 { 01856 for ( i=0; i<numTexLoc*3; i++ ) 01857 fprintf( outStream, "texcoords[%d] = ( %f , %f )\n", i, 01858 uCoords[i], vCoords[i] ); 01859 } 01860 01861 // allocate arrays of texture info 01862 uScale = ( float *)malloc(sizeof(float)*numTri); 01863 vScale = ( float *)malloc(sizeof(float)*numTri); 01864 uOffset = ( float *)malloc(sizeof(float)*numTri); 01865 vOffset = ( float *)malloc(sizeof(float)*numTri); 01866 texNameArray = ( char **)malloc(sizeof(char *)*numTri); 01867 01868 for ( i = 0; i < numTri; i++ ) 01869 { 01870 // initialize the array value 01871 texNameArray[i] = NULL; 01872 01873 SAA_Boolean valid = FALSE; 01874 // check to see if texture is present 01875 result = SAA_elementIsValid( scene, &textures[i], &valid ); 01876 01877 if ( result != SI_SUCCESS ) 01878 fprintf( outStream, "SAA_elementIsValid failed!!!!\n" ); 01879 01880 // texture present - get the name and uv info 01881 if ( valid ) 01882 { 01883 texNameArray[i] = ConvertTexture( scene, &textures[i] ); 01884 01885 if ( verbose >= 2 ) 01886 fprintf( outStream, " tritex[%d] named: %s\n", i, 01887 texNameArray[i] ); 01888 01889 SAA_texture2DGetUVSwap( scene, &textures[i], &uv_swap ); 01890 01891 if ( verbose >= 2 ) 01892 if ( uv_swap == TRUE ) 01893 fprintf( outStream, " swapping u and v...\n" ); 01894 01895 SAA_texture2DGetUScale( scene, &textures[i], &uScale[i] ); 01896 SAA_texture2DGetVScale( scene, &textures[i], &vScale[i] ); 01897 SAA_texture2DGetUOffset( scene, &textures[i], &uOffset[i] ); 01898 SAA_texture2DGetVOffset( scene, &textures[i], &vOffset[i] ); 01899 01900 if ( verbose >= 2 ) 01901 { 01902 fprintf(outStream, "tritex[%d] uScale: %f vScale: %f\n", i, uScale[i], vScale[i] ); 01903 fprintf(outStream, " uOffset: %f vOffset: %f\n", 01904 uOffset[i], vOffset[i] ); 01905 } 01906 01907 01908 SAA_texture2DGetRepeats( scene, &textures[i], &uRepeat, 01909 &vRepeat ); 01910 01911 if ( verbose >= 2 ) 01912 { 01913 fprintf(outStream, "uRepeat = %d, vRepeat = %d\n", 01914 uRepeat, vRepeat ); 01915 } 01916 } 01917 else 01918 { 01919 if ( verbose >= 2 ) 01920 { 01921 fprintf( outStream, "Invalid texture...\n"); 01922 fprintf( outStream, " tritex[%d] named: (null)\n", i ); 01923 } 01924 } 01925 } 01926 01927 //debug 01928 //for ( i = 0; i < numTri; i++ ) 01929 //{ 01930 //if ( texNameArray[i] != NULL ) 01931 //fprintf( outStream, " tritex[%d] named: %s\n", i, 01932 //texNameArray[i] ); 01933 //else 01934 //fprintf( outStream, " tritex[%d] named: (null)\n", i ); 01935 //} 01936 } 01937 // make sure we have textures before we get t-coords 01938 else if ( numTexGlb ) 01939 { 01940 SAA_Boolean valid; 01941 01942 // check to see if texture is present 01943 SAA_elementIsValid( scene, textures, &valid ); 01944 01945 // texture present - get the name and uv info 01946 if ( valid ) 01947 { 01948 SAA_texture2DGetUVSwap( scene, textures, &uv_swap ); 01949 01950 if ( verbose >= 1 ) 01951 if ( uv_swap == TRUE ) 01952 fprintf( outStream, " swapping u and v...\n" ); 01953 01954 // allocate arrays for u & v coords 01955 uCoords = (float *)malloc(sizeof(float)*numTri*numTexGlb*3); 01956 vCoords = (float *)malloc(sizeof(float)*numTri*numTexGlb*3); 01957 01958 for ( i = 0; i < numTri*numTexGlb*3; i++ ) 01959 { 01960 uCoords[i] = vCoords[i] = 0.0f; 01961 } 01962 01963 // read the u & v coords into the arrays 01964 if ( uCoords != NULL && vCoords != NULL) 01965 { 01966 SAA_triCtrlVertexGetGlobalUVTxtCoords( scene, model, 01967 numTri*3, cvertices, numTexGlb, textures, 01968 uCoords, vCoords ); 01969 } 01970 else 01971 fprintf( outStream, "Not enough Memory for texture coords...\n"); 01972 01973 if ( verbose >= 2 ) 01974 { 01975 for ( i=0; i<numTri*numTexGlb*3; i++ ) 01976 fprintf( outStream, "texcoords[%d] = ( %f , %f )\n", i, 01977 uCoords[i], vCoords[i] ); 01978 } 01979 01980 texNameArray = ( char **)malloc(sizeof(char *)); 01981 *texNameArray = ConvertTexture( scene, textures ); 01982 01983 if ( verbose >= 1 ) 01984 fprintf( outStream, " global tex named: %s\n", 01985 texNameArray ); 01986 01987 // allocate arrays of texture info 01988 uScale = ( float *)malloc(sizeof(float)); 01989 vScale = ( float *)malloc(sizeof(float)); 01990 uOffset = ( float *)malloc(sizeof(float)); 01991 vOffset = ( float *)malloc(sizeof(float)); 01992 01993 SAA_texture2DGetUScale( scene, textures, uScale ); 01994 SAA_texture2DGetVScale( scene, textures, vScale ); 01995 SAA_texture2DGetUOffset( scene, textures, uOffset ); 01996 SAA_texture2DGetVOffset( scene, textures, vOffset ); 01997 01998 if ( verbose >= 1 ) 01999 { 02000 fprintf( outStream, " global tex uScale: %f vScale: %f\n", 02001 *uScale, *vScale ); 02002 fprintf( outStream, " uOffset: %f vOffset: %f\n", 02003 *uOffset, *vOffset ); 02004 } 02005 02006 SAA_texture2DGetRepeats( scene, textures, &uRepeat, 02007 &vRepeat ); 02008 02009 if ( verbose >= 2 ) 02010 { 02011 fprintf(outStream, "uRepeat = %d, vRepeat = %d\n", 02012 uRepeat, vRepeat ); 02013 } 02014 } 02015 else fprintf( outStream, "Invalid texture...\n"); 02016 } 02017 02018 // make the egg vertex pool 02019 EggVertexPool *pool = _data.CreateVertexPool( parent, name ); 02020 02021 for ( i = 0; i < numVert; i++ ) 02022 { 02023 pfVec3 eggVert; 02024 pfVec3 eggNorm; 02025 02026 //convert to global coords 02027 SAA_DVector local = vertices[i]; 02028 SAA_DVector global; 02029 02030 _VCT_X_MAT( global, local, matrix ); 02031 02032 // set vertices array to reflect global coords 02033 //vertices[i].x = global.x; 02034 //vertices[i].y = global.y; 02035 //vertices[i].z = global.z; 02036 02037 //eggVert.set( vertices[i].x, vertices[i].y, vertices[i].z ); 02038 02039 // we'll preserve original verts for now 02040 eggVert.set( global.x, global.y, global.z ); 02041 02042 local = normals[indexMap[i]]; 02043 02044 _VCT_X_MAT( global, local, matrix ); 02045 02046 eggNorm.set( global.x, global.y, global.z ); 02047 eggNorm.normalize(); 02048 02049 pool->AddVertex( eggVert, i ); 02050 pool->Vertex(i)->attrib.SetNormal( eggNorm ); 02051 02052 // translate local uv's to global and add to vertex pool 02053 if ( numTexLoc && (uCoords != NULL && vCoords !=NULL )) 02054 { 02055 float u, v; 02056 02057 if ( ignore_tex_offsets ) { 02058 u = uCoords[indexMap[i]]; 02059 v = 1.0f - vCoords[indexMap[i]]; 02060 } else { 02061 u = (uCoords[indexMap[i]] - uOffset[indexMap[i]/3]) / 02062 uScale[indexMap[i]/3]; 02063 02064 v = 1.0f - ((vCoords[indexMap[i]] - vOffset[indexMap[i]/3]) / 02065 vScale[indexMap[i]/3]); 02066 } 02067 02068 if ( isNum(u) && isNum(v) ) 02069 { 02070 if ( uv_swap == TRUE ) 02071 pool->Vertex(i)->attrib.SetUV( v, u ); 02072 else 02073 pool->Vertex(i)->attrib.SetUV( u, v ); 02074 } 02075 } 02076 else if ( numTexGlb && (uCoords != NULL && vCoords !=NULL ) ) 02077 { 02078 float u, v; 02079 02080 if ( ignore_tex_offsets ) { 02081 u = uCoords[indexMap[i]]; 02082 v = 1.0f - vCoords[indexMap[i]]; 02083 } else { 02084 u = (uCoords[indexMap[i]] - *uOffset) / *uScale; 02085 v = 1.0f - (( vCoords[indexMap[i]] - *vOffset ) / *vScale); 02086 } 02087 02088 if ( isNum(u) && isNum(v) ) 02089 { 02090 if ( uv_swap == TRUE ) 02091 pool->Vertex(i)->attrib.SetUV( v, u ); 02092 else 02093 pool->Vertex(i)->attrib.SetUV( u, v ); 02094 } 02095 02096 } 02097 02098 // if we've encountered textures and we desire duv anims 02099 if (( numTexLoc || numTexGlb ) && make_duv ) 02100 { 02101 int numExp; 02102 SAA_Elem *tex; 02103 02104 // grab the current texture 02105 if ( numTexLoc ) 02106 tex = &textures[0]; 02107 else 02108 tex = textures; 02109 02110 // find how many expressions for this shape 02111 SAA_elementGetNbExpressions( scene, tex, NULL, FALSE, 02112 &numExp ); 02113 02114 // if it has expressions we'll assume its animated 02115 if ( numExp ) 02116 { 02117 // if animated object make base duv's, animtables 02118 // for the duv's and store the original offsets 02119 strstream uName, vName; 02120 02121 // create duv target names 02122 uName << name << ".u" << ends; 02123 vName << name << ".v" << ends; 02124 02125 // only create tables and store offsets 02126 // on a per model basis (not per vertex) 02127 if ( !i ) 02128 { 02129 02130 // make sure root morph table exists 02131 if ( morphRoot == NULL ) 02132 morphRoot = animData.CreateTable( animRoot, 02133 "morph" ); 02134 02135 // create morph table entry for each duv 02136 SAnimTable *uTable = new SAnimTable( ); 02137 uTable->name = uName.str(); 02138 uTable->fps = anim_rate; 02139 morphRoot->children.push_back( uTable ); 02140 if ( verbose >= 1 ) 02141 fprintf( outStream, "created duv table named: %s\n", uName.str() ); 02142 02143 SAnimTable *vTable = new SAnimTable( ); 02144 vTable->name = vName.str(); 02145 vTable->fps = anim_rate; 02146 morphRoot->children.push_back( vTable ); 02147 if ( verbose >= 1 ) 02148 fprintf( outStream, "created duv table named: %s\n", vName.str() ); 02149 02150 float texOffsets[4]; 02151 02152 if ( numTexGlb ) 02153 { 02154 texOffsets[0] = *uOffset; 02155 texOffsets[1] = *vOffset; 02156 texOffsets[2] = *uScale; 02157 texOffsets[3] = *vScale; 02158 } 02159 else 02160 { 02161 texOffsets[0] = uOffset[indexMap[i]/3]; 02162 texOffsets[1] = vOffset[indexMap[i]/3]; 02163 texOffsets[2] = uScale[indexMap[i]/3]; 02164 texOffsets[3] = vScale[indexMap[i]/3]; 02165 } 02166 02167 // remember original texture offsets future reference 02168 SAA_elementSetUserData( scene, model, "TEX_OFFSETS", 02169 sizeof( texOffsets ), TRUE, (void **)&texOffsets ); 02170 } 02171 02172 EggMorphOffset *duvU; 02173 EggMorphOffset *duvV; 02174 02175 // generate base duv's for this vertex 02176 duvU = new EggMorphOffset( uName.str(), 1.0 , 0.0 ); 02177 pool->Vertex(i)->attrib.uv_morphs.push_back( *duvU ); 02178 02179 duvV = new EggMorphOffset( vName.str(), 0.0 , 1.0 ); 02180 pool->Vertex(i)->attrib.uv_morphs.push_back( *duvV ); 02181 02182 } // if ( numExp ) 02183 02184 } // if ( numTexLoc || numTexGlb ) 02185 02186 } // for ( i = 0; i < numVert; i++ ) 02187 02188 // if model has key shapes, generate vertex offsets 02189 if ( has_morph && make_morph ) 02190 MakeVertexOffsets( scene, model, type, numShapes, numVert, 02191 vertices, matrix, name ); 02192 02193 02194 // create vertex ref list for all polygons in the model 02195 EggVertexRef *vref; 02196 02197 vref = new EggVertexRef( pool); 02198 for ( i = 0; i < numVert; i++ ) 02199 { 02200 //add each vert in pool to last joint for hard skinning 02201 vref->indices.push_back( EggVertexIndex( i ) ); 02202 } 02203 02204 // hard assign poly geometry if no soft-skinning requested 02205 // 02206 //disabled 1/1/99 to streamline joint assignments. 02207 // all hard-skinning now done in CleanUpSoftSkin. 02208 //if ( !make_soft ) 02209 //{ 02210 //if ( lastJoint != NULL ) 02211 //{ 02212 //lastJoint->vrefs.AddUniqueNode( *vref ); 02213 02214 //if ( verbose >= 1 ) 02215 //fprintf( outStream, "hard-skinning %s (%d vertices)\n", 02216 //name, i+1 ); 02217 //} 02218 //} 02219 02220 // make an egg group to hold all triangles 02221 EggGroup *group = _data.CreateGroup( parent, name); 02222 02223 // make this group the current parent 02224 parent = group; 02225 02226 EggPolygon *poly = NULL; 02227 EggColor *cref = NULL; 02228 EggTexture *tref = NULL; 02229 02230 // for each triangle 02231 for ( i = 0; i < numTri*3; i+=3 ) 02232 { 02233 float r,g,b,a; 02234 pfVec4 color; 02235 02236 // make egg poly for each traingle and reference 02237 // the appropriate vertex in the pool 02238 poly = _data.CreatePolygon( group, pool ); 02239 poly->AddVertex(indices[i]); 02240 poly->AddVertex(indices[i+1]); 02241 poly->AddVertex(indices[i+2]); 02242 02243 // check for back face flag in model note info 02244 char *modelNoteStr = GetModelNoteInfo( scene, model ); 02245 02246 if ( modelNoteStr != NULL ) 02247 { 02248 if ( strstr( modelNoteStr, "bface" ) != NULL ) 02249 poly->flags |= EG_BFACE; 02250 } 02251 02252 // check to see if material is present 02253 SAA_Boolean valid; 02254 SAA_elementIsValid( scene, &materials[i/3], &valid ); 02255 02256 // material present - get the color 02257 if ( valid ) 02258 { 02259 SAA_materialGetDiffuse( scene, &materials[i/3], &r, &g, &b ); 02260 SAA_materialGetTransparency( scene, &materials[i/3], &a ); 02261 color.set( r, g, b, 1.0f - a ); 02262 } 02263 // no material - default to white 02264 else 02265 color.set( 1.0, 1.0, 1.0, 1.0 ); 02266 02267 cref = _data.CreateColor(color); 02268 poly->attrib.SetCRef(cref); 02269 02270 strstream uniqueTexName; 02271 02272 if (numTexLoc) 02273 { 02274 // polytex 02275 if ( (texNameArray[i/3] != NULL) && 02276 (strcmp(texNameArray[i/3], "NULL") != 0) ) 02277 { 02278 // append unique identifier to texname for 02279 // this particular object 02280 uniqueTexName << name << "-" 02281 << RemovePathName(texNameArray[i/3]); 02282 02283 tref = _data.CreateTexture( texNameArray[i/3], 02284 uniqueTexName.str() ); 02285 02286 if ( verbose >= 1 ) 02287 fprintf( outStream, " tritex[%d] named: %s\n", i/3, 02288 texNameArray[i/3] ); 02289 } 02290 } 02291 else if ( numTexGlb ) 02292 { 02293 if ( texNameArray != NULL ) 02294 { 02295 // append unique identifier to texname for 02296 // this particular object 02297 uniqueTexName << name << "-" 02298 << RemovePathName(*texNameArray); 02299 02300 tref = _data.CreateTexture( *texNameArray, 02301 uniqueTexName.str() ); 02302 02303 if ( verbose >= 1 ) 02304 fprintf( outStream, " tritex named: %s\n", 02305 *texNameArray ); 02306 } 02307 } 02308 02309 // set the clamp on the texture 02310 if ( tref != NULL ) 02311 { 02312 if ( uRepeat > 0 ) 02313 tref->wrapu = EggTexture::WM_repeat; 02314 else 02315 tref->wrapu = EggTexture::WM_clamp; 02316 02317 if ( vRepeat > 1 ) 02318 tref->wrapv = EggTexture::WM_repeat; 02319 else 02320 tref->wrapv = EggTexture::WM_clamp; 02321 02322 poly->attrib.SetTRef(tref); 02323 } 02324 02325 } 02326 02327 // we're done - trash triangles... 02328 SAA_modelClearTriangles( scene, model ); 02329 02330 // free molloc'd memory 02331 //free( triangles ); 02332 //free( materials ); 02333 //free( normals ); 02334 //free( cvertices ); 02335 //free( vertices ); 02336 //free( indices ); 02337 //free( indexMap ); 02338 02339 // free these only if they were malloc'd for textures 02340 if (numTexLoc || numTexGlb) 02341 { 02342 //free( textures ); 02343 //free( uCoords ); 02344 //free( vCoords ); 02345 //free( texNameArray ); 02346 //free( uScale ); 02347 //free( vScale ); 02348 //free( uOffset ); 02349 //free( vOffset ); 02350 } 02351 } 02352 } 02353 else 02354 { 02355 /////////////////////////////////////// 02356 // check to see if its a nurbs surface 02357 /////////////////////////////////////// 02358 if ( (type == SAA_MNSRF) && ( visible ) && (( make_nurbs ) 02359 || ( !make_nurbs && !make_poly && make_duv )) ) 02360 { 02361 // check to see if NURBS is also skeleton... 02362 SAA_Boolean isSkeleton = FALSE; 02363 02364 SAA_modelIsSkeleton( scene, model, &isSkeleton ); 02365 02366 // check to see if this NURBS is used as a skeleton 02367 // or is animated via constraint only ( these nodes are 02368 // tagged by the animator with the keyword "joint" 02369 // somewhere in the nodes name) 02370 if ( isSkeleton || (strstr( name, "joint" ) != NULL) ) 02371 { 02372 MakeJoint( scene, lastJoint, lastAnim, model, name ); 02373 geom_as_joint = 1; 02374 if ( verbose >= 1 ) 02375 fprintf( outStream, "animating NURBS as joint!!!\n" ); 02376 } 02377 02378 EggNurbsSurface *eggNurbsSurf = new EggNurbsSurface( name ); 02379 int uDegree, vDegree; 02380 02381 // create nurbs representation of surface 02382 SAA_nurbsSurfaceGetDegree( scene, model, &uDegree, &vDegree ); 02383 eggNurbsSurf->u_order = uDegree + 1; 02384 eggNurbsSurf->v_order = vDegree + 1; 02385 if ( verbose >= 1 ) 02386 { 02387 fprintf( outStream, "nurbs degree: %d u, %d v\n", 02388 uDegree, vDegree ); 02389 fprintf( outStream, "nurbs order: %d u, %d v\n", 02390 uDegree + 1, vDegree + 1 ); 02391 } 02392 02393 SAA_Boolean uClosed = FALSE; 02394 SAA_Boolean vClosed = FALSE; 02395 02396 SAA_nurbsSurfaceGetClosed( scene, model, &uClosed, &vClosed); 02397 02398 if ( verbose >= 1 ) 02399 { 02400 if ( uClosed ) 02401 fprintf( outStream, "nurbs is closed in u...\n"); 02402 if ( vClosed ) 02403 fprintf( outStream, "nurbs is closed in v...\n"); 02404 } 02405 02406 int uRows, vRows; 02407 SAA_nurbsSurfaceGetNbVertices( scene, model, &uRows, &vRows ); 02408 if ( verbose >= 1 ) 02409 fprintf( outStream, "nurbs vertices: %d u, %d v\n", 02410 uRows, vRows ); 02411 02412 int uCurves, vCurves; 02413 SAA_nurbsSurfaceGetNbCurves( scene, model, &uCurves, &vCurves ); 02414 if ( verbose >= 1 ) 02415 fprintf( outStream, "nurbs curves: %d u, %d v\n", 02416 uCurves, vCurves ); 02417 02418 if ( shift_textures ) 02419 { 02420 if ( uClosed ) 02421 // shift starting point on NURBS surface for correct textures 02422 SAA_nurbsSurfaceShiftParameterization( scene, model, -2, 0 ); 02423 02424 if ( vClosed ) 02425 // shift starting point on NURBS surface for correct textures 02426 SAA_nurbsSurfaceShiftParameterization( scene, model, 0, -2 ); 02427 } 02428 02429 SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step ); 02430 02431 // check for back face flag in model note info 02432 char *modelNoteStr = GetModelNoteInfo( scene, model ); 02433 02434 if ( modelNoteStr != NULL ) 02435 { 02436 if ( strstr( modelNoteStr, "bface" ) != NULL ) 02437 eggNurbsSurf->flags |= EG_BFACE; 02438 } 02439 02440 int numKnotsU, numKnotsV; 02441 02442 SAA_nurbsSurfaceGetNbKnots( scene, model, &numKnotsU, &numKnotsV ); 02443 if ( verbose >= 1 ) 02444 fprintf( outStream, "nurbs knots: %d u, %d v\n", 02445 numKnotsU, numKnotsV ); 02446 02447 double *knotsU, *knotsV; 02448 knotsU = (double *)malloc(sizeof(double)*numKnotsU); 02449 knotsV = (double *)malloc(sizeof(double)*numKnotsV); 02450 SAA_nurbsSurfaceGetKnots( scene, model, gtype, 0, 02451 numKnotsU, numKnotsV, knotsU, knotsV ); 02452 02453 if ( verbose >= 2 ) 02454 fprintf( outStream, "u knots:\n" ); 02455 02456 AddKnots( eggNurbsSurf->u_knots, knotsU, numKnotsU, uClosed, uDegree ); 02457 if ( verbose >= 2 ) 02458 fprintf( outStream, "v knots:\n" ); 02459 02460 AddKnots( eggNurbsSurf->v_knots, knotsV, numKnotsV, vClosed, vDegree); 02461 02462 //free( knotsU ); 02463 //free( knotsV ); 02464 02465 // set sub_div so we can see it in perfly 02466 eggNurbsSurf->u_subdiv = (uRows-1)*nurbs_step; 02467 eggNurbsSurf->v_subdiv = (vRows-1)*nurbs_step; 02468 02469 SAA_modelGetNbVertices( scene, model, &numVert ); 02470 02471 if ( verbose >= 2 ) 02472 fprintf( outStream, "%d CV's\n", numVert ); 02473 02474 // get the CV's 02475 vertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numVert); 02476 SAA_modelGetVertices( scene, model, gtype, 0, 02477 numVert, vertices ); 02478 02479 // create pool of NURBS vertices 02480 EggVertexPool *pool = _data.CreateVertexPool( parent, name ); 02481 eggNurbsSurf->SetVertexPool( pool ); 02482 02483 // create vertex ref list for all cv's in the model 02484 EggVertexRef *vref; 02485 02486 vref = new EggVertexRef( pool); 02487 02488 for ( int k = 0; k<numVert; k++ ) 02489 { 02490 if ( verbose >= 2 ) 02491 { 02492 fprintf( outStream, "original cv[%d] = %f %f %f %f\n", k, 02493 vertices[k].x, vertices[k].y, vertices[k].z, 02494 vertices[k].w ); 02495 } 02496 02497 pfVec4 eggVert; 02498 02499 // convert to global coords 02500 SAA_DVector global; 02501 02502 _VCT_X_MAT( global, vertices[k], matrix ); 02503 02504 //preserve original weight 02505 global.w = vertices[k].w; 02506 02507 // normalize coords to weight 02508 global.x *= global.w; 02509 global.y *= global.w; 02510 global.z *= global.w; 02511 02512 // this code is commented out because I 02513 // am no longer sending global data to 02514 // the other routines (ie makevertexoffset) 02515 02516 // set vertices array to reflect global coords 02517 //vertices[k].x = global.x; 02518 //vertices[k].y = global.y; 02519 //vertices[k].z = global.z; 02520 //vertices[k].w = global.w; 02521 02522 //if ( verbose >= 2 ) 02523 //{ 02524 //fprintf( outStream, "global cv[%d] = %f %f %f %f\n", k, 02525 //vertices[k].x, vertices[k].y, vertices[k].z, 02526 //vertices[k].w ); 02527 //} 02528 02529 //eggVert.set( vertices[k].x, vertices[k].y, vertices[k].z, 02530 //vertices[k].w ); 02531 02532 if ( verbose >= 2 ) 02533 { 02534 fprintf( outStream, "global cv[%d] = %f %f %f %f\n", k, 02535 global.x, global.y, global.z, 02536 global.w ); 02537 } 02538 02539 eggVert.set( global.x, global.y, global.z, 02540 global.w ); 02541 02542 // populate vertex pool 02543 pool->AddVertex( eggVert, k ); 02544 02545 // add vref's to NURBS info 02546 eggNurbsSurf->AddVertex( k ); 02547 02548 //add each vert in pool to vref for hard skinning 02549 vref->indices.push_back( EggVertexIndex( k ) ); 02550 02551 // check to see if the NURB is closed in u 02552 if ( uClosed ) 02553 { 02554 // add first uDegree verts to end of row 02555 if ( (k % uRows) == ( uRows - 1) ) 02556 for ( int i = 0; i < uDegree; i++ ) 02557 { 02558 // add vref's to NURBS info 02559 eggNurbsSurf->AddVertex( i+((k/uRows)*uRows) ); 02560 02561 //add each vert to vref 02562 vref->indices.push_back( 02563 EggVertexIndex( i+((k/uRows)*uRows) ) ); 02564 } 02565 } 02566 } 02567 02568 // if hard skinned or this nurb is also a joint 02569 // 02570 //disabled 1/1/99 to streamline joint assignments. 02571 // all hard skinning now done in CleanUpSoftSkin. 02572 //if (!make_soft || geom_as_joint) 02573 //{ 02574 //add the new cv references to the last 02575 //joint for hard skinning only 02576 //if ( lastJoint != NULL ) 02577 //{ 02578 //lastJoint->vrefs.AddUniqueNode( *vref ); 02579 //geom_as_joint = 0; 02580 //if ( verbose >= 1 ) 02581 //fprintf( outStream, "Doing NURBS hard skinning...\n"); 02582 //} 02583 //} 02584 02585 // check to see if the NURB is closed in v 02586 if ( vClosed && !uClosed ) 02587 { 02588 // add first vDegree rows of verts to end of list 02589 for ( int i = 0; i < vDegree*uRows; i++ ) 02590 eggNurbsSurf->AddVertex( i ); 02591 } 02592 // check to see if the NURB is closed in u and v 02593 else if ( vClosed && uClosed ) 02594 { 02595 // add the first (degree) v verts and a few 02596 // extra - for good measure 02597 for ( i = 0; i < vDegree; i++ ) 02598 { 02599 // add first vDegree rows of verts to end of list 02600 for ( j = 0; j < uRows; j++ ) 02601 eggNurbsSurf->AddVertex( j+(i*uRows) ); 02602 02603 // if u is closed to we have added uDegree 02604 // verts onto the ends of the rows - add them here too 02605 for ( k = 0; k < uDegree; k++ ) 02606 eggNurbsSurf->AddVertex( k+(i*uRows)+((k/uRows)*uRows) ); 02607 } 02608 02609 } 02610 02611 // get the color of the NURBS surface 02612 int numNurbMats; 02613 EggColor *nurbCref; 02614 pfVec4 nurbColor; 02615 02616 SAA_modelRelationGetMatNbElements( scene, model, FALSE, &relinfo, 02617 &numNurbMats ); 02618 02619 if ( verbose >= 1 ) 02620 fprintf( outStream, "nurbs surf has %d materials\n", 02621 numNurbMats ); 02622 02623 if ( numNurbMats ) 02624 { 02625 float r,g,b,a; 02626 02627 materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numNurbMats); 02628 02629 SAA_modelRelationGetMatElements( scene, model, relinfo, 02630 numNurbMats, materials ); 02631 02632 SAA_materialGetDiffuse( scene, &materials[0], &r, &g, &b ); 02633 SAA_materialGetTransparency( scene, &materials[0], &a ); 02634 nurbColor.set( r, g, b, 1.0f - a ); 02635 //nurbColor.set( r, g, b, 1.0 ); 02636 02637 nurbCref = _data.CreateColor(nurbColor); 02638 eggNurbsSurf->attrib.SetCRef(nurbCref); 02639 02640 //get the texture of the NURBS surface from the material 02641 int numNurbTexLoc = 0; 02642 int numNurbTexGlb = 0; 02643 02644 // ASSUME only one texture per material 02645 SAA_Elem nurbTex; 02646 02647 // find out how many local textures per NURBS surface 02648 // ASSUME it only has one material 02649 SAA_materialRelationGetT2DLocNbElements( scene, &materials[0], 02650 FALSE, &relinfo, &numNurbTexLoc ); 02651 02652 // if present, get local textures 02653 if ( numNurbTexLoc ) 02654 { 02655 if ( verbose >= 1 ) 02656 fprintf( outStream, "%s had %d local tex\n", name, 02657 numNurbTexLoc ); 02658 02659 // get the referenced texture 02660 SAA_materialRelationGetT2DLocElements( scene, &materials[0], 02661 TEX_PER_MAT, &nurbTex ); 02662 02663 } 02664 // if no locals, try to get globals 02665 else 02666 { 02667 SAA_modelRelationGetT2DGlbNbElements( scene, model, 02668 FALSE, &relinfo, &numNurbTexGlb ); 02669 02670 if ( numNurbTexGlb ) 02671 { 02672 if ( verbose >= 1 ) 02673 fprintf( outStream, "%s had %d global tex\n", name, 02674 numNurbTexGlb ); 02675 02676 // get the referenced texture 02677 SAA_modelRelationGetT2DGlbElements( scene, 02678 model, TEX_PER_MAT, &nurbTex ); 02679 } 02680 } 02681 02682 // add tex ref's if we found any textures 02683 if ( numNurbTexLoc || numNurbTexGlb) 02684 { 02685 char *texName = NULL; 02686 char *uniqueTexName = NULL; 02687 EggTexture *tref; 02688 pfMatrix nurbTexMat; 02689 02690 02691 // convert the texture to .rgb and adjust name 02692 texName = ConvertTexture( scene, &nurbTex ); 02693 02694 // append unique identifier to texname for 02695 // this particular object 02696 uniqueTexName = (char *)malloc(sizeof(char)* 02697 (strlen(name)+strlen(texName)+3) ); 02698 sprintf( uniqueTexName, "%s-%s", name, 02699 RemovePathName(texName) ); 02700 02701 if ( verbose >= 1 ) 02702 { 02703 fprintf( outStream, "creating tref %s\n", 02704 uniqueTexName ); 02705 } 02706 02707 tref = _data.CreateTexture( texName, uniqueTexName ); 02708 02709 uScale = ( float *)malloc(sizeof(float)); 02710 vScale = ( float *)malloc(sizeof(float)); 02711 uOffset = ( float *)malloc(sizeof(float)); 02712 vOffset = ( float *)malloc(sizeof(float)); 02713 02714 // get texture offset info 02715 SAA_texture2DGetUScale( scene, &nurbTex, uScale ); 02716 SAA_texture2DGetVScale( scene, &nurbTex, vScale ); 02717 SAA_texture2DGetUOffset( scene, &nurbTex, uOffset ); 02718 SAA_texture2DGetVOffset( scene, &nurbTex, vOffset ); 02719 SAA_texture2DGetUVSwap( scene, &nurbTex, &uv_swap ); 02720 02721 02722 if ( verbose >= 1 ) 02723 { 02724 fprintf( outStream, "nurbTex uScale: %f\n", *uScale ); 02725 fprintf( outStream, "nurbTex vScale: %f\n", *vScale ); 02726 fprintf( outStream, "nurbTex uOffset: %f\n", *uOffset ); 02727 fprintf( outStream, "nurbTex vOffset: %f\n", *vOffset ); 02728 if ( uv_swap ) 02729 fprintf( outStream, "nurbTex u & v swapped!\n" ); 02730 else 02731 fprintf( outStream, "nurbTex u & v NOT swapped\n" ); 02732 } 02733 02734 nurbTexMat.makeIdent(); 02735 02736 if ( !ignore_tex_offsets ) 02737 { 02738 if ( uv_swap ) 02739 { 02740 nurbTexMat[0][0] = 0.0f; 02741 nurbTexMat[1][1] = 0.0f; 02742 nurbTexMat[0][1] = 1 / *vScale; 02743 nurbTexMat[1][0] = 1 / *uScale; 02744 nurbTexMat[2][1] = -(*uOffset / *uScale); 02745 nurbTexMat[2][0] = -(*vOffset / *vScale); 02746 } 02747 else 02748 { 02749 nurbTexMat[0][0] = 1 / *uScale; 02750 nurbTexMat[1][1] = 1 / *vScale; 02751 nurbTexMat[2][0] = -(*uOffset / *uScale); 02752 nurbTexMat[2][1] = -(*vOffset / *vScale); 02753 } 02754 } 02755 02756 02757 //call printMat 02758 if ( verbose >= 2 ) 02759 { 02760 fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[0][0], 02761 nurbTexMat[0][1], nurbTexMat[0][2], nurbTexMat[0][3] ); 02762 fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[1][0], 02763 nurbTexMat[1][1], nurbTexMat[1][2], nurbTexMat[1][3] ); 02764 fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[2][0], 02765 nurbTexMat[2][1], nurbTexMat[2][2], nurbTexMat[2][3] ); 02766 fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[3][0], 02767 nurbTexMat[3][1], nurbTexMat[3][2], nurbTexMat[3][3] ); 02768 } 02769 02770 02771 tref->tex_mat = nurbTexMat; 02772 tref->flags |= EFT_TRANSFORM; 02773 02774 eggNurbsSurf->attrib.SetTRef(tref); 02775 02776 } 02777 02778 // if we've encountered textures and we desire duv anims 02779 if (( numNurbTexLoc || numNurbTexGlb ) && make_duv ) 02780 { 02781 int numExp; 02782 02783 // find how many expressions for this shape 02784 SAA_elementGetNbExpressions( scene, &nurbTex, NULL, FALSE, 02785 &numExp ); 02786 02787 // if it has expressions we'll assume its animated 02788 if ( numExp ) 02789 { 02790 if ( verbose > 1 ) 02791 printf( "nurbTex has %d expressions...\n", numExp ); 02792 02793 // if animated object make base duv's, animtables 02794 // for the duv's and store the original offsets 02795 strstream uName, vName; 02796 02797 // create duv target names 02798 uName << name << ".u" << ends; 02799 vName << name << ".v" << ends; 02800 02801 // make sure root morph table exists 02802 if ( morphRoot == NULL ) 02803 morphRoot = animData.CreateTable( animRoot, 02804 "morph" ); 02805 02806 // create morph table entry for each duv 02807 SAnimTable *uTable = new SAnimTable( ); 02808 uTable->name = uName.str(); 02809 uTable->fps = anim_rate; 02810 morphRoot->children.push_back( uTable ); 02811 if ( verbose >= 1 ) 02812 fprintf( outStream, "created duv table named: %s\n", uName.str() ); 02813 02814 SAnimTable *vTable = new SAnimTable( ); 02815 vTable->name = vName.str(); 02816 vTable->fps = anim_rate; 02817 morphRoot->children.push_back( vTable ); 02818 if ( verbose >= 1 ) 02819 fprintf( outStream, "created duv table named: %s\n", vName.str() ); 02820 02821 float texOffsets[4]; 02822 02823 texOffsets[0] = *uOffset; 02824 texOffsets[1] = *vOffset; 02825 texOffsets[2] = *uScale; 02826 texOffsets[3] = *vScale; 02827 02828 // remember original texture offsets future reference 02829 SAA_elementSetUserData( scene, model, "TEX_OFFSETS", 02830 sizeof( texOffsets ), TRUE, (void **)&texOffsets ); 02831 02832 // create UV's and duv's for each vertex 02833 for( i = 0; i < numVert; i++ ) 02834 { 02835 pfVec2 tmpUV; 02836 EggMorphOffset *duvU; 02837 EggMorphOffset *duvV; 02838 02839 //create uv's so we can store duv's 02840 eggNurbsSurf->CalcActualUV( i, tmpUV ); 02841 pool->Vertex(i)->attrib.SetUV( tmpUV[0], tmpUV[1] ); 02842 02843 // generate base duv's for this vertex 02844 duvU = new EggMorphOffset(uName.str(), 1.0 , 0.0); 02845 pool->Vertex(i)->attrib.uv_morphs.push_back(*duvU); 02846 02847 duvV = new EggMorphOffset(vName.str(), 0.0 , 1.0); 02848 pool->Vertex(i)->attrib.uv_morphs.push_back(*duvV); 02849 } 02850 02851 } // if ( numExp ) 02852 } // if ( numTexLoc || numTexGlb ) 02853 02854 //free( uScale ); 02855 //free( vScale ); 02856 //free( uOffset ); 02857 //free( vOffset ); 02858 02859 //free( materials ); 02860 } 02861 else 02862 { 02863 // no material present - default to white 02864 nurbColor.set( 1.0, 1.0, 1.0, 1.0 ); 02865 } 02866 02867 ////////////////////////////////////////// 02868 // check NURBS surface for trim curves 02869 ////////////////////////////////////////// 02870 int numTrims; 02871 bool isTrim = TRUE; 02872 SAA_SubElem *trims; 02873 02874 SAA_nurbsSurfaceGetNbTrimCurves( scene, model, SAA_TRIMTYPE_TRIM, 02875 &numTrims ); 02876 02877 if ( verbose >= 1 ) 02878 fprintf( outStream, "nurbs surf has %d trim curves\n", 02879 numTrims ); 02880 02881 if ( numTrims) 02882 { 02883 trims = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTrims); 02884 02885 if ( trims ) 02886 { 02887 SAA_nurbsSurfaceGetTrimCurves( scene, model, 02888 gtype, 0, SAA_TRIMTYPE_TRIM, numTrims, 02889 trims ); 02890 02891 MakeSurfaceCurve( scene, model, parent, eggNurbsSurf, 02892 numTrims, trims, isTrim ); 02893 } 02894 02895 //free( trims ); 02896 } 02897 02898 ////////////////////////////////////////// 02899 // check NURBS surface for surface curves 02900 ////////////////////////////////////////// 02901 isTrim = FALSE; 02902 02903 SAA_nurbsSurfaceGetNbTrimCurves( scene, model, 02904 SAA_TRIMTYPE_PROJECTION, &numTrims ); 02905 02906 if ( verbose >= 1 ) 02907 fprintf( outStream, "nurbs surf has %d surface curves\n", 02908 numTrims ); 02909 02910 if ( numTrims) 02911 { 02912 trims = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTrims); 02913 02914 if ( trims ) 02915 { 02916 SAA_nurbsSurfaceGetTrimCurves( scene, model, 02917 gtype, 0, SAA_TRIMTYPE_PROJECTION, 02918 numTrims, trims ); 02919 02920 MakeSurfaceCurve( scene, model, parent, eggNurbsSurf, 02921 numTrims, trims, isTrim ); 02922 } 02923 02924 //free( trims ); 02925 } 02926 02927 // push the NURBS into the egg data 02928 parent->children.push_back( eggNurbsSurf ); 02929 02930 // if model has key shapes, generate vertex offsets 02931 if ( has_morph && make_morph ) 02932 MakeVertexOffsets( scene, model, type, numShapes, numVert, 02933 vertices, matrix, name ); 02934 02935 02936 //free( vertices ); 02937 02938 } 02939 ///////////////////////////////////// 02940 // check to see if its a NURBS curve 02941 ///////////////////////////////////// 02942 else if ( (type == SAA_MNCRV) && ( visible ) && ( make_nurbs ) ) 02943 { 02944 // ignore for now 02945 // make the NURBS curve and push it into the egg data 02946 //parent->children.push_back( MakeNurbsCurve( scene, model, parent, 02947 //matrix, name ) ); 02948 } 02949 else if ( type == SAA_MJNT ) 02950 { 02951 MakeJoint( scene, lastJoint, lastAnim, model, name ); 02952 if ( verbose >= 1 ) 02953 fprintf( outStream, "encountered IK joint: %s\n", name ); 02954 } 02955 ///////////////////// 02956 // it must be a NULL 02957 ///////////////////// 02958 else 02959 { 02960 SAA_AlgorithmType algo; 02961 02962 SAA_modelGetAlgorithm( scene, model, &algo ); 02963 if ( verbose >= 1 ) 02964 fprintf( outStream, "null algorithm: %d\n", algo ); 02965 02966 if ( algo == SAA_ALG_INV_KIN ) 02967 { 02968 MakeJoint( scene, lastJoint, lastAnim, model, name ); 02969 if ( verbose >= 1 ) 02970 fprintf( outStream, "encountered IK root: %s\n", name ); 02971 } 02972 else if ( algo == SAA_ALG_INV_KIN_LEAF ) 02973 { 02974 MakeJoint( scene, lastJoint, lastAnim, model, name ); 02975 if ( verbose >= 1 ) 02976 fprintf( outStream, "encountered IK leaf: %s\n", name ); 02977 } 02978 else if ( algo == SAA_ALG_STANDARD ) 02979 { 02980 SAA_Boolean isSkeleton = FALSE; 02981 02982 if ( verbose >= 1 ) 02983 fprintf( outStream, "encountered Standard null: %s\n", name); 02984 02985 SAA_modelIsSkeleton( scene, model, &isSkeleton ); 02986 02987 // check to see if this NULL is used as a skeleton 02988 // or is animated via constraint only ( these nodes are 02989 // tagged by the animator with the keyword "joint" 02990 // somewhere in the nodes name) 02991 if ( isSkeleton || (strstr( name, "joint" ) != NULL) ) 02992 { 02993 MakeJoint( scene, lastJoint, lastAnim, model, name ); 02994 if ( verbose >= 1 ) 02995 fprintf( outStream, "animating Standard null!!!\n" ); 02996 } 02997 02998 } 02999 else 03000 if ( verbose >= 1 ) 03001 fprintf( outStream, "encountered some other NULL: %d\n", 03002 algo ); 03003 } 03004 } 03005 03006 03007 // check for children... 03008 int numChildren; 03009 int thisChild; 03010 SAA_Elem *children; 03011 03012 SAA_modelGetNbChildren( scene, model, &numChildren ); 03013 if ( verbose >= 1 ) 03014 fprintf( outStream, "Model children: %d\n", numChildren ); 03015 03016 if ( numChildren ) 03017 { 03018 children = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numChildren); 03019 SAA_modelGetChildren( scene, model, numChildren, children ); 03020 if ( children != NULL ) 03021 { 03022 for ( thisChild = 0; thisChild < numChildren; thisChild++ ) 03023 { 03024 if ( verbose >= 1 ) 03025 fprintf( outStream, "\negging child %d...\n", thisChild); 03026 MakeEgg( parent, lastJoint, lastAnim, scene, 03027 &children[thisChild] ); 03028 } 03029 } 03030 else 03031 fprintf( outStream, "Not enough Memory for children...\n"); 03032 //free( children ); 03033 } 03034 fflush( outStream ); 03035 } 03036 else 03037 if ( verbose >= 1 ) 03038 fprintf( outStream, "Don't descend this branch!\n" ); 03039 03040 // we are done for the most part - start cleaning up memory 03041 //free( name ); 03042 } 03043 03044 03045 //////////////////////////////////////////////////////////////////// 03046 // Function: MakeSurfaceCurve 03047 // Access: Public 03048 // Description: Given a scene and lists of u and v samples create a 03049 // an egg NURBS curve of degree two from the samples 03050 //////////////////////////////////////////////////////////////////// 03051 void soft2egg:: 03052 MakeSurfaceCurve( SAA_Scene *scene, SAA_Elem *model, EggGroup *parent, 03053 EggNurbsSurface *&nurbsSurf, int numTrims, SAA_SubElem *trims, 03054 bool isTrim ) 03055 { 03056 int i; 03057 long totalSamples = 0; 03058 long *numSamples; 03059 double *uSamples; 03060 double *vSamples; 03061 SAA_Elem *trimCurves; 03062 char *name; 03063 03064 //get UV coord data 03065 numSamples = (long *)malloc(sizeof(long)*numTrims); 03066 03067 SAA_surfaceCurveGetNbLinearSamples( scene, model, numTrims, trims, 03068 numSamples ); 03069 03070 for ( i = 0; i < numTrims; i++ ) 03071 { 03072 totalSamples += numSamples[i]; 03073 if ( verbose >= 2 ) 03074 fprintf( outStream, "numSamples[%d] = %d\n", i, numSamples[i] ); 03075 } 03076 03077 if ( verbose >= 2 ) 03078 fprintf( outStream, "total samples = %ld\n", totalSamples ); 03079 03080 uSamples = (double *)malloc(sizeof(double)*totalSamples); 03081 vSamples = (double *)malloc(sizeof(double)*totalSamples); 03082 03083 SAA_surfaceCurveGetLinearSamples( scene, model, numTrims, trims, 03084 numSamples, uSamples, vSamples ); 03085 03086 if ( verbose >= 2 ) 03087 for ( long li = 0; li < totalSamples; li++ ) 03088 fprintf( outStream, "master list cv[%ld] = %f, %f\n", li, 03089 uSamples[li], vSamples[li] ); 03090 03091 trimCurves = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTrims); 03092 03093 SAA_surfaceCurveExtract( scene, model, numTrims, trims, trimCurves ); 03094 03095 // if it's a trim create a trim to assign trim curves to 03096 EggNurbsSurface::Trim *eggTrim = new EggNurbsSurface::Trim(); 03097 03098 // for each trim curve, make an egg curve and 03099 // add it to the trims of the NURBS surface 03100 for ( i = 0; i < numTrims; i++ ) 03101 { 03102 if ( use_prefix ) 03103 { 03104 // Get the FULL name of the trim curve 03105 name = GetFullName( scene, &trimCurves[i] ); 03106 } 03107 else 03108 { 03109 // Get the name of the trim curve 03110 name = GetName( scene, &trimCurves[i] ); 03111 } 03112 03113 if ( isTrim ) 03114 { 03115 // add to trim list 03116 EggNurbsSurface::Loop *eggLoop = new EggNurbsSurface::Loop(); 03117 eggLoop->push_back( MakeUVNurbsCurve( i, numSamples, uSamples, 03118 vSamples, parent, name ) ); 03119 eggTrim->push_back( *eggLoop ); 03120 } 03121 else 03122 // add to curve list 03123 nurbsSurf->curves.push_back( MakeUVNurbsCurve( i, numSamples, uSamples, vSamples, parent, name ) ); 03124 } 03125 03126 if ( isTrim ) 03127 // pus trim list onto trims list 03128 nurbsSurf->trims.push_back( *eggTrim ); 03129 03130 //free( name ); 03131 //free( trimCurves ); 03132 //free( uSamples ); 03133 //free( vSamples ); 03134 } 03135 03136 //////////////////////////////////////////////////////////////////// 03137 // Function: MakeUVNurbsCurve 03138 // Access: Public 03139 // Description: Given a scene and lists of u and v samples create a 03140 // an egg NURBS curve of degree two from the samples 03141 //////////////////////////////////////////////////////////////////// 03142 EggNurbsCurve *soft2egg:: 03143 MakeUVNurbsCurve( int numCurve, long *numSamples, double *uSamples, 03144 double *vSamples, EggGroup *parent, char *name ) 03145 { 03146 EggNurbsCurve *eggNurbsCurve = new EggNurbsCurve( name ); 03147 03148 eggNurbsCurve->order = 2; 03149 03150 03151 if ( verbose >= 2 ) 03152 fprintf( outStream, "nurbs UV curve %s:\n", name ); 03153 03154 //set sub_div so we can see it in perfly 03155 //eggNurbsCurve->subdiv = numSamples[numCurve]/4; 03156 // perfly chokes on big numbers - keep it reasonable 03157 eggNurbsCurve->subdiv = 150; 03158 03159 //create pool of NURBS vertices 03160 EggVertexPool *pool = _data.CreateVertexPool( parent, name ); 03161 eggNurbsCurve->SetVertexPool( pool ); 03162 03163 // calculate offset to this curve's samples 03164 // in list of all curve samples 03165 int offset = 0; 03166 03167 for ( int o = 0; o < numCurve; o++ ) 03168 offset += numSamples[o]; 03169 03170 for ( int k = 0; k<numSamples[numCurve]; k++ ) 03171 { 03172 pfVec3 eggVert; 03173 03174 // index into the array of samples for this curve 03175 eggVert.set( uSamples[k+offset], vSamples[k+offset], 1.0f ); 03176 03177 if ( verbose >= 2 ) 03178 fprintf( outStream, "cv[%d] = %f %f %f\n", k, eggVert[0], 03179 eggVert[1], eggVert[2] ); 03180 03181 //populate vertex pool 03182 pool->AddVertex( eggVert, k ); 03183 03184 //add vref's to NURBS info 03185 eggNurbsCurve->AddVertex( k ); 03186 } 03187 03188 // create numSamples[numCurve]+2 knots 03189 eggNurbsCurve->knots.push_back( 0 ); 03190 for ( k = 0; k < numSamples[numCurve]; k++ ) 03191 eggNurbsCurve->knots.push_back( k ); 03192 eggNurbsCurve->knots.push_back( numSamples[numCurve] - 1 ); 03193 03194 //set color to bright green for now 03195 EggColor *nurbCref; 03196 pfVec4 nurbColor; 03197 03198 nurbColor.set( 0.5, 1.0, 0.5, 1.0 ); 03199 nurbCref = _data.CreateColor(nurbColor); 03200 eggNurbsCurve->attrib.SetCRef(nurbCref); 03201 03202 return( eggNurbsCurve ); 03203 } 03204 03205 //////////////////////////////////////////////////////////////////// 03206 // Function: MakeNurbsCurve 03207 // Access: Public 03208 // Description: Given a scene and a NURBS curve model create the 03209 // the appropriate egg structures 03210 //////////////////////////////////////////////////////////////////// 03211 EggNurbsCurve *soft2egg:: 03212 MakeNurbsCurve( SAA_Scene *scene, SAA_Elem *model, EggGroup *parent, 03213 float matrix[4][4], char *name ) 03214 { 03215 EggNurbsCurve *eggNurbsCurve = new EggNurbsCurve( name ); 03216 int degree; 03217 03218 if ( verbose >= 2 ) 03219 fprintf( outStream, "nurbs curve %s:\n", name ); 03220 03221 //create nurbs representation of surface 03222 SAA_nurbsCurveGetDegree( scene, model, °ree ); 03223 eggNurbsCurve->order = degree + 1; 03224 if ( verbose >= 2 ) 03225 fprintf( outStream, "nurbs curve order: %d\n", degree + 1 ); 03226 03227 SAA_nurbsCurveSetStep( scene, model, nurbs_step ); 03228 03229 SAA_Boolean closed = FALSE; 03230 03231 SAA_nurbsCurveGetClosed( scene, model, &closed ); 03232 if ( closed ) 03233 if ( verbose >= 2 ) 03234 fprintf( outStream, "nurbs curve is closed...\n"); 03235 03236 int numKnots; 03237 03238 SAA_nurbsCurveGetNbKnots( scene, model, &numKnots ); 03239 if ( verbose >= 2 ) 03240 fprintf( outStream, "nurbs curve knots: %d\n", numKnots ); 03241 double *knots; 03242 knots = (double *)malloc(sizeof(double)*numKnots); 03243 SAA_nurbsCurveGetKnots( scene, model, SAA_GEOM_ORIGINAL, 0, 03244 numKnots, knots ); 03245 03246 AddKnots( eggNurbsCurve->knots, knots, numKnots, closed, degree ); 03247 03248 //free( knots ); 03249 03250 int numCV; 03251 03252 SAA_modelGetNbVertices( scene, model, &numCV ); 03253 if ( verbose >= 2 ) 03254 fprintf( outStream, "%d CV's (=? %d)\n", numCV, (numKnots-(degree+1)) ); 03255 03256 //set sub_div so we can see it in perfly 03257 eggNurbsCurve->subdiv = (numCV-1)*nurbs_step; 03258 03259 // get the CV's 03260 SAA_DVector *cvArray; 03261 cvArray = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV); 03262 SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0, 03263 numCV, cvArray ); 03264 03265 //create pool of NURBS vertices 03266 EggVertexPool *pool = _data.CreateVertexPool( parent, name ); 03267 eggNurbsCurve->SetVertexPool( pool ); 03268 03269 for ( int k = 0; k<numCV; k++ ) 03270 { 03271 if ( verbose >= 2 ) 03272 fprintf( outStream, "cv[%d] = %f %f %f %f\n", k, cvArray[k].x, 03273 cvArray[k].y, cvArray[k].z, cvArray[k].w ); 03274 03275 pfVec4 eggVert; 03276 03277 //convert to global coords 03278 SAA_DVector local = cvArray[k]; 03279 SAA_DVector global; 03280 03281 _HVCT_X_MAT( global, local, matrix ); 03282 03283 eggVert.set( global.x, global.y, global.z, global.w ); 03284 03285 //populate vertex pool 03286 pool->AddVertex( eggVert, k ); 03287 03288 //add vref's to NURBS info 03289 eggNurbsCurve->AddVertex( k ); 03290 } 03291 03292 if ( closed ) 03293 { 03294 // need to replicate first (degree) vertices 03295 for ( k = 0; k < degree; k++ ) 03296 { 03297 eggNurbsCurve->AddVertex( k ); 03298 if ( verbose >= 2 ) 03299 fprintf( outStream, "adding cv[%d] = %f %f %f %f\n", k, 03300 cvArray[k].x, cvArray[k].y, cvArray[k].z, cvArray[k].w ); 03301 } 03302 } 03303 03304 //free( cvArray ); 03305 03306 //set color to bright green for now 03307 EggColor *nurbCref; 03308 pfVec4 nurbColor; 03309 03310 nurbColor.set( 0.5, 1.0, 0.5, 1.0 ); 03311 nurbCref = _data.CreateColor(nurbColor); 03312 eggNurbsCurve->attrib.SetCRef(nurbCref); 03313 03314 return( eggNurbsCurve ); 03315 } 03316 03317 //////////////////////////////////////////////////////////////////// 03318 // Function: AddKnots 03319 // Access: Public 03320 // Description: Given a parametric surface, and its knots, create 03321 // the appropriate egg structure by filling in Soft's 03322 // implicit knots and assigning the rest to eggKnots. 03323 //////////////////////////////////////////////////////////////////// 03324 void soft2egg:: 03325 AddKnots( perf_vector<double> &eggKnots, double *knots, int numKnots, 03326 SAA_Boolean closed, int degree ) 03327 { 03328 int k = 0; 03329 double lastKnot = knots[0]; 03330 double *newKnots; 03331 03332 // add initial implicit knot(s) 03333 if ( closed ) 03334 { 03335 int i = 0; 03336 newKnots = (double *)malloc(sizeof(double)*degree); 03337 03338 // need to add (degree) number of knots 03339 for ( k = numKnots - 1; k >= numKnots - degree; k-- ) 03340 { 03341 // we have to know these in order to calculate 03342 // next knot value so hold them in temp array 03343 newKnots[i] = lastKnot - (knots[k] - knots[k-1]); 03344 lastKnot = newKnots[i]; 03345 i++; 03346 } 03347 for ( k = degree - 1; k >= 0; k-- ) 03348 { 03349 eggKnots.push_back( newKnots[k] ); 03350 if ( verbose >= 2 ) 03351 fprintf( outStream, "knots[%d] = %f\n", k, newKnots[k] ); 03352 } 03353 03354 //free( newKnots ); 03355 } 03356 else 03357 { 03358 eggKnots.push_back( knots[k] ); 03359 if ( verbose >= 2 ) 03360 fprintf( outStream, "knots[%d] = %f\n", k, knots[k] ); 03361 } 03362 03363 // add the regular complement of knots 03364 for (k = 0; k < numKnots; k++) 03365 { 03366 eggKnots.push_back( knots[k] ); 03367 if ( verbose >= 2 ) 03368 fprintf( outStream, "knots[%d] = %f\n", k+1, knots[k] ); 03369 } 03370 03371 lastKnot = knots[numKnots-1]; 03372 03373 // add trailing implicit knots 03374 if ( closed ) 03375 { 03376 03377 // need to add (degree) number of knots 03378 for ( k = 1; k <= degree; k++ ) 03379 { 03380 eggKnots.push_back( lastKnot + (knots[k] - knots[k-1]) ); 03381 if ( verbose >= 2 ) 03382 fprintf( outStream, "knots[%d] = %f\n", k, 03383 lastKnot + (knots[k] - knots[k-1]) ); 03384 lastKnot = lastKnot + (knots[k] - knots[k-1]); 03385 } 03386 } 03387 else 03388 { 03389 eggKnots.push_back( knots[k-1] ); 03390 if ( verbose >= 2 ) 03391 fprintf( outStream, "knots[%d] = %f\n", k+1, knots[k-1] ); 03392 } 03393 } 03394 03395 //////////////////////////////////////////////////////////////////// 03396 // Function: MakeJoint 03397 // Access: Public 03398 // Description: Given a name, a parent and a model create a new 03399 // a new EggJoint for that model. 03400 //////////////////////////////////////////////////////////////////// 03401 void soft2egg:: 03402 MakeJoint( SAA_Scene *scene, EggJoint *&lastJoint, AnimGroup *&lastAnim, 03403 SAA_Elem *model, char *name ) 03404 { 03405 float matrix[4][4]; 03406 pfMatrix Matrix; 03407 EggJoint *joint; 03408 SAA_Boolean globalFlag = FALSE; 03409 int scale_joint = 0; 03410 03411 03412 // this is a quick fix to make scaled skeletons possible 03413 // if the parent contains the keyword "scale" make this joint 03414 // a global root joint instead of a child... 03415 if (lastJoint != NULL) 03416 { 03417 if ( strstr( lastJoint->name.Str(), "scale" ) != NULL ) 03418 { 03419 scale_joint = 1; 03420 if ( verbose >= 1 ) 03421 fprintf( outStream, "scale joint flag set!\n" ); 03422 } 03423 } 03424 03425 // if not root, flatten is false, and last joint had no scaling 03426 // applied to it, then create joint in skeleton tree 03427 if ( (lastJoint != NULL) && !flatten && !scale_joint ) 03428 { 03429 if ( verbose >= 1 ) 03430 { 03431 fprintf( outStream, "lastJoint = %s\n", lastJoint->name.Str() ); 03432 fprintf( outStream, "getting local transform\n" ); 03433 } 03434 03435 SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ), 03436 TRUE, (void **)&globalFlag ); 03437 03438 // get the local matrix 03439 SAA_modelGetMatrix( scene, model, SAA_COORDSYS_LOCAL, matrix ); 03440 03441 // make this into a pfMatrix 03442 Matrix[0][0] = matrix[0][0]; 03443 Matrix[0][1] = matrix[0][1]; 03444 Matrix[0][2] = matrix[0][2]; 03445 Matrix[0][3] = matrix[0][3]; 03446 Matrix[1][0] = matrix[1][0]; 03447 Matrix[1][1] = matrix[1][1]; 03448 Matrix[1][2] = matrix[1][2]; 03449 Matrix[1][3] = matrix[1][3]; 03450 Matrix[2][0] = matrix[2][0]; 03451 Matrix[2][1] = matrix[2][1]; 03452 Matrix[2][2] = matrix[2][2]; 03453 Matrix[2][3] = matrix[2][3]; 03454 Matrix[3][0] = matrix[3][0]; 03455 Matrix[3][1] = matrix[3][1]; 03456 Matrix[3][2] = matrix[3][2]; 03457 Matrix[3][3] = matrix[3][3]; 03458 03459 joint = _data.CreateJoint( lastJoint, name ); 03460 joint->transform = Matrix; 03461 } 03462 // if we already have a root attach this joint to it 03463 else if (foundRoot) 03464 { 03465 if ( verbose >= 1 ) 03466 fprintf( outStream, "getting global transform\n" ); 03467 03468 globalFlag = TRUE; 03469 03470 SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ), 03471 TRUE, (void *)&globalFlag ); 03472 03473 // get the global matrix 03474 SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix ); 03475 03476 // make this into a pfMatrix 03477 Matrix[0][0] = matrix[0][0]; 03478 Matrix[0][1] = matrix[0][1]; 03479 Matrix[0][2] = matrix[0][2]; 03480 Matrix[0][3] = matrix[0][3]; 03481 Matrix[1][0] = matrix[1][0]; 03482 Matrix[1][1] = matrix[1][1]; 03483 Matrix[1][2] = matrix[1][2]; 03484 Matrix[1][3] = matrix[1][3]; 03485 Matrix[2][0] = matrix[2][0]; 03486 Matrix[2][1] = matrix[2][1]; 03487 Matrix[2][2] = matrix[2][2]; 03488 Matrix[2][3] = matrix[2][3]; 03489 Matrix[3][0] = matrix[3][0]; 03490 Matrix[3][1] = matrix[3][1]; 03491 Matrix[3][2] = matrix[3][2]; 03492 Matrix[3][3] = matrix[3][3]; 03493 03494 if ( verbose >= 1 ) 03495 fprintf( outStream, "attaching orphan chain to root\n" ); 03496 03497 joint = _data.CreateJoint( rootJnt, name ); 03498 joint->transform = Matrix; 03499 lastAnim = rootAnim; 03500 } 03501 // if root, make a seperate tree for skeleton and 03502 // create required Table for the Egg heirarchy 03503 else 03504 { 03505 if ( verbose >= 1 ) 03506 fprintf( outStream, "getting global transform\n" ); 03507 03508 globalFlag = TRUE; 03509 03510 SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ), 03511 TRUE, (void *)&globalFlag ); 03512 03513 // get the global matrix 03514 SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix ); 03515 03516 // make this into a pfMatrix 03517 Matrix[0][0] = matrix[0][0]; 03518 Matrix[0][1] = matrix[0][1]; 03519 Matrix[0][2] = matrix[0][2]; 03520 Matrix[0][3] = matrix[0][3]; 03521 Matrix[1][0] = matrix[1][0]; 03522 Matrix[1][1] = matrix[1][1]; 03523 Matrix[1][2] = matrix[1][2]; 03524 Matrix[1][3] = matrix[1][3]; 03525 Matrix[2][0] = matrix[2][0]; 03526 Matrix[2][1] = matrix[2][1]; 03527 Matrix[2][2] = matrix[2][2]; 03528 Matrix[2][3] = matrix[2][3]; 03529 Matrix[3][0] = matrix[3][0]; 03530 Matrix[3][1] = matrix[3][1]; 03531 Matrix[3][2] = matrix[3][2]; 03532 Matrix[3][3] = matrix[3][3]; 03533 03534 rootJnt = _data.CreateJoint( skeleton, "root" ); 03535 rootJnt->transform.makeIdent(); 03536 if ( verbose >= 1 ) 03537 fprintf( outStream, "setting skeleton root\n" ); 03538 rootJnt->flags |= EF_TRANSFORM; 03539 03540 joint = _data.CreateJoint( rootJnt, name ); 03541 joint->transform = Matrix; 03542 foundRoot = TRUE; 03543 if ( verbose >= 1 ) 03544 fprintf( outStream, "found first chain\n" ); 03545 03546 // make skeleton table 03547 AnimGroup *skeletonTable; 03548 skeletonTable = animData.CreateTable( animRoot, "<skeleton>" ); 03549 rootAnim = animData.CreateTable( skeletonTable, "root" ); 03550 XfmSAnimTable *table = new XfmSAnimTable( ); 03551 table->name = "xform"; 03552 table->fps = anim_rate; 03553 rootAnim->children.push_back( table ); 03554 lastAnim = rootAnim; 03555 } 03556 03557 joint->flags |= EF_TRANSFORM; 03558 03559 //if ( make_anim) 03560 //{ 03561 AnimGroup *anim = animData.CreateTable( lastAnim, name ); 03562 XfmSAnimTable *table = new XfmSAnimTable( ); 03563 if ( verbose >= 1 ) 03564 fprintf( outStream, "created anim table: %s\n", "xform" ); 03565 table->name = "xform"; 03566 table->fps = anim_rate; 03567 anim->children.push_back( table ); 03568 lastAnim = anim; 03569 //} 03570 03571 // make this joint current parent of chain 03572 lastJoint = joint; 03573 } 03574 03575 03576 //////////////////////////////////////////////////////////////////// 03577 // Function: MakeSoftSkin 03578 // Access: Public 03579 // Description: Given a skeleton part find its envelopes (if any) 03580 // get the vertices associated with the envelopes and 03581 // their weights and make vertex ref's for the joint 03582 //////////////////////////////////////////////////////////////////// 03583 void soft2egg:: 03584 MakeSoftSkin( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models, 03585 int numModels, char *name ) 03586 { 03587 int numEnv; 03588 SAA_ModelType type; 03589 SAA_Elem *envelopes; 03590 03591 if ( verbose >= 1 ) 03592 fprintf( outStream, "\n>found skeleton part( %s )!\n", name ); 03593 03594 SAA_skeletonGetNbEnvelopes( scene, model, &numEnv ); 03595 03596 if ( numEnv ) 03597 { 03598 // it's got envelopes - must be soft skinned 03599 if ( verbose >= 1 ) 03600 fprintf( outStream, "numEnv = %d\n", numEnv ); 03601 03602 // allocate envelope array 03603 envelopes = ( SAA_Elem *)malloc( sizeof( SAA_Elem )*numEnv ); 03604 03605 if ( envelopes != NULL ) 03606 { 03607 int thisEnv; 03608 SAA_EnvType envType; 03609 bool hasEnvVertices = 0; 03610 03611 SAA_skeletonGetEnvelopes( scene, model, numEnv, envelopes ); 03612 03613 for ( thisEnv = 0; thisEnv < numEnv; thisEnv++ ) 03614 { 03615 if ( verbose >= 1 ) 03616 fprintf( outStream, "env[%d]: ", thisEnv ); 03617 03618 SAA_envelopeGetType( scene, &envelopes[thisEnv], &envType ); 03619 03620 if ( envType == SAA_ENVTYPE_NONE ) 03621 { 03622 if ( verbose >= 1 ) 03623 fprintf( outStream, "envType = none\n" ); 03624 } 03625 else if ( envType == SAA_ENVTYPE_FLXLCL ) 03626 { 03627 if ( verbose >= 1 ) 03628 fprintf( outStream, "envType = flexible, local\n" ); 03629 hasEnvVertices = 1; 03630 } 03631 else if ( envType == SAA_ENVTYPE_FLXGLB ) 03632 { 03633 if ( verbose >= 1 ) 03634 fprintf( outStream, "envType = flexible, global\n" ); 03635 hasEnvVertices = 1; 03636 } 03637 else if ( envType == SAA_ENVTYPE_RGDGLB ) 03638 { 03639 if ( verbose >= 1 ) 03640 fprintf( outStream, "envType = rigid, global\n" ); 03641 hasEnvVertices = 1; 03642 } 03643 else 03644 { 03645 if ( verbose >= 1 ) 03646 fprintf( outStream, "envType = unknown\n" ); 03647 } 03648 } 03649 03650 if ( hasEnvVertices) 03651 { 03652 int *numEnvVertices; 03653 SAA_SubElem *envVertices = NULL; 03654 03655 numEnvVertices = (int *)malloc(sizeof(int)*numEnv); 03656 03657 SAA_envelopeGetNbCtrlVertices( scene, model, numEnv, 03658 envelopes, numEnvVertices ); 03659 03660 if ( numEnvVertices != NULL ) 03661 { 03662 int totalEnvVertices = 0; 03663 int i,j,k; 03664 03665 for( i = 0; i < numEnv; i++ ) 03666 { 03667 totalEnvVertices += numEnvVertices[i]; 03668 if ( verbose >= 1 ) 03669 fprintf( outStream, "numEnvVertices[%d] = %d\n", 03670 i, numEnvVertices[i] ); 03671 } 03672 03673 03674 if ( verbose >= 1 ) 03675 fprintf( outStream, "total env verts = %d\n", 03676 totalEnvVertices ); 03677 03678 if ( totalEnvVertices ) 03679 { 03680 envVertices = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*totalEnvVertices); 03681 03682 if ( envVertices != NULL ) 03683 { 03684 03685 SAA_envelopeGetCtrlVertices( scene, model, 03686 numEnv, envelopes, numEnvVertices, envVertices); 03687 03688 // loop through for each envelope 03689 for ( i = 0; i < numEnv; i++ ) 03690 { 03691 float *weights = NULL; 03692 int vertArrayOffset = 0; 03693 03694 if ( verbose >= 2 ) 03695 fprintf( outStream, "\nenvelope[%d]:\n", i ); 03696 03697 weights = (float *)malloc(sizeof(float)*numEnvVertices[i]); 03698 03699 if ( weights ) 03700 { 03701 char *envName; 03702 int *vpoolMap = NULL; 03703 03704 for ( j = 0; j < i; j++ ) 03705 vertArrayOffset += numEnvVertices[j]; 03706 03707 if ( verbose >= 1 ) 03708 fprintf( outStream, 03709 "envVertArray offset = %d\n", 03710 vertArrayOffset ); 03711 03712 // get the weights of the envelope vertices 03713 SAA_ctrlVertexGetEnvelopeWeights( 03714 scene, model, &envelopes[i], 03715 numEnvVertices[i], 03716 &envVertices[vertArrayOffset], weights ); 03717 03718 // Get the name of the envelope model 03719 if ( use_prefix ) 03720 { 03721 // Get the FULL name of the envelope 03722 envName = GetFullName( scene, &envelopes[i] ); 03723 } 03724 else 03725 { 03726 // Get the name of the envelope 03727 envName = GetName( scene, &envelopes[i] ); 03728 } 03729 03730 if ( verbose >= 1 ) 03731 fprintf( outStream, "envelope name %s\n", envName ); 03732 03733 // find out if envelope geometry is poly or nurb 03734 //SAA_modelGetType( scene, 03735 //FindModelByName( envName, scene, 03736 //models, numModels ), &type ); 03737 03738 SAA_modelGetType( scene, &envelopes[i], &type ); 03739 03740 if ( verbose >= 1 ) 03741 { 03742 fprintf( outStream, "envelope model type "); 03743 03744 if ( type == SAA_MSMSH ) 03745 fprintf( outStream, "MESH\n" ); 03746 else if ( type == SAA_MNSRF ) 03747 fprintf( outStream, "NURBS\n" ); 03748 else 03749 fprintf( outStream, "OTHER\n" ); 03750 } 03751 03752 int *envVtxIndices = NULL; 03753 envVtxIndices = (int *)malloc(sizeof(int)*numEnvVertices[i]); 03754 03755 // Get the envelope vertex indices 03756 SAA_ctrlVertexGetIndices( scene, &envelopes[i], numEnvVertices[i], 03757 &envVertices[vertArrayOffset], envVtxIndices ); 03758 03759 // find out how many vertices the model has 03760 int modelNumVert; 03761 03762 SAA_modelGetNbVertices( scene, &envelopes[i], &modelNumVert ); 03763 03764 SAA_DVector *modelVertices = NULL; 03765 modelVertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*modelNumVert); 03766 03767 // get the model vertices 03768 SAA_modelGetVertices( scene, &envelopes[i], 03769 SAA_GEOM_ORIGINAL, 0, modelNumVert, 03770 modelVertices ); 03771 03772 // create array of global model coords 03773 SAA_DVector *globalModelVertices = NULL; 03774 globalModelVertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*modelNumVert); 03775 float matrix[4][4]; 03776 03777 // tranform local model vert coords to global 03778 03779 // first get the global matrix 03780 SAA_modelGetMatrix( scene, &envelopes[i], SAA_COORDSYS_GLOBAL, matrix ); 03781 03782 // populate array of global model verts 03783 for ( j = 0; j < modelNumVert; j++ ) 03784 { 03785 _VCT_X_MAT( globalModelVertices[j], 03786 modelVertices[j], matrix ); 03787 } 03788 03789 // find the egg vertex pool that corresponds 03790 // to this envelope model 03791 EggVertexPool *envPool = 03792 (EggVertexPool *)(_data.pools.FindName( envName )); 03793 // If we are outputting triangles: 03794 // create an array that maps from a referenced 03795 // vertex in the envelope to a corresponding 03796 // vertex in the egg vertex pool 03797 //if ( (type == SAA_MNSRF) && !make_nurbs ) 03798 if ( !make_nurbs || (type == SAA_MSMSH) ) 03799 { 03800 vpoolMap = FindClosestTriVert( envPool, 03801 globalModelVertices, modelNumVert ); 03802 } 03803 03804 03805 if ( envPool != NULL ) 03806 { 03807 03808 // find the egg joint that corresponds to this model 03809 EggJoint *joint = 03810 (EggJoint *)(skeleton->FindDescendent( name )); 03811 03812 // this doesn't seem to be necessary 4/7/99 03813 //EggJoint *parent = (EggJoint *)joint->parent; 03814 //assert(parent->IsA(NT_EggJoint)); 03815 03816 // for every envelope vertex 03817 for (j = 0; j < numEnvVertices[i]; j++) 03818 { 03819 double scaledWeight = weights[j]/ 100.0f; 03820 03821 // make sure its in legal range 03822 if (( envVtxIndices[j] < modelNumVert ) 03823 && ( envVtxIndices[j] >= 0 )) 03824 { 03825 if ( (type == SAA_MNSRF) && make_nurbs ) 03826 { 03827 // assign all referenced control vertices 03828 joint->AddVertex( envPool->Vertex(envVtxIndices[j]), scaledWeight ); 03829 03830 if ( verbose >= 2 ) 03831 fprintf( outStream, 03832 "%d: adding vref to cv %d with weight %f\n", 03833 j, envVtxIndices[j], scaledWeight ); 03834 03835 envPool->Vertex(envVtxIndices[j])->AddJoint( joint, scaledWeight ); 03836 // set flag to show this vertex has 03837 // been assigned 03838 envPool->Vertex(envVtxIndices[j])->multipleJoints = 1; 03839 } 03840 else 03841 { 03842 //assign all the tri verts associated 03843 // with this control vertex to joint 03844 for ( k = 0; k < envPool->NumVertices(); k++ ) 03845 { 03846 if ( vpoolMap[k] == envVtxIndices[j] ) 03847 { 03848 03849 // add each vert in pool to last 03850 // joint for soft skinning 03851 joint->AddVertex(envPool->Vertex(k), 03852 scaledWeight); 03853 03854 if ( verbose >= 2 ) 03855 fprintf( outStream, 03856 "%d: adding vref from cv %d to vert %d with weight %f(vpool)\n", 03857 j, envVtxIndices[j], k, scaledWeight ); 03858 03859 envPool->Vertex(k)->AddJoint( joint, scaledWeight ); 03860 // set flag to show this vertex has 03861 // been assigned 03862 envPool->Vertex(k)->multipleJoints = 1; 03863 } 03864 } 03865 } 03866 } 03867 else 03868 if ( verbose >= 2 ) 03869 fprintf( outStream, 03870 "%d: Omitted vref from cv %d with weight %f (out of range 0 to %d )\n", 03871 j, envVtxIndices[j], scaledWeight, modelNumVert ); 03872 03873 } 03874 03875 } 03876 else 03877 if ( verbose >= 2 ) 03878 fprintf( outStream, "Couldn't find vpool %s!\n", envName ); 03879 03880 //free( modelVertices ); 03881 //free( globalModelVertices ); 03882 //free( envVtxIndices ); 03883 //free( envName ); 03884 } //if (weights) 03885 //free( weights ); 03886 03887 } // for i 03888 03889 } // if (envVertices != NULL) 03890 else 03891 fprintf( outStream, "Not enough memory for envelope vertices...\n"); 03892 //free( envVertices ); 03893 } // if (totalEnvVertices) 03894 else 03895 if ( verbose >= 1 ) 03896 fprintf( outStream, "No envelope vertices present...\n"); 03897 03898 //free( numEnvVertices ); 03899 03900 } // if (numEnvVertices != NULL) 03901 03902 } // if (hasEnvVertices) 03903 03904 } // if (envelopes != NULL) 03905 else 03906 fprintf( outStream, "Not enough memory for envelopes...\n" ); 03907 03908 //free( envelopes ); 03909 03910 } //if (numEnv) 03911 03912 else 03913 if ( verbose >= 1 ) 03914 fprintf( outStream, "Skeleton member has no envelopes...\n" ); 03915 } 03916 03917 03918 //////////////////////////////////////////////////////////////////// 03919 // Function: CleanUpSoftSkin 03920 // Access: Public 03921 // Description: Given a model, make sure all its vertices have been 03922 // soft assigned. If not hard assign to the last 03923 // joint we saw. 03924 //////////////////////////////////////////////////////////////////// 03925 void soft2egg:: 03926 CleanUpSoftSkin( SAA_Scene *scene, SAA_Elem *model, char *name ) 03927 { 03928 static EggJoint *joint; 03929 SAA_Elem parent; 03930 SAA_ModelType type; 03931 SAA_Boolean skel; 03932 03933 ///////////////////////////////////////////////// 03934 // find out what type of node we're dealing with 03935 ///////////////////////////////////////////////// 03936 SAA_modelGetType( scene, model, &type ); 03937 03938 char *parentName; 03939 int level; 03940 SAA_Elem *searchNode = model; 03941 03942 if ( verbose >= 1 ) 03943 fprintf( outStream, "\nCleaning up model %s\n", name ); 03944 03945 // this step is weird - I think I want it here but it seems 03946 // to break some models. Files like props-props_wh_cookietime.3-0 in 03947 // /ful/rnd/pub/vrml/chip/chips_adventure/char/zone1/rooms/warehouse_final 03948 // need to do the "if (skel)" bit. 03949 03950 // am I a skeleton too? 03951 SAA_modelIsSkeleton( scene, model, &skel ); 03952 03953 // if not look for the last skeleton part 03954 if ( skel ) 03955 parentName = name; 03956 else do 03957 { 03958 SAA_elementGetHierarchyLevel( scene, searchNode, &level ); 03959 03960 // make sure we don't try to get the root's parent 03961 if ( level ) 03962 { 03963 SAA_modelGetParent( scene, searchNode, &parent ); 03964 03965 if ( use_prefix ) 03966 { 03967 // Get the FULL name of the parent 03968 parentName = GetFullName( scene, &parent ); 03969 } 03970 else 03971 { 03972 // Get the name of the parent 03973 parentName = GetName( scene, &parent ); 03974 } 03975 03976 SAA_modelGetType( scene, &parent, &type ); 03977 03978 SAA_modelIsSkeleton( scene, &parent, &skel ); 03979 03980 if ( verbose >= 1 ) 03981 fprintf( outStream, "model %s, level %d, type %d, skel %d\n", 03982 parentName, level, type, skel ); 03983 03984 searchNode = &parent; 03985 } 03986 else 03987 { 03988 // we reached the root of the tree 03989 parentName = NULL; 03990 if ( verbose >= 1 ) 03991 fprintf( outStream, "at root of tree! level %d\n", level ); 03992 break; 03993 } 03994 03995 // look until parent is a joint or acts like one 03996 } while ( !skel && ( strstr( parentName,"joint") == NULL )); 03997 03998 EggJoint *thisJoint = NULL; 03999 04000 if ( parentName != NULL ) 04001 { 04002 if ( verbose >= 1 ) 04003 { 04004 fprintf( outStream, "found model parent joint %s\n", parentName); 04005 fprintf( outStream, "looking for joint %s\n", parentName ); 04006 } 04007 thisJoint = (EggJoint *)(skeleton->FindDescendent( parentName )); 04008 } 04009 else 04010 if ( verbose >= 1 ) 04011 fprintf( outStream, "Couldn't find parent joint!\n"); 04012 04013 if ( thisJoint != NULL ) 04014 { 04015 joint = thisJoint; 04016 if ( verbose >= 1 ) 04017 fprintf( outStream, "setting joint to %s\n", parentName ); 04018 04019 //find the vpool for this model 04020 EggVertexPool *vPool = 04021 (EggVertexPool *)(_data.pools.FindName( name )); 04022 04023 if (vPool != NULL) 04024 { 04025 int i; 04026 double membership; 04027 int numVerts = vPool->NumVertices() ; 04028 04029 04030 if ( verbose >= 1 ) 04031 fprintf( outStream, "found vpool %s w/ %d verts\n", 04032 name, numVerts ); 04033 04034 for ( i = 0; i < numVerts; i++ ) 04035 { 04036 if ( vPool->Vertex(i)->multipleJoints != 1 ) 04037 { 04038 if ( verbose >= 1 ) 04039 { 04040 fprintf( outStream, "vpool %s vert %d", name, i ); 04041 fprintf( outStream, " not assigned!\n" ); 04042 } 04043 04044 // hard skin this vertex 04045 joint->AddVertex( vPool->Vertex(i), 1.0f ); 04046 } 04047 else 04048 { 04049 membership = vPool->Vertex(i)->NetMembership(); 04050 04051 04052 if ( verbose >= 1 ) 04053 { 04054 fprintf( outStream, "vpool %s vert %d", name, 04055 i ); 04056 fprintf( outStream, " has membership %f\n", 04057 membership ); 04058 } 04059 04060 if ( membership == 0 ) 04061 { 04062 if ( verbose >= 1 ) 04063 fprintf( outStream, "adding full weight..\n" ); 04064 04065 // hard skin this vertex 04066 joint->AddVertex( vPool->Vertex(i), 1.0f ); 04067 } 04068 } 04069 } 04070 } 04071 else 04072 if ( verbose >= 1 ) 04073 fprintf( outStream, "couldn't find vpool %s\n", name ); 04074 } 04075 else 04076 { 04077 if ( parentName != NULL ) 04078 if ( verbose >= 1 ) 04079 fprintf( outStream, "Couldn't find joint %s\n", parentName ); 04080 } 04081 } 04082 04083 ////////////////////////////////////////////////////////////////////// 04084 // Function: MakeAnimTable 04085 // Access: Public 04086 // Description: Given a scene and a skeleton part ,get all the 04087 // position, rotation, and scale for the skeleton 04088 // part for this frame and write them out as Egg 04089 // animation tables. 04090 //////////////////////////////////////////////////////////////////// 04091 void soft2egg:: 04092 MakeAnimTable( SAA_Scene *scene, SAA_Elem *skeletonPart, char *name ) 04093 { 04094 04095 if ( skeletonPart != NULL ) 04096 { 04097 float i,j,k; 04098 float h,p,r; 04099 float x,y,z; 04100 int size; 04101 SAA_Boolean globalFlag = FALSE; 04102 SAA_Boolean bigEndian; 04103 04104 if ( verbose >= 1 ) 04105 fprintf( outStream, "\n\nanimating child %s\n", name ); 04106 04107 SAA_elementGetUserDataSize( scene, skeletonPart, "GLOBAL", &size ); 04108 04109 if ( size != 0 ) 04110 SAA_elementGetUserData( scene, skeletonPart, "GLOBAL", 04111 sizeof( SAA_Boolean), &bigEndian, (void *)&globalFlag ); 04112 04113 if ( globalFlag ) 04114 { 04115 if ( verbose >= 1 ) 04116 fprintf( outStream, " using global matrix\n" ); 04117 04118 //get SAA orientation 04119 SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 04120 &p, &h, &r ); 04121 04122 //get SAA translation 04123 SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 04124 &x, &y, &z ); 04125 04126 //get SAA scaling 04127 SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL, 04128 &i, &j, &k ); 04129 } 04130 else 04131 { 04132 if ( verbose >= 1 ) 04133 fprintf( outStream, "using local matrix\n" ); 04134 04135 //get SAA orientation 04136 SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 04137 &p, &h, &r ); 04138 04139 //get SAA translation 04140 SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL, 04141 &x, &y, &z ); 04142 04143 //get SAA scaling 04144 SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL, 04145 &i, &j, &k ); 04146 } 04147 04148 04149 if ( verbose >= 2 ) 04150 fprintf( outStream, "\nanim data: %f %f %f\n\t%f %f %f\n\t%f %f %f\n", 04151 i, j, k, h, p, r, x, y, z ); 04152 04153 // find the appropriate anim table for this skeleton part 04154 AnimGroup *thisGroup; 04155 XfmSAnimTable *thisTable; 04156 04157 //find the anim table associated with this group 04158 thisGroup = (AnimGroup *)(animRoot->FindDescendent( name )); 04159 if ( verbose >= 2 ) 04160 fprintf( outStream, "\nlooking for anim group %s\n", name ); 04161 if ( thisGroup != NULL ) 04162 { 04163 thisTable = (XfmSAnimTable *)(thisGroup->FindDescendent( "xform" )); 04164 04165 if ( thisTable != NULL ) 04166 { 04167 thisTable->sub_tables[0].AddElement( i ); 04168 thisTable->sub_tables[1].AddElement( j ); 04169 thisTable->sub_tables[2].AddElement( k ); 04170 thisTable->sub_tables[3].AddElement( p ); 04171 thisTable->sub_tables[4].AddElement( h ); 04172 thisTable->sub_tables[5].AddElement( r ); 04173 thisTable->sub_tables[6].AddElement( x ); 04174 thisTable->sub_tables[7].AddElement( y ); 04175 thisTable->sub_tables[8].AddElement( z ); 04176 } 04177 else 04178 fprintf( outStream, "Couldn't allocate anim table\n" ); 04179 } 04180 else 04181 if ( verbose >= 2 ) 04182 fprintf( outStream, "Couldn't find anim group %s\n", name ); 04183 } 04184 else 04185 { 04186 if ( verbose >= 2 ) 04187 fprintf( outStream, "Cannot build anim table - no skeleton\n" ); 04188 } 04189 04190 } 04191 04192 //////////////////////////////////////////////////////////////////// 04193 // Function: MakeVertexOffsets 04194 // Access: Public 04195 // Description: Given a scene, a model , the vertices of its original 04196 // shape and its name find the difference between the 04197 // geometry of its key shapes and the models original 04198 // geometry and add morph vertices to the egg data to 04199 // reflect these changes. 04200 //////////////////////////////////////////////////////////////////// 04201 void soft2egg:: 04202 MakeVertexOffsets( SAA_Scene *scene, SAA_Elem *model, SAA_ModelType type, 04203 int numShapes, int numOrigVert, SAA_DVector *originalVerts, float 04204 matrix[4][4], char *name ) 04205 { 04206 int i, j; 04207 int offset; 04208 int numCV; 04209 char *mTableName; 04210 SAA_DVector *shapeVerts = NULL; 04211 SAA_DVector *uniqueVerts = NULL; 04212 04213 if ( (type == SAA_MNSRF) && make_nurbs ) 04214 SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step ); 04215 04216 SAA_modelGetNbVertices( scene, model, &numCV ); 04217 04218 // get the shape verts 04219 uniqueVerts = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV); 04220 SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0, 04221 numCV, uniqueVerts ); 04222 04223 if ( verbose >= 2 ) 04224 fprintf( outStream, "%d CV's\n", numCV ); 04225 04226 if ( verbose >= 2 ) 04227 { 04228 for ( i = 0; i < numCV; i++ ) 04229 fprintf( outStream, "uniqueVerts[%d] = %f %f %f %f\n", i, 04230 uniqueVerts[i].x, uniqueVerts[i].y, 04231 uniqueVerts[i].z, uniqueVerts[i].w ); 04232 } 04233 04234 // iterate through for each key shape (except original) 04235 for ( i = 1; i < numShapes; i++ ) 04236 { 04237 mTableName = MakeTableName( name, i ); 04238 04239 if ( verbose >= 1 ) 04240 { 04241 fprintf( outStream, "\nMaking geometry offsets for %s...\n", 04242 mTableName ); 04243 04244 if ( (type == SAA_MNSRF) && make_nurbs ) 04245 fprintf( outStream, "calculating NURBS morphs...\n" ); 04246 else 04247 fprintf( outStream, "calculating triangle morphs...\n" ); 04248 } 04249 04250 // get the shape verts 04251 shapeVerts = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV); 04252 SAA_modelGetVertices( scene, model, SAA_GEOM_SHAPE, i+1, 04253 numCV, shapeVerts ); 04254 04255 if ( verbose >= 2 ) 04256 { 04257 for ( j=0; j < numCV; j++ ) 04258 { 04259 fprintf( outStream, "shapeVerts[%d] = %f %f %f\n", j, 04260 shapeVerts[j].x, shapeVerts[j].y, shapeVerts[j].z ); 04261 } 04262 } 04263 04264 // find the appropriate vertex pool 04265 EggVertexPool *vPool = 04266 (EggVertexPool *)(_data.pools.FindName( name )); 04267 04268 // for every original vertex, compare to the corresponding 04269 // key shape vertex and see if a vertex offset is needed 04270 for ( j=0; j < numOrigVert; j++ ) 04271 { 04272 double dx, dy, dz; 04273 04274 if ( (type == SAA_MNSRF) && make_nurbs ) 04275 { 04276 //dx = shapeVerts[j].x - (originalVerts[j].x/originalVerts[j].w); 04277 //dy = shapeVerts[j].y - (originalVerts[j].y/originalVerts[j].w); 04278 //dz = shapeVerts[j].z - (originalVerts[j].z/originalVerts[j].w); 04279 dx = shapeVerts[j].x - originalVerts[j].x; 04280 dy = shapeVerts[j].y - originalVerts[j].y; 04281 dz = shapeVerts[j].z - originalVerts[j].z; 04282 } 04283 else 04284 { 04285 // we need to map from original vertices 04286 // to triangle shape vertices here 04287 offset = findShapeVert( originalVerts[j], uniqueVerts, 04288 numCV ); 04289 04290 dx = shapeVerts[offset].x - originalVerts[j].x; 04291 dy = shapeVerts[offset].y - originalVerts[j].y; 04292 dz = shapeVerts[offset].z - originalVerts[j].z; 04293 } 04294 04295 if ( verbose >= 2 ) 04296 { 04297 fprintf( outStream, "oVert[%d] = %f %f %f %f\n", j, 04298 originalVerts[j].x, originalVerts[j].y, 04299 originalVerts[j].z, originalVerts[j].w ); 04300 04301 if ( (type == SAA_MNSRF) && make_nurbs ) 04302 { 04303 fprintf( outStream, "global shapeVerts[%d] = %f %f %f %f\n", j, shapeVerts[j].x, shapeVerts[j].y, 04304 shapeVerts[j].z, shapeVerts[j].w ); 04305 } 04306 else 04307 { 04308 fprintf( outStream, 04309 "global shapeVerts[%d] = %f %f %f\n", offset, 04310 shapeVerts[offset].x, 04311 shapeVerts[offset].y, 04312 shapeVerts[offset].z ); 04313 } 04314 04315 fprintf( outStream, "%d: dx = %f, dy = %f, dz = %f\n", j, 04316 dx, dy, dz ); 04317 } 04318 04319 // if change isn't negligible, make a morph vertex entry 04320 double total = fabs(dx)+fabs(dy)+fabs(dz); 04321 if ( total > 0.00001 ) 04322 { 04323 if ( vPool != NULL ) 04324 { 04325 // create offset 04326 EggMorphOffset *dxyz = 04327 new EggMorphOffset( mTableName, dx, dy, dz ); 04328 04329 EggVertex *eggVert; 04330 04331 // get the appropriate egg vertex 04332 eggVert = vPool->Vertex(j); 04333 04334 // add the offset to the vertex 04335 eggVert->morphs.push_back( *dxyz ); 04336 } 04337 else 04338 fprintf( outStream, "Error: couldn't find vertex pool %s\n", name ); 04339 04340 } // if total 04341 } //for j 04342 } //for i 04343 } 04344 04345 04346 //////////////////////////////////////////////////////////////////// 04347 // Function: MakeMorphTable 04348 // Access: Public 04349 // Description: Given a scene, a model, a name and a frame time, 04350 // determine what type of shape interpolation is 04351 // used and call the appropriate function to extract 04352 // the shape weight info for this frame... 04353 //////////////////////////////////////////////////////////////////// 04354 void soft2egg:: 04355 MakeMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models, 04356 int numModels, char *name, float time ) 04357 { 04358 int numShapes; 04359 SAA_AnimInterpType type; 04360 04361 // Get the number of key shapes 04362 SAA_modelGetNbShapes( scene, model, &numShapes ); 04363 04364 if ( numShapes > 0 ) 04365 { 04366 if ( verbose >= 1 ) 04367 fprintf( outStream, "MakeMorphTable: %s: num shapes: %d\n", 04368 name, numShapes); 04369 04370 SAA_modelGetShapeInterpolation( scene, model, &type ); 04371 04372 if ( type == SAA_ANIM_LINEAR || type == SAA_ANIM_CARDINAL ) 04373 { 04374 MakeLinearMorphTable( scene, model, numShapes, name, time ); 04375 } 04376 else // must be weighted... 04377 { 04378 // check first for expressions 04379 MakeExpressionMorphTable( scene, model, models, numModels, 04380 numShapes, name, time ); 04381 } 04382 04383 } 04384 04385 } 04386 04387 04388 //////////////////////////////////////////////////////////////////// 04389 // Function: MakeLinearMorphTable 04390 // Access: Public 04391 // Description: Given a scene, a model, its name, and the time, 04392 // get the shape fcurve for the model and determine 04393 // the shape weights for the given time and use them 04394 // to populate the morph table. 04395 //////////////////////////////////////////////////////////////////// 04396 void soft2egg:: 04397 MakeLinearMorphTable( SAA_Scene *scene, SAA_Elem *model, int numShapes, 04398 char *name, float time ) 04399 { 04400 int i; 04401 SAA_Elem fcurve; 04402 float curveVal; 04403 SAnimTable *thisTable; 04404 char *tableName; 04405 04406 if ( verbose >= 1 ) 04407 fprintf( outStream, "linear interp, getting fcurve\n" ); 04408 04409 SAA_modelFcurveGetShape( scene, model, &fcurve ); 04410 04411 SAA_fcurveEval( scene, &fcurve, time, &curveVal ); 04412 04413 if ( verbose >= 2 ) 04414 fprintf( outStream, "at time %f, fcurve for %s = %f\n", time, 04415 name, curveVal ); 04416 04417 float nextVal = 0.0f; 04418 04419 // populate morph table values for this frame 04420 for ( i = 1; i < numShapes; i++ ) 04421 { 04422 // derive table name from the model name 04423 tableName = MakeTableName( name, i ); 04424 04425 if ( verbose >= 2 ) 04426 fprintf( outStream, "Linear: looking for table '%s'\n", tableName ); 04427 04428 //find the morph table associated with this key shape 04429 thisTable = (SAnimTable *)(morphRoot->FindDescendent( tableName )); 04430 04431 if ( thisTable != NULL ) 04432 { 04433 if ( i == (int)curveVal ) 04434 { 04435 if ( curveVal - i == 0 ) 04436 { 04437 thisTable->AddElement( 1.0f ); 04438 if ( verbose >= 2 ) 04439 fprintf( outStream, "adding element 1.0f\n" ); 04440 } 04441 else 04442 { 04443 thisTable->AddElement( 1.0f - (curveVal - i) ); 04444 nextVal = curveVal - i; 04445 if ( verbose >= 2 ) 04446 fprintf( outStream, "adding element %f\n", 1.0f - (curveVal - i) ); 04447 } 04448 } 04449 else 04450 { 04451 if ( nextVal ) 04452 { 04453 thisTable->AddElement( nextVal ); 04454 nextVal = 0.0f; 04455 if ( verbose >= 2 ) 04456 fprintf( outStream, "adding element %f\n", nextVal ); 04457 } 04458 else 04459 { 04460 thisTable->AddElement( 0.0f ); 04461 if ( verbose >= 2 ) 04462 fprintf( outStream, "adding element 0.0f\n" ); 04463 } 04464 } 04465 04466 if ( verbose >= 2 ) 04467 fprintf( outStream, " to '%s'\n", tableName ); 04468 } 04469 else 04470 fprintf( outStream, "%d: Couldn't find table '%s'\n", 04471 i, tableName ); 04472 } 04473 04474 } 04475 04476 //////////////////////////////////////////////////////////////////// 04477 // Function: MakeWeightedMorphTable 04478 // Access: Public 04479 // Description: Given a scene, a model, a list of all models in the 04480 // scene, the number of models in the scece, the number 04481 // of key shapes for this model, the name of the model 04482 // and the current time, determine what method of 04483 // controlling the shape weights is used and call the 04484 // appropriate routine. 04485 //////////////////////////////////////////////////////////////////// 04486 void soft2egg:: 04487 MakeWeightedMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models, 04488 int numModels, int numShapes, char *name, float time ) 04489 { 04490 SI_Error result; 04491 SAA_Elem *weightCurves; 04492 float curveVal; 04493 SAnimTable *thisTable; 04494 char *tableName; 04495 04496 // allocate array of weight curves (one for each shape) 04497 weightCurves = ( SAA_Elem *)malloc( sizeof( SAA_Elem ) * numShapes ); 04498 04499 result = SAA_modelFcurveGetShapeWeights( 04500 scene, model, numShapes, weightCurves ); 04501 04502 if ( result == SI_SUCCESS ) 04503 { 04504 for ( int i = 1; i < numShapes; i++ ) 04505 { 04506 SAA_fcurveEval( scene, &weightCurves[i], time, &curveVal ); 04507 04508 // make sure soft gave us a reasonable number 04509 if (!isNum(curveVal)) 04510 curveVal = 0.0f; 04511 04512 if ( verbose >= 2 ) 04513 fprintf( outStream, "at time %f, weightCurve[%d] for %s = %f\n", time, i, name, curveVal ); 04514 04515 04516 // derive table name from the model name 04517 tableName = MakeTableName( name, i ); 04518 04519 // find and populate shape table 04520 if ( verbose >= 2 ) 04521 fprintf( outStream, "Weight: looking for table '%s'\n", 04522 tableName ); 04523 04524 //find the morph table associated with this key shape 04525 thisTable = (SAnimTable *)(morphRoot->FindDescendent( tableName )); 04526 04527 if ( thisTable != NULL ) 04528 { 04529 thisTable->AddElement( curveVal ); 04530 if ( verbose >= 2 ) 04531 fprintf( outStream, "adding element %f\n", curveVal ); 04532 } 04533 else 04534 fprintf( outStream, "%d: Couldn't find table '%s'\n", 04535 i, tableName ); 04536 } 04537 } 04538 } 04539 04540 04541 //////////////////////////////////////////////////////////////////// 04542 // Function: MakeExpressionMorphTable 04543 // Access: Public 04544 // Description: Given a scene, a model and its number of key shapes 04545 // generate a morph table describing transitions btwn 04546 // the key shapes by evaluating the positions of the 04547 // controlling sliders. 04548 //////////////////////////////////////////////////////////////////// 04549 void soft2egg:: 04550 MakeExpressionMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models, 04551 int numModels, int numShapes, char *name, float time ) 04552 { 04553 int j; 04554 SAnimTable *thisTable; 04555 char *tableName; 04556 char *sliderName; 04557 char *track; 04558 int numExp; 04559 SAA_Elem *expressions; 04560 float expVal; 04561 float sliderVal; 04562 04563 // populate morph table values for this frame 04564 04565 // compose track name 04566 track = NULL; 04567 04568 // find how many expressions for this shape 04569 SAA_elementGetNbExpressions( scene, model, track, FALSE, &numExp ); 04570 04571 if ( verbose >= 2 ) 04572 fprintf( outStream, "%s has %d RHS expressions\n", name, numExp ); 04573 04574 if ( numExp ) 04575 { 04576 // get the expressions for this shape 04577 expressions = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numExp); 04578 04579 if ( verbose >= 1 ) 04580 fprintf( outStream, "getting %d RHS expressions...\n", numExp ); 04581 04582 result = SAA_elementGetExpressions( scene, model, track, FALSE, 04583 numExp, expressions ); 04584 04585 if ( !result ) 04586 { 04587 for ( j = 1; j < numExp; j++ ) 04588 { 04589 if ( verbose >= 2 ) 04590 { 04591 // debug see what we got 04592 int numvars; 04593 04594 SAA_expressionGetNbVars( scene, &expressions[j], &numvars ); 04595 04596 int *varnamelen; 04597 int *varstrlen; 04598 int expstrlen; 04599 04600 varnamelen = (int *)malloc(sizeof(int)*numvars); 04601 varstrlen = (int *)malloc(sizeof(int)*numvars); 04602 04603 SAA_expressionGetStringLengths( scene, &expressions[j], 04604 numvars, varnamelen, varstrlen, &expstrlen ); 04605 04606 int *varnamesizes; 04607 int *varstrsizes; 04608 04609 varnamesizes = (int *)malloc(sizeof(int)*numvars); 04610 varstrsizes = (int *)malloc(sizeof(int)*numvars); 04611 04612 for ( int k = 0; k < numvars; k++ ) 04613 { 04614 varnamesizes[k] = varnamelen[k] + 1; 04615 varstrsizes[k] = varstrlen[k] + 1; 04616 } 04617 04618 int expstrsize = expstrlen + 1; 04619 04620 char **varnames; 04621 char **varstrs; 04622 04623 varnames = (char **)malloc(sizeof(char *)*numvars); 04624 varstrs = (char **)malloc(sizeof(char *)*numvars); 04625 04626 for ( k = 0; k < numvars; k++ ) 04627 { 04628 varnames[k] = (char *)malloc(sizeof(char)* 04629 varnamesizes[k]); 04630 04631 varstrs[k] = (char *)malloc(sizeof(char)* 04632 varstrsizes[k]); 04633 } 04634 04635 char *expstr = (char *)malloc(sizeof(char)* expstrsize ); 04636 04637 SAA_expressionGetStrings( scene, &expressions[j], numvars, 04638 varnamesizes, varstrsizes, expstrsize, varnames, 04639 varstrs, expstr ); 04640 04641 if ( verbose >= 2 ) 04642 { 04643 fprintf( outStream, "expression = '%s'\n", expstr ); 04644 fprintf( outStream, "has %d variables\n", numvars ); 04645 } 04646 } //if verbose 04647 04648 if ( verbose >= 2 ) 04649 fprintf( outStream, "evaling expression...\n" ); 04650 04651 SAA_expressionEval( scene, &expressions[j], time, &expVal ); 04652 04653 if ( verbose >= 2 ) 04654 fprintf( outStream, "time %f: exp val %f\n", 04655 time, expVal ); 04656 04657 // derive table name from the model name 04658 tableName = MakeTableName( name, j ); 04659 04660 if ( verbose >= 2 ) 04661 fprintf( outStream, "Exp: looking for table '%s'\n", 04662 tableName ); 04663 04664 //find the morph table associated with this key shape 04665 thisTable = (SAnimTable *) 04666 (morphRoot->FindDescendent( tableName )); 04667 04668 if ( thisTable != NULL ) 04669 { 04670 thisTable->AddElement( expVal ); 04671 if ( verbose >= 1 ) 04672 fprintf( outStream, "%d: adding element %f to %s\n", 04673 j, expVal, tableName ); 04674 fflush( outStream ); 04675 } 04676 else 04677 { 04678 fprintf( outStream, "%d: Couldn't find table '%s'", j, 04679 tableName ); 04680 04681 fprintf( outStream, " for value %f\n", expVal ); 04682 } 04683 } 04684 } 04685 else 04686 fprintf( outStream, "couldn't get expressions!!!\n" ); 04687 } 04688 else 04689 // no expression, use weight curves 04690 MakeWeightedMorphTable( scene, model, models, numModels, 04691 numShapes, name, time ); 04692 04693 } 04694 04695 04696 //////////////////////////////////////////////////////////////////// 04697 // Function: MakeTexAnim 04698 // Access: Public 04699 // Description: Given a scene, a POLYGON model, and the name 04700 // of the that model, get the u and v offsets for 04701 // the current frame. 04702 //////////////////////////////////////////////////////////////////// 04703 void soft2egg:: 04704 MakeTexAnim( SAA_Scene *scene, SAA_Elem *model, char *modelName ) 04705 { 04706 if ( verbose >= 1 ) 04707 fprintf( outStream, "\n\nmaking texture animation for %s...\n", 04708 modelName ); 04709 04710 // get the color of the surface 04711 int numMats; 04712 pfVec4 Color; 04713 SAA_Elem *materials; 04714 void *relinfo; 04715 04716 SAA_modelRelationGetMatNbElements( scene, model, FALSE, &relinfo, 04717 &numMats ); 04718 04719 if ( verbose >= 2 ) 04720 fprintf( outStream, "surface has %d materials\n", numMats ); 04721 04722 if ( numMats ) 04723 { 04724 float r,g,b,a; 04725 04726 materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numMats); 04727 04728 SAA_modelRelationGetMatElements( scene, model, relinfo, 04729 numMats, materials ); 04730 04731 SAA_materialGetDiffuse( scene, &materials[0], &r, &g, &b ); 04732 SAA_materialGetTransparency( scene, &materials[0], &a ); 04733 Color.set( r, g, b, 1.0f - a ); 04734 04735 int numTexLoc = 0; 04736 int numTexGlb = 0; 04737 04738 // ASSUME only one texture per material 04739 SAA_Elem tex; 04740 04741 // find out how many local textures per surface 04742 // ASSUME it only has one material 04743 SAA_materialRelationGetT2DLocNbElements( scene, &materials[0], 04744 FALSE, &relinfo, &numTexLoc ); 04745 04746 // if present, get local textures 04747 if ( numTexLoc ) 04748 { 04749 if ( verbose >= 1 ) 04750 fprintf( outStream, "%s had %d local tex\n", modelName, 04751 numTexLoc ); 04752 04753 // get the referenced texture 04754 SAA_materialRelationGetT2DLocElements( scene, &materials[0], 04755 TEX_PER_MAT, &tex ); 04756 04757 } 04758 // if no locals, try to get globals 04759 else 04760 { 04761 SAA_modelRelationGetT2DGlbNbElements( scene, model, 04762 FALSE, &relinfo, &numTexGlb ); 04763 04764 if ( numTexGlb ) 04765 { 04766 if ( verbose >= 1 ) 04767 fprintf( outStream, "%s had %d global tex\n", modelName, numTexGlb ); 04768 04769 // get the referenced texture 04770 SAA_modelRelationGetT2DGlbElements( scene, 04771 model, TEX_PER_MAT, &tex ); 04772 } 04773 } 04774 04775 // add tex ref's if we found any textures 04776 if ( numTexLoc || numTexGlb) 04777 { 04778 char *fullTexName = NULL; 04779 char *texName = NULL; 04780 char *uniqueTexName = NULL; 04781 int texNameLen; 04782 04783 // get its name 04784 SAA_texture2DGetPicNameLength( scene, &tex, &texNameLen); 04785 fullTexName = (char *)malloc(sizeof(char)*++texNameLen); 04786 SAA_texture2DGetPicName( scene, &tex, texNameLen, 04787 fullTexName ); 04788 04789 // append unique identifier to texname for 04790 // this particular object 04791 uniqueTexName = (char *)malloc(sizeof(char)* 04792 (strlen(modelName)+strlen(texName)+3) ); 04793 sprintf( uniqueTexName, "%s-%s", modelName, texName ); 04794 if ( verbose >= 2 ) 04795 fprintf( outStream, "referencing tref %s\n", 04796 uniqueTexName ); 04797 04798 float uScale; 04799 float vScale; 04800 float uOffset; 04801 float vOffset; 04802 SAA_Boolean uv_swap = FALSE; 04803 04804 // get texture offset info 04805 SAA_texture2DGetUScale( scene, &tex, &uScale ); 04806 SAA_texture2DGetVScale( scene, &tex, &vScale ); 04807 SAA_texture2DGetUOffset( scene, &tex, &uOffset ); 04808 SAA_texture2DGetVOffset( scene, &tex, &vOffset ); 04809 SAA_texture2DGetUVSwap( scene, &tex, &uv_swap ); 04810 04811 04812 if ( verbose >= 2 ) 04813 { 04814 fprintf( outStream, "tex uScale: %f\n", uScale ); 04815 fprintf( outStream, "tex vScale: %f\n", vScale ); 04816 fprintf( outStream, "tex uOffset: %f\n", uOffset ); 04817 fprintf( outStream, "tex vOffset: %f\n", vOffset ); 04818 if ( uv_swap ) 04819 fprintf( outStream, "nurbTex u & v swapped!\n" ); 04820 else 04821 fprintf( outStream, "nurbTex u & v NOT swapped\n" ); 04822 } 04823 04824 04825 // find the vpool for this model 04826 EggVertexPool *vPool = 04827 (EggVertexPool *)(_data.pools.FindName( modelName )); 04828 04829 // if we found the pool 04830 if ( vPool != NULL ) 04831 { 04832 // generate duv's for model 04833 float oldOffsets[4]; 04834 double u, v, du, dv; 04835 int size; 04836 SAA_Boolean bigEndian; 04837 04838 SAA_elementGetUserDataSize( scene, model, "TEX_OFFSETS", &size ); 04839 04840 if ( size != 0 ) 04841 { 04842 // remember original texture offsets future reference 04843 SAA_elementGetUserData( scene, model, "TEX_OFFSETS", 04844 size, &bigEndian, (void *)&oldOffsets ); 04845 04846 // get the original scales and offsets 04847 u = oldOffsets[0]; 04848 v = oldOffsets[1]; 04849 04850 du = u - uOffset; 04851 dv = v - vOffset; 04852 04853 if ( verbose >= 1 ) 04854 { 04855 fprintf( outStream, "original u = %f, v = %f\n", 04856 u, v ); 04857 fprintf( outStream, "u = %f, v = %f\n", 04858 uOffset, vOffset ); 04859 fprintf( outStream, "du = %f, dv = %f\n", 04860 du, dv ); 04861 } 04862 04863 strstream uName, vName; 04864 04865 // create duv target names 04866 uName << modelName << ".u" << ends; 04867 vName << modelName << ".v" << ends; 04868 04869 // find the appropriate table to store the 04870 // duv animation info into 04871 SAnimTable *thisTable; 04872 04873 //find the duv U table associated with this model 04874 thisTable = (SAnimTable *)(morphRoot->FindDescendent( 04875 uName.str() )); 04876 04877 if ( thisTable != NULL ) 04878 { 04879 thisTable->AddElement( du ); 04880 if ( verbose >= 1 ) 04881 fprintf( outStream, "adding element %f to %s\n", 04882 du, uName.str() ); 04883 } 04884 else 04885 fprintf( outStream, "Couldn't find uTable %s\n", 04886 uName.str() ); 04887 04888 //find the duv V table associated with this model 04889 thisTable = (SAnimTable *)(morphRoot->FindDescendent( 04890 vName.str() )); 04891 04892 if ( thisTable != NULL ) 04893 { 04894 thisTable->AddElement( dv ); 04895 if ( verbose >= 1 ) 04896 fprintf( outStream, "adding element %f to %s\n", 04897 dv, uName.str() ); 04898 } 04899 else 04900 fprintf( outStream, "Couldn't find vTable %s\n", 04901 uName.str() ); 04902 } 04903 } 04904 else 04905 if ( verbose >= 2 ) 04906 fprintf( outStream, "Couldn't find vpool %s\n", modelName ); 04907 04908 } 04909 04910 //free( materials ); 04911 04912 } 04913 04914 } 04915 #endif 04916 04917 //////////////////////////////////////////////////////////////////// 04918 // Function: Main 04919 // Access: Private 04920 // Description: Instantiate converter and process a file 04921 //////////////////////////////////////////////////////////////////// 04922 EXPCL_MISC SI_Error soft2egg(int argc, char *argv[]) { 04923 // pass control to the c++ system 04924 init_soft2egg(argc, argv); 04925 return SI_SUCCESS; 04926 } 04927 #ifdef __cplusplus 04928 } 04929 #endif