|
|
@@ -0,0 +1,4933 @@
|
|
|
+// Filename: soft2Egg.c
|
|
|
+// Created by: masad (26Sep03)
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+//
|
|
|
+// PANDA 3D SOFTWARE
|
|
|
+// Copyright (c) 2003, Disney Enterprises, Inc. All rights reserved
|
|
|
+//
|
|
|
+// All use of this software is subject to the terms of the Panda 3d
|
|
|
+// Software license. You should have received a copy of this license
|
|
|
+// along with this source code; you will also find a current copy of
|
|
|
+// the license at http://www.panda3d.org/license.txt .
|
|
|
+//
|
|
|
+// To contact the maintainers of this program write to
|
|
|
+// [email protected] .
|
|
|
+//
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Includes
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+#include <SAA.h>
|
|
|
+
|
|
|
+#ifdef __cplusplus
|
|
|
+extern "C" {
|
|
|
+#endif
|
|
|
+
|
|
|
+#include "pandatoolbase.h"
|
|
|
+
|
|
|
+int init_soft2egg(int, char **);
|
|
|
+
|
|
|
+#if 0
|
|
|
+// DWD includes
|
|
|
+#include "eggBase.h"
|
|
|
+#include <eggParametrics.h>
|
|
|
+#include <animTable.h>
|
|
|
+#include <linMathOutput.h>
|
|
|
+
|
|
|
+// system includes
|
|
|
+#include <fstream.h>
|
|
|
+#include <strstream.h>
|
|
|
+#include <math.h>
|
|
|
+#include <assert.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <ieeefp.h>
|
|
|
+
|
|
|
+// Performer includes
|
|
|
+#include <Performer/pr/pfLinMath.h>
|
|
|
+
|
|
|
+// SoftImage includes
|
|
|
+#include <SAA.h>
|
|
|
+#include <SI_macros.h>
|
|
|
+
|
|
|
+static const int TEX_PER_MAT = 1;
|
|
|
+static FILE *outStream = stdout;
|
|
|
+//static FILE *outStream = stderr;
|
|
|
+
|
|
|
+class soft2egg : public EggBase
|
|
|
+{
|
|
|
+ public:
|
|
|
+
|
|
|
+ soft2egg() : EggBase("r:d:s:m:t:P:b:e:f:T:S:M:A:N:v:o:FhknpaxiucCD")
|
|
|
+ {
|
|
|
+ rsrc_path = "/ful/ufs/soft371_mips2/3D/rsrc";
|
|
|
+ database_name = NULL;
|
|
|
+ scene_name = NULL;
|
|
|
+ model_name = NULL;
|
|
|
+ animFileName = NULL;
|
|
|
+ eggFileName = NULL;
|
|
|
+ tex_path = NULL;
|
|
|
+ eggGroupName = NULL;
|
|
|
+ tex_filename = NULL;
|
|
|
+ search_prefix = NULL;
|
|
|
+ result = SI_SUCCESS;
|
|
|
+
|
|
|
+ skeleton = new EggGroup();
|
|
|
+ foundRoot = FALSE;
|
|
|
+ animRoot = NULL;
|
|
|
+ morphRoot = NULL;
|
|
|
+ geom_as_joint = 0;
|
|
|
+ make_anim = 0;
|
|
|
+ make_nurbs = 0;
|
|
|
+ make_poly = 0;
|
|
|
+ make_soft = 0;
|
|
|
+ make_morph = 1;
|
|
|
+ make_duv = 1;
|
|
|
+ make_dart = TRUE;
|
|
|
+ has_morph = 0;
|
|
|
+ make_pose = 0;
|
|
|
+ animData.is_z_up = FALSE;
|
|
|
+ nurbs_step = 1;
|
|
|
+ anim_start = -1000;
|
|
|
+ anim_end = -1000;
|
|
|
+ anim_rate = 24;
|
|
|
+ pose_frame = -1;
|
|
|
+ verbose = 0;
|
|
|
+ flatten = 0;
|
|
|
+ shift_textures = 0;
|
|
|
+ ignore_tex_offsets = 0;
|
|
|
+ use_prefix = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual void Help();
|
|
|
+ virtual void Usage();
|
|
|
+ virtual void ShowOpts();
|
|
|
+
|
|
|
+ virtual boolean UseOutputSwitch() const {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ virtual boolean
|
|
|
+ HandleGetopts(char flag, char *optarg, int &optind, int argc, char **argv);
|
|
|
+
|
|
|
+ int isNum( float );
|
|
|
+ char *GetRootName( const char * );
|
|
|
+ char *RemovePathName( const char * );
|
|
|
+ char *GetSliderName( const char * );
|
|
|
+ char *GetFullName( SAA_Scene *, SAA_Elem * );
|
|
|
+ char *GetName( SAA_Scene *, SAA_Elem * );
|
|
|
+ char *GetModelNoteInfo( SAA_Scene *, SAA_Elem * );
|
|
|
+ char *MakeTableName( const char *, int );
|
|
|
+ char *DepointellizeName( char * );
|
|
|
+ SAA_Elem *FindModelByName( char *, SAA_Scene *, SAA_Elem *, int );
|
|
|
+ char *ConvertTexture( SAA_Scene *, SAA_Elem * );
|
|
|
+ int *FindClosestTriVert( EggVertexPool *, SAA_DVector *, int );
|
|
|
+ int *MakeIndexMap( int *, int, int );
|
|
|
+ int findShapeVert( SAA_DVector, SAA_DVector *, int );
|
|
|
+ void LoadSoft();
|
|
|
+ void MakeEgg( EggGroup *, EggJoint *, AnimGroup *, SAA_Scene *, SAA_Elem * );
|
|
|
+ void MakeSurfaceCurve( SAA_Scene *, SAA_Elem *, EggGroup *,
|
|
|
+ EggNurbsSurface *&, int , SAA_SubElem *, bool );
|
|
|
+
|
|
|
+ EggNurbsCurve *MakeUVNurbsCurve( int, long *, double *, double *,
|
|
|
+ EggGroup *, char * );
|
|
|
+
|
|
|
+ EggNurbsCurve *MakeNurbsCurve( SAA_Scene *, SAA_Elem *, EggGroup *,
|
|
|
+ float [4][4], char * );
|
|
|
+
|
|
|
+ void AddKnots( perf_vector<double> &, double *, int, SAA_Boolean, int );
|
|
|
+ void MakeJoint( SAA_Scene *, EggJoint *&, AnimGroup *&, SAA_Elem *, char * );
|
|
|
+ void MakeSoftSkin( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, char * );
|
|
|
+ void CleanUpSoftSkin( SAA_Scene *, SAA_Elem *, char * );
|
|
|
+ void MakeAnimTable( SAA_Scene *, SAA_Elem *, char * );
|
|
|
+ void MakeVertexOffsets( SAA_Scene *, SAA_Elem *, SAA_ModelType type,
|
|
|
+ int, int, SAA_DVector *, float (*)[4], char * );
|
|
|
+ void MakeMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int, char *,
|
|
|
+ float );
|
|
|
+ void MakeLinearMorphTable( SAA_Scene *, SAA_Elem *, int, char *, float );
|
|
|
+ void MakeWeightedMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int,
|
|
|
+ int, char *, float );
|
|
|
+ void MakeExpressionMorphTable( SAA_Scene *, SAA_Elem *, SAA_Elem *, int,
|
|
|
+ int, char *, float );
|
|
|
+ void MakeTexAnim( SAA_Scene *, SAA_Elem *, char * );
|
|
|
+
|
|
|
+ private:
|
|
|
+
|
|
|
+ char *rsrc_path;
|
|
|
+ char *database_name;
|
|
|
+ char *scene_name;
|
|
|
+ char *model_name;
|
|
|
+ char *eggFileName;
|
|
|
+ char *animFileName;
|
|
|
+ char *eggGroupName;
|
|
|
+ char *tex_path;
|
|
|
+ char *tex_filename;
|
|
|
+ char *search_prefix;
|
|
|
+
|
|
|
+ SI_Error result;
|
|
|
+ SAA_Scene scene;
|
|
|
+ SAA_Elem model;
|
|
|
+ SAA_Database database;
|
|
|
+ EggGroup *dart;
|
|
|
+ EggGroup *skeleton;
|
|
|
+ AnimGroup *rootAnim;
|
|
|
+ EggJoint *rootJnt;
|
|
|
+ AnimGroup *animRoot;
|
|
|
+ AnimGroup *morphRoot;
|
|
|
+ EggData animData;
|
|
|
+
|
|
|
+ int nurbs_step;
|
|
|
+ int anim_start;
|
|
|
+ int anim_end;
|
|
|
+ int anim_rate;
|
|
|
+ int pose_frame;
|
|
|
+ int verbose;
|
|
|
+ int flatten;
|
|
|
+ int shift_textures;
|
|
|
+ int ignore_tex_offsets;
|
|
|
+ int use_prefix;
|
|
|
+
|
|
|
+ bool foundRoot;
|
|
|
+ bool geom_as_joint;
|
|
|
+ bool make_anim;
|
|
|
+ bool make_nurbs;
|
|
|
+ bool make_poly;
|
|
|
+ bool make_soft;
|
|
|
+ bool make_morph;
|
|
|
+ bool make_duv;
|
|
|
+ bool make_dart;
|
|
|
+ bool has_morph;
|
|
|
+ bool make_pose;
|
|
|
+
|
|
|
+ ofstream eggFile;
|
|
|
+ ofstream animFile;
|
|
|
+ ofstream texFile;
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Help
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Displays the "what is this program" message, along
|
|
|
+// with the usage message. Should be overridden in base
|
|
|
+// classes to describe the current program.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+Help()
|
|
|
+{
|
|
|
+ cerr <<
|
|
|
+ "soft2egg takes a SoftImage scene or model\n"
|
|
|
+ "and outputs its contents as an egg file\n";
|
|
|
+
|
|
|
+ Usage();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Usage
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Displays the usage message.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+Usage() {
|
|
|
+ cerr << "\nUsage:\n"
|
|
|
+ << _commandName << " [opts] (must specify -m or -s)\n\n"
|
|
|
+ << "Options:\n";
|
|
|
+
|
|
|
+ ShowOpts();
|
|
|
+ cerr << "\n";
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: ShowOpts
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Displays the valid options. Should be extended in
|
|
|
+// base classes to show additional options relevant to
|
|
|
+// the current program.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+ShowOpts()
|
|
|
+{
|
|
|
+ cerr <<
|
|
|
+ " -r <path> - Used to provide soft with the resource\n"
|
|
|
+ " Defaults to 'c:/Softimage/SOFT_3.9.2/3D/test'.\n"
|
|
|
+ // " Defaults to '/ful/ufs/soft371_mips2/3D/rsrc'.\n"
|
|
|
+ " -d <path> - Database path.\n"
|
|
|
+ " -s <scene> - Indicates that a scene will be converted.\n"
|
|
|
+ " -m <model> - Indicates that a model will be converted.\n"
|
|
|
+ " -t <path> - Specify path to place converted textures.\n"
|
|
|
+ " -T <name> - Specify filename for texture map listing.\n"
|
|
|
+ " -S <step> - Specify step for nurbs surface triangulation.\n"
|
|
|
+ " -M <name> - Specify model output filename. Defaults to scene name.\n"
|
|
|
+ " -A <name> - Specify anim output filename. Defaults to scene name.\n"
|
|
|
+ " -N <name> - Specify egg group name.\n"
|
|
|
+ " -k - Enable soft assignment for geometry.\n"
|
|
|
+ " -n - Specify egg NURBS representation instead of poly's.\n"
|
|
|
+ " -p - Specify egg polygon output for geometry.\n"
|
|
|
+ " -P <frame> - Specify frame number for static pose.\n"
|
|
|
+ " -b <frame> - Specify starting frame for animation (default = first).\n"
|
|
|
+ " -e <frame> - Specify ending frame for animation (default = last).\n"
|
|
|
+ " -f <fps> - Specify frame rate for animation playback.\n"
|
|
|
+ " -a - Compile animation tables if animation present.\n"
|
|
|
+ " -F - Ignore hierarchy and build a completely flat skeleton.\n"
|
|
|
+ " -v <level> - Set debug level.\n"
|
|
|
+ " -x - Shift NURBS parameters to preserve Alias textures.\n"
|
|
|
+ " -i - Ignore Soft texture uv offsets.\n"
|
|
|
+ " -u - Use Soft prefix in model names.\n"
|
|
|
+ " -c - Cancel morph conversion.\n"
|
|
|
+ " -C - Cancel duv conversion.\n"
|
|
|
+ " -D - Don't make the output model a character.\n"
|
|
|
+ " -o <prefix>- Convert only models with given prefix.\n";
|
|
|
+
|
|
|
+ EggBase::ShowOpts();
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: HandleGetopts
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description:
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+boolean soft2egg::
|
|
|
+HandleGetopts(char flag, char *optarg, int &optind, int argc, char **argv)
|
|
|
+{
|
|
|
+ boolean okflag = true;
|
|
|
+
|
|
|
+ switch (flag)
|
|
|
+ {
|
|
|
+ case 'r': // Set the resource path for soft.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ // Get the path.
|
|
|
+ rsrc_path = optarg;
|
|
|
+ fprintf( outStream, "using rsrc path %s\n", rsrc_path );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'd': // Set the database path.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ // Get the path.
|
|
|
+ database_name = optarg;
|
|
|
+ fprintf( outStream, "using database %s\n", database_name );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 's': // Check if its a scene.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ // Get scene name.
|
|
|
+ scene_name = optarg;
|
|
|
+ fprintf( outStream, "loading scene %s\n", scene_name );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'm': // Check if its a model.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ // Get model name.
|
|
|
+ model_name = optarg;
|
|
|
+ fprintf( outStream, "loading model %s\n", model_name );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 't': // Get converted texture path.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ // Get tex path name.
|
|
|
+ tex_path = optarg;
|
|
|
+ fprintf( outStream, "texture path: %s\n", tex_path );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'T': // Specify texture list filename.
|
|
|
+ if ( strcmp( optarg, "") )
|
|
|
+ {
|
|
|
+ // Get the name.
|
|
|
+ tex_filename = optarg;
|
|
|
+ fprintf( outStream, "creating texture list file: %s\n",
|
|
|
+ tex_filename );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case 'S': // Set NURBS step.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ nurbs_step = atoi(optarg);
|
|
|
+ fprintf( outStream, "NURBS step: %d\n", nurbs_step );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'M': // Set model output file name.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ eggFileName = optarg;
|
|
|
+ fprintf( outStream, "Model output filename: %s\n", eggFileName );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'A': // Set anim output file name.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ animFileName = optarg;
|
|
|
+ fprintf( outStream, "Anim output filename: %s\n", animFileName );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'N': // Set egg model name.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ eggGroupName = optarg;
|
|
|
+ fprintf( outStream, "Egg group name: %s\n", eggGroupName );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'o': // Set search_prefix.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ search_prefix = optarg;
|
|
|
+ fprintf( outStream, "Only converting models with prefix: %s\n",
|
|
|
+ search_prefix );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'h': // print help message
|
|
|
+ Help();
|
|
|
+ exit(1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'c': // Cancel morph animation conversion
|
|
|
+ make_morph = FALSE;
|
|
|
+ fprintf( outStream, "canceling morph conversion\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'C': // Cancel uv animation conversion
|
|
|
+ make_duv = FALSE;
|
|
|
+ fprintf( outStream, "canceling uv animation conversion\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'D': // Omit the Dart flag
|
|
|
+ make_dart = FALSE;
|
|
|
+ fprintf( outStream, "making a non-character model\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'k': // Enable soft skinning
|
|
|
+ //make_soft = TRUE;
|
|
|
+ //fprintf( outStream, "enabling soft skinning\n" );
|
|
|
+ fprintf( outStream, "-k flag no longer necessary\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'n': // Generate egg NURBS output
|
|
|
+ make_nurbs = TRUE;
|
|
|
+ fprintf( outStream, "outputting egg NURBS info\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'p': // Generate egg polygon output
|
|
|
+ make_poly = TRUE;
|
|
|
+ fprintf( outStream, "outputting egg polygon info\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'P': // Generate static pose from given frame
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ make_pose = TRUE;
|
|
|
+ pose_frame = atoi(optarg);
|
|
|
+ fprintf( outStream, "generating static pose from frame %d\n",
|
|
|
+ pose_frame );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'a': // Compile animation tables.
|
|
|
+ make_anim = TRUE;
|
|
|
+ fprintf( outStream, "attempting to compile anim tables\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'F': // Build a flat skeleton.
|
|
|
+ flatten = TRUE;
|
|
|
+ fprintf( outStream, "building a flat skeleton!!!\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'x': // Shift NURBS parameters to preserve Alias textures.
|
|
|
+ shift_textures = TRUE;
|
|
|
+ fprintf( outStream, "shifting NURBS parameters...\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'i': // Ignore Soft uv texture offsets
|
|
|
+ ignore_tex_offsets = TRUE;
|
|
|
+ fprintf( outStream, "ignoring texture offsets...\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'u': // Use Soft prefix in model names
|
|
|
+ use_prefix = TRUE;
|
|
|
+ fprintf( outStream, "using prefix in model names...\n" );
|
|
|
+ break;
|
|
|
+
|
|
|
+
|
|
|
+ case 'v': // print debug messages.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ verbose = atoi(optarg);
|
|
|
+ fprintf( outStream, "using debug level %d\n", verbose );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'b': // Set animation start frame.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ anim_start = atoi(optarg);
|
|
|
+ fprintf( outStream, "animation starting at frame: %d\n",
|
|
|
+ anim_start );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'e': /// Set animation end frame.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ anim_end = atoi(optarg);
|
|
|
+ fprintf( outStream, "animation ending at frame: %d\n", anim_end );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 'f': /// Set animation frame rate.
|
|
|
+ if ( strcmp( optarg, "" ) )
|
|
|
+ {
|
|
|
+ anim_rate = atoi(optarg);
|
|
|
+ fprintf( outStream, "animation frame rate: %d\n", anim_rate );
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ okflag = EggBase::HandleGetopts(flag, optarg, optind, argc, argv);
|
|
|
+ }
|
|
|
+
|
|
|
+ return (okflag);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: isNum
|
|
|
+// Access: Public, Virtual
|
|
|
+// Description: Take a float and make sure it is of the body.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int soft2egg::
|
|
|
+isNum( float num )
|
|
|
+{
|
|
|
+ return( ( num < HUGE_VAL ) && finite( num ) );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GetRootName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, return a copy of the string up to
|
|
|
+// the first occurence of '-'.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+GetRootName( const char *name )
|
|
|
+{
|
|
|
+ char *hyphen;
|
|
|
+ char *root;
|
|
|
+ int len;
|
|
|
+
|
|
|
+ hyphen = strchr( name, '-' );
|
|
|
+ len = hyphen-name;
|
|
|
+
|
|
|
+ if ( (hyphen != NULL) && len )
|
|
|
+ {
|
|
|
+ root = (char *)malloc(sizeof(char)*(len+1));
|
|
|
+ strncpy( root, name, len );
|
|
|
+ root[sizeof(char)*(len)] = '\0';
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ root = (char *)malloc( sizeof(char)*(strlen(name)+1));
|
|
|
+ strcpy( root, name );
|
|
|
+ }
|
|
|
+
|
|
|
+ return( root );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: RemovePathName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, return a copy of the string after
|
|
|
+// the last occurence of '/
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+RemovePathName( const char *name )
|
|
|
+{
|
|
|
+ char *slash;
|
|
|
+ char *root;
|
|
|
+
|
|
|
+ if ( *name != NULL )
|
|
|
+ {
|
|
|
+ slash = strrchr( name, '/' );
|
|
|
+
|
|
|
+ root = (char *)malloc( sizeof(char)*(strlen(name)+1));
|
|
|
+
|
|
|
+ if ( slash != NULL )
|
|
|
+ strcpy( root, ++slash );
|
|
|
+ else
|
|
|
+ strcpy( root, name );
|
|
|
+
|
|
|
+ return( root );
|
|
|
+ }
|
|
|
+
|
|
|
+ fprintf( stderr, "Error: RemovePathName received NULL string!\n" );
|
|
|
+ return ( (char *)name );
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GetSliderName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, return that part of the string after
|
|
|
+// the first occurence of '-' and before the last
|
|
|
+// occurance of '.'
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+GetSliderName( const char *name )
|
|
|
+{
|
|
|
+ if ( name != NULL )
|
|
|
+ {
|
|
|
+ strstream newStr;
|
|
|
+ char *hyphen;
|
|
|
+ char *end;
|
|
|
+
|
|
|
+ hyphen = strchr( name, '-' );
|
|
|
+
|
|
|
+ // pull off stuff before first hyphen
|
|
|
+ if (hyphen != NULL)
|
|
|
+ {
|
|
|
+ newStr << ++hyphen;
|
|
|
+ end = newStr.str();
|
|
|
+ }
|
|
|
+
|
|
|
+ char *lastPeriod;
|
|
|
+
|
|
|
+ lastPeriod = strrchr( end, '.' );
|
|
|
+
|
|
|
+ // ignore stuff after last period
|
|
|
+ if ( lastPeriod != NULL )
|
|
|
+ {
|
|
|
+ *lastPeriod = '\0';
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( stdout, "slider name: '%s'\n", end );
|
|
|
+
|
|
|
+ return( end );
|
|
|
+ }
|
|
|
+
|
|
|
+ return( (char *)name );
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GetName
|
|
|
+// Access: Public
|
|
|
+// Description: Given an element, return a copy of the element's
|
|
|
+// name WITHOUT prefix.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+GetName( SAA_Scene *scene, SAA_Elem *element )
|
|
|
+{
|
|
|
+ int nameLen;
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ // get the name
|
|
|
+ SAA_elementGetNameLength( scene, element, &nameLen );
|
|
|
+ name = (char *)malloc(sizeof(char)*++nameLen);
|
|
|
+ SAA_elementGetName( scene, element, nameLen, name );
|
|
|
+
|
|
|
+ return name;
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GetFullName
|
|
|
+// Access: Public
|
|
|
+// Description: Given an element, return a copy of the element's
|
|
|
+// name complete with prefix.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+GetFullName( SAA_Scene *scene, SAA_Elem *element )
|
|
|
+{
|
|
|
+ int nameLen;
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ // get the name
|
|
|
+ SAA_elementGetNameLength( scene, element, &nameLen );
|
|
|
+ name = (char *)malloc(sizeof(char)*++nameLen);
|
|
|
+ SAA_elementGetName( scene, element, nameLen, name );
|
|
|
+
|
|
|
+ int prefixLen;
|
|
|
+ char *prefix;
|
|
|
+
|
|
|
+ // get the prefix
|
|
|
+ SAA_elementGetPrefixLength( scene, element, &prefixLen );
|
|
|
+ prefix = (char *)malloc(sizeof(char)*++prefixLen);
|
|
|
+ SAA_elementGetPrefix( scene, element, prefixLen, prefix );
|
|
|
+
|
|
|
+ strstream fullNameStrm;
|
|
|
+
|
|
|
+ // add 'em together
|
|
|
+ fullNameStrm << prefix << "-" << name << ends;
|
|
|
+
|
|
|
+ //free( name );
|
|
|
+ //free( prefix );
|
|
|
+
|
|
|
+ return fullNameStrm.str();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: GetModelNoteInfo
|
|
|
+// Access: Public
|
|
|
+// Description: Given an element, return a string containing the
|
|
|
+// contents of its MODEL NOTE entry
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+GetModelNoteInfo( SAA_Scene *scene, SAA_Elem *model )
|
|
|
+{
|
|
|
+
|
|
|
+ int size;
|
|
|
+ char *modelNote = NULL;
|
|
|
+ SAA_Boolean bigEndian;
|
|
|
+
|
|
|
+
|
|
|
+ SAA_elementGetUserDataSize( scene, model, "MNOT", &size );
|
|
|
+
|
|
|
+ if ( size != 0 )
|
|
|
+ {
|
|
|
+ // allocate modelNote string
|
|
|
+ modelNote = (char *)malloc(sizeof(char)*(size + 1));
|
|
|
+
|
|
|
+ // get ModelNote data from this model
|
|
|
+ SAA_elementGetUserData( scene, model, "MNOT", size,
|
|
|
+ &bigEndian, (void *)modelNote );
|
|
|
+
|
|
|
+ //strip off newline, if present
|
|
|
+ char *eol = strchr( modelNote, '\n' );
|
|
|
+ if ( eol != NULL)
|
|
|
+ *eol = '\0';
|
|
|
+ else
|
|
|
+ modelNote[size] = '\0';
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\nmodelNote = %s\n",
|
|
|
+ modelNote );
|
|
|
+ }
|
|
|
+
|
|
|
+ return modelNote;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeTableName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, and a number, return a new string
|
|
|
+// consisting of "string.number".
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+MakeTableName( const char *name, int number )
|
|
|
+{
|
|
|
+ strstream namestrm;
|
|
|
+
|
|
|
+ namestrm << name << "." << number << ends;
|
|
|
+ return namestrm.str();
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: FindModelByName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, find the model in the scene
|
|
|
+// whose name corresponds to the given string.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+SAA_Elem *soft2egg::
|
|
|
+FindModelByName( char *name, SAA_Scene *scene, SAA_Elem *models,
|
|
|
+ int numModels )
|
|
|
+{
|
|
|
+ char *foundName;
|
|
|
+ SAA_Elem *foundModel = NULL;
|
|
|
+
|
|
|
+ for ( int model = 0; model < numModels; model++ )
|
|
|
+ {
|
|
|
+ foundName = GetName( scene, &models[model] );
|
|
|
+
|
|
|
+ if ( !strcmp( name, foundName ) )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "foundModel: '%s' = '%s'\n",
|
|
|
+ name, foundName );
|
|
|
+
|
|
|
+ foundModel = &models[model];
|
|
|
+ return( foundModel );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fprintf( outStream, "findModelByName: failed to find model named: '%s'\n",
|
|
|
+ name );
|
|
|
+
|
|
|
+ return ( foundModel );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: DepointellizeName
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, return the string up to the first
|
|
|
+// period.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+DepointellizeName( char *name )
|
|
|
+{
|
|
|
+ char *endPtr;
|
|
|
+ char *newName;
|
|
|
+
|
|
|
+ newName = (char *)malloc(sizeof(char)*(strlen(name)+1));
|
|
|
+ sprintf( newName, "%s", name );
|
|
|
+
|
|
|
+ endPtr = strchr( newName, '.' );
|
|
|
+ if ( endPtr != NULL )
|
|
|
+ *endPtr = '\0';
|
|
|
+
|
|
|
+ return ( newName );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: ConvertTexture
|
|
|
+// Access: Public
|
|
|
+// Description: Given a string, return a copy of the string without
|
|
|
+// the leading file path, and make an rgb file of the
|
|
|
+// same name in the tex_path directory.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+char *soft2egg::
|
|
|
+ConvertTexture( SAA_Scene *scene, SAA_Elem *texture )
|
|
|
+{
|
|
|
+ char *fileName = NULL;
|
|
|
+ int fileNameLen = 0;
|
|
|
+
|
|
|
+ // get the texture's name
|
|
|
+ SAA_texture2DGetPicNameLength( scene, texture, &fileNameLen);
|
|
|
+
|
|
|
+ if ( fileNameLen )
|
|
|
+ {
|
|
|
+ fileName = (char *)malloc(sizeof(char)*++fileNameLen);
|
|
|
+ SAA_texture2DGetPicName( scene, texture, fileNameLen, fileName );
|
|
|
+ }
|
|
|
+
|
|
|
+ // make sure we are not being passed a NULL image, an empty image
|
|
|
+ // string or the default image created by egg2soft
|
|
|
+ if ( (fileName != NULL) && strlen( fileName ) && strcmp( fileName,
|
|
|
+ "/fat/people/gregw/new_test/PICTURES/default") &&
|
|
|
+ ( strstr( fileName, "noIcon" ) == NULL) )
|
|
|
+ {
|
|
|
+ char *texName = NULL;
|
|
|
+ char *texNamePath = NULL;
|
|
|
+ char *tmpName = NULL;
|
|
|
+ char *fileNameExt = NULL;
|
|
|
+
|
|
|
+ // strip off path and add .rgb
|
|
|
+ tmpName = strrchr( fileName, '/' );
|
|
|
+
|
|
|
+ if ( tmpName == NULL )
|
|
|
+ tmpName = fileName;
|
|
|
+ else
|
|
|
+ tmpName++;
|
|
|
+
|
|
|
+ float transp;
|
|
|
+
|
|
|
+ // check for alpha
|
|
|
+ SAA_texture2DGetTransparency( scene, texture, &transp );
|
|
|
+
|
|
|
+ if ( transp != 0.0f ) {
|
|
|
+ texName = (char *)malloc(sizeof(char)*(strlen(tmpName)+6));
|
|
|
+ sprintf( texName, "%s.rgba", tmpName );
|
|
|
+ } else {
|
|
|
+ texName = (char *)malloc(sizeof(char)*(strlen(tmpName)+5));
|
|
|
+ sprintf( texName, "%s.rgb", tmpName );
|
|
|
+ }
|
|
|
+
|
|
|
+ fileNameExt = (char *)malloc(sizeof(char)*(strlen(fileName)+5));
|
|
|
+ sprintf( fileNameExt, "%s.pic", fileName );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Looking for texture file: '%s'\n", fileNameExt );
|
|
|
+
|
|
|
+ // try to make conversion of file
|
|
|
+ int found_file = ( access( fileNameExt, F_OK ) == 0);
|
|
|
+
|
|
|
+ if ( found_file )
|
|
|
+ {
|
|
|
+ if ( tex_path )
|
|
|
+ {
|
|
|
+ texNamePath = (char *)malloc(sizeof(char)*(strlen(tex_path) +
|
|
|
+ strlen(texName) + 2));
|
|
|
+
|
|
|
+ sprintf( texNamePath, "%s/%s", tex_path, texName );
|
|
|
+
|
|
|
+ if ( texFile )
|
|
|
+ texFile << texNamePath << ": " << fileNameExt << "\n";
|
|
|
+
|
|
|
+ // make sure conversion doesn't already exist
|
|
|
+ if ( (access( texNamePath, F_OK ) != 0) && !texFile )
|
|
|
+ {
|
|
|
+ char *command = (char *)malloc(sizeof(char)*
|
|
|
+ (strlen(fileNameExt) + strlen(texNamePath) + 20));
|
|
|
+
|
|
|
+ sprintf( command, "image-resize -1 %s %s",
|
|
|
+ fileNameExt, texNamePath );
|
|
|
+
|
|
|
+ if ( verbose >=1 )
|
|
|
+ fprintf( outStream, "executing %s\n", command );
|
|
|
+
|
|
|
+ system( command );
|
|
|
+
|
|
|
+ //free( command );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >=1 )
|
|
|
+ fprintf( outStream, "%s already exists!\n", texNamePath );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Warning: No texture path defined" );
|
|
|
+ fprintf( outStream, " - No automatic conversion performed\n" );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Warning: Couldn't find texture file: %s\n",
|
|
|
+ fileNameExt );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( fileNameExt );
|
|
|
+
|
|
|
+ if (tex_path)
|
|
|
+ return( texNamePath );
|
|
|
+ else
|
|
|
+ return( texName );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Warning: ConvertTexture received NULL fileName\n" );
|
|
|
+ return( NULL );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: FindClosestTriVert
|
|
|
+// Access: Public
|
|
|
+// Description: Given an egg vertex pool, map each vertex therein to
|
|
|
+// a vertex within an array of SAA model vertices of
|
|
|
+// size numVert. Mapping is done by closest proximity.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int *soft2egg::
|
|
|
+FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert )
|
|
|
+{
|
|
|
+ int *vertMap = NULL;
|
|
|
+ int vpoolSize = vpool->NumVertices();
|
|
|
+ int i,j;
|
|
|
+ float thisDist;
|
|
|
+ float closestDist;
|
|
|
+ int closest;
|
|
|
+
|
|
|
+
|
|
|
+ vertMap = (int *)malloc(sizeof(int)*vpoolSize);
|
|
|
+
|
|
|
+ // for each vertex in vpool
|
|
|
+ for ( i = 0; i < vpoolSize; i++ )
|
|
|
+ {
|
|
|
+ // find closest model vertex
|
|
|
+ for ( j = 0; j < numVert-1; j++ )
|
|
|
+ {
|
|
|
+ // calculate distance
|
|
|
+ thisDist = sqrtf(
|
|
|
+ powf( vpool->Vertex(i)->position[0] - vertices[j].x , 2 ) +
|
|
|
+ powf( vpool->Vertex(i)->position[1] - vertices[j].y , 2 ) +
|
|
|
+ powf( vpool->Vertex(i)->position[2] - vertices[j].z , 2 ) );
|
|
|
+
|
|
|
+ // remember this if its the closest so far
|
|
|
+ if ( !j || ( thisDist < closestDist ) )
|
|
|
+ {
|
|
|
+ closest = j;
|
|
|
+ closestDist = thisDist;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ vertMap[i] = closest;
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "mapping v %d of %d:( %f, %f, %f )\n", i,
|
|
|
+ vpoolSize, vpool->Vertex(i)->position[0],
|
|
|
+ vpool->Vertex(i)->position[1],
|
|
|
+ vpool->Vertex(i)->position[2] );
|
|
|
+ fprintf( outStream, "to cv %d of %d:( %f, %f, %f )\tdelta = %f\n",
|
|
|
+ closest, numVert-1, vertices[closest].x, vertices[closest].y,
|
|
|
+ vertices[closest].z, closestDist );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return( vertMap );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeIndexMap
|
|
|
+// Access: Public
|
|
|
+// Description: Given an array of indices that is a map from one
|
|
|
+// set of vertices to another, return an array that
|
|
|
+// performs the reverse mapping of the indices array
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int *soft2egg::
|
|
|
+MakeIndexMap( int *indices, int numIndices, int mapSize )
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ // allocate map array
|
|
|
+ int *map = (int *)malloc(sizeof(int)*mapSize);
|
|
|
+
|
|
|
+ if ( map != NULL )
|
|
|
+ {
|
|
|
+ for ( i = 0; i < mapSize; i++ )
|
|
|
+ {
|
|
|
+ j = 0;
|
|
|
+ int found = 0;
|
|
|
+ while( j < numIndices )
|
|
|
+ {
|
|
|
+ if ( indices[j] == i )
|
|
|
+ {
|
|
|
+ map[i] = j;
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "map[%d] = %d\n", i, map[i] );
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ j++;
|
|
|
+ }
|
|
|
+ if ( !found)
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Warning: orphan vertex (%d)\n", i );
|
|
|
+ // default to -1 for now
|
|
|
+ map[i] = -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for index Map...\n");
|
|
|
+
|
|
|
+
|
|
|
+ return( map );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: findShapeVert
|
|
|
+// Access: Public
|
|
|
+// Description: given a vertex, find its corresponding shape vertex
|
|
|
+// and return its index.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+int soft2egg::
|
|
|
+findShapeVert( SAA_DVector vertex, SAA_DVector *vertices, int numVert )
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ int found = 0;
|
|
|
+
|
|
|
+ for ( i = 0; i < numVert && !found ; i++ )
|
|
|
+ {
|
|
|
+ if ( ( vertex.x == vertices[i].x ) &&
|
|
|
+ ( vertex.y == vertices[i].y ) &&
|
|
|
+ ( vertex.z == vertices[i].z ) )
|
|
|
+ {
|
|
|
+ found = 1;
|
|
|
+
|
|
|
+ if ( verbose >= 2)
|
|
|
+ fprintf( outStream, "found shape vert at index %d\n", i );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found )
|
|
|
+ i = -1;
|
|
|
+ else
|
|
|
+ i--;
|
|
|
+
|
|
|
+ return( i );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: LoadSoft
|
|
|
+// Access: Public
|
|
|
+// Description: Open the SI database and grab the scene & model info
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+LoadSoft()
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if ( (scene_name == NULL && model_name == NULL) || database_name == NULL )
|
|
|
+ {
|
|
|
+ Usage();
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((result = SAA_Init(rsrc_path, FALSE)) != SI_SUCCESS)
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Error: Couldn't get resource path!\n");
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((result = SAA_databaseLoad(database_name, &database)) != SI_SUCCESS)
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Error: Couldn't load database!\n");
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((result = SAA_sceneGetCurrent(&scene)) == SI_SUCCESS)
|
|
|
+ {
|
|
|
+ // load scene if present
|
|
|
+ if ( scene_name != NULL )
|
|
|
+ {
|
|
|
+ SAA_sceneLoad( &database, scene_name, &scene );
|
|
|
+
|
|
|
+ // if no egg filename specified, make up a name
|
|
|
+ if ( eggFileName == NULL )
|
|
|
+ {
|
|
|
+ eggFileName = (char *)malloc(sizeof(char)*
|
|
|
+ (strlen( scene_name ) + 14 ));
|
|
|
+ sprintf( eggFileName, "%s", DepointellizeName(scene_name) );
|
|
|
+ if ( make_nurbs )
|
|
|
+ strcat( eggFileName, "-nurb" );
|
|
|
+ strcat( eggFileName, "-mod.egg" );
|
|
|
+ }
|
|
|
+
|
|
|
+ // open an output file for the geometry if necessary
|
|
|
+ if ( make_poly || make_nurbs )
|
|
|
+ {
|
|
|
+ unlink( eggFileName );
|
|
|
+ eggFile.open( eggFileName, ios::out, 0666 );
|
|
|
+
|
|
|
+ if ( !eggFile )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Couldn't open output file: %s\n",
|
|
|
+ eggFileName );
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // open an output file for texture list if specified
|
|
|
+ if ( tex_filename != NULL )
|
|
|
+ {
|
|
|
+ unlink( tex_filename );
|
|
|
+ texFile.open( tex_filename, ios::out, 0666 );
|
|
|
+
|
|
|
+ if ( !texFile )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Couldn't open output file: %s\n",
|
|
|
+ tex_filename );
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( SAA_updatelistGet( &scene ) == SI_SUCCESS )
|
|
|
+ {
|
|
|
+ float time;
|
|
|
+
|
|
|
+ fprintf( outStream, "setting Scene to frame %d...\n", pose_frame );
|
|
|
+ //SAA_sceneSetPlayCtrlCurrentFrame( &scene, pose_frame );
|
|
|
+ SAA_frame2Seconds( &scene, pose_frame, &time );
|
|
|
+ SAA_updatelistEvalScene( &scene, time );
|
|
|
+ sginap( 100 );
|
|
|
+ SAA_updatelistEvalScene( &scene, time );
|
|
|
+ if ( make_pose )
|
|
|
+ SAA_sceneFreeze( &scene );
|
|
|
+ }
|
|
|
+
|
|
|
+ int numModels;
|
|
|
+ SAA_Elem *models;
|
|
|
+
|
|
|
+ SAA_sceneGetNbModels( &scene, &numModels );
|
|
|
+ fprintf( outStream, "Scene has %d model(s)...\n", numModels );
|
|
|
+
|
|
|
+ if ( numModels )
|
|
|
+ {
|
|
|
+ // allocate array of models
|
|
|
+ models = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numModels);
|
|
|
+
|
|
|
+ if ( models != NULL )
|
|
|
+ {
|
|
|
+ char *rootName = GetRootName( eggFileName );
|
|
|
+
|
|
|
+
|
|
|
+ if ( eggGroupName == NULL )
|
|
|
+ dart = _data.CreateGroup( NULL, rootName );
|
|
|
+ else
|
|
|
+ dart = _data.CreateGroup( NULL, eggGroupName );
|
|
|
+
|
|
|
+ if (make_dart)
|
|
|
+ dart->flags |= EF_DART;
|
|
|
+
|
|
|
+ AnimGroup *rootTable;
|
|
|
+
|
|
|
+ rootTable = animData.CreateTable( NULL, eggFileName );
|
|
|
+
|
|
|
+ if ( eggGroupName == NULL )
|
|
|
+ animRoot = animData.CreateBundle( rootTable, rootName );
|
|
|
+ else
|
|
|
+ animRoot = animData.CreateBundle( rootTable,
|
|
|
+ eggGroupName );
|
|
|
+
|
|
|
+ // propagate commet to anim data
|
|
|
+ animData.root_group.children.push_front(
|
|
|
+ new EggComment( _commandLine ) );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "made animRoot: %s\n", rootName );
|
|
|
+
|
|
|
+ SAA_sceneGetModels( &scene, numModels, models );
|
|
|
+
|
|
|
+ for ( i = 0; i < numModels; i++ )
|
|
|
+ {
|
|
|
+ int level;
|
|
|
+
|
|
|
+ SAA_elementGetHierarchyLevel( &scene, &models[i], &level );
|
|
|
+ if ( !level )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream,
|
|
|
+ "\negging scene model[%d]\n", i );
|
|
|
+
|
|
|
+ MakeEgg( dart, NULL, NULL, &scene, &models[i] );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( make_poly || make_nurbs )
|
|
|
+ {
|
|
|
+ // generate soft skinning assignments if desired
|
|
|
+ //
|
|
|
+ //disabled 1/1/99 to streamline joint assignments.
|
|
|
+ // all joint assignments now done here. Hard & Soft.
|
|
|
+ //if ( make_soft)
|
|
|
+ {
|
|
|
+ char *name;
|
|
|
+ char *fullname;
|
|
|
+ SAA_Boolean isSkeleton;
|
|
|
+
|
|
|
+ // search through models and look for skeleton parts
|
|
|
+ for ( i = 0; i < numModels; i++ )
|
|
|
+ {
|
|
|
+ SAA_modelIsSkeleton( &scene, &models[i], &isSkeleton );
|
|
|
+
|
|
|
+ // get fullname for splitting files, but
|
|
|
+ // only use it in file if requested
|
|
|
+ fullname = GetFullName( &scene, &models[i] );
|
|
|
+ if ( use_prefix )
|
|
|
+ name = fullname;
|
|
|
+ else
|
|
|
+ name = GetName( &scene, &models[i] );
|
|
|
+
|
|
|
+ // split
|
|
|
+ if ( strstr( fullname, search_prefix ) != NULL )
|
|
|
+ {
|
|
|
+ // for every skel part: get soft skin info
|
|
|
+ if ( isSkeleton )
|
|
|
+ MakeSoftSkin( &scene, &models[i], models,
|
|
|
+ numModels, name );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( name );
|
|
|
+ }
|
|
|
+
|
|
|
+ // make sure all vertices were assigned
|
|
|
+ // via soft skinning - if not hard assign them
|
|
|
+ for ( i = 0; i < numModels; i++ )
|
|
|
+ {
|
|
|
+ // get fullname for splitting files, but
|
|
|
+ // only use it in file if requested
|
|
|
+ fullname = GetFullName( &scene, &models[i] );
|
|
|
+ if ( use_prefix )
|
|
|
+ name = fullname;
|
|
|
+ else
|
|
|
+ name = GetName( &scene, &models[i] );
|
|
|
+
|
|
|
+ // split
|
|
|
+ if ( strstr( fullname, search_prefix ) != NULL )
|
|
|
+ CleanUpSoftSkin( &scene, &models[i], name );
|
|
|
+
|
|
|
+ //free( name );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // put the skeleton data into the egg data
|
|
|
+ dart->StealChildren( *skeleton );
|
|
|
+
|
|
|
+ // make sure all elements have unique names
|
|
|
+ _data.UniquifyNames();
|
|
|
+
|
|
|
+ // write out the geometry data if requested
|
|
|
+ //if ( make_poly || make_nurbs )
|
|
|
+ //{
|
|
|
+ eggFile << _data << "\n";
|
|
|
+ fprintf( outStream, "\nwriting out %s...\n", eggFileName );
|
|
|
+ eggFile.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ // close texture list file if opened
|
|
|
+ if ( texFile )
|
|
|
+ texFile.close();
|
|
|
+
|
|
|
+ // generate animation data if desired
|
|
|
+ if ( make_anim )
|
|
|
+ {
|
|
|
+ if ( animFileName == NULL )
|
|
|
+ {
|
|
|
+ animFileName = (char *)malloc(sizeof(char)*
|
|
|
+ (strlen(scene_name)+ 10 ));
|
|
|
+ sprintf( animFileName, "%s", DepointellizeName(scene_name) );
|
|
|
+ strcat( animFileName, "-chan.egg" );
|
|
|
+ }
|
|
|
+
|
|
|
+ unlink( animFileName );
|
|
|
+ animFile.open( animFileName, ios::out, 0666 );
|
|
|
+
|
|
|
+ if ( !animFile )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Couldn't open output file: %s\n",
|
|
|
+ animFileName );
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ int frame;
|
|
|
+ //int frameStep;
|
|
|
+ float time;
|
|
|
+
|
|
|
+ // get all the animation frame info if not specified
|
|
|
+ // on the command line
|
|
|
+ if (anim_start == -1000)
|
|
|
+ SAA_sceneGetPlayCtrlStartFrame( &scene, &anim_start );
|
|
|
+
|
|
|
+ if (anim_end == -1000)
|
|
|
+ SAA_sceneGetPlayCtrlEndFrame( &scene, &anim_end );
|
|
|
+
|
|
|
+ //SAA_sceneGetPlayCtrlFrameStep( &scene, &frameStep );
|
|
|
+
|
|
|
+ fprintf( outStream, "\nframeStart = %d\n", anim_start );
|
|
|
+ fprintf( outStream, "frameEnd = %d\n", anim_end );
|
|
|
+ //fprintf( outStream, "frameStep = %d\n", frameStep );
|
|
|
+
|
|
|
+ // start at first frame and go to last
|
|
|
+ for ( frame = anim_start; frame <= anim_end;
|
|
|
+ frame += 1)
|
|
|
+ {
|
|
|
+ SAA_frame2Seconds( &scene, frame, &time );
|
|
|
+ SAA_updatelistEvalScene( &scene, time );
|
|
|
+ sginap( 100 );
|
|
|
+ SAA_updatelistEvalScene( &scene, time );
|
|
|
+ fprintf( outStream, "\n> animating frame %d\n", frame );
|
|
|
+
|
|
|
+ // for each model
|
|
|
+ for ( i = 0; i < numModels; i++ )
|
|
|
+ {
|
|
|
+ char *name;
|
|
|
+ char *fullname;
|
|
|
+ SAA_Boolean isSkeleton;
|
|
|
+ SAA_ModelType type;
|
|
|
+
|
|
|
+ SAA_modelIsSkeleton( &scene, &models[i], &isSkeleton );
|
|
|
+
|
|
|
+ // get fullname for splitting files, but
|
|
|
+ // only use it in file if requested
|
|
|
+ fullname = GetFullName( &scene, &models[i] );
|
|
|
+ if ( use_prefix )
|
|
|
+ name = fullname;
|
|
|
+ else
|
|
|
+ name = GetName( &scene, &models[i] );
|
|
|
+
|
|
|
+ // split
|
|
|
+ if ( strstr( fullname, search_prefix ) != NULL )
|
|
|
+ {
|
|
|
+ // make the morph table for this critter
|
|
|
+ if ( make_morph )
|
|
|
+ {
|
|
|
+ MakeMorphTable( &scene, &models[i], models,
|
|
|
+ numModels, name, time );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // find out what type of node we're dealing with
|
|
|
+ result = SAA_modelGetType( &scene, &models[i], &type );
|
|
|
+
|
|
|
+ int size;
|
|
|
+
|
|
|
+ // check for uv texture animation
|
|
|
+ SAA_elementGetUserDataSize( &scene, &models[i],
|
|
|
+ "TEX_OFFSETS", &size );
|
|
|
+
|
|
|
+ // if so, update for this frame if desired
|
|
|
+ if ( ( size != 0 ) && make_duv )
|
|
|
+ MakeTexAnim( &scene, &models[i], name );
|
|
|
+
|
|
|
+ // if we have a skeleton or something that acts
|
|
|
+ // like one - build anim tables
|
|
|
+ if ( isSkeleton ||
|
|
|
+ ( strstr( name, "joint") != NULL ) )
|
|
|
+ MakeAnimTable( &scene, &models[i], name );
|
|
|
+
|
|
|
+ //free( name );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ animFile << animData << "\n";
|
|
|
+ fprintf( outStream, "\nwriting out %s...\n", animFileName );
|
|
|
+ animFile.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( models );
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Error: Not enough Memory for models...\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // otherwise try to load a model
|
|
|
+ else if ( model_name != NULL )
|
|
|
+ {
|
|
|
+
|
|
|
+ if ( eggFileName == NULL )
|
|
|
+ {
|
|
|
+ eggFileName =
|
|
|
+ (char *)malloc(sizeof(char)*(strlen( model_name )+13));
|
|
|
+ sprintf( eggFileName, "%s", DepointellizeName( model_name ) );
|
|
|
+
|
|
|
+ if ( make_nurbs )
|
|
|
+ strcat( eggFileName, "-nurb" );
|
|
|
+ strcat( eggFileName, "-mod.egg" );
|
|
|
+ }
|
|
|
+
|
|
|
+ eggFile.open( eggFileName );
|
|
|
+
|
|
|
+ if ( !eggFile )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Couldn't open output file: %s\n",
|
|
|
+ eggFileName );
|
|
|
+ exit( 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((result =
|
|
|
+ SAA_elementLoad(&database, &scene, model_name, &model))
|
|
|
+ == SI_SUCCESS)
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Loading single model...\n");
|
|
|
+ MakeEgg( NULL, NULL, NULL, &scene, &model );
|
|
|
+ }
|
|
|
+
|
|
|
+ eggFile << _data << "\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeEgg
|
|
|
+// Access: Public
|
|
|
+// Description: Make egg geometry from a given model. This include
|
|
|
+// textures, tex coords, colors, normals, and joints.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeEgg( EggGroup *parent, EggJoint *lastJoint, AnimGroup *lastAnim,
|
|
|
+ SAA_Scene *scene, SAA_Elem *model )
|
|
|
+{
|
|
|
+ char *name;
|
|
|
+ char *fullname;
|
|
|
+ SAA_ModelType type;
|
|
|
+ int id = 0;
|
|
|
+ int numShapes;
|
|
|
+ int numTri;
|
|
|
+ int numVert;
|
|
|
+ int numTexLoc = 0;
|
|
|
+ int numTexGlb = 0;
|
|
|
+ int i, j;
|
|
|
+ float matrix[4][4];
|
|
|
+ float *uScale = NULL;
|
|
|
+ float *vScale = NULL;
|
|
|
+ float *uOffset = NULL;
|
|
|
+ float *vOffset = NULL;
|
|
|
+ SAA_Boolean uv_swap = FALSE;
|
|
|
+ void *relinfo;
|
|
|
+ SAA_SubElem *triangles = NULL;
|
|
|
+ SAA_Elem *materials = NULL;
|
|
|
+ SAA_SubElem *cvertices = NULL;
|
|
|
+ SAA_DVector *cvertPos = NULL;
|
|
|
+ SAA_DVector *vertices = NULL;
|
|
|
+ SAA_DVector *normals = NULL;
|
|
|
+ int *indices = NULL;
|
|
|
+ int *indexMap = NULL;
|
|
|
+ int *numTexTri = NULL;
|
|
|
+ SAA_Elem *textures = NULL;
|
|
|
+ char **texNameArray;
|
|
|
+ float *uCoords = NULL;
|
|
|
+ float *vCoords = NULL;
|
|
|
+ SAA_GeomType gtype = SAA_GEOM_ORIGINAL;
|
|
|
+ SAA_Boolean visible;
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////
|
|
|
+ // find out what type of node we're dealing with
|
|
|
+ /////////////////////////////////////////////////
|
|
|
+ result = SAA_modelGetType( scene, model, &type );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ if ( type == SAA_MNILL )
|
|
|
+ fprintf( outStream, "encountered null\n");
|
|
|
+ else if ( type == SAA_MPTCH )
|
|
|
+ fprintf( outStream, "encountered patch\n" );
|
|
|
+ else if ( type == SAA_MFACE )
|
|
|
+ fprintf( outStream, "encountered face\n" );
|
|
|
+ else if ( type == SAA_MSMSH )
|
|
|
+ fprintf( outStream, "encountered mesh\n" );
|
|
|
+ else if ( type == SAA_MJNT )
|
|
|
+ fprintf( outStream, "encountered joint\n" );
|
|
|
+ else if ( type == SAA_MSPLN )
|
|
|
+ fprintf( outStream, "encountered spline\n" );
|
|
|
+ else if ( type == SAA_MMETA )
|
|
|
+ fprintf( outStream, "encountered meta element\n" );
|
|
|
+ else if ( type == SAA_MBALL )
|
|
|
+ fprintf( outStream, "encountered metaball\n" );
|
|
|
+ else if ( type == SAA_MNCRV )
|
|
|
+ fprintf( outStream, "encountered nurb curve\n" );
|
|
|
+ else if ( type == SAA_MNSRF )
|
|
|
+ fprintf( outStream, "encountered nurbs surf\n" );
|
|
|
+ else
|
|
|
+ fprintf( outStream, "encountered unknown type: %d\n", type );
|
|
|
+ }
|
|
|
+
|
|
|
+ /////////////////////////////
|
|
|
+ // Get the name of the model
|
|
|
+ /////////////////////////////
|
|
|
+
|
|
|
+ // Get the FULL name of the model
|
|
|
+ fullname = GetFullName( scene, model );
|
|
|
+
|
|
|
+ if ( use_prefix )
|
|
|
+ {
|
|
|
+ // Get the FULL name of the trim curve
|
|
|
+ name = fullname;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Get the name of the trim curve
|
|
|
+ name = GetName( scene, model );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "element name <%s>\n", name );
|
|
|
+
|
|
|
+ fflush( outStream );
|
|
|
+
|
|
|
+ // get the model's matrix
|
|
|
+ SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[0][0],
|
|
|
+ matrix[0][1], matrix[0][2], matrix[0][3] );
|
|
|
+ fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[1][0],
|
|
|
+ matrix[1][1], matrix[1][2], matrix[1][3] );
|
|
|
+ fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[2][0],
|
|
|
+ matrix[2][1], matrix[2][2], matrix[2][3] );
|
|
|
+ fprintf( outStream, "model matrix = %f %f %f %f\n", matrix[3][0],
|
|
|
+ matrix[3][1], matrix[3][2], matrix[3][3] );
|
|
|
+ }
|
|
|
+
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ // check to see if this is a branch we don't want to descend - this
|
|
|
+ // will prevent creating geometry for animation control structures
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ if ( (strstr( name, "con-" ) == NULL) &&
|
|
|
+ (strstr( name, "con_" ) == NULL) &&
|
|
|
+ (strstr( name, "fly_" ) == NULL) &&
|
|
|
+ (strstr( name, "fly-" ) == NULL) &&
|
|
|
+ (strstr( name, "camRIG" ) == NULL) &&
|
|
|
+ (strstr( name, "bars" ) == NULL) &&
|
|
|
+ // split
|
|
|
+ (strstr( fullname, search_prefix ) != NULL) )
|
|
|
+ {
|
|
|
+
|
|
|
+ // if making a pose - get deformed geometry
|
|
|
+ if ( make_pose )
|
|
|
+ gtype = SAA_GEOM_DEFORMED;
|
|
|
+
|
|
|
+ // Get the number of key shapes
|
|
|
+ SAA_modelGetNbShapes( scene, model, &numShapes );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "MakeEgg: num shapes: %d\n", numShapes);
|
|
|
+
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ // if multiple key shapes exist create table entries for each
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ if ( (numShapes > 0) && make_morph )
|
|
|
+ {
|
|
|
+ has_morph = 1;
|
|
|
+
|
|
|
+ // make sure root morph table exists
|
|
|
+ if ( morphRoot == NULL )
|
|
|
+ morphRoot = animData.CreateTable( animRoot, "morph" );
|
|
|
+
|
|
|
+ char *tableName;
|
|
|
+
|
|
|
+ // create morph table entry for each key shape
|
|
|
+ // (start at second shape - as first is the original geometry)
|
|
|
+ for ( i = 1; i < numShapes; i++ )
|
|
|
+ {
|
|
|
+ tableName = MakeTableName( name, i );
|
|
|
+ SAnimTable *table = new SAnimTable( );
|
|
|
+ table->name = tableName;
|
|
|
+ table->fps = anim_rate;
|
|
|
+ morphRoot->children.push_back( table );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created table named: '%s'\n", tableName );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( tableName );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_modelGetNodeVisibility( scene, model, &visible );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "model visibility: %d\n", visible );
|
|
|
+
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ // Only create egg polygon data if: the node is visible, and its not
|
|
|
+ // a NULL or a Joint, and we're outputing polys (or if we are outputing
|
|
|
+ // NURBS and the model is a poly mesh or a face)
|
|
|
+ ///////////////////////////////////////////////////////////////////////
|
|
|
+ if ( visible &&
|
|
|
+ (type != SAA_MNILL) &&
|
|
|
+ (type != SAA_MJNT) &&
|
|
|
+ ((make_poly ||
|
|
|
+ (make_nurbs && ((type == SAA_MSMSH) || (type == SAA_MFACE )) ))
|
|
|
+ || (!make_poly && !make_nurbs && make_duv &&
|
|
|
+ ((type == SAA_MSMSH) || (type == SAA_MFACE )) ))
|
|
|
+ )
|
|
|
+ {
|
|
|
+ // If the model is a NURBS in soft, set its step before tesselating
|
|
|
+ if ( type == SAA_MNSRF )
|
|
|
+ SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step );
|
|
|
+
|
|
|
+ // If the model is a PATCH in soft, set its step before tesselating
|
|
|
+ else if ( type == SAA_MPTCH )
|
|
|
+ SAA_patchSetStep( scene, model, nurbs_step, nurbs_step );
|
|
|
+
|
|
|
+ // Get the number of triangles
|
|
|
+ result = SAA_modelGetNbTriangles( scene, model, gtype, id, &numTri);
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "triangles: %d\n", numTri);
|
|
|
+
|
|
|
+ if ( result != SI_SUCCESS )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 ) {
|
|
|
+ fprintf( outStream,
|
|
|
+ "Error: couldn't get number of triangles!\n" );
|
|
|
+ fprintf( outStream, "\tbailing on model: '%s'\n", name );
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // check to see if surface is also skeleton...
|
|
|
+ SAA_Boolean isSkeleton = FALSE;
|
|
|
+
|
|
|
+ SAA_modelIsSkeleton( scene, model, &isSkeleton );
|
|
|
+
|
|
|
+ // check to see if this surface is used as a skeleton
|
|
|
+ // or is animated via constraint only ( these nodes are
|
|
|
+ // tagged by the animator with the keyword "joint"
|
|
|
+ // somewhere in the nodes name)
|
|
|
+ if ( isSkeleton || (strstr( name, "joint" ) != NULL) )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "animating Polys as joint!!!\n" );
|
|
|
+
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ }
|
|
|
+
|
|
|
+ // model is not a null and has no triangles!
|
|
|
+ if ( !numTri )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "no triangles!\n");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // allocate array of triangles
|
|
|
+ triangles = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTri);
|
|
|
+ if ( triangles != NULL )
|
|
|
+ {
|
|
|
+ // triangulate model and read the triangles into array
|
|
|
+ SAA_modelGetTriangles( scene, model, gtype, id, numTri, triangles );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for triangles...\n");
|
|
|
+
|
|
|
+ // allocate array of materials
|
|
|
+ materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTri);
|
|
|
+ if ( materials != NULL )
|
|
|
+ {
|
|
|
+ // read each triangle's material into array
|
|
|
+ SAA_triangleGetMaterials( scene, model, numTri, triangles,
|
|
|
+ materials );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for materials...\n");
|
|
|
+
|
|
|
+ // allocate array of textures per triangle
|
|
|
+ numTexTri = (int *)malloc(sizeof(int)*numTri);
|
|
|
+
|
|
|
+ // find out how many local textures per triangle
|
|
|
+ for ( i = 0; i < numTri; i++ )
|
|
|
+ {
|
|
|
+ result = SAA_materialRelationGetT2DLocNbElements( scene,
|
|
|
+ &materials[i], FALSE, &relinfo, &numTexTri[i] );
|
|
|
+
|
|
|
+ // polytex
|
|
|
+ if ( result == SI_SUCCESS )
|
|
|
+ numTexLoc += numTexTri[i];
|
|
|
+ }
|
|
|
+
|
|
|
+ // don't need this anymore...
|
|
|
+ //free( numTexTri );
|
|
|
+
|
|
|
+ // get local textures if present
|
|
|
+ if ( numTexLoc )
|
|
|
+ {
|
|
|
+ // ASSUME only one texture per material
|
|
|
+ textures = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTri);
|
|
|
+
|
|
|
+ for ( i = 0; i < numTri; i++ )
|
|
|
+ {
|
|
|
+ // and read all referenced local textures into array
|
|
|
+ SAA_materialRelationGetT2DLocElements( scene, &materials[i],
|
|
|
+ TEX_PER_MAT , &textures[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "numTexLoc = %d\n", numTexLoc);
|
|
|
+ }
|
|
|
+ // if no local textures, try to get global textures
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SAA_modelRelationGetT2DGlbNbElements( scene, model,
|
|
|
+ FALSE, &relinfo, &numTexGlb );
|
|
|
+
|
|
|
+ if ( numTexGlb )
|
|
|
+ {
|
|
|
+ // ASSUME only one texture per model
|
|
|
+ textures = (SAA_Elem *)malloc(sizeof(SAA_Elem));
|
|
|
+
|
|
|
+ // get the referenced texture
|
|
|
+ SAA_modelRelationGetT2DGlbElements( scene, model,
|
|
|
+ TEX_PER_MAT, textures );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "numTexGlb = %d\n", numTexGlb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // allocate array of control vertices
|
|
|
+ cvertices = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTri*3);
|
|
|
+ if ( cvertices != NULL )
|
|
|
+ {
|
|
|
+ // read each triangle's control vertices into array
|
|
|
+ SAA_triangleGetCtrlVertices( scene, model, gtype, id,
|
|
|
+ numTri, triangles, cvertices );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ cvertPos = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numTri*3);
|
|
|
+ SAA_ctrlVertexGetPositions( scene, model, numTri*3,
|
|
|
+ cvertices, cvertPos);
|
|
|
+
|
|
|
+ for ( i=0; i < numTri*3; i++ )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "cvert[%d] = %f %f %f %f\n", i,
|
|
|
+ cvertPos[i].x, cvertPos[i].y, cvertPos[i].z,
|
|
|
+ cvertPos[i].w );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for control vertices...\n");
|
|
|
+
|
|
|
+ // allocate array of control vertex indices
|
|
|
+ // this array maps from the redundant cvertices array into
|
|
|
+ // the unique vertices array (cvertices->vertices)
|
|
|
+ indices = (int *)malloc(sizeof(int)*numTri*3);
|
|
|
+ if ( indices != NULL )
|
|
|
+ {
|
|
|
+ for ( i=0; i < numTri*3; i++ )
|
|
|
+ indices[i] = 0;
|
|
|
+
|
|
|
+ SAA_ctrlVertexGetIndices( scene, model, numTri*3,
|
|
|
+ cvertices, indices );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ for ( i=0; i < numTri*3; i++ )
|
|
|
+ fprintf( outStream, "indices[%d] = %d\n", i, indices[i] );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for indices...\n");
|
|
|
+
|
|
|
+ // get number of UNIQUE vertices in model
|
|
|
+ SAA_modelGetNbTriVertices( scene, model, &numVert );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "num unique verts = %d\n", numVert );
|
|
|
+
|
|
|
+ //allocate array of vertices
|
|
|
+ vertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numVert);
|
|
|
+
|
|
|
+ // get the UNIQUE vertices of all triangles in model
|
|
|
+ SAA_modelGetTriVertices( scene, model, numVert, vertices );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( i=0; i < numVert; i++ )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "vertices[%d] = %f ", i, vertices[i].x );
|
|
|
+ fprintf( outStream, "%f %f %f\n", vertices[i].y,
|
|
|
+ vertices[i].z, vertices[i].w );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // allocate indexMap array
|
|
|
+ // we contruct this array to map from the unique vertices
|
|
|
+ // array to the redundant cvertices array - it will save
|
|
|
+ // us from doing repetitive searches later
|
|
|
+ indexMap = MakeIndexMap( indices, numTri*3, numVert );
|
|
|
+
|
|
|
+ // allocate array of normals
|
|
|
+ normals = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numTri*3);
|
|
|
+ if ( normals != NULL )
|
|
|
+ {
|
|
|
+ // read each control vertex's normals into an array
|
|
|
+ SAA_ctrlVertexGetNormals( scene, model, numTri*3,
|
|
|
+ cvertices, normals );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for normals...\n");
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( i=0; i<numTri*3; i++ )
|
|
|
+ fprintf( outStream, "normals[%d] = %f %f %f %f\n", i,
|
|
|
+ normals[i].x, normals[i].y, normals[i].z, normals[i].w );
|
|
|
+ }
|
|
|
+
|
|
|
+ int uRepeat, vRepeat;
|
|
|
+
|
|
|
+ // make sure we have textures before we get t-coords
|
|
|
+ if ( numTexLoc )
|
|
|
+ {
|
|
|
+ // allocate arrays for u & v coords
|
|
|
+ uCoords = (float *)malloc(sizeof(float)*numTri*numTexLoc*3);
|
|
|
+ vCoords = (float *)malloc(sizeof(float)*numTri*numTexLoc*3);
|
|
|
+
|
|
|
+ // read the u & v coords into the arrays
|
|
|
+ if ( uCoords != NULL && vCoords != NULL)
|
|
|
+ {
|
|
|
+ for ( i = 0; i < numTri*numTexLoc*3; i++ )
|
|
|
+ uCoords[i] = vCoords[i] = 0.0f;
|
|
|
+
|
|
|
+ SAA_ctrlVertexGetUVTxtCoords( scene, model, numTri*3,
|
|
|
+ cvertices, numTexLoc*3, uCoords, vCoords );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for texture coords...\n");
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( i=0; i<numTexLoc*3; i++ )
|
|
|
+ fprintf( outStream, "texcoords[%d] = ( %f , %f )\n", i,
|
|
|
+ uCoords[i], vCoords[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ // allocate arrays of texture info
|
|
|
+ uScale = ( float *)malloc(sizeof(float)*numTri);
|
|
|
+ vScale = ( float *)malloc(sizeof(float)*numTri);
|
|
|
+ uOffset = ( float *)malloc(sizeof(float)*numTri);
|
|
|
+ vOffset = ( float *)malloc(sizeof(float)*numTri);
|
|
|
+ texNameArray = ( char **)malloc(sizeof(char *)*numTri);
|
|
|
+
|
|
|
+ for ( i = 0; i < numTri; i++ )
|
|
|
+ {
|
|
|
+ // initialize the array value
|
|
|
+ texNameArray[i] = NULL;
|
|
|
+
|
|
|
+ SAA_Boolean valid = FALSE;
|
|
|
+ // check to see if texture is present
|
|
|
+ result = SAA_elementIsValid( scene, &textures[i], &valid );
|
|
|
+
|
|
|
+ if ( result != SI_SUCCESS )
|
|
|
+ fprintf( outStream, "SAA_elementIsValid failed!!!!\n" );
|
|
|
+
|
|
|
+ // texture present - get the name and uv info
|
|
|
+ if ( valid )
|
|
|
+ {
|
|
|
+ texNameArray[i] = ConvertTexture( scene, &textures[i] );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, " tritex[%d] named: %s\n", i,
|
|
|
+ texNameArray[i] );
|
|
|
+
|
|
|
+ SAA_texture2DGetUVSwap( scene, &textures[i], &uv_swap );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ if ( uv_swap == TRUE )
|
|
|
+ fprintf( outStream, " swapping u and v...\n" );
|
|
|
+
|
|
|
+ SAA_texture2DGetUScale( scene, &textures[i], &uScale[i] );
|
|
|
+ SAA_texture2DGetVScale( scene, &textures[i], &vScale[i] );
|
|
|
+ SAA_texture2DGetUOffset( scene, &textures[i], &uOffset[i] );
|
|
|
+ SAA_texture2DGetVOffset( scene, &textures[i], &vOffset[i] );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf(outStream, "tritex[%d] uScale: %f vScale: %f\n", i, uScale[i], vScale[i] );
|
|
|
+ fprintf(outStream, " uOffset: %f vOffset: %f\n",
|
|
|
+ uOffset[i], vOffset[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ SAA_texture2DGetRepeats( scene, &textures[i], &uRepeat,
|
|
|
+ &vRepeat );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf(outStream, "uRepeat = %d, vRepeat = %d\n",
|
|
|
+ uRepeat, vRepeat );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "Invalid texture...\n");
|
|
|
+ fprintf( outStream, " tritex[%d] named: (null)\n", i );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //debug
|
|
|
+ //for ( i = 0; i < numTri; i++ )
|
|
|
+ //{
|
|
|
+ //if ( texNameArray[i] != NULL )
|
|
|
+ //fprintf( outStream, " tritex[%d] named: %s\n", i,
|
|
|
+ //texNameArray[i] );
|
|
|
+ //else
|
|
|
+ //fprintf( outStream, " tritex[%d] named: (null)\n", i );
|
|
|
+ //}
|
|
|
+ }
|
|
|
+ // make sure we have textures before we get t-coords
|
|
|
+ else if ( numTexGlb )
|
|
|
+ {
|
|
|
+ SAA_Boolean valid;
|
|
|
+
|
|
|
+ // check to see if texture is present
|
|
|
+ SAA_elementIsValid( scene, textures, &valid );
|
|
|
+
|
|
|
+ // texture present - get the name and uv info
|
|
|
+ if ( valid )
|
|
|
+ {
|
|
|
+ SAA_texture2DGetUVSwap( scene, textures, &uv_swap );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ if ( uv_swap == TRUE )
|
|
|
+ fprintf( outStream, " swapping u and v...\n" );
|
|
|
+
|
|
|
+ // allocate arrays for u & v coords
|
|
|
+ uCoords = (float *)malloc(sizeof(float)*numTri*numTexGlb*3);
|
|
|
+ vCoords = (float *)malloc(sizeof(float)*numTri*numTexGlb*3);
|
|
|
+
|
|
|
+ for ( i = 0; i < numTri*numTexGlb*3; i++ )
|
|
|
+ {
|
|
|
+ uCoords[i] = vCoords[i] = 0.0f;
|
|
|
+ }
|
|
|
+
|
|
|
+ // read the u & v coords into the arrays
|
|
|
+ if ( uCoords != NULL && vCoords != NULL)
|
|
|
+ {
|
|
|
+ SAA_triCtrlVertexGetGlobalUVTxtCoords( scene, model,
|
|
|
+ numTri*3, cvertices, numTexGlb, textures,
|
|
|
+ uCoords, vCoords );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for texture coords...\n");
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( i=0; i<numTri*numTexGlb*3; i++ )
|
|
|
+ fprintf( outStream, "texcoords[%d] = ( %f , %f )\n", i,
|
|
|
+ uCoords[i], vCoords[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ texNameArray = ( char **)malloc(sizeof(char *));
|
|
|
+ *texNameArray = ConvertTexture( scene, textures );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, " global tex named: %s\n",
|
|
|
+ texNameArray );
|
|
|
+
|
|
|
+ // allocate arrays of texture info
|
|
|
+ uScale = ( float *)malloc(sizeof(float));
|
|
|
+ vScale = ( float *)malloc(sizeof(float));
|
|
|
+ uOffset = ( float *)malloc(sizeof(float));
|
|
|
+ vOffset = ( float *)malloc(sizeof(float));
|
|
|
+
|
|
|
+ SAA_texture2DGetUScale( scene, textures, uScale );
|
|
|
+ SAA_texture2DGetVScale( scene, textures, vScale );
|
|
|
+ SAA_texture2DGetUOffset( scene, textures, uOffset );
|
|
|
+ SAA_texture2DGetVOffset( scene, textures, vOffset );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, " global tex uScale: %f vScale: %f\n",
|
|
|
+ *uScale, *vScale );
|
|
|
+ fprintf( outStream, " uOffset: %f vOffset: %f\n",
|
|
|
+ *uOffset, *vOffset );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_texture2DGetRepeats( scene, textures, &uRepeat,
|
|
|
+ &vRepeat );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf(outStream, "uRepeat = %d, vRepeat = %d\n",
|
|
|
+ uRepeat, vRepeat );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else fprintf( outStream, "Invalid texture...\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ // make the egg vertex pool
|
|
|
+ EggVertexPool *pool = _data.CreateVertexPool( parent, name );
|
|
|
+
|
|
|
+ for ( i = 0; i < numVert; i++ )
|
|
|
+ {
|
|
|
+ pfVec3 eggVert;
|
|
|
+ pfVec3 eggNorm;
|
|
|
+
|
|
|
+ //convert to global coords
|
|
|
+ SAA_DVector local = vertices[i];
|
|
|
+ SAA_DVector global;
|
|
|
+
|
|
|
+ _VCT_X_MAT( global, local, matrix );
|
|
|
+
|
|
|
+ // set vertices array to reflect global coords
|
|
|
+ //vertices[i].x = global.x;
|
|
|
+ //vertices[i].y = global.y;
|
|
|
+ //vertices[i].z = global.z;
|
|
|
+
|
|
|
+ //eggVert.set( vertices[i].x, vertices[i].y, vertices[i].z );
|
|
|
+
|
|
|
+ // we'll preserve original verts for now
|
|
|
+ eggVert.set( global.x, global.y, global.z );
|
|
|
+
|
|
|
+ local = normals[indexMap[i]];
|
|
|
+
|
|
|
+ _VCT_X_MAT( global, local, matrix );
|
|
|
+
|
|
|
+ eggNorm.set( global.x, global.y, global.z );
|
|
|
+ eggNorm.normalize();
|
|
|
+
|
|
|
+ pool->AddVertex( eggVert, i );
|
|
|
+ pool->Vertex(i)->attrib.SetNormal( eggNorm );
|
|
|
+
|
|
|
+ // translate local uv's to global and add to vertex pool
|
|
|
+ if ( numTexLoc && (uCoords != NULL && vCoords !=NULL ))
|
|
|
+ {
|
|
|
+ float u, v;
|
|
|
+
|
|
|
+ if ( ignore_tex_offsets ) {
|
|
|
+ u = uCoords[indexMap[i]];
|
|
|
+ v = 1.0f - vCoords[indexMap[i]];
|
|
|
+ } else {
|
|
|
+ u = (uCoords[indexMap[i]] - uOffset[indexMap[i]/3]) /
|
|
|
+ uScale[indexMap[i]/3];
|
|
|
+
|
|
|
+ v = 1.0f - ((vCoords[indexMap[i]] - vOffset[indexMap[i]/3]) /
|
|
|
+ vScale[indexMap[i]/3]);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( isNum(u) && isNum(v) )
|
|
|
+ {
|
|
|
+ if ( uv_swap == TRUE )
|
|
|
+ pool->Vertex(i)->attrib.SetUV( v, u );
|
|
|
+ else
|
|
|
+ pool->Vertex(i)->attrib.SetUV( u, v );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ( numTexGlb && (uCoords != NULL && vCoords !=NULL ) )
|
|
|
+ {
|
|
|
+ float u, v;
|
|
|
+
|
|
|
+ if ( ignore_tex_offsets ) {
|
|
|
+ u = uCoords[indexMap[i]];
|
|
|
+ v = 1.0f - vCoords[indexMap[i]];
|
|
|
+ } else {
|
|
|
+ u = (uCoords[indexMap[i]] - *uOffset) / *uScale;
|
|
|
+ v = 1.0f - (( vCoords[indexMap[i]] - *vOffset ) / *vScale);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( isNum(u) && isNum(v) )
|
|
|
+ {
|
|
|
+ if ( uv_swap == TRUE )
|
|
|
+ pool->Vertex(i)->attrib.SetUV( v, u );
|
|
|
+ else
|
|
|
+ pool->Vertex(i)->attrib.SetUV( u, v );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // if we've encountered textures and we desire duv anims
|
|
|
+ if (( numTexLoc || numTexGlb ) && make_duv )
|
|
|
+ {
|
|
|
+ int numExp;
|
|
|
+ SAA_Elem *tex;
|
|
|
+
|
|
|
+ // grab the current texture
|
|
|
+ if ( numTexLoc )
|
|
|
+ tex = &textures[0];
|
|
|
+ else
|
|
|
+ tex = textures;
|
|
|
+
|
|
|
+ // find how many expressions for this shape
|
|
|
+ SAA_elementGetNbExpressions( scene, tex, NULL, FALSE,
|
|
|
+ &numExp );
|
|
|
+
|
|
|
+ // if it has expressions we'll assume its animated
|
|
|
+ if ( numExp )
|
|
|
+ {
|
|
|
+ // if animated object make base duv's, animtables
|
|
|
+ // for the duv's and store the original offsets
|
|
|
+ strstream uName, vName;
|
|
|
+
|
|
|
+ // create duv target names
|
|
|
+ uName << name << ".u" << ends;
|
|
|
+ vName << name << ".v" << ends;
|
|
|
+
|
|
|
+ // only create tables and store offsets
|
|
|
+ // on a per model basis (not per vertex)
|
|
|
+ if ( !i )
|
|
|
+ {
|
|
|
+
|
|
|
+ // make sure root morph table exists
|
|
|
+ if ( morphRoot == NULL )
|
|
|
+ morphRoot = animData.CreateTable( animRoot,
|
|
|
+ "morph" );
|
|
|
+
|
|
|
+ // create morph table entry for each duv
|
|
|
+ SAnimTable *uTable = new SAnimTable( );
|
|
|
+ uTable->name = uName.str();
|
|
|
+ uTable->fps = anim_rate;
|
|
|
+ morphRoot->children.push_back( uTable );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created duv table named: %s\n", uName.str() );
|
|
|
+
|
|
|
+ SAnimTable *vTable = new SAnimTable( );
|
|
|
+ vTable->name = vName.str();
|
|
|
+ vTable->fps = anim_rate;
|
|
|
+ morphRoot->children.push_back( vTable );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created duv table named: %s\n", vName.str() );
|
|
|
+
|
|
|
+ float texOffsets[4];
|
|
|
+
|
|
|
+ if ( numTexGlb )
|
|
|
+ {
|
|
|
+ texOffsets[0] = *uOffset;
|
|
|
+ texOffsets[1] = *vOffset;
|
|
|
+ texOffsets[2] = *uScale;
|
|
|
+ texOffsets[3] = *vScale;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ texOffsets[0] = uOffset[indexMap[i]/3];
|
|
|
+ texOffsets[1] = vOffset[indexMap[i]/3];
|
|
|
+ texOffsets[2] = uScale[indexMap[i]/3];
|
|
|
+ texOffsets[3] = vScale[indexMap[i]/3];
|
|
|
+ }
|
|
|
+
|
|
|
+ // remember original texture offsets future reference
|
|
|
+ SAA_elementSetUserData( scene, model, "TEX_OFFSETS",
|
|
|
+ sizeof( texOffsets ), TRUE, (void **)&texOffsets );
|
|
|
+ }
|
|
|
+
|
|
|
+ EggMorphOffset *duvU;
|
|
|
+ EggMorphOffset *duvV;
|
|
|
+
|
|
|
+ // generate base duv's for this vertex
|
|
|
+ duvU = new EggMorphOffset( uName.str(), 1.0 , 0.0 );
|
|
|
+ pool->Vertex(i)->attrib.uv_morphs.push_back( *duvU );
|
|
|
+
|
|
|
+ duvV = new EggMorphOffset( vName.str(), 0.0 , 1.0 );
|
|
|
+ pool->Vertex(i)->attrib.uv_morphs.push_back( *duvV );
|
|
|
+
|
|
|
+ } // if ( numExp )
|
|
|
+
|
|
|
+ } // if ( numTexLoc || numTexGlb )
|
|
|
+
|
|
|
+ } // for ( i = 0; i < numVert; i++ )
|
|
|
+
|
|
|
+ // if model has key shapes, generate vertex offsets
|
|
|
+ if ( has_morph && make_morph )
|
|
|
+ MakeVertexOffsets( scene, model, type, numShapes, numVert,
|
|
|
+ vertices, matrix, name );
|
|
|
+
|
|
|
+
|
|
|
+ // create vertex ref list for all polygons in the model
|
|
|
+ EggVertexRef *vref;
|
|
|
+
|
|
|
+ vref = new EggVertexRef( pool);
|
|
|
+ for ( i = 0; i < numVert; i++ )
|
|
|
+ {
|
|
|
+ //add each vert in pool to last joint for hard skinning
|
|
|
+ vref->indices.push_back( EggVertexIndex( i ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ // hard assign poly geometry if no soft-skinning requested
|
|
|
+ //
|
|
|
+ //disabled 1/1/99 to streamline joint assignments.
|
|
|
+ // all hard-skinning now done in CleanUpSoftSkin.
|
|
|
+ //if ( !make_soft )
|
|
|
+ //{
|
|
|
+ //if ( lastJoint != NULL )
|
|
|
+ //{
|
|
|
+ //lastJoint->vrefs.AddUniqueNode( *vref );
|
|
|
+
|
|
|
+ //if ( verbose >= 1 )
|
|
|
+ //fprintf( outStream, "hard-skinning %s (%d vertices)\n",
|
|
|
+ //name, i+1 );
|
|
|
+ //}
|
|
|
+ //}
|
|
|
+
|
|
|
+ // make an egg group to hold all triangles
|
|
|
+ EggGroup *group = _data.CreateGroup( parent, name);
|
|
|
+
|
|
|
+ // make this group the current parent
|
|
|
+ parent = group;
|
|
|
+
|
|
|
+ EggPolygon *poly = NULL;
|
|
|
+ EggColor *cref = NULL;
|
|
|
+ EggTexture *tref = NULL;
|
|
|
+
|
|
|
+ // for each triangle
|
|
|
+ for ( i = 0; i < numTri*3; i+=3 )
|
|
|
+ {
|
|
|
+ float r,g,b,a;
|
|
|
+ pfVec4 color;
|
|
|
+
|
|
|
+ // make egg poly for each traingle and reference
|
|
|
+ // the appropriate vertex in the pool
|
|
|
+ poly = _data.CreatePolygon( group, pool );
|
|
|
+ poly->AddVertex(indices[i]);
|
|
|
+ poly->AddVertex(indices[i+1]);
|
|
|
+ poly->AddVertex(indices[i+2]);
|
|
|
+
|
|
|
+ // check for back face flag in model note info
|
|
|
+ char *modelNoteStr = GetModelNoteInfo( scene, model );
|
|
|
+
|
|
|
+ if ( modelNoteStr != NULL )
|
|
|
+ {
|
|
|
+ if ( strstr( modelNoteStr, "bface" ) != NULL )
|
|
|
+ poly->flags |= EG_BFACE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // check to see if material is present
|
|
|
+ SAA_Boolean valid;
|
|
|
+ SAA_elementIsValid( scene, &materials[i/3], &valid );
|
|
|
+
|
|
|
+ // material present - get the color
|
|
|
+ if ( valid )
|
|
|
+ {
|
|
|
+ SAA_materialGetDiffuse( scene, &materials[i/3], &r, &g, &b );
|
|
|
+ SAA_materialGetTransparency( scene, &materials[i/3], &a );
|
|
|
+ color.set( r, g, b, 1.0f - a );
|
|
|
+ }
|
|
|
+ // no material - default to white
|
|
|
+ else
|
|
|
+ color.set( 1.0, 1.0, 1.0, 1.0 );
|
|
|
+
|
|
|
+ cref = _data.CreateColor(color);
|
|
|
+ poly->attrib.SetCRef(cref);
|
|
|
+
|
|
|
+ strstream uniqueTexName;
|
|
|
+
|
|
|
+ if (numTexLoc)
|
|
|
+ {
|
|
|
+ // polytex
|
|
|
+ if ( (texNameArray[i/3] != NULL) &&
|
|
|
+ (strcmp(texNameArray[i/3], "NULL") != 0) )
|
|
|
+ {
|
|
|
+ // append unique identifier to texname for
|
|
|
+ // this particular object
|
|
|
+ uniqueTexName << name << "-"
|
|
|
+ << RemovePathName(texNameArray[i/3]);
|
|
|
+
|
|
|
+ tref = _data.CreateTexture( texNameArray[i/3],
|
|
|
+ uniqueTexName.str() );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, " tritex[%d] named: %s\n", i/3,
|
|
|
+ texNameArray[i/3] );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if ( numTexGlb )
|
|
|
+ {
|
|
|
+ if ( texNameArray != NULL )
|
|
|
+ {
|
|
|
+ // append unique identifier to texname for
|
|
|
+ // this particular object
|
|
|
+ uniqueTexName << name << "-"
|
|
|
+ << RemovePathName(*texNameArray);
|
|
|
+
|
|
|
+ tref = _data.CreateTexture( *texNameArray,
|
|
|
+ uniqueTexName.str() );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, " tritex named: %s\n",
|
|
|
+ *texNameArray );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // set the clamp on the texture
|
|
|
+ if ( tref != NULL )
|
|
|
+ {
|
|
|
+ if ( uRepeat > 0 )
|
|
|
+ tref->wrapu = EggTexture::WM_repeat;
|
|
|
+ else
|
|
|
+ tref->wrapu = EggTexture::WM_clamp;
|
|
|
+
|
|
|
+ if ( vRepeat > 1 )
|
|
|
+ tref->wrapv = EggTexture::WM_repeat;
|
|
|
+ else
|
|
|
+ tref->wrapv = EggTexture::WM_clamp;
|
|
|
+
|
|
|
+ poly->attrib.SetTRef(tref);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // we're done - trash triangles...
|
|
|
+ SAA_modelClearTriangles( scene, model );
|
|
|
+
|
|
|
+ // free molloc'd memory
|
|
|
+ //free( triangles );
|
|
|
+ //free( materials );
|
|
|
+ //free( normals );
|
|
|
+ //free( cvertices );
|
|
|
+ //free( vertices );
|
|
|
+ //free( indices );
|
|
|
+ //free( indexMap );
|
|
|
+
|
|
|
+ // free these only if they were malloc'd for textures
|
|
|
+ if (numTexLoc || numTexGlb)
|
|
|
+ {
|
|
|
+ //free( textures );
|
|
|
+ //free( uCoords );
|
|
|
+ //free( vCoords );
|
|
|
+ //free( texNameArray );
|
|
|
+ //free( uScale );
|
|
|
+ //free( vScale );
|
|
|
+ //free( uOffset );
|
|
|
+ //free( vOffset );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ///////////////////////////////////////
|
|
|
+ // check to see if its a nurbs surface
|
|
|
+ ///////////////////////////////////////
|
|
|
+ if ( (type == SAA_MNSRF) && ( visible ) && (( make_nurbs )
|
|
|
+ || ( !make_nurbs && !make_poly && make_duv )) )
|
|
|
+ {
|
|
|
+ // check to see if NURBS is also skeleton...
|
|
|
+ SAA_Boolean isSkeleton = FALSE;
|
|
|
+
|
|
|
+ SAA_modelIsSkeleton( scene, model, &isSkeleton );
|
|
|
+
|
|
|
+ // check to see if this NURBS is used as a skeleton
|
|
|
+ // or is animated via constraint only ( these nodes are
|
|
|
+ // tagged by the animator with the keyword "joint"
|
|
|
+ // somewhere in the nodes name)
|
|
|
+ if ( isSkeleton || (strstr( name, "joint" ) != NULL) )
|
|
|
+ {
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ geom_as_joint = 1;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "animating NURBS as joint!!!\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ EggNurbsSurface *eggNurbsSurf = new EggNurbsSurface( name );
|
|
|
+ int uDegree, vDegree;
|
|
|
+
|
|
|
+ // create nurbs representation of surface
|
|
|
+ SAA_nurbsSurfaceGetDegree( scene, model, &uDegree, &vDegree );
|
|
|
+ eggNurbsSurf->u_order = uDegree + 1;
|
|
|
+ eggNurbsSurf->v_order = vDegree + 1;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "nurbs degree: %d u, %d v\n",
|
|
|
+ uDegree, vDegree );
|
|
|
+ fprintf( outStream, "nurbs order: %d u, %d v\n",
|
|
|
+ uDegree + 1, vDegree + 1 );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_Boolean uClosed = FALSE;
|
|
|
+ SAA_Boolean vClosed = FALSE;
|
|
|
+
|
|
|
+ SAA_nurbsSurfaceGetClosed( scene, model, &uClosed, &vClosed);
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ if ( uClosed )
|
|
|
+ fprintf( outStream, "nurbs is closed in u...\n");
|
|
|
+ if ( vClosed )
|
|
|
+ fprintf( outStream, "nurbs is closed in v...\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ int uRows, vRows;
|
|
|
+ SAA_nurbsSurfaceGetNbVertices( scene, model, &uRows, &vRows );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs vertices: %d u, %d v\n",
|
|
|
+ uRows, vRows );
|
|
|
+
|
|
|
+ int uCurves, vCurves;
|
|
|
+ SAA_nurbsSurfaceGetNbCurves( scene, model, &uCurves, &vCurves );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs curves: %d u, %d v\n",
|
|
|
+ uCurves, vCurves );
|
|
|
+
|
|
|
+ if ( shift_textures )
|
|
|
+ {
|
|
|
+ if ( uClosed )
|
|
|
+ // shift starting point on NURBS surface for correct textures
|
|
|
+ SAA_nurbsSurfaceShiftParameterization( scene, model, -2, 0 );
|
|
|
+
|
|
|
+ if ( vClosed )
|
|
|
+ // shift starting point on NURBS surface for correct textures
|
|
|
+ SAA_nurbsSurfaceShiftParameterization( scene, model, 0, -2 );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step );
|
|
|
+
|
|
|
+ // check for back face flag in model note info
|
|
|
+ char *modelNoteStr = GetModelNoteInfo( scene, model );
|
|
|
+
|
|
|
+ if ( modelNoteStr != NULL )
|
|
|
+ {
|
|
|
+ if ( strstr( modelNoteStr, "bface" ) != NULL )
|
|
|
+ eggNurbsSurf->flags |= EG_BFACE;
|
|
|
+ }
|
|
|
+
|
|
|
+ int numKnotsU, numKnotsV;
|
|
|
+
|
|
|
+ SAA_nurbsSurfaceGetNbKnots( scene, model, &numKnotsU, &numKnotsV );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs knots: %d u, %d v\n",
|
|
|
+ numKnotsU, numKnotsV );
|
|
|
+
|
|
|
+ double *knotsU, *knotsV;
|
|
|
+ knotsU = (double *)malloc(sizeof(double)*numKnotsU);
|
|
|
+ knotsV = (double *)malloc(sizeof(double)*numKnotsV);
|
|
|
+ SAA_nurbsSurfaceGetKnots( scene, model, gtype, 0,
|
|
|
+ numKnotsU, numKnotsV, knotsU, knotsV );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "u knots:\n" );
|
|
|
+
|
|
|
+ AddKnots( eggNurbsSurf->u_knots, knotsU, numKnotsU, uClosed, uDegree );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "v knots:\n" );
|
|
|
+
|
|
|
+ AddKnots( eggNurbsSurf->v_knots, knotsV, numKnotsV, vClosed, vDegree);
|
|
|
+
|
|
|
+ //free( knotsU );
|
|
|
+ //free( knotsV );
|
|
|
+
|
|
|
+ // set sub_div so we can see it in perfly
|
|
|
+ eggNurbsSurf->u_subdiv = (uRows-1)*nurbs_step;
|
|
|
+ eggNurbsSurf->v_subdiv = (vRows-1)*nurbs_step;
|
|
|
+
|
|
|
+ SAA_modelGetNbVertices( scene, model, &numVert );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "%d CV's\n", numVert );
|
|
|
+
|
|
|
+ // get the CV's
|
|
|
+ vertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numVert);
|
|
|
+ SAA_modelGetVertices( scene, model, gtype, 0,
|
|
|
+ numVert, vertices );
|
|
|
+
|
|
|
+ // create pool of NURBS vertices
|
|
|
+ EggVertexPool *pool = _data.CreateVertexPool( parent, name );
|
|
|
+ eggNurbsSurf->SetVertexPool( pool );
|
|
|
+
|
|
|
+ // create vertex ref list for all cv's in the model
|
|
|
+ EggVertexRef *vref;
|
|
|
+
|
|
|
+ vref = new EggVertexRef( pool);
|
|
|
+
|
|
|
+ for ( int k = 0; k<numVert; k++ )
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "original cv[%d] = %f %f %f %f\n", k,
|
|
|
+ vertices[k].x, vertices[k].y, vertices[k].z,
|
|
|
+ vertices[k].w );
|
|
|
+ }
|
|
|
+
|
|
|
+ pfVec4 eggVert;
|
|
|
+
|
|
|
+ // convert to global coords
|
|
|
+ SAA_DVector global;
|
|
|
+
|
|
|
+ _VCT_X_MAT( global, vertices[k], matrix );
|
|
|
+
|
|
|
+ //preserve original weight
|
|
|
+ global.w = vertices[k].w;
|
|
|
+
|
|
|
+ // normalize coords to weight
|
|
|
+ global.x *= global.w;
|
|
|
+ global.y *= global.w;
|
|
|
+ global.z *= global.w;
|
|
|
+
|
|
|
+ // this code is commented out because I
|
|
|
+ // am no longer sending global data to
|
|
|
+ // the other routines (ie makevertexoffset)
|
|
|
+
|
|
|
+ // set vertices array to reflect global coords
|
|
|
+ //vertices[k].x = global.x;
|
|
|
+ //vertices[k].y = global.y;
|
|
|
+ //vertices[k].z = global.z;
|
|
|
+ //vertices[k].w = global.w;
|
|
|
+
|
|
|
+ //if ( verbose >= 2 )
|
|
|
+ //{
|
|
|
+ //fprintf( outStream, "global cv[%d] = %f %f %f %f\n", k,
|
|
|
+ //vertices[k].x, vertices[k].y, vertices[k].z,
|
|
|
+ //vertices[k].w );
|
|
|
+ //}
|
|
|
+
|
|
|
+ //eggVert.set( vertices[k].x, vertices[k].y, vertices[k].z,
|
|
|
+ //vertices[k].w );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "global cv[%d] = %f %f %f %f\n", k,
|
|
|
+ global.x, global.y, global.z,
|
|
|
+ global.w );
|
|
|
+ }
|
|
|
+
|
|
|
+ eggVert.set( global.x, global.y, global.z,
|
|
|
+ global.w );
|
|
|
+
|
|
|
+ // populate vertex pool
|
|
|
+ pool->AddVertex( eggVert, k );
|
|
|
+
|
|
|
+ // add vref's to NURBS info
|
|
|
+ eggNurbsSurf->AddVertex( k );
|
|
|
+
|
|
|
+ //add each vert in pool to vref for hard skinning
|
|
|
+ vref->indices.push_back( EggVertexIndex( k ) );
|
|
|
+
|
|
|
+ // check to see if the NURB is closed in u
|
|
|
+ if ( uClosed )
|
|
|
+ {
|
|
|
+ // add first uDegree verts to end of row
|
|
|
+ if ( (k % uRows) == ( uRows - 1) )
|
|
|
+ for ( int i = 0; i < uDegree; i++ )
|
|
|
+ {
|
|
|
+ // add vref's to NURBS info
|
|
|
+ eggNurbsSurf->AddVertex( i+((k/uRows)*uRows) );
|
|
|
+
|
|
|
+ //add each vert to vref
|
|
|
+ vref->indices.push_back(
|
|
|
+ EggVertexIndex( i+((k/uRows)*uRows) ) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // if hard skinned or this nurb is also a joint
|
|
|
+ //
|
|
|
+ //disabled 1/1/99 to streamline joint assignments.
|
|
|
+ // all hard skinning now done in CleanUpSoftSkin.
|
|
|
+ //if (!make_soft || geom_as_joint)
|
|
|
+ //{
|
|
|
+ //add the new cv references to the last
|
|
|
+ //joint for hard skinning only
|
|
|
+ //if ( lastJoint != NULL )
|
|
|
+ //{
|
|
|
+ //lastJoint->vrefs.AddUniqueNode( *vref );
|
|
|
+ //geom_as_joint = 0;
|
|
|
+ //if ( verbose >= 1 )
|
|
|
+ //fprintf( outStream, "Doing NURBS hard skinning...\n");
|
|
|
+ //}
|
|
|
+ //}
|
|
|
+
|
|
|
+ // check to see if the NURB is closed in v
|
|
|
+ if ( vClosed && !uClosed )
|
|
|
+ {
|
|
|
+ // add first vDegree rows of verts to end of list
|
|
|
+ for ( int i = 0; i < vDegree*uRows; i++ )
|
|
|
+ eggNurbsSurf->AddVertex( i );
|
|
|
+ }
|
|
|
+ // check to see if the NURB is closed in u and v
|
|
|
+ else if ( vClosed && uClosed )
|
|
|
+ {
|
|
|
+ // add the first (degree) v verts and a few
|
|
|
+ // extra - for good measure
|
|
|
+ for ( i = 0; i < vDegree; i++ )
|
|
|
+ {
|
|
|
+ // add first vDegree rows of verts to end of list
|
|
|
+ for ( j = 0; j < uRows; j++ )
|
|
|
+ eggNurbsSurf->AddVertex( j+(i*uRows) );
|
|
|
+
|
|
|
+ // if u is closed to we have added uDegree
|
|
|
+ // verts onto the ends of the rows - add them here too
|
|
|
+ for ( k = 0; k < uDegree; k++ )
|
|
|
+ eggNurbsSurf->AddVertex( k+(i*uRows)+((k/uRows)*uRows) );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // get the color of the NURBS surface
|
|
|
+ int numNurbMats;
|
|
|
+ EggColor *nurbCref;
|
|
|
+ pfVec4 nurbColor;
|
|
|
+
|
|
|
+ SAA_modelRelationGetMatNbElements( scene, model, FALSE, &relinfo,
|
|
|
+ &numNurbMats );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs surf has %d materials\n",
|
|
|
+ numNurbMats );
|
|
|
+
|
|
|
+ if ( numNurbMats )
|
|
|
+ {
|
|
|
+ float r,g,b,a;
|
|
|
+
|
|
|
+ materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numNurbMats);
|
|
|
+
|
|
|
+ SAA_modelRelationGetMatElements( scene, model, relinfo,
|
|
|
+ numNurbMats, materials );
|
|
|
+
|
|
|
+ SAA_materialGetDiffuse( scene, &materials[0], &r, &g, &b );
|
|
|
+ SAA_materialGetTransparency( scene, &materials[0], &a );
|
|
|
+ nurbColor.set( r, g, b, 1.0f - a );
|
|
|
+ //nurbColor.set( r, g, b, 1.0 );
|
|
|
+
|
|
|
+ nurbCref = _data.CreateColor(nurbColor);
|
|
|
+ eggNurbsSurf->attrib.SetCRef(nurbCref);
|
|
|
+
|
|
|
+ //get the texture of the NURBS surface from the material
|
|
|
+ int numNurbTexLoc = 0;
|
|
|
+ int numNurbTexGlb = 0;
|
|
|
+
|
|
|
+ // ASSUME only one texture per material
|
|
|
+ SAA_Elem nurbTex;
|
|
|
+
|
|
|
+ // find out how many local textures per NURBS surface
|
|
|
+ // ASSUME it only has one material
|
|
|
+ SAA_materialRelationGetT2DLocNbElements( scene, &materials[0],
|
|
|
+ FALSE, &relinfo, &numNurbTexLoc );
|
|
|
+
|
|
|
+ // if present, get local textures
|
|
|
+ if ( numNurbTexLoc )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "%s had %d local tex\n", name,
|
|
|
+ numNurbTexLoc );
|
|
|
+
|
|
|
+ // get the referenced texture
|
|
|
+ SAA_materialRelationGetT2DLocElements( scene, &materials[0],
|
|
|
+ TEX_PER_MAT, &nurbTex );
|
|
|
+
|
|
|
+ }
|
|
|
+ // if no locals, try to get globals
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SAA_modelRelationGetT2DGlbNbElements( scene, model,
|
|
|
+ FALSE, &relinfo, &numNurbTexGlb );
|
|
|
+
|
|
|
+ if ( numNurbTexGlb )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "%s had %d global tex\n", name,
|
|
|
+ numNurbTexGlb );
|
|
|
+
|
|
|
+ // get the referenced texture
|
|
|
+ SAA_modelRelationGetT2DGlbElements( scene,
|
|
|
+ model, TEX_PER_MAT, &nurbTex );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // add tex ref's if we found any textures
|
|
|
+ if ( numNurbTexLoc || numNurbTexGlb)
|
|
|
+ {
|
|
|
+ char *texName = NULL;
|
|
|
+ char *uniqueTexName = NULL;
|
|
|
+ EggTexture *tref;
|
|
|
+ pfMatrix nurbTexMat;
|
|
|
+
|
|
|
+
|
|
|
+ // convert the texture to .rgb and adjust name
|
|
|
+ texName = ConvertTexture( scene, &nurbTex );
|
|
|
+
|
|
|
+ // append unique identifier to texname for
|
|
|
+ // this particular object
|
|
|
+ uniqueTexName = (char *)malloc(sizeof(char)*
|
|
|
+ (strlen(name)+strlen(texName)+3) );
|
|
|
+ sprintf( uniqueTexName, "%s-%s", name,
|
|
|
+ RemovePathName(texName) );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "creating tref %s\n",
|
|
|
+ uniqueTexName );
|
|
|
+ }
|
|
|
+
|
|
|
+ tref = _data.CreateTexture( texName, uniqueTexName );
|
|
|
+
|
|
|
+ uScale = ( float *)malloc(sizeof(float));
|
|
|
+ vScale = ( float *)malloc(sizeof(float));
|
|
|
+ uOffset = ( float *)malloc(sizeof(float));
|
|
|
+ vOffset = ( float *)malloc(sizeof(float));
|
|
|
+
|
|
|
+ // get texture offset info
|
|
|
+ SAA_texture2DGetUScale( scene, &nurbTex, uScale );
|
|
|
+ SAA_texture2DGetVScale( scene, &nurbTex, vScale );
|
|
|
+ SAA_texture2DGetUOffset( scene, &nurbTex, uOffset );
|
|
|
+ SAA_texture2DGetVOffset( scene, &nurbTex, vOffset );
|
|
|
+ SAA_texture2DGetUVSwap( scene, &nurbTex, &uv_swap );
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "nurbTex uScale: %f\n", *uScale );
|
|
|
+ fprintf( outStream, "nurbTex vScale: %f\n", *vScale );
|
|
|
+ fprintf( outStream, "nurbTex uOffset: %f\n", *uOffset );
|
|
|
+ fprintf( outStream, "nurbTex vOffset: %f\n", *vOffset );
|
|
|
+ if ( uv_swap )
|
|
|
+ fprintf( outStream, "nurbTex u & v swapped!\n" );
|
|
|
+ else
|
|
|
+ fprintf( outStream, "nurbTex u & v NOT swapped\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ nurbTexMat.makeIdent();
|
|
|
+
|
|
|
+ if ( !ignore_tex_offsets )
|
|
|
+ {
|
|
|
+ if ( uv_swap )
|
|
|
+ {
|
|
|
+ nurbTexMat[0][0] = 0.0f;
|
|
|
+ nurbTexMat[1][1] = 0.0f;
|
|
|
+ nurbTexMat[0][1] = 1 / *vScale;
|
|
|
+ nurbTexMat[1][0] = 1 / *uScale;
|
|
|
+ nurbTexMat[2][1] = -(*uOffset / *uScale);
|
|
|
+ nurbTexMat[2][0] = -(*vOffset / *vScale);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ nurbTexMat[0][0] = 1 / *uScale;
|
|
|
+ nurbTexMat[1][1] = 1 / *vScale;
|
|
|
+ nurbTexMat[2][0] = -(*uOffset / *uScale);
|
|
|
+ nurbTexMat[2][1] = -(*vOffset / *vScale);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //call printMat
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[0][0],
|
|
|
+ nurbTexMat[0][1], nurbTexMat[0][2], nurbTexMat[0][3] );
|
|
|
+ fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[1][0],
|
|
|
+ nurbTexMat[1][1], nurbTexMat[1][2], nurbTexMat[1][3] );
|
|
|
+ fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[2][0],
|
|
|
+ nurbTexMat[2][1], nurbTexMat[2][2], nurbTexMat[2][3] );
|
|
|
+ fprintf( outStream, "nurb tex matrix = %f %f %f %f\n", nurbTexMat[3][0],
|
|
|
+ nurbTexMat[3][1], nurbTexMat[3][2], nurbTexMat[3][3] );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ tref->tex_mat = nurbTexMat;
|
|
|
+ tref->flags |= EFT_TRANSFORM;
|
|
|
+
|
|
|
+ eggNurbsSurf->attrib.SetTRef(tref);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // if we've encountered textures and we desire duv anims
|
|
|
+ if (( numNurbTexLoc || numNurbTexGlb ) && make_duv )
|
|
|
+ {
|
|
|
+ int numExp;
|
|
|
+
|
|
|
+ // find how many expressions for this shape
|
|
|
+ SAA_elementGetNbExpressions( scene, &nurbTex, NULL, FALSE,
|
|
|
+ &numExp );
|
|
|
+
|
|
|
+ // if it has expressions we'll assume its animated
|
|
|
+ if ( numExp )
|
|
|
+ {
|
|
|
+ if ( verbose > 1 )
|
|
|
+ printf( "nurbTex has %d expressions...\n", numExp );
|
|
|
+
|
|
|
+ // if animated object make base duv's, animtables
|
|
|
+ // for the duv's and store the original offsets
|
|
|
+ strstream uName, vName;
|
|
|
+
|
|
|
+ // create duv target names
|
|
|
+ uName << name << ".u" << ends;
|
|
|
+ vName << name << ".v" << ends;
|
|
|
+
|
|
|
+ // make sure root morph table exists
|
|
|
+ if ( morphRoot == NULL )
|
|
|
+ morphRoot = animData.CreateTable( animRoot,
|
|
|
+ "morph" );
|
|
|
+
|
|
|
+ // create morph table entry for each duv
|
|
|
+ SAnimTable *uTable = new SAnimTable( );
|
|
|
+ uTable->name = uName.str();
|
|
|
+ uTable->fps = anim_rate;
|
|
|
+ morphRoot->children.push_back( uTable );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created duv table named: %s\n", uName.str() );
|
|
|
+
|
|
|
+ SAnimTable *vTable = new SAnimTable( );
|
|
|
+ vTable->name = vName.str();
|
|
|
+ vTable->fps = anim_rate;
|
|
|
+ morphRoot->children.push_back( vTable );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created duv table named: %s\n", vName.str() );
|
|
|
+
|
|
|
+ float texOffsets[4];
|
|
|
+
|
|
|
+ texOffsets[0] = *uOffset;
|
|
|
+ texOffsets[1] = *vOffset;
|
|
|
+ texOffsets[2] = *uScale;
|
|
|
+ texOffsets[3] = *vScale;
|
|
|
+
|
|
|
+ // remember original texture offsets future reference
|
|
|
+ SAA_elementSetUserData( scene, model, "TEX_OFFSETS",
|
|
|
+ sizeof( texOffsets ), TRUE, (void **)&texOffsets );
|
|
|
+
|
|
|
+ // create UV's and duv's for each vertex
|
|
|
+ for( i = 0; i < numVert; i++ )
|
|
|
+ {
|
|
|
+ pfVec2 tmpUV;
|
|
|
+ EggMorphOffset *duvU;
|
|
|
+ EggMorphOffset *duvV;
|
|
|
+
|
|
|
+ //create uv's so we can store duv's
|
|
|
+ eggNurbsSurf->CalcActualUV( i, tmpUV );
|
|
|
+ pool->Vertex(i)->attrib.SetUV( tmpUV[0], tmpUV[1] );
|
|
|
+
|
|
|
+ // generate base duv's for this vertex
|
|
|
+ duvU = new EggMorphOffset(uName.str(), 1.0 , 0.0);
|
|
|
+ pool->Vertex(i)->attrib.uv_morphs.push_back(*duvU);
|
|
|
+
|
|
|
+ duvV = new EggMorphOffset(vName.str(), 0.0 , 1.0);
|
|
|
+ pool->Vertex(i)->attrib.uv_morphs.push_back(*duvV);
|
|
|
+ }
|
|
|
+
|
|
|
+ } // if ( numExp )
|
|
|
+ } // if ( numTexLoc || numTexGlb )
|
|
|
+
|
|
|
+ //free( uScale );
|
|
|
+ //free( vScale );
|
|
|
+ //free( uOffset );
|
|
|
+ //free( vOffset );
|
|
|
+
|
|
|
+ //free( materials );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // no material present - default to white
|
|
|
+ nurbColor.set( 1.0, 1.0, 1.0, 1.0 );
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////////
|
|
|
+ // check NURBS surface for trim curves
|
|
|
+ //////////////////////////////////////////
|
|
|
+ int numTrims;
|
|
|
+ bool isTrim = TRUE;
|
|
|
+ SAA_SubElem *trims;
|
|
|
+
|
|
|
+ SAA_nurbsSurfaceGetNbTrimCurves( scene, model, SAA_TRIMTYPE_TRIM,
|
|
|
+ &numTrims );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs surf has %d trim curves\n",
|
|
|
+ numTrims );
|
|
|
+
|
|
|
+ if ( numTrims)
|
|
|
+ {
|
|
|
+ trims = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTrims);
|
|
|
+
|
|
|
+ if ( trims )
|
|
|
+ {
|
|
|
+ SAA_nurbsSurfaceGetTrimCurves( scene, model,
|
|
|
+ gtype, 0, SAA_TRIMTYPE_TRIM, numTrims,
|
|
|
+ trims );
|
|
|
+
|
|
|
+ MakeSurfaceCurve( scene, model, parent, eggNurbsSurf,
|
|
|
+ numTrims, trims, isTrim );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( trims );
|
|
|
+ }
|
|
|
+
|
|
|
+ //////////////////////////////////////////
|
|
|
+ // check NURBS surface for surface curves
|
|
|
+ //////////////////////////////////////////
|
|
|
+ isTrim = FALSE;
|
|
|
+
|
|
|
+ SAA_nurbsSurfaceGetNbTrimCurves( scene, model,
|
|
|
+ SAA_TRIMTYPE_PROJECTION, &numTrims );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "nurbs surf has %d surface curves\n",
|
|
|
+ numTrims );
|
|
|
+
|
|
|
+ if ( numTrims)
|
|
|
+ {
|
|
|
+ trims = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*numTrims);
|
|
|
+
|
|
|
+ if ( trims )
|
|
|
+ {
|
|
|
+ SAA_nurbsSurfaceGetTrimCurves( scene, model,
|
|
|
+ gtype, 0, SAA_TRIMTYPE_PROJECTION,
|
|
|
+ numTrims, trims );
|
|
|
+
|
|
|
+ MakeSurfaceCurve( scene, model, parent, eggNurbsSurf,
|
|
|
+ numTrims, trims, isTrim );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( trims );
|
|
|
+ }
|
|
|
+
|
|
|
+ // push the NURBS into the egg data
|
|
|
+ parent->children.push_back( eggNurbsSurf );
|
|
|
+
|
|
|
+ // if model has key shapes, generate vertex offsets
|
|
|
+ if ( has_morph && make_morph )
|
|
|
+ MakeVertexOffsets( scene, model, type, numShapes, numVert,
|
|
|
+ vertices, matrix, name );
|
|
|
+
|
|
|
+
|
|
|
+ //free( vertices );
|
|
|
+
|
|
|
+ }
|
|
|
+ /////////////////////////////////////
|
|
|
+ // check to see if its a NURBS curve
|
|
|
+ /////////////////////////////////////
|
|
|
+ else if ( (type == SAA_MNCRV) && ( visible ) && ( make_nurbs ) )
|
|
|
+ {
|
|
|
+ // ignore for now
|
|
|
+ // make the NURBS curve and push it into the egg data
|
|
|
+ //parent->children.push_back( MakeNurbsCurve( scene, model, parent,
|
|
|
+ //matrix, name ) );
|
|
|
+ }
|
|
|
+ else if ( type == SAA_MJNT )
|
|
|
+ {
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "encountered IK joint: %s\n", name );
|
|
|
+ }
|
|
|
+ /////////////////////
|
|
|
+ // it must be a NULL
|
|
|
+ /////////////////////
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SAA_AlgorithmType algo;
|
|
|
+
|
|
|
+ SAA_modelGetAlgorithm( scene, model, &algo );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "null algorithm: %d\n", algo );
|
|
|
+
|
|
|
+ if ( algo == SAA_ALG_INV_KIN )
|
|
|
+ {
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "encountered IK root: %s\n", name );
|
|
|
+ }
|
|
|
+ else if ( algo == SAA_ALG_INV_KIN_LEAF )
|
|
|
+ {
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "encountered IK leaf: %s\n", name );
|
|
|
+ }
|
|
|
+ else if ( algo == SAA_ALG_STANDARD )
|
|
|
+ {
|
|
|
+ SAA_Boolean isSkeleton = FALSE;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "encountered Standard null: %s\n", name);
|
|
|
+
|
|
|
+ SAA_modelIsSkeleton( scene, model, &isSkeleton );
|
|
|
+
|
|
|
+ // check to see if this NULL is used as a skeleton
|
|
|
+ // or is animated via constraint only ( these nodes are
|
|
|
+ // tagged by the animator with the keyword "joint"
|
|
|
+ // somewhere in the nodes name)
|
|
|
+ if ( isSkeleton || (strstr( name, "joint" ) != NULL) )
|
|
|
+ {
|
|
|
+ MakeJoint( scene, lastJoint, lastAnim, model, name );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "animating Standard null!!!\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "encountered some other NULL: %d\n",
|
|
|
+ algo );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // check for children...
|
|
|
+ int numChildren;
|
|
|
+ int thisChild;
|
|
|
+ SAA_Elem *children;
|
|
|
+
|
|
|
+ SAA_modelGetNbChildren( scene, model, &numChildren );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Model children: %d\n", numChildren );
|
|
|
+
|
|
|
+ if ( numChildren )
|
|
|
+ {
|
|
|
+ children = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numChildren);
|
|
|
+ SAA_modelGetChildren( scene, model, numChildren, children );
|
|
|
+ if ( children != NULL )
|
|
|
+ {
|
|
|
+ for ( thisChild = 0; thisChild < numChildren; thisChild++ )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\negging child %d...\n", thisChild);
|
|
|
+ MakeEgg( parent, lastJoint, lastAnim, scene,
|
|
|
+ &children[thisChild] );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough Memory for children...\n");
|
|
|
+ //free( children );
|
|
|
+ }
|
|
|
+ fflush( outStream );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Don't descend this branch!\n" );
|
|
|
+
|
|
|
+ // we are done for the most part - start cleaning up memory
|
|
|
+ //free( name );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeSurfaceCurve
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene and lists of u and v samples create a
|
|
|
+// an egg NURBS curve of degree two from the samples
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeSurfaceCurve( SAA_Scene *scene, SAA_Elem *model, EggGroup *parent,
|
|
|
+ EggNurbsSurface *&nurbsSurf, int numTrims, SAA_SubElem *trims,
|
|
|
+ bool isTrim )
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ long totalSamples = 0;
|
|
|
+ long *numSamples;
|
|
|
+ double *uSamples;
|
|
|
+ double *vSamples;
|
|
|
+ SAA_Elem *trimCurves;
|
|
|
+ char *name;
|
|
|
+
|
|
|
+ //get UV coord data
|
|
|
+ numSamples = (long *)malloc(sizeof(long)*numTrims);
|
|
|
+
|
|
|
+ SAA_surfaceCurveGetNbLinearSamples( scene, model, numTrims, trims,
|
|
|
+ numSamples );
|
|
|
+
|
|
|
+ for ( i = 0; i < numTrims; i++ )
|
|
|
+ {
|
|
|
+ totalSamples += numSamples[i];
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "numSamples[%d] = %d\n", i, numSamples[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "total samples = %ld\n", totalSamples );
|
|
|
+
|
|
|
+ uSamples = (double *)malloc(sizeof(double)*totalSamples);
|
|
|
+ vSamples = (double *)malloc(sizeof(double)*totalSamples);
|
|
|
+
|
|
|
+ SAA_surfaceCurveGetLinearSamples( scene, model, numTrims, trims,
|
|
|
+ numSamples, uSamples, vSamples );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ for ( long li = 0; li < totalSamples; li++ )
|
|
|
+ fprintf( outStream, "master list cv[%ld] = %f, %f\n", li,
|
|
|
+ uSamples[li], vSamples[li] );
|
|
|
+
|
|
|
+ trimCurves = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numTrims);
|
|
|
+
|
|
|
+ SAA_surfaceCurveExtract( scene, model, numTrims, trims, trimCurves );
|
|
|
+
|
|
|
+ // if it's a trim create a trim to assign trim curves to
|
|
|
+ EggNurbsSurface::Trim *eggTrim = new EggNurbsSurface::Trim();
|
|
|
+
|
|
|
+ // for each trim curve, make an egg curve and
|
|
|
+ // add it to the trims of the NURBS surface
|
|
|
+ for ( i = 0; i < numTrims; i++ )
|
|
|
+ {
|
|
|
+ if ( use_prefix )
|
|
|
+ {
|
|
|
+ // Get the FULL name of the trim curve
|
|
|
+ name = GetFullName( scene, &trimCurves[i] );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Get the name of the trim curve
|
|
|
+ name = GetName( scene, &trimCurves[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( isTrim )
|
|
|
+ {
|
|
|
+ // add to trim list
|
|
|
+ EggNurbsSurface::Loop *eggLoop = new EggNurbsSurface::Loop();
|
|
|
+ eggLoop->push_back( MakeUVNurbsCurve( i, numSamples, uSamples,
|
|
|
+ vSamples, parent, name ) );
|
|
|
+ eggTrim->push_back( *eggLoop );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ // add to curve list
|
|
|
+ nurbsSurf->curves.push_back( MakeUVNurbsCurve( i, numSamples, uSamples, vSamples, parent, name ) );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( isTrim )
|
|
|
+ // pus trim list onto trims list
|
|
|
+ nurbsSurf->trims.push_back( *eggTrim );
|
|
|
+
|
|
|
+ //free( name );
|
|
|
+ //free( trimCurves );
|
|
|
+ //free( uSamples );
|
|
|
+ //free( vSamples );
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeUVNurbsCurve
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene and lists of u and v samples create a
|
|
|
+// an egg NURBS curve of degree two from the samples
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+EggNurbsCurve *soft2egg::
|
|
|
+MakeUVNurbsCurve( int numCurve, long *numSamples, double *uSamples,
|
|
|
+ double *vSamples, EggGroup *parent, char *name )
|
|
|
+{
|
|
|
+ EggNurbsCurve *eggNurbsCurve = new EggNurbsCurve( name );
|
|
|
+
|
|
|
+ eggNurbsCurve->order = 2;
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "nurbs UV curve %s:\n", name );
|
|
|
+
|
|
|
+ //set sub_div so we can see it in perfly
|
|
|
+ //eggNurbsCurve->subdiv = numSamples[numCurve]/4;
|
|
|
+ // perfly chokes on big numbers - keep it reasonable
|
|
|
+ eggNurbsCurve->subdiv = 150;
|
|
|
+
|
|
|
+ //create pool of NURBS vertices
|
|
|
+ EggVertexPool *pool = _data.CreateVertexPool( parent, name );
|
|
|
+ eggNurbsCurve->SetVertexPool( pool );
|
|
|
+
|
|
|
+ // calculate offset to this curve's samples
|
|
|
+ // in list of all curve samples
|
|
|
+ int offset = 0;
|
|
|
+
|
|
|
+ for ( int o = 0; o < numCurve; o++ )
|
|
|
+ offset += numSamples[o];
|
|
|
+
|
|
|
+ for ( int k = 0; k<numSamples[numCurve]; k++ )
|
|
|
+ {
|
|
|
+ pfVec3 eggVert;
|
|
|
+
|
|
|
+ // index into the array of samples for this curve
|
|
|
+ eggVert.set( uSamples[k+offset], vSamples[k+offset], 1.0f );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "cv[%d] = %f %f %f\n", k, eggVert[0],
|
|
|
+ eggVert[1], eggVert[2] );
|
|
|
+
|
|
|
+ //populate vertex pool
|
|
|
+ pool->AddVertex( eggVert, k );
|
|
|
+
|
|
|
+ //add vref's to NURBS info
|
|
|
+ eggNurbsCurve->AddVertex( k );
|
|
|
+ }
|
|
|
+
|
|
|
+ // create numSamples[numCurve]+2 knots
|
|
|
+ eggNurbsCurve->knots.push_back( 0 );
|
|
|
+ for ( k = 0; k < numSamples[numCurve]; k++ )
|
|
|
+ eggNurbsCurve->knots.push_back( k );
|
|
|
+ eggNurbsCurve->knots.push_back( numSamples[numCurve] - 1 );
|
|
|
+
|
|
|
+ //set color to bright green for now
|
|
|
+ EggColor *nurbCref;
|
|
|
+ pfVec4 nurbColor;
|
|
|
+
|
|
|
+ nurbColor.set( 0.5, 1.0, 0.5, 1.0 );
|
|
|
+ nurbCref = _data.CreateColor(nurbColor);
|
|
|
+ eggNurbsCurve->attrib.SetCRef(nurbCref);
|
|
|
+
|
|
|
+ return( eggNurbsCurve );
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeNurbsCurve
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene and a NURBS curve model create the
|
|
|
+// the appropriate egg structures
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+EggNurbsCurve *soft2egg::
|
|
|
+MakeNurbsCurve( SAA_Scene *scene, SAA_Elem *model, EggGroup *parent,
|
|
|
+ float matrix[4][4], char *name )
|
|
|
+{
|
|
|
+ EggNurbsCurve *eggNurbsCurve = new EggNurbsCurve( name );
|
|
|
+ int degree;
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "nurbs curve %s:\n", name );
|
|
|
+
|
|
|
+ //create nurbs representation of surface
|
|
|
+ SAA_nurbsCurveGetDegree( scene, model, °ree );
|
|
|
+ eggNurbsCurve->order = degree + 1;
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "nurbs curve order: %d\n", degree + 1 );
|
|
|
+
|
|
|
+ SAA_nurbsCurveSetStep( scene, model, nurbs_step );
|
|
|
+
|
|
|
+ SAA_Boolean closed = FALSE;
|
|
|
+
|
|
|
+ SAA_nurbsCurveGetClosed( scene, model, &closed );
|
|
|
+ if ( closed )
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "nurbs curve is closed...\n");
|
|
|
+
|
|
|
+ int numKnots;
|
|
|
+
|
|
|
+ SAA_nurbsCurveGetNbKnots( scene, model, &numKnots );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "nurbs curve knots: %d\n", numKnots );
|
|
|
+ double *knots;
|
|
|
+ knots = (double *)malloc(sizeof(double)*numKnots);
|
|
|
+ SAA_nurbsCurveGetKnots( scene, model, SAA_GEOM_ORIGINAL, 0,
|
|
|
+ numKnots, knots );
|
|
|
+
|
|
|
+ AddKnots( eggNurbsCurve->knots, knots, numKnots, closed, degree );
|
|
|
+
|
|
|
+ //free( knots );
|
|
|
+
|
|
|
+ int numCV;
|
|
|
+
|
|
|
+ SAA_modelGetNbVertices( scene, model, &numCV );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "%d CV's (=? %d)\n", numCV, (numKnots-(degree+1)) );
|
|
|
+
|
|
|
+ //set sub_div so we can see it in perfly
|
|
|
+ eggNurbsCurve->subdiv = (numCV-1)*nurbs_step;
|
|
|
+
|
|
|
+ // get the CV's
|
|
|
+ SAA_DVector *cvArray;
|
|
|
+ cvArray = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV);
|
|
|
+ SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0,
|
|
|
+ numCV, cvArray );
|
|
|
+
|
|
|
+ //create pool of NURBS vertices
|
|
|
+ EggVertexPool *pool = _data.CreateVertexPool( parent, name );
|
|
|
+ eggNurbsCurve->SetVertexPool( pool );
|
|
|
+
|
|
|
+ for ( int k = 0; k<numCV; k++ )
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "cv[%d] = %f %f %f %f\n", k, cvArray[k].x,
|
|
|
+ cvArray[k].y, cvArray[k].z, cvArray[k].w );
|
|
|
+
|
|
|
+ pfVec4 eggVert;
|
|
|
+
|
|
|
+ //convert to global coords
|
|
|
+ SAA_DVector local = cvArray[k];
|
|
|
+ SAA_DVector global;
|
|
|
+
|
|
|
+ _HVCT_X_MAT( global, local, matrix );
|
|
|
+
|
|
|
+ eggVert.set( global.x, global.y, global.z, global.w );
|
|
|
+
|
|
|
+ //populate vertex pool
|
|
|
+ pool->AddVertex( eggVert, k );
|
|
|
+
|
|
|
+ //add vref's to NURBS info
|
|
|
+ eggNurbsCurve->AddVertex( k );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( closed )
|
|
|
+ {
|
|
|
+ // need to replicate first (degree) vertices
|
|
|
+ for ( k = 0; k < degree; k++ )
|
|
|
+ {
|
|
|
+ eggNurbsCurve->AddVertex( k );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding cv[%d] = %f %f %f %f\n", k,
|
|
|
+ cvArray[k].x, cvArray[k].y, cvArray[k].z, cvArray[k].w );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( cvArray );
|
|
|
+
|
|
|
+ //set color to bright green for now
|
|
|
+ EggColor *nurbCref;
|
|
|
+ pfVec4 nurbColor;
|
|
|
+
|
|
|
+ nurbColor.set( 0.5, 1.0, 0.5, 1.0 );
|
|
|
+ nurbCref = _data.CreateColor(nurbColor);
|
|
|
+ eggNurbsCurve->attrib.SetCRef(nurbCref);
|
|
|
+
|
|
|
+ return( eggNurbsCurve );
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: AddKnots
|
|
|
+// Access: Public
|
|
|
+// Description: Given a parametric surface, and its knots, create
|
|
|
+// the appropriate egg structure by filling in Soft's
|
|
|
+// implicit knots and assigning the rest to eggKnots.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+AddKnots( perf_vector<double> &eggKnots, double *knots, int numKnots,
|
|
|
+ SAA_Boolean closed, int degree )
|
|
|
+{
|
|
|
+ int k = 0;
|
|
|
+ double lastKnot = knots[0];
|
|
|
+ double *newKnots;
|
|
|
+
|
|
|
+ // add initial implicit knot(s)
|
|
|
+ if ( closed )
|
|
|
+ {
|
|
|
+ int i = 0;
|
|
|
+ newKnots = (double *)malloc(sizeof(double)*degree);
|
|
|
+
|
|
|
+ // need to add (degree) number of knots
|
|
|
+ for ( k = numKnots - 1; k >= numKnots - degree; k-- )
|
|
|
+ {
|
|
|
+ // we have to know these in order to calculate
|
|
|
+ // next knot value so hold them in temp array
|
|
|
+ newKnots[i] = lastKnot - (knots[k] - knots[k-1]);
|
|
|
+ lastKnot = newKnots[i];
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ for ( k = degree - 1; k >= 0; k-- )
|
|
|
+ {
|
|
|
+ eggKnots.push_back( newKnots[k] );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "knots[%d] = %f\n", k, newKnots[k] );
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( newKnots );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ eggKnots.push_back( knots[k] );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "knots[%d] = %f\n", k, knots[k] );
|
|
|
+ }
|
|
|
+
|
|
|
+ // add the regular complement of knots
|
|
|
+ for (k = 0; k < numKnots; k++)
|
|
|
+ {
|
|
|
+ eggKnots.push_back( knots[k] );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "knots[%d] = %f\n", k+1, knots[k] );
|
|
|
+ }
|
|
|
+
|
|
|
+ lastKnot = knots[numKnots-1];
|
|
|
+
|
|
|
+ // add trailing implicit knots
|
|
|
+ if ( closed )
|
|
|
+ {
|
|
|
+
|
|
|
+ // need to add (degree) number of knots
|
|
|
+ for ( k = 1; k <= degree; k++ )
|
|
|
+ {
|
|
|
+ eggKnots.push_back( lastKnot + (knots[k] - knots[k-1]) );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "knots[%d] = %f\n", k,
|
|
|
+ lastKnot + (knots[k] - knots[k-1]) );
|
|
|
+ lastKnot = lastKnot + (knots[k] - knots[k-1]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ eggKnots.push_back( knots[k-1] );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "knots[%d] = %f\n", k+1, knots[k-1] );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeJoint
|
|
|
+// Access: Public
|
|
|
+// Description: Given a name, a parent and a model create a new
|
|
|
+// a new EggJoint for that model.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeJoint( SAA_Scene *scene, EggJoint *&lastJoint, AnimGroup *&lastAnim,
|
|
|
+ SAA_Elem *model, char *name )
|
|
|
+{
|
|
|
+ float matrix[4][4];
|
|
|
+ pfMatrix Matrix;
|
|
|
+ EggJoint *joint;
|
|
|
+ SAA_Boolean globalFlag = FALSE;
|
|
|
+ int scale_joint = 0;
|
|
|
+
|
|
|
+
|
|
|
+ // this is a quick fix to make scaled skeletons possible
|
|
|
+ // if the parent contains the keyword "scale" make this joint
|
|
|
+ // a global root joint instead of a child...
|
|
|
+ if (lastJoint != NULL)
|
|
|
+ {
|
|
|
+ if ( strstr( lastJoint->name.Str(), "scale" ) != NULL )
|
|
|
+ {
|
|
|
+ scale_joint = 1;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "scale joint flag set!\n" );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // if not root, flatten is false, and last joint had no scaling
|
|
|
+ // applied to it, then create joint in skeleton tree
|
|
|
+ if ( (lastJoint != NULL) && !flatten && !scale_joint )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "lastJoint = %s\n", lastJoint->name.Str() );
|
|
|
+ fprintf( outStream, "getting local transform\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ),
|
|
|
+ TRUE, (void **)&globalFlag );
|
|
|
+
|
|
|
+ // get the local matrix
|
|
|
+ SAA_modelGetMatrix( scene, model, SAA_COORDSYS_LOCAL, matrix );
|
|
|
+
|
|
|
+ // make this into a pfMatrix
|
|
|
+ Matrix[0][0] = matrix[0][0];
|
|
|
+ Matrix[0][1] = matrix[0][1];
|
|
|
+ Matrix[0][2] = matrix[0][2];
|
|
|
+ Matrix[0][3] = matrix[0][3];
|
|
|
+ Matrix[1][0] = matrix[1][0];
|
|
|
+ Matrix[1][1] = matrix[1][1];
|
|
|
+ Matrix[1][2] = matrix[1][2];
|
|
|
+ Matrix[1][3] = matrix[1][3];
|
|
|
+ Matrix[2][0] = matrix[2][0];
|
|
|
+ Matrix[2][1] = matrix[2][1];
|
|
|
+ Matrix[2][2] = matrix[2][2];
|
|
|
+ Matrix[2][3] = matrix[2][3];
|
|
|
+ Matrix[3][0] = matrix[3][0];
|
|
|
+ Matrix[3][1] = matrix[3][1];
|
|
|
+ Matrix[3][2] = matrix[3][2];
|
|
|
+ Matrix[3][3] = matrix[3][3];
|
|
|
+
|
|
|
+ joint = _data.CreateJoint( lastJoint, name );
|
|
|
+ joint->transform = Matrix;
|
|
|
+ }
|
|
|
+ // if we already have a root attach this joint to it
|
|
|
+ else if (foundRoot)
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "getting global transform\n" );
|
|
|
+
|
|
|
+ globalFlag = TRUE;
|
|
|
+
|
|
|
+ SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ),
|
|
|
+ TRUE, (void *)&globalFlag );
|
|
|
+
|
|
|
+ // get the global matrix
|
|
|
+ SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix );
|
|
|
+
|
|
|
+ // make this into a pfMatrix
|
|
|
+ Matrix[0][0] = matrix[0][0];
|
|
|
+ Matrix[0][1] = matrix[0][1];
|
|
|
+ Matrix[0][2] = matrix[0][2];
|
|
|
+ Matrix[0][3] = matrix[0][3];
|
|
|
+ Matrix[1][0] = matrix[1][0];
|
|
|
+ Matrix[1][1] = matrix[1][1];
|
|
|
+ Matrix[1][2] = matrix[1][2];
|
|
|
+ Matrix[1][3] = matrix[1][3];
|
|
|
+ Matrix[2][0] = matrix[2][0];
|
|
|
+ Matrix[2][1] = matrix[2][1];
|
|
|
+ Matrix[2][2] = matrix[2][2];
|
|
|
+ Matrix[2][3] = matrix[2][3];
|
|
|
+ Matrix[3][0] = matrix[3][0];
|
|
|
+ Matrix[3][1] = matrix[3][1];
|
|
|
+ Matrix[3][2] = matrix[3][2];
|
|
|
+ Matrix[3][3] = matrix[3][3];
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "attaching orphan chain to root\n" );
|
|
|
+
|
|
|
+ joint = _data.CreateJoint( rootJnt, name );
|
|
|
+ joint->transform = Matrix;
|
|
|
+ lastAnim = rootAnim;
|
|
|
+ }
|
|
|
+ // if root, make a seperate tree for skeleton and
|
|
|
+ // create required Table for the Egg heirarchy
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "getting global transform\n" );
|
|
|
+
|
|
|
+ globalFlag = TRUE;
|
|
|
+
|
|
|
+ SAA_elementSetUserData( scene, model, "GLOBAL", sizeof( SAA_Boolean ),
|
|
|
+ TRUE, (void *)&globalFlag );
|
|
|
+
|
|
|
+ // get the global matrix
|
|
|
+ SAA_modelGetMatrix( scene, model, SAA_COORDSYS_GLOBAL, matrix );
|
|
|
+
|
|
|
+ // make this into a pfMatrix
|
|
|
+ Matrix[0][0] = matrix[0][0];
|
|
|
+ Matrix[0][1] = matrix[0][1];
|
|
|
+ Matrix[0][2] = matrix[0][2];
|
|
|
+ Matrix[0][3] = matrix[0][3];
|
|
|
+ Matrix[1][0] = matrix[1][0];
|
|
|
+ Matrix[1][1] = matrix[1][1];
|
|
|
+ Matrix[1][2] = matrix[1][2];
|
|
|
+ Matrix[1][3] = matrix[1][3];
|
|
|
+ Matrix[2][0] = matrix[2][0];
|
|
|
+ Matrix[2][1] = matrix[2][1];
|
|
|
+ Matrix[2][2] = matrix[2][2];
|
|
|
+ Matrix[2][3] = matrix[2][3];
|
|
|
+ Matrix[3][0] = matrix[3][0];
|
|
|
+ Matrix[3][1] = matrix[3][1];
|
|
|
+ Matrix[3][2] = matrix[3][2];
|
|
|
+ Matrix[3][3] = matrix[3][3];
|
|
|
+
|
|
|
+ rootJnt = _data.CreateJoint( skeleton, "root" );
|
|
|
+ rootJnt->transform.makeIdent();
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "setting skeleton root\n" );
|
|
|
+ rootJnt->flags |= EF_TRANSFORM;
|
|
|
+
|
|
|
+ joint = _data.CreateJoint( rootJnt, name );
|
|
|
+ joint->transform = Matrix;
|
|
|
+ foundRoot = TRUE;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "found first chain\n" );
|
|
|
+
|
|
|
+ // make skeleton table
|
|
|
+ AnimGroup *skeletonTable;
|
|
|
+ skeletonTable = animData.CreateTable( animRoot, "<skeleton>" );
|
|
|
+ rootAnim = animData.CreateTable( skeletonTable, "root" );
|
|
|
+ XfmSAnimTable *table = new XfmSAnimTable( );
|
|
|
+ table->name = "xform";
|
|
|
+ table->fps = anim_rate;
|
|
|
+ rootAnim->children.push_back( table );
|
|
|
+ lastAnim = rootAnim;
|
|
|
+ }
|
|
|
+
|
|
|
+ joint->flags |= EF_TRANSFORM;
|
|
|
+
|
|
|
+ //if ( make_anim)
|
|
|
+ //{
|
|
|
+ AnimGroup *anim = animData.CreateTable( lastAnim, name );
|
|
|
+ XfmSAnimTable *table = new XfmSAnimTable( );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "created anim table: %s\n", "xform" );
|
|
|
+ table->name = "xform";
|
|
|
+ table->fps = anim_rate;
|
|
|
+ anim->children.push_back( table );
|
|
|
+ lastAnim = anim;
|
|
|
+ //}
|
|
|
+
|
|
|
+ // make this joint current parent of chain
|
|
|
+ lastJoint = joint;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeSoftSkin
|
|
|
+// Access: Public
|
|
|
+// Description: Given a skeleton part find its envelopes (if any)
|
|
|
+// get the vertices associated with the envelopes and
|
|
|
+// their weights and make vertex ref's for the joint
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeSoftSkin( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models,
|
|
|
+ int numModels, char *name )
|
|
|
+{
|
|
|
+ int numEnv;
|
|
|
+ SAA_ModelType type;
|
|
|
+ SAA_Elem *envelopes;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\n>found skeleton part( %s )!\n", name );
|
|
|
+
|
|
|
+ SAA_skeletonGetNbEnvelopes( scene, model, &numEnv );
|
|
|
+
|
|
|
+ if ( numEnv )
|
|
|
+ {
|
|
|
+ // it's got envelopes - must be soft skinned
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "numEnv = %d\n", numEnv );
|
|
|
+
|
|
|
+ // allocate envelope array
|
|
|
+ envelopes = ( SAA_Elem *)malloc( sizeof( SAA_Elem )*numEnv );
|
|
|
+
|
|
|
+ if ( envelopes != NULL )
|
|
|
+ {
|
|
|
+ int thisEnv;
|
|
|
+ SAA_EnvType envType;
|
|
|
+ bool hasEnvVertices = 0;
|
|
|
+
|
|
|
+ SAA_skeletonGetEnvelopes( scene, model, numEnv, envelopes );
|
|
|
+
|
|
|
+ for ( thisEnv = 0; thisEnv < numEnv; thisEnv++ )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "env[%d]: ", thisEnv );
|
|
|
+
|
|
|
+ SAA_envelopeGetType( scene, &envelopes[thisEnv], &envType );
|
|
|
+
|
|
|
+ if ( envType == SAA_ENVTYPE_NONE )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envType = none\n" );
|
|
|
+ }
|
|
|
+ else if ( envType == SAA_ENVTYPE_FLXLCL )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envType = flexible, local\n" );
|
|
|
+ hasEnvVertices = 1;
|
|
|
+ }
|
|
|
+ else if ( envType == SAA_ENVTYPE_FLXGLB )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envType = flexible, global\n" );
|
|
|
+ hasEnvVertices = 1;
|
|
|
+ }
|
|
|
+ else if ( envType == SAA_ENVTYPE_RGDGLB )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envType = rigid, global\n" );
|
|
|
+ hasEnvVertices = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envType = unknown\n" );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( hasEnvVertices)
|
|
|
+ {
|
|
|
+ int *numEnvVertices;
|
|
|
+ SAA_SubElem *envVertices = NULL;
|
|
|
+
|
|
|
+ numEnvVertices = (int *)malloc(sizeof(int)*numEnv);
|
|
|
+
|
|
|
+ SAA_envelopeGetNbCtrlVertices( scene, model, numEnv,
|
|
|
+ envelopes, numEnvVertices );
|
|
|
+
|
|
|
+ if ( numEnvVertices != NULL )
|
|
|
+ {
|
|
|
+ int totalEnvVertices = 0;
|
|
|
+ int i,j,k;
|
|
|
+
|
|
|
+ for( i = 0; i < numEnv; i++ )
|
|
|
+ {
|
|
|
+ totalEnvVertices += numEnvVertices[i];
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "numEnvVertices[%d] = %d\n",
|
|
|
+ i, numEnvVertices[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "total env verts = %d\n",
|
|
|
+ totalEnvVertices );
|
|
|
+
|
|
|
+ if ( totalEnvVertices )
|
|
|
+ {
|
|
|
+ envVertices = (SAA_SubElem *)malloc(sizeof(SAA_SubElem)*totalEnvVertices);
|
|
|
+
|
|
|
+ if ( envVertices != NULL )
|
|
|
+ {
|
|
|
+
|
|
|
+ SAA_envelopeGetCtrlVertices( scene, model,
|
|
|
+ numEnv, envelopes, numEnvVertices, envVertices);
|
|
|
+
|
|
|
+ // loop through for each envelope
|
|
|
+ for ( i = 0; i < numEnv; i++ )
|
|
|
+ {
|
|
|
+ float *weights = NULL;
|
|
|
+ int vertArrayOffset = 0;
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "\nenvelope[%d]:\n", i );
|
|
|
+
|
|
|
+ weights = (float *)malloc(sizeof(float)*numEnvVertices[i]);
|
|
|
+
|
|
|
+ if ( weights )
|
|
|
+ {
|
|
|
+ char *envName;
|
|
|
+ int *vpoolMap = NULL;
|
|
|
+
|
|
|
+ for ( j = 0; j < i; j++ )
|
|
|
+ vertArrayOffset += numEnvVertices[j];
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream,
|
|
|
+ "envVertArray offset = %d\n",
|
|
|
+ vertArrayOffset );
|
|
|
+
|
|
|
+ // get the weights of the envelope vertices
|
|
|
+ SAA_ctrlVertexGetEnvelopeWeights(
|
|
|
+ scene, model, &envelopes[i],
|
|
|
+ numEnvVertices[i],
|
|
|
+ &envVertices[vertArrayOffset], weights );
|
|
|
+
|
|
|
+ // Get the name of the envelope model
|
|
|
+ if ( use_prefix )
|
|
|
+ {
|
|
|
+ // Get the FULL name of the envelope
|
|
|
+ envName = GetFullName( scene, &envelopes[i] );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Get the name of the envelope
|
|
|
+ envName = GetName( scene, &envelopes[i] );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "envelope name %s\n", envName );
|
|
|
+
|
|
|
+ // find out if envelope geometry is poly or nurb
|
|
|
+ //SAA_modelGetType( scene,
|
|
|
+ //FindModelByName( envName, scene,
|
|
|
+ //models, numModels ), &type );
|
|
|
+
|
|
|
+ SAA_modelGetType( scene, &envelopes[i], &type );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "envelope model type ");
|
|
|
+
|
|
|
+ if ( type == SAA_MSMSH )
|
|
|
+ fprintf( outStream, "MESH\n" );
|
|
|
+ else if ( type == SAA_MNSRF )
|
|
|
+ fprintf( outStream, "NURBS\n" );
|
|
|
+ else
|
|
|
+ fprintf( outStream, "OTHER\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ int *envVtxIndices = NULL;
|
|
|
+ envVtxIndices = (int *)malloc(sizeof(int)*numEnvVertices[i]);
|
|
|
+
|
|
|
+ // Get the envelope vertex indices
|
|
|
+ SAA_ctrlVertexGetIndices( scene, &envelopes[i], numEnvVertices[i],
|
|
|
+ &envVertices[vertArrayOffset], envVtxIndices );
|
|
|
+
|
|
|
+ // find out how many vertices the model has
|
|
|
+ int modelNumVert;
|
|
|
+
|
|
|
+ SAA_modelGetNbVertices( scene, &envelopes[i], &modelNumVert );
|
|
|
+
|
|
|
+ SAA_DVector *modelVertices = NULL;
|
|
|
+ modelVertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*modelNumVert);
|
|
|
+
|
|
|
+ // get the model vertices
|
|
|
+ SAA_modelGetVertices( scene, &envelopes[i],
|
|
|
+ SAA_GEOM_ORIGINAL, 0, modelNumVert,
|
|
|
+ modelVertices );
|
|
|
+
|
|
|
+ // create array of global model coords
|
|
|
+ SAA_DVector *globalModelVertices = NULL;
|
|
|
+ globalModelVertices = (SAA_DVector *)malloc(sizeof(SAA_DVector)*modelNumVert);
|
|
|
+ float matrix[4][4];
|
|
|
+
|
|
|
+ // tranform local model vert coords to global
|
|
|
+
|
|
|
+ // first get the global matrix
|
|
|
+ SAA_modelGetMatrix( scene, &envelopes[i], SAA_COORDSYS_GLOBAL, matrix );
|
|
|
+
|
|
|
+ // populate array of global model verts
|
|
|
+ for ( j = 0; j < modelNumVert; j++ )
|
|
|
+ {
|
|
|
+ _VCT_X_MAT( globalModelVertices[j],
|
|
|
+ modelVertices[j], matrix );
|
|
|
+ }
|
|
|
+
|
|
|
+ // find the egg vertex pool that corresponds
|
|
|
+ // to this envelope model
|
|
|
+ EggVertexPool *envPool =
|
|
|
+ (EggVertexPool *)(_data.pools.FindName( envName ));
|
|
|
+ // If we are outputting triangles:
|
|
|
+ // create an array that maps from a referenced
|
|
|
+ // vertex in the envelope to a corresponding
|
|
|
+ // vertex in the egg vertex pool
|
|
|
+ //if ( (type == SAA_MNSRF) && !make_nurbs )
|
|
|
+ if ( !make_nurbs || (type == SAA_MSMSH) )
|
|
|
+ {
|
|
|
+ vpoolMap = FindClosestTriVert( envPool,
|
|
|
+ globalModelVertices, modelNumVert );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ( envPool != NULL )
|
|
|
+ {
|
|
|
+
|
|
|
+ // find the egg joint that corresponds to this model
|
|
|
+ EggJoint *joint =
|
|
|
+ (EggJoint *)(skeleton->FindDescendent( name ));
|
|
|
+
|
|
|
+ // this doesn't seem to be necessary 4/7/99
|
|
|
+ //EggJoint *parent = (EggJoint *)joint->parent;
|
|
|
+ //assert(parent->IsA(NT_EggJoint));
|
|
|
+
|
|
|
+ // for every envelope vertex
|
|
|
+ for (j = 0; j < numEnvVertices[i]; j++)
|
|
|
+ {
|
|
|
+ double scaledWeight = weights[j]/ 100.0f;
|
|
|
+
|
|
|
+ // make sure its in legal range
|
|
|
+ if (( envVtxIndices[j] < modelNumVert )
|
|
|
+ && ( envVtxIndices[j] >= 0 ))
|
|
|
+ {
|
|
|
+ if ( (type == SAA_MNSRF) && make_nurbs )
|
|
|
+ {
|
|
|
+ // assign all referenced control vertices
|
|
|
+ joint->AddVertex( envPool->Vertex(envVtxIndices[j]), scaledWeight );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream,
|
|
|
+ "%d: adding vref to cv %d with weight %f\n",
|
|
|
+ j, envVtxIndices[j], scaledWeight );
|
|
|
+
|
|
|
+ envPool->Vertex(envVtxIndices[j])->AddJoint( joint, scaledWeight );
|
|
|
+ // set flag to show this vertex has
|
|
|
+ // been assigned
|
|
|
+ envPool->Vertex(envVtxIndices[j])->multipleJoints = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ //assign all the tri verts associated
|
|
|
+ // with this control vertex to joint
|
|
|
+ for ( k = 0; k < envPool->NumVertices(); k++ )
|
|
|
+ {
|
|
|
+ if ( vpoolMap[k] == envVtxIndices[j] )
|
|
|
+ {
|
|
|
+
|
|
|
+ // add each vert in pool to last
|
|
|
+ // joint for soft skinning
|
|
|
+ joint->AddVertex(envPool->Vertex(k),
|
|
|
+ scaledWeight);
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream,
|
|
|
+ "%d: adding vref from cv %d to vert %d with weight %f(vpool)\n",
|
|
|
+ j, envVtxIndices[j], k, scaledWeight );
|
|
|
+
|
|
|
+ envPool->Vertex(k)->AddJoint( joint, scaledWeight );
|
|
|
+ // set flag to show this vertex has
|
|
|
+ // been assigned
|
|
|
+ envPool->Vertex(k)->multipleJoints = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream,
|
|
|
+ "%d: Omitted vref from cv %d with weight %f (out of range 0 to %d )\n",
|
|
|
+ j, envVtxIndices[j], scaledWeight, modelNumVert );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Couldn't find vpool %s!\n", envName );
|
|
|
+
|
|
|
+ //free( modelVertices );
|
|
|
+ //free( globalModelVertices );
|
|
|
+ //free( envVtxIndices );
|
|
|
+ //free( envName );
|
|
|
+ } //if (weights)
|
|
|
+ //free( weights );
|
|
|
+
|
|
|
+ } // for i
|
|
|
+
|
|
|
+ } // if (envVertices != NULL)
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough memory for envelope vertices...\n");
|
|
|
+ //free( envVertices );
|
|
|
+ } // if (totalEnvVertices)
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "No envelope vertices present...\n");
|
|
|
+
|
|
|
+ //free( numEnvVertices );
|
|
|
+
|
|
|
+ } // if (numEnvVertices != NULL)
|
|
|
+
|
|
|
+ } // if (hasEnvVertices)
|
|
|
+
|
|
|
+ } // if (envelopes != NULL)
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Not enough memory for envelopes...\n" );
|
|
|
+
|
|
|
+ //free( envelopes );
|
|
|
+
|
|
|
+ } //if (numEnv)
|
|
|
+
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Skeleton member has no envelopes...\n" );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: CleanUpSoftSkin
|
|
|
+// Access: Public
|
|
|
+// Description: Given a model, make sure all its vertices have been
|
|
|
+// soft assigned. If not hard assign to the last
|
|
|
+// joint we saw.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+CleanUpSoftSkin( SAA_Scene *scene, SAA_Elem *model, char *name )
|
|
|
+{
|
|
|
+ static EggJoint *joint;
|
|
|
+ SAA_Elem parent;
|
|
|
+ SAA_ModelType type;
|
|
|
+ SAA_Boolean skel;
|
|
|
+
|
|
|
+ /////////////////////////////////////////////////
|
|
|
+ // find out what type of node we're dealing with
|
|
|
+ /////////////////////////////////////////////////
|
|
|
+ SAA_modelGetType( scene, model, &type );
|
|
|
+
|
|
|
+ char *parentName;
|
|
|
+ int level;
|
|
|
+ SAA_Elem *searchNode = model;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\nCleaning up model %s\n", name );
|
|
|
+
|
|
|
+ // this step is weird - I think I want it here but it seems
|
|
|
+ // to break some models. Files like props-props_wh_cookietime.3-0 in
|
|
|
+ // /ful/rnd/pub/vrml/chip/chips_adventure/char/zone1/rooms/warehouse_final
|
|
|
+ // need to do the "if (skel)" bit.
|
|
|
+
|
|
|
+ // am I a skeleton too?
|
|
|
+ SAA_modelIsSkeleton( scene, model, &skel );
|
|
|
+
|
|
|
+ // if not look for the last skeleton part
|
|
|
+ if ( skel )
|
|
|
+ parentName = name;
|
|
|
+ else do
|
|
|
+ {
|
|
|
+ SAA_elementGetHierarchyLevel( scene, searchNode, &level );
|
|
|
+
|
|
|
+ // make sure we don't try to get the root's parent
|
|
|
+ if ( level )
|
|
|
+ {
|
|
|
+ SAA_modelGetParent( scene, searchNode, &parent );
|
|
|
+
|
|
|
+ if ( use_prefix )
|
|
|
+ {
|
|
|
+ // Get the FULL name of the parent
|
|
|
+ parentName = GetFullName( scene, &parent );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // Get the name of the parent
|
|
|
+ parentName = GetName( scene, &parent );
|
|
|
+ }
|
|
|
+
|
|
|
+ SAA_modelGetType( scene, &parent, &type );
|
|
|
+
|
|
|
+ SAA_modelIsSkeleton( scene, &parent, &skel );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "model %s, level %d, type %d, skel %d\n",
|
|
|
+ parentName, level, type, skel );
|
|
|
+
|
|
|
+ searchNode = &parent;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // we reached the root of the tree
|
|
|
+ parentName = NULL;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "at root of tree! level %d\n", level );
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // look until parent is a joint or acts like one
|
|
|
+ } while ( !skel && ( strstr( parentName,"joint") == NULL ));
|
|
|
+
|
|
|
+ EggJoint *thisJoint = NULL;
|
|
|
+
|
|
|
+ if ( parentName != NULL )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "found model parent joint %s\n", parentName);
|
|
|
+ fprintf( outStream, "looking for joint %s\n", parentName );
|
|
|
+ }
|
|
|
+ thisJoint = (EggJoint *)(skeleton->FindDescendent( parentName ));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Couldn't find parent joint!\n");
|
|
|
+
|
|
|
+ if ( thisJoint != NULL )
|
|
|
+ {
|
|
|
+ joint = thisJoint;
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "setting joint to %s\n", parentName );
|
|
|
+
|
|
|
+ //find the vpool for this model
|
|
|
+ EggVertexPool *vPool =
|
|
|
+ (EggVertexPool *)(_data.pools.FindName( name ));
|
|
|
+
|
|
|
+ if (vPool != NULL)
|
|
|
+ {
|
|
|
+ int i;
|
|
|
+ double membership;
|
|
|
+ int numVerts = vPool->NumVertices() ;
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "found vpool %s w/ %d verts\n",
|
|
|
+ name, numVerts );
|
|
|
+
|
|
|
+ for ( i = 0; i < numVerts; i++ )
|
|
|
+ {
|
|
|
+ if ( vPool->Vertex(i)->multipleJoints != 1 )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "vpool %s vert %d", name, i );
|
|
|
+ fprintf( outStream, " not assigned!\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ // hard skin this vertex
|
|
|
+ joint->AddVertex( vPool->Vertex(i), 1.0f );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ membership = vPool->Vertex(i)->NetMembership();
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "vpool %s vert %d", name,
|
|
|
+ i );
|
|
|
+ fprintf( outStream, " has membership %f\n",
|
|
|
+ membership );
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( membership == 0 )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "adding full weight..\n" );
|
|
|
+
|
|
|
+ // hard skin this vertex
|
|
|
+ joint->AddVertex( vPool->Vertex(i), 1.0f );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "couldn't find vpool %s\n", name );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( parentName != NULL )
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "Couldn't find joint %s\n", parentName );
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+//////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeAnimTable
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene and a skeleton part ,get all the
|
|
|
+// position, rotation, and scale for the skeleton
|
|
|
+// part for this frame and write them out as Egg
|
|
|
+// animation tables.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeAnimTable( SAA_Scene *scene, SAA_Elem *skeletonPart, char *name )
|
|
|
+{
|
|
|
+
|
|
|
+ if ( skeletonPart != NULL )
|
|
|
+ {
|
|
|
+ float i,j,k;
|
|
|
+ float h,p,r;
|
|
|
+ float x,y,z;
|
|
|
+ int size;
|
|
|
+ SAA_Boolean globalFlag = FALSE;
|
|
|
+ SAA_Boolean bigEndian;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\n\nanimating child %s\n", name );
|
|
|
+
|
|
|
+ SAA_elementGetUserDataSize( scene, skeletonPart, "GLOBAL", &size );
|
|
|
+
|
|
|
+ if ( size != 0 )
|
|
|
+ SAA_elementGetUserData( scene, skeletonPart, "GLOBAL",
|
|
|
+ sizeof( SAA_Boolean), &bigEndian, (void *)&globalFlag );
|
|
|
+
|
|
|
+ if ( globalFlag )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, " using global matrix\n" );
|
|
|
+
|
|
|
+ //get SAA orientation
|
|
|
+ SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
|
|
|
+ &p, &h, &r );
|
|
|
+
|
|
|
+ //get SAA translation
|
|
|
+ SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
|
|
|
+ &x, &y, &z );
|
|
|
+
|
|
|
+ //get SAA scaling
|
|
|
+ SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_GLOBAL,
|
|
|
+ &i, &j, &k );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "using local matrix\n" );
|
|
|
+
|
|
|
+ //get SAA orientation
|
|
|
+ SAA_modelGetRotation( scene, skeletonPart, SAA_COORDSYS_LOCAL,
|
|
|
+ &p, &h, &r );
|
|
|
+
|
|
|
+ //get SAA translation
|
|
|
+ SAA_modelGetTranslation( scene, skeletonPart, SAA_COORDSYS_LOCAL,
|
|
|
+ &x, &y, &z );
|
|
|
+
|
|
|
+ //get SAA scaling
|
|
|
+ SAA_modelGetScaling( scene, skeletonPart, SAA_COORDSYS_LOCAL,
|
|
|
+ &i, &j, &k );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "\nanim data: %f %f %f\n\t%f %f %f\n\t%f %f %f\n",
|
|
|
+ i, j, k, h, p, r, x, y, z );
|
|
|
+
|
|
|
+ // find the appropriate anim table for this skeleton part
|
|
|
+ AnimGroup *thisGroup;
|
|
|
+ XfmSAnimTable *thisTable;
|
|
|
+
|
|
|
+ //find the anim table associated with this group
|
|
|
+ thisGroup = (AnimGroup *)(animRoot->FindDescendent( name ));
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "\nlooking for anim group %s\n", name );
|
|
|
+ if ( thisGroup != NULL )
|
|
|
+ {
|
|
|
+ thisTable = (XfmSAnimTable *)(thisGroup->FindDescendent( "xform" ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ thisTable->sub_tables[0].AddElement( i );
|
|
|
+ thisTable->sub_tables[1].AddElement( j );
|
|
|
+ thisTable->sub_tables[2].AddElement( k );
|
|
|
+ thisTable->sub_tables[3].AddElement( p );
|
|
|
+ thisTable->sub_tables[4].AddElement( h );
|
|
|
+ thisTable->sub_tables[5].AddElement( r );
|
|
|
+ thisTable->sub_tables[6].AddElement( x );
|
|
|
+ thisTable->sub_tables[7].AddElement( y );
|
|
|
+ thisTable->sub_tables[8].AddElement( z );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Couldn't allocate anim table\n" );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Couldn't find anim group %s\n", name );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Cannot build anim table - no skeleton\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeVertexOffsets
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a model , the vertices of its original
|
|
|
+// shape and its name find the difference between the
|
|
|
+// geometry of its key shapes and the models original
|
|
|
+// geometry and add morph vertices to the egg data to
|
|
|
+// reflect these changes.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeVertexOffsets( SAA_Scene *scene, SAA_Elem *model, SAA_ModelType type,
|
|
|
+ int numShapes, int numOrigVert, SAA_DVector *originalVerts, float
|
|
|
+ matrix[4][4], char *name )
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+ int offset;
|
|
|
+ int numCV;
|
|
|
+ char *mTableName;
|
|
|
+ SAA_DVector *shapeVerts = NULL;
|
|
|
+ SAA_DVector *uniqueVerts = NULL;
|
|
|
+
|
|
|
+ if ( (type == SAA_MNSRF) && make_nurbs )
|
|
|
+ SAA_nurbsSurfaceSetStep( scene, model, nurbs_step, nurbs_step );
|
|
|
+
|
|
|
+ SAA_modelGetNbVertices( scene, model, &numCV );
|
|
|
+
|
|
|
+ // get the shape verts
|
|
|
+ uniqueVerts = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV);
|
|
|
+ SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0,
|
|
|
+ numCV, uniqueVerts );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "%d CV's\n", numCV );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( i = 0; i < numCV; i++ )
|
|
|
+ fprintf( outStream, "uniqueVerts[%d] = %f %f %f %f\n", i,
|
|
|
+ uniqueVerts[i].x, uniqueVerts[i].y,
|
|
|
+ uniqueVerts[i].z, uniqueVerts[i].w );
|
|
|
+ }
|
|
|
+
|
|
|
+ // iterate through for each key shape (except original)
|
|
|
+ for ( i = 1; i < numShapes; i++ )
|
|
|
+ {
|
|
|
+ mTableName = MakeTableName( name, i );
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "\nMaking geometry offsets for %s...\n",
|
|
|
+ mTableName );
|
|
|
+
|
|
|
+ if ( (type == SAA_MNSRF) && make_nurbs )
|
|
|
+ fprintf( outStream, "calculating NURBS morphs...\n" );
|
|
|
+ else
|
|
|
+ fprintf( outStream, "calculating triangle morphs...\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+ // get the shape verts
|
|
|
+ shapeVerts = (SAA_DVector *)malloc(sizeof(SAA_DVector)*numCV);
|
|
|
+ SAA_modelGetVertices( scene, model, SAA_GEOM_SHAPE, i+1,
|
|
|
+ numCV, shapeVerts );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ for ( j=0; j < numCV; j++ )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "shapeVerts[%d] = %f %f %f\n", j,
|
|
|
+ shapeVerts[j].x, shapeVerts[j].y, shapeVerts[j].z );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // find the appropriate vertex pool
|
|
|
+ EggVertexPool *vPool =
|
|
|
+ (EggVertexPool *)(_data.pools.FindName( name ));
|
|
|
+
|
|
|
+ // for every original vertex, compare to the corresponding
|
|
|
+ // key shape vertex and see if a vertex offset is needed
|
|
|
+ for ( j=0; j < numOrigVert; j++ )
|
|
|
+ {
|
|
|
+ double dx, dy, dz;
|
|
|
+
|
|
|
+ if ( (type == SAA_MNSRF) && make_nurbs )
|
|
|
+ {
|
|
|
+ //dx = shapeVerts[j].x - (originalVerts[j].x/originalVerts[j].w);
|
|
|
+ //dy = shapeVerts[j].y - (originalVerts[j].y/originalVerts[j].w);
|
|
|
+ //dz = shapeVerts[j].z - (originalVerts[j].z/originalVerts[j].w);
|
|
|
+ dx = shapeVerts[j].x - originalVerts[j].x;
|
|
|
+ dy = shapeVerts[j].y - originalVerts[j].y;
|
|
|
+ dz = shapeVerts[j].z - originalVerts[j].z;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // we need to map from original vertices
|
|
|
+ // to triangle shape vertices here
|
|
|
+ offset = findShapeVert( originalVerts[j], uniqueVerts,
|
|
|
+ numCV );
|
|
|
+
|
|
|
+ dx = shapeVerts[offset].x - originalVerts[j].x;
|
|
|
+ dy = shapeVerts[offset].y - originalVerts[j].y;
|
|
|
+ dz = shapeVerts[offset].z - originalVerts[j].z;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "oVert[%d] = %f %f %f %f\n", j,
|
|
|
+ originalVerts[j].x, originalVerts[j].y,
|
|
|
+ originalVerts[j].z, originalVerts[j].w );
|
|
|
+
|
|
|
+ if ( (type == SAA_MNSRF) && make_nurbs )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "global shapeVerts[%d] = %f %f %f %f\n", j, shapeVerts[j].x, shapeVerts[j].y,
|
|
|
+ shapeVerts[j].z, shapeVerts[j].w );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fprintf( outStream,
|
|
|
+ "global shapeVerts[%d] = %f %f %f\n", offset,
|
|
|
+ shapeVerts[offset].x,
|
|
|
+ shapeVerts[offset].y,
|
|
|
+ shapeVerts[offset].z );
|
|
|
+ }
|
|
|
+
|
|
|
+ fprintf( outStream, "%d: dx = %f, dy = %f, dz = %f\n", j,
|
|
|
+ dx, dy, dz );
|
|
|
+ }
|
|
|
+
|
|
|
+ // if change isn't negligible, make a morph vertex entry
|
|
|
+ double total = fabs(dx)+fabs(dy)+fabs(dz);
|
|
|
+ if ( total > 0.00001 )
|
|
|
+ {
|
|
|
+ if ( vPool != NULL )
|
|
|
+ {
|
|
|
+ // create offset
|
|
|
+ EggMorphOffset *dxyz =
|
|
|
+ new EggMorphOffset( mTableName, dx, dy, dz );
|
|
|
+
|
|
|
+ EggVertex *eggVert;
|
|
|
+
|
|
|
+ // get the appropriate egg vertex
|
|
|
+ eggVert = vPool->Vertex(j);
|
|
|
+
|
|
|
+ // add the offset to the vertex
|
|
|
+ eggVert->morphs.push_back( *dxyz );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Error: couldn't find vertex pool %s\n", name );
|
|
|
+
|
|
|
+ } // if total
|
|
|
+ } //for j
|
|
|
+ } //for i
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeMorphTable
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a model, a name and a frame time,
|
|
|
+// determine what type of shape interpolation is
|
|
|
+// used and call the appropriate function to extract
|
|
|
+// the shape weight info for this frame...
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models,
|
|
|
+ int numModels, char *name, float time )
|
|
|
+{
|
|
|
+ int numShapes;
|
|
|
+ SAA_AnimInterpType type;
|
|
|
+
|
|
|
+ // Get the number of key shapes
|
|
|
+ SAA_modelGetNbShapes( scene, model, &numShapes );
|
|
|
+
|
|
|
+ if ( numShapes > 0 )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "MakeMorphTable: %s: num shapes: %d\n",
|
|
|
+ name, numShapes);
|
|
|
+
|
|
|
+ SAA_modelGetShapeInterpolation( scene, model, &type );
|
|
|
+
|
|
|
+ if ( type == SAA_ANIM_LINEAR || type == SAA_ANIM_CARDINAL )
|
|
|
+ {
|
|
|
+ MakeLinearMorphTable( scene, model, numShapes, name, time );
|
|
|
+ }
|
|
|
+ else // must be weighted...
|
|
|
+ {
|
|
|
+ // check first for expressions
|
|
|
+ MakeExpressionMorphTable( scene, model, models, numModels,
|
|
|
+ numShapes, name, time );
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeLinearMorphTable
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a model, its name, and the time,
|
|
|
+// get the shape fcurve for the model and determine
|
|
|
+// the shape weights for the given time and use them
|
|
|
+// to populate the morph table.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeLinearMorphTable( SAA_Scene *scene, SAA_Elem *model, int numShapes,
|
|
|
+ char *name, float time )
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ SAA_Elem fcurve;
|
|
|
+ float curveVal;
|
|
|
+ SAnimTable *thisTable;
|
|
|
+ char *tableName;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "linear interp, getting fcurve\n" );
|
|
|
+
|
|
|
+ SAA_modelFcurveGetShape( scene, model, &fcurve );
|
|
|
+
|
|
|
+ SAA_fcurveEval( scene, &fcurve, time, &curveVal );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "at time %f, fcurve for %s = %f\n", time,
|
|
|
+ name, curveVal );
|
|
|
+
|
|
|
+ float nextVal = 0.0f;
|
|
|
+
|
|
|
+ // populate morph table values for this frame
|
|
|
+ for ( i = 1; i < numShapes; i++ )
|
|
|
+ {
|
|
|
+ // derive table name from the model name
|
|
|
+ tableName = MakeTableName( name, i );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Linear: looking for table '%s'\n", tableName );
|
|
|
+
|
|
|
+ //find the morph table associated with this key shape
|
|
|
+ thisTable = (SAnimTable *)(morphRoot->FindDescendent( tableName ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ if ( i == (int)curveVal )
|
|
|
+ {
|
|
|
+ if ( curveVal - i == 0 )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( 1.0f );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding element 1.0f\n" );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ thisTable->AddElement( 1.0f - (curveVal - i) );
|
|
|
+ nextVal = curveVal - i;
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding element %f\n", 1.0f - (curveVal - i) );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ( nextVal )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( nextVal );
|
|
|
+ nextVal = 0.0f;
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding element %f\n", nextVal );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ thisTable->AddElement( 0.0f );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding element 0.0f\n" );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, " to '%s'\n", tableName );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "%d: Couldn't find table '%s'\n",
|
|
|
+ i, tableName );
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeWeightedMorphTable
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a model, a list of all models in the
|
|
|
+// scene, the number of models in the scece, the number
|
|
|
+// of key shapes for this model, the name of the model
|
|
|
+// and the current time, determine what method of
|
|
|
+// controlling the shape weights is used and call the
|
|
|
+// appropriate routine.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeWeightedMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models,
|
|
|
+ int numModels, int numShapes, char *name, float time )
|
|
|
+{
|
|
|
+ SI_Error result;
|
|
|
+ SAA_Elem *weightCurves;
|
|
|
+ float curveVal;
|
|
|
+ SAnimTable *thisTable;
|
|
|
+ char *tableName;
|
|
|
+
|
|
|
+ // allocate array of weight curves (one for each shape)
|
|
|
+ weightCurves = ( SAA_Elem *)malloc( sizeof( SAA_Elem ) * numShapes );
|
|
|
+
|
|
|
+ result = SAA_modelFcurveGetShapeWeights(
|
|
|
+ scene, model, numShapes, weightCurves );
|
|
|
+
|
|
|
+ if ( result == SI_SUCCESS )
|
|
|
+ {
|
|
|
+ for ( int i = 1; i < numShapes; i++ )
|
|
|
+ {
|
|
|
+ SAA_fcurveEval( scene, &weightCurves[i], time, &curveVal );
|
|
|
+
|
|
|
+ // make sure soft gave us a reasonable number
|
|
|
+ if (!isNum(curveVal))
|
|
|
+ curveVal = 0.0f;
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "at time %f, weightCurve[%d] for %s = %f\n", time, i, name, curveVal );
|
|
|
+
|
|
|
+
|
|
|
+ // derive table name from the model name
|
|
|
+ tableName = MakeTableName( name, i );
|
|
|
+
|
|
|
+ // find and populate shape table
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Weight: looking for table '%s'\n",
|
|
|
+ tableName );
|
|
|
+
|
|
|
+ //find the morph table associated with this key shape
|
|
|
+ thisTable = (SAnimTable *)(morphRoot->FindDescendent( tableName ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( curveVal );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "adding element %f\n", curveVal );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "%d: Couldn't find table '%s'\n",
|
|
|
+ i, tableName );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeExpressionMorphTable
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a model and its number of key shapes
|
|
|
+// generate a morph table describing transitions btwn
|
|
|
+// the key shapes by evaluating the positions of the
|
|
|
+// controlling sliders.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeExpressionMorphTable( SAA_Scene *scene, SAA_Elem *model, SAA_Elem *models,
|
|
|
+ int numModels, int numShapes, char *name, float time )
|
|
|
+{
|
|
|
+ int j;
|
|
|
+ SAnimTable *thisTable;
|
|
|
+ char *tableName;
|
|
|
+ char *sliderName;
|
|
|
+ char *track;
|
|
|
+ int numExp;
|
|
|
+ SAA_Elem *expressions;
|
|
|
+ float expVal;
|
|
|
+ float sliderVal;
|
|
|
+
|
|
|
+ // populate morph table values for this frame
|
|
|
+
|
|
|
+ // compose track name
|
|
|
+ track = NULL;
|
|
|
+
|
|
|
+ // find how many expressions for this shape
|
|
|
+ SAA_elementGetNbExpressions( scene, model, track, FALSE, &numExp );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "%s has %d RHS expressions\n", name, numExp );
|
|
|
+
|
|
|
+ if ( numExp )
|
|
|
+ {
|
|
|
+ // get the expressions for this shape
|
|
|
+ expressions = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numExp);
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "getting %d RHS expressions...\n", numExp );
|
|
|
+
|
|
|
+ result = SAA_elementGetExpressions( scene, model, track, FALSE,
|
|
|
+ numExp, expressions );
|
|
|
+
|
|
|
+ if ( !result )
|
|
|
+ {
|
|
|
+ for ( j = 1; j < numExp; j++ )
|
|
|
+ {
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ // debug see what we got
|
|
|
+ int numvars;
|
|
|
+
|
|
|
+ SAA_expressionGetNbVars( scene, &expressions[j], &numvars );
|
|
|
+
|
|
|
+ int *varnamelen;
|
|
|
+ int *varstrlen;
|
|
|
+ int expstrlen;
|
|
|
+
|
|
|
+ varnamelen = (int *)malloc(sizeof(int)*numvars);
|
|
|
+ varstrlen = (int *)malloc(sizeof(int)*numvars);
|
|
|
+
|
|
|
+ SAA_expressionGetStringLengths( scene, &expressions[j],
|
|
|
+ numvars, varnamelen, varstrlen, &expstrlen );
|
|
|
+
|
|
|
+ int *varnamesizes;
|
|
|
+ int *varstrsizes;
|
|
|
+
|
|
|
+ varnamesizes = (int *)malloc(sizeof(int)*numvars);
|
|
|
+ varstrsizes = (int *)malloc(sizeof(int)*numvars);
|
|
|
+
|
|
|
+ for ( int k = 0; k < numvars; k++ )
|
|
|
+ {
|
|
|
+ varnamesizes[k] = varnamelen[k] + 1;
|
|
|
+ varstrsizes[k] = varstrlen[k] + 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ int expstrsize = expstrlen + 1;
|
|
|
+
|
|
|
+ char **varnames;
|
|
|
+ char **varstrs;
|
|
|
+
|
|
|
+ varnames = (char **)malloc(sizeof(char *)*numvars);
|
|
|
+ varstrs = (char **)malloc(sizeof(char *)*numvars);
|
|
|
+
|
|
|
+ for ( k = 0; k < numvars; k++ )
|
|
|
+ {
|
|
|
+ varnames[k] = (char *)malloc(sizeof(char)*
|
|
|
+ varnamesizes[k]);
|
|
|
+
|
|
|
+ varstrs[k] = (char *)malloc(sizeof(char)*
|
|
|
+ varstrsizes[k]);
|
|
|
+ }
|
|
|
+
|
|
|
+ char *expstr = (char *)malloc(sizeof(char)* expstrsize );
|
|
|
+
|
|
|
+ SAA_expressionGetStrings( scene, &expressions[j], numvars,
|
|
|
+ varnamesizes, varstrsizes, expstrsize, varnames,
|
|
|
+ varstrs, expstr );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "expression = '%s'\n", expstr );
|
|
|
+ fprintf( outStream, "has %d variables\n", numvars );
|
|
|
+ }
|
|
|
+ } //if verbose
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "evaling expression...\n" );
|
|
|
+
|
|
|
+ SAA_expressionEval( scene, &expressions[j], time, &expVal );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "time %f: exp val %f\n",
|
|
|
+ time, expVal );
|
|
|
+
|
|
|
+ // derive table name from the model name
|
|
|
+ tableName = MakeTableName( name, j );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Exp: looking for table '%s'\n",
|
|
|
+ tableName );
|
|
|
+
|
|
|
+ //find the morph table associated with this key shape
|
|
|
+ thisTable = (SAnimTable *)
|
|
|
+ (morphRoot->FindDescendent( tableName ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( expVal );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "%d: adding element %f to %s\n",
|
|
|
+ j, expVal, tableName );
|
|
|
+ fflush( outStream );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ fprintf( outStream, "%d: Couldn't find table '%s'", j,
|
|
|
+ tableName );
|
|
|
+
|
|
|
+ fprintf( outStream, " for value %f\n", expVal );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "couldn't get expressions!!!\n" );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ // no expression, use weight curves
|
|
|
+ MakeWeightedMorphTable( scene, model, models, numModels,
|
|
|
+ numShapes, name, time );
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: MakeTexAnim
|
|
|
+// Access: Public
|
|
|
+// Description: Given a scene, a POLYGON model, and the name
|
|
|
+// of the that model, get the u and v offsets for
|
|
|
+// the current frame.
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+void soft2egg::
|
|
|
+MakeTexAnim( SAA_Scene *scene, SAA_Elem *model, char *modelName )
|
|
|
+{
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "\n\nmaking texture animation for %s...\n",
|
|
|
+ modelName );
|
|
|
+
|
|
|
+ // get the color of the surface
|
|
|
+ int numMats;
|
|
|
+ pfVec4 Color;
|
|
|
+ SAA_Elem *materials;
|
|
|
+ void *relinfo;
|
|
|
+
|
|
|
+ SAA_modelRelationGetMatNbElements( scene, model, FALSE, &relinfo,
|
|
|
+ &numMats );
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "surface has %d materials\n", numMats );
|
|
|
+
|
|
|
+ if ( numMats )
|
|
|
+ {
|
|
|
+ float r,g,b,a;
|
|
|
+
|
|
|
+ materials = (SAA_Elem *)malloc(sizeof(SAA_Elem)*numMats);
|
|
|
+
|
|
|
+ SAA_modelRelationGetMatElements( scene, model, relinfo,
|
|
|
+ numMats, materials );
|
|
|
+
|
|
|
+ SAA_materialGetDiffuse( scene, &materials[0], &r, &g, &b );
|
|
|
+ SAA_materialGetTransparency( scene, &materials[0], &a );
|
|
|
+ Color.set( r, g, b, 1.0f - a );
|
|
|
+
|
|
|
+ int numTexLoc = 0;
|
|
|
+ int numTexGlb = 0;
|
|
|
+
|
|
|
+ // ASSUME only one texture per material
|
|
|
+ SAA_Elem tex;
|
|
|
+
|
|
|
+ // find out how many local textures per surface
|
|
|
+ // ASSUME it only has one material
|
|
|
+ SAA_materialRelationGetT2DLocNbElements( scene, &materials[0],
|
|
|
+ FALSE, &relinfo, &numTexLoc );
|
|
|
+
|
|
|
+ // if present, get local textures
|
|
|
+ if ( numTexLoc )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "%s had %d local tex\n", modelName,
|
|
|
+ numTexLoc );
|
|
|
+
|
|
|
+ // get the referenced texture
|
|
|
+ SAA_materialRelationGetT2DLocElements( scene, &materials[0],
|
|
|
+ TEX_PER_MAT, &tex );
|
|
|
+
|
|
|
+ }
|
|
|
+ // if no locals, try to get globals
|
|
|
+ else
|
|
|
+ {
|
|
|
+ SAA_modelRelationGetT2DGlbNbElements( scene, model,
|
|
|
+ FALSE, &relinfo, &numTexGlb );
|
|
|
+
|
|
|
+ if ( numTexGlb )
|
|
|
+ {
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "%s had %d global tex\n", modelName, numTexGlb );
|
|
|
+
|
|
|
+ // get the referenced texture
|
|
|
+ SAA_modelRelationGetT2DGlbElements( scene,
|
|
|
+ model, TEX_PER_MAT, &tex );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // add tex ref's if we found any textures
|
|
|
+ if ( numTexLoc || numTexGlb)
|
|
|
+ {
|
|
|
+ char *fullTexName = NULL;
|
|
|
+ char *texName = NULL;
|
|
|
+ char *uniqueTexName = NULL;
|
|
|
+ int texNameLen;
|
|
|
+
|
|
|
+ // get its name
|
|
|
+ SAA_texture2DGetPicNameLength( scene, &tex, &texNameLen);
|
|
|
+ fullTexName = (char *)malloc(sizeof(char)*++texNameLen);
|
|
|
+ SAA_texture2DGetPicName( scene, &tex, texNameLen,
|
|
|
+ fullTexName );
|
|
|
+
|
|
|
+ // append unique identifier to texname for
|
|
|
+ // this particular object
|
|
|
+ uniqueTexName = (char *)malloc(sizeof(char)*
|
|
|
+ (strlen(modelName)+strlen(texName)+3) );
|
|
|
+ sprintf( uniqueTexName, "%s-%s", modelName, texName );
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "referencing tref %s\n",
|
|
|
+ uniqueTexName );
|
|
|
+
|
|
|
+ float uScale;
|
|
|
+ float vScale;
|
|
|
+ float uOffset;
|
|
|
+ float vOffset;
|
|
|
+ SAA_Boolean uv_swap = FALSE;
|
|
|
+
|
|
|
+ // get texture offset info
|
|
|
+ SAA_texture2DGetUScale( scene, &tex, &uScale );
|
|
|
+ SAA_texture2DGetVScale( scene, &tex, &vScale );
|
|
|
+ SAA_texture2DGetUOffset( scene, &tex, &uOffset );
|
|
|
+ SAA_texture2DGetVOffset( scene, &tex, &vOffset );
|
|
|
+ SAA_texture2DGetUVSwap( scene, &tex, &uv_swap );
|
|
|
+
|
|
|
+
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "tex uScale: %f\n", uScale );
|
|
|
+ fprintf( outStream, "tex vScale: %f\n", vScale );
|
|
|
+ fprintf( outStream, "tex uOffset: %f\n", uOffset );
|
|
|
+ fprintf( outStream, "tex vOffset: %f\n", vOffset );
|
|
|
+ if ( uv_swap )
|
|
|
+ fprintf( outStream, "nurbTex u & v swapped!\n" );
|
|
|
+ else
|
|
|
+ fprintf( outStream, "nurbTex u & v NOT swapped\n" );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // find the vpool for this model
|
|
|
+ EggVertexPool *vPool =
|
|
|
+ (EggVertexPool *)(_data.pools.FindName( modelName ));
|
|
|
+
|
|
|
+ // if we found the pool
|
|
|
+ if ( vPool != NULL )
|
|
|
+ {
|
|
|
+ // generate duv's for model
|
|
|
+ float oldOffsets[4];
|
|
|
+ double u, v, du, dv;
|
|
|
+ int size;
|
|
|
+ SAA_Boolean bigEndian;
|
|
|
+
|
|
|
+ SAA_elementGetUserDataSize( scene, model, "TEX_OFFSETS", &size );
|
|
|
+
|
|
|
+ if ( size != 0 )
|
|
|
+ {
|
|
|
+ // remember original texture offsets future reference
|
|
|
+ SAA_elementGetUserData( scene, model, "TEX_OFFSETS",
|
|
|
+ size, &bigEndian, (void *)&oldOffsets );
|
|
|
+
|
|
|
+ // get the original scales and offsets
|
|
|
+ u = oldOffsets[0];
|
|
|
+ v = oldOffsets[1];
|
|
|
+
|
|
|
+ du = u - uOffset;
|
|
|
+ dv = v - vOffset;
|
|
|
+
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ {
|
|
|
+ fprintf( outStream, "original u = %f, v = %f\n",
|
|
|
+ u, v );
|
|
|
+ fprintf( outStream, "u = %f, v = %f\n",
|
|
|
+ uOffset, vOffset );
|
|
|
+ fprintf( outStream, "du = %f, dv = %f\n",
|
|
|
+ du, dv );
|
|
|
+ }
|
|
|
+
|
|
|
+ strstream uName, vName;
|
|
|
+
|
|
|
+ // create duv target names
|
|
|
+ uName << modelName << ".u" << ends;
|
|
|
+ vName << modelName << ".v" << ends;
|
|
|
+
|
|
|
+ // find the appropriate table to store the
|
|
|
+ // duv animation info into
|
|
|
+ SAnimTable *thisTable;
|
|
|
+
|
|
|
+ //find the duv U table associated with this model
|
|
|
+ thisTable = (SAnimTable *)(morphRoot->FindDescendent(
|
|
|
+ uName.str() ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( du );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "adding element %f to %s\n",
|
|
|
+ du, uName.str() );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Couldn't find uTable %s\n",
|
|
|
+ uName.str() );
|
|
|
+
|
|
|
+ //find the duv V table associated with this model
|
|
|
+ thisTable = (SAnimTable *)(morphRoot->FindDescendent(
|
|
|
+ vName.str() ));
|
|
|
+
|
|
|
+ if ( thisTable != NULL )
|
|
|
+ {
|
|
|
+ thisTable->AddElement( dv );
|
|
|
+ if ( verbose >= 1 )
|
|
|
+ fprintf( outStream, "adding element %f to %s\n",
|
|
|
+ dv, uName.str() );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ fprintf( outStream, "Couldn't find vTable %s\n",
|
|
|
+ uName.str() );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ if ( verbose >= 2 )
|
|
|
+ fprintf( outStream, "Couldn't find vpool %s\n", modelName );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //free( materials );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+// Function: Main
|
|
|
+// Access: Private
|
|
|
+// Description: Instantiate converter and process a file
|
|
|
+////////////////////////////////////////////////////////////////////
|
|
|
+EXPCL_MISC SI_Error soft2egg(int argc, char *argv[]) {
|
|
|
+ // pass control to the c++ system
|
|
|
+ init_soft2egg(argc, argv);
|
|
|
+ return SI_SUCCESS;
|
|
|
+}
|
|
|
+#ifdef __cplusplus
|
|
|
+}
|
|
|
+#endif
|