Browse Source

Merge branch 'master' into cmake

Sam Edwards 7 years ago
parent
commit
58c065d970
98 changed files with 560 additions and 10989 deletions
  1. 4 1
      direct/src/interval/FunctionInterval.py
  2. 0 20
      doc/INSTALLING-PLUGINS.TXT
  3. 0 183
      doc/InstallerNotes
  4. 8 0
      dtool/src/dtoolbase/dtoolbase.cxx
  5. 2 0
      dtool/src/dtoolbase/dtoolbase.h
  6. 9 0
      dtool/src/dtoolbase/dtoolbase_cc.h
  7. 10 10
      dtool/src/dtoolutil/textEncoder.I
  8. 10 10
      dtool/src/dtoolutil/textEncoder.h
  9. 6 1
      dtool/src/dtoolutil/textEncoder_ext.cxx
  10. 1 1
      dtool/src/dtoolutil/unicodeLatinMap.cxx
  11. 5 5
      dtool/src/dtoolutil/unicodeLatinMap.h
  12. 9 1
      dtool/src/interrogatedb/py_panda.cxx
  13. 1 1
      dtool/src/parser-inc/Python.h
  14. 0 20
      dtool/src/prc/notifyCategory.I
  15. 2 2
      dtool/src/prc/notifyCategory.h
  16. 0 12
      dtool/src/prc/notifyCategoryProxy.I
  17. 2 2
      dtool/src/prc/notifyCategoryProxy.h
  18. 36 46
      makepanda/makepanda.py
  19. 0 20
      makepanda/makepanda.vcproj
  20. 2 2
      panda/src/chan/animControl.cxx
  21. 3 1
      panda/src/chan/animControl.h
  22. 7 0
      panda/src/chan/partBundle.cxx
  23. 1 1
      panda/src/collide/collisionTraverser.cxx
  24. 5 5
      panda/src/display/graphicsEngine.cxx
  25. 13 13
      panda/src/display/graphicsOutput.cxx
  26. 1 0
      panda/src/display/graphicsOutput.h
  27. 14 28
      panda/src/display/graphicsPipeSelection.cxx
  28. 47 39
      panda/src/display/graphicsStateGuardian.cxx
  29. 0 1
      panda/src/display/p3display_composite2.cxx
  30. 3 5
      panda/src/distort/projectionScreen.cxx
  31. 5 5
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  32. 1 1
      panda/src/gles2gsg/gles2gsg.h
  33. 1 1
      panda/src/glesgsg/glesgsg.h
  34. 11 9
      panda/src/glstuff/glCgShaderContext_src.cxx
  35. 9 0
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  36. 3 0
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  37. 23 2
      panda/src/gobj/geom.cxx
  38. 2 0
      panda/src/gobj/geom.h
  39. 3 1
      panda/src/gobj/geomVertexArrayData.I
  40. 16 3
      panda/src/gobj/geomVertexData.I
  41. 18 5
      panda/src/gobj/geomVertexData.cxx
  42. 2 2
      panda/src/gobj/preparedGraphicsObjects.cxx
  43. 1 1
      panda/src/gobj/textureReloadRequest.cxx
  44. 1 1
      panda/src/grutil/multitexReducer.cxx
  45. 1 1
      panda/src/net/connection.cxx
  46. 3 0
      panda/src/pgraph/cullTraverserData.cxx
  47. 2 3
      panda/src/pgraph/geomNode.cxx
  48. 4 1
      panda/src/pgraph/renderAttrib.cxx
  49. 3 0
      panda/src/pgraph/renderState.cxx
  50. 3 0
      panda/src/pgraph/transformState.cxx
  51. 0 8
      panda/src/pipeline/blockerSimple.I
  52. 2 2
      panda/src/pipeline/blockerSimple.h
  53. 3 0
      panda/src/pipeline/config_pipeline.cxx
  54. 9 10
      panda/src/pipeline/contextSwitch_longjmp_src.c
  55. 14 15
      panda/src/pipeline/contextSwitch_posix_src.c
  56. 6 7
      panda/src/pipeline/contextSwitch_ucontext_src.c
  57. 9 10
      panda/src/pipeline/contextSwitch_windows_src.c
  58. 3 0
      panda/src/pipeline/cycleData.h
  59. 25 13
      panda/src/pipeline/cycleDataLockedReader.I
  60. 37 14
      panda/src/pipeline/cycleDataLockedStageReader.I
  61. 40 17
      panda/src/pipeline/cycleDataStageWriter.I
  62. 1 1
      panda/src/pipeline/pythonThread.cxx
  63. 0 8
      panda/src/pipeline/threadSimpleImpl.I
  64. 11 3
      panda/src/pipeline/threadSimpleImpl.cxx
  65. 1 1
      panda/src/pipeline/threadSimpleImpl.h
  66. 5 13
      panda/src/pipeline/threadSimpleManager.cxx
  67. 1 1
      panda/src/text/textNode.cxx
  68. 5 5
      panda/src/wgldisplay/wglGraphicsStateGuardian.cxx
  69. 19 3
      panda/src/windisplay/winGraphicsWindow.cxx
  70. 2 0
      pandatool/src/eggcharbase/eggBackPointer.cxx
  71. 1 0
      pandatool/src/eggcharbase/eggCharacterDb.h
  72. 2 0
      pandatool/src/eggcharbase/eggJointData.cxx
  73. 2 1
      pandatool/src/eggcharbase/eggJointNodePointer.cxx
  74. 2 0
      pandatool/src/eggcharbase/eggMatrixTablePointer.cxx
  75. 1 0
      pandatool/src/palettizer/paletteGroup.cxx
  76. 0 55
      pandatool/src/softegg/config_softegg.cxx
  77. 0 28
      pandatool/src/softegg/config_softegg.h
  78. 0 4751
      pandatool/src/softegg/soft2Egg.c
  79. 0 44
      pandatool/src/softegg/softEggGroupUserData.I
  80. 0 16
      pandatool/src/softegg/softEggGroupUserData.cxx
  81. 0 53
      pandatool/src/softegg/softEggGroupUserData.h
  82. 0 1310
      pandatool/src/softegg/softNodeDesc.cxx
  83. 0 159
      pandatool/src/softegg/softNodeDesc.h
  84. 0 561
      pandatool/src/softegg/softNodeTree.cxx
  85. 0 78
      pandatool/src/softegg/softNodeTree.h
  86. 0 2122
      pandatool/src/softegg/softToEggConverter.cxx
  87. 0 179
      pandatool/src/softegg/softToEggConverter.h
  88. 0 588
      pandatool/src/softprogs/softCVS.cxx
  89. 0 70
      pandatool/src/softprogs/softCVS.h
  90. 0 291
      pandatool/src/softprogs/softFilename.cxx
  91. 0 73
      pandatool/src/softprogs/softFilename.h
  92. 1 0
      pandatool/src/xfileegg/xFileMaterial.cxx
  93. 2 0
      pandatool/src/xfileegg/xFileMesh.cxx
  94. 2 0
      pandatool/src/xfileegg/xFileMesh.h
  95. 1 0
      pandatool/src/xfileegg/xFileToEggConverter.cxx
  96. 25 12
      tests/display/test_glsl_shader.py
  97. 8 1
      tests/event/test_futures.py
  98. 7 0
      tests/text/test_textnode.py

+ 4 - 1
direct/src/interval/FunctionInterval.py

@@ -77,7 +77,10 @@ class FunctionInterval(Interval.Interval):
 
 
     @staticmethod
     @staticmethod
     def makeUniqueName(func, suffix = ''):
     def makeUniqueName(func, suffix = ''):
-        name = 'Func-%s-%d' % (getattr(func, '__name__', str(func)), FunctionInterval.functionIntervalNum)
+        func_name = getattr(func, '__name__', None)
+        if func_name is None:
+            func_name = str(func)
+        name = 'Func-%s-%d' % (func_name, FunctionInterval.functionIntervalNum)
         FunctionInterval.functionIntervalNum += 1
         FunctionInterval.functionIntervalNum += 1
         if suffix:
         if suffix:
             name = '%s-%s' % (name, str(suffix))
             name = '%s-%s' % (name, str(suffix))

+ 0 - 20
doc/INSTALLING-PLUGINS.TXT

@@ -1,20 +0,0 @@
-HOW TO INSTALL MAX PANDA PLUGINS.
-
-Step 1. Install the visual studio 2008 runtime by
-running "vcredist_x86-sp1.exe" as administrator.
-As a convenience, this installer is included with panda.
-
-Step 2. Make sure that there is only one copy of panda
-in your system PATH.  If you only have one copy of panda
-installed, you can skip this step.
-
-Step 3. Copy the relevant DLLs for your version
-of max from the panda plugins directory to the
-max plugins directory.  For instance, if you are 
-using Max 9, copy maxegg9.dlo and maxeggimport9.dlo
-
-HOW TO INSTALL MAYA PANDA PLUGINS.
-
-(To be written)
-
-

+ 0 - 183
doc/InstallerNotes

@@ -1,183 +0,0 @@
-------------------------  RELEASE 1.0.0  ---------------------------------
-
-	* We now have working exporters for Max5, Max6, Max7, Maya5, Maya6
-
-	* The Max exporter is dramatically improved:
-
-	  - it now includes support for character studio.
-	  - the polygon winding bug has been fixed.
-
-	* Panda no longer requires any registry keys or environment
-	variables. This means it is now possible to:
-
-	     - run panda directly from a compact disc
-	     - install multiple copies of panda on a single machine
-	     - install panda by copying the tree from another computer
-
-        Note that the installer does add the panda 'bin' directory to
-	your PATH, and it does store an uninstall key in the registry,
-	but neither of these is needed for panda to function.
-
-	* The 'makepanda' build system is now capable of building
-	prepackaged games for Windows.  These prepackaged games are simply
-	copies of panda with the game code included, some of the
-	unnecessary stuff stripped out, and some changes to the start
-	menu.  See "Airblade - Installer" on the panda downloads page
-	for an example.
-
-	* All of the sample programs have been tested.  The ones that didn't
-	work have been removed, the ones that do work have been (lightly)
-	documented.
-
-	* This is the first release to include not just a binary installer
-	for windows, but:
-
-	    - a binary installer (RPM) for Fedora 2
-	    - a binary installer (RPM) for Fedora 3
-	    - a binary installer (RPM) for Redhat 9
-	    - a binary installer for windows, as always
-	    - a source tar-ball for linux
-	    - a source zip-file for windows
-
-------------------------  RELEASE 2004-12-13  ---------------------------------
-
-	* Basic server-client networking support is back in Panda3D. There is a
-	networking sample in the samples directory. This uses the Panda3d
-	distributed object system.The README file will explain how to run this.
-	Documentation of this if forthcoming.
-
-	* Panda3d now reduces the number of environment variables such that only 2
-	are needed now - PRC_PATH and PLAYER.
-
-	* GraphicsChannel and GraphicsLayer class have been removed from the
-	panda/src/display directory. Most Panda applications won't need to be
-	changed, since most applications simply use ShowBase.py (which has been
-	adjustedappropriately) to open a window and do the initial setup.  For
-	those rare applications where you need to create your own DisplayRegions,
-	the makeDisplayRegion() interface has been moved from GraphicsLayer to
-	GraphicsWindow (actually, to GraphicsOutput, which is the base class of
-	GraphicsWindow).  You can modify your application to call
-	base.win.makeDisplayRegion() accordingly.  If you have something like
-	displayRegion.getLayer(), replace it with displayRegion.getWindow()
-	instead.
-
-	* Effective with the current version of Panda, the way that HPR angles are
-	calculated will be changing. The change will make a difference to existing
-	code or databases that store a hard-coded rotation as a HPR, but only when
-	R is involved, or both H and P are involved together.  That is to say more
-	precisely, HPR angles with (R != 0 || (H != 0 && P != 0)) now represent a
-	different rotation than they used to. If you find some legacy code that no
-	longer works correctly (e.g. it introduces crazy rotations), try putting
-	the following in your Config.prc file:
-
-		  temp-hpr-fix 0
-
-	To turn off the correct behavior and return to the old, broken behavior.
-	Note that a longer-term solution will be to represent the HPR angles
-	correctly in all legacy code.  The function oldToNewHpr() is provided to
-	aid this transition.
-
-	* PandaNode definition has been changed to support setting an
-	into_collide_mask for any arbitrary node, in particular for any GeomNode.
-	It used to be that only CollisionNodes had an into_collide_mask.  This
-	change obviates the need for CollisionNode::set_collide_geom(), which is
-	now a deprecated interface and will be removed at some point in the future.
-
-	Details:
-	There's now a NodePath::set_collide_mask() and
-	NodePath::get_collide_mask(), which operate on all CollisionNodes and
-	GeomNodes at and below the current node. By default, set_collide_mask()
-	will replace the entire collide mask, but you may also specify (via a
-	second parameter) the subset of bits that are to be changed; other bits
-	will be left alone.  You can also specify a particular type of node to
-	modify via a third parameter, e.g. you can adjust the masks for GeomNodes
-	or CollisionNodes only.
-
-	The NodePath set_collide_mask() interface changes the into_collide_mask.
-	Those familiar with the collision system will recall that a CollisionNode
-	(but only a CollisionNode) also has a from_collide_mask.  The
-	from_collide_mask of the active mover is compared with the into_collide_mask
-	of each object in the world; a collision is only possible if there are some
-	bits in common.
-
-	It used to be that only other CollisionNodes had an into_collide_mask.  A
-	mover would only test for collisions with CollisionNodes that matched its
-	collide_mask. If you wanted to make your mover detect collisions with
-	visible geometry which had no into_collide_mask, you had to call
-	set_collide_geom(1). This allowed the mover to detect collisions with *all*
-	visible geometry; it was either an all-or-none thing.
-
-	Now that GeomNodes also have an into_collide_mask, there's no longer a need
-	for set_collide_geom().  A mover will detect collisions with any
-	CollisionNodes or GeomNodes that match its collide_mask.  This means, for
-	the purposes of collision detection, you can use CollisionNodes and
-	GeomNodes pretty much interchangeably; simply set the appropriate bits on
-	the objects you want to collide with, regardless of whether they are
-	invisible collision solids or visible geometry.
-
-	(This should not be taken as a license to avoid using CollisionNodes
-	altogether. The intersection computation with visible geometry is still
-	less efficient than the same computation with collision solids. And visible
-	geometry tends to be many times more complex than is strictly necessary for
-	collisions.)
-
-	There's one more detail: every GeomNode, by default, has one bit set on in
-	its collide_mask, unless it is explicitly turned off.  This bit is
-	GeomNode::get_default_collide_mask().  This bit is provided for the
-	convenience of programmers who still want the old behavior of
-	set_collide_geom(): it allows you to easily create a CollisionNode that
-	will collide with all visible geometry in the world.
-
-	Along the same lines, there's also CollisionNode::get_default_collide_mask(),
-	which is 0x000fffff.  This is the default mask that is created for a new
-	CollisionNode (and it does not include the bit reserved for GeomNodes, 
-	above). Previously, a new CollisionNode would have all bits on by default.
-
-
-
-------------------------  RELEASE 2004-11-11  -----------------------------------
-
-	* Multiple mice can now be used with Panda3D. showbase has a list called
-	pointerWatcherNodes. The first mouse on this list is the system mouse. The
-	getMouseX() and getMouseY() will return coordinates relative to the
-	application window. The rest of the mice on the list will give raw mouse
-	positions and will change when they are moved on the screen.
-
-	In addition there are new events for mouse buttons. Each mouse will be have
-	a corresponding event. mouse1 will send mousedev1-mouse1, mousedev1-mouse2
-	and mousedev1-mouse3 events. mouse2 and any other mouse attached
-	will send similar events mousedev2-mouse1 etc.
-
-	The old mouse buttons work too. mouse1, mouse2, mouse3 events will be
-	triggered if that button is pressed on any mouse
-
-------------------------  RELEASE 2004-10-13  -----------------------------------
-
-General
-
-	* Release notes: Each release will now have an entry associated with
-	it in this document. This will be updated in reverse-chronological order.
-
-Panda3D
-	* Distributed with this release is a working version of the SceneEditor
-	created in Spring 2004 at the ETC. Documentation will be forthcoming on the
-	website. This can be found in <InstallPath>/SceneEditor
-
-	* The latest version of FMOD is distributed with this release. The latest
-	version is 3.73.
-
-	* AudioSound object now allows more types of sound. These include wma and 
-	ogg vorbis formats. This is valid when using the fmod sound system. Midi, 
-	Mod, s3m, it, xm and such sequencer type file formats are not supported. 
-	Exception - Midi files can be played. This is not fully implemented.
-
-	* A bug in SoundInterval is fixed. SoundInterval looping would incorrectly 
-	add a minimum of 1.5 seconds to the sound. This has been fixed. Sound 
-	looping problems in general should be fixed. Midi's still don't support 
-	looping through the AudioSound object. They should loop through 
-	SoundIntervals though.
-
-	* Cg support has been added to Panda3D. Documentation for this is 
-	forthcoming.
-
-

+ 8 - 0
dtool/src/dtoolbase/dtoolbase.cxx

@@ -62,4 +62,12 @@ default_thread_consider_yield() {
 void (*global_thread_yield)() = default_thread_yield;
 void (*global_thread_yield)() = default_thread_yield;
 void (*global_thread_consider_yield)() = default_thread_consider_yield;
 void (*global_thread_consider_yield)() = default_thread_consider_yield;
 
 
+#ifdef HAVE_PYTHON
+static PyThreadState *
+default_thread_state_swap(PyThreadState *state) {
+  return nullptr;
+}
+PyThreadState *(*global_thread_state_swap)(PyThreadState *tstate) = default_thread_state_swap;
+#endif  // HAVE_PYTHON
+
 #endif  // HAVE_THREADS && SIMPLE_THREADS
 #endif  // HAVE_THREADS && SIMPLE_THREADS

+ 2 - 0
dtool/src/dtoolbase/dtoolbase.h

@@ -63,8 +63,10 @@
 /* Windows likes to define min() and max() macros, which will conflict with
 /* Windows likes to define min() and max() macros, which will conflict with
    std::min() and std::max() respectively, unless we do this: */
    std::min() and std::max() respectively, unless we do this: */
 #ifdef WIN32
 #ifdef WIN32
+#ifndef NOMINMAX
 #define NOMINMAX
 #define NOMINMAX
 #endif
 #endif
+#endif
 
 
 #ifndef __has_builtin
 #ifndef __has_builtin
 #define __has_builtin(x) 0
 #define __has_builtin(x) 0

+ 9 - 0
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -233,6 +233,15 @@ INLINE void thread_consider_yield() {
   (*global_thread_consider_yield)();
   (*global_thread_consider_yield)();
 }
 }
 
 
+#ifdef HAVE_PYTHON
+typedef struct _ts PyThreadState;
+extern EXPCL_DTOOL_DTOOLBASE PyThreadState *(*global_thread_state_swap)(PyThreadState *tstate);
+
+INLINE PyThreadState *thread_state_swap(PyThreadState *tstate) {
+  return (*global_thread_state_swap)(tstate);
+}
+#endif  // HAVE_PYTHON
+
 #else
 #else
 
 
 INLINE void thread_yield() {
 INLINE void thread_yield() {

+ 10 - 10
dtool/src/dtoolutil/textEncoder.I

@@ -220,7 +220,7 @@ get_unicode_char(size_t index) const {
  * according to set_encoding().
  * according to set_encoding().
  */
  */
 INLINE void TextEncoder::
 INLINE void TextEncoder::
-set_unicode_char(size_t index, int character) {
+set_unicode_char(size_t index, char32_t character) {
   get_wtext();
   get_wtext();
   if (index < _wtext.length()) {
   if (index < _wtext.length()) {
     _wtext[index] = character;
     _wtext[index] = character;
@@ -283,7 +283,7 @@ reencode_text(const std::string &text, TextEncoder::Encoding from,
  * otherwise.  This is akin to ctype's isalpha(), extended to Unicode.
  * otherwise.  This is akin to ctype's isalpha(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_isalpha(int character) {
+unicode_isalpha(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     return false;
     return false;
@@ -297,7 +297,7 @@ unicode_isalpha(int character) {
  * otherwise.  This is akin to ctype's isdigit(), extended to Unicode.
  * otherwise.  This is akin to ctype's isdigit(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_isdigit(int character) {
+unicode_isdigit(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     // The digits aren't actually listed in the map.
     // The digits aren't actually listed in the map.
@@ -312,11 +312,11 @@ unicode_isdigit(int character) {
  * otherwise.  This is akin to ctype's ispunct(), extended to Unicode.
  * otherwise.  This is akin to ctype's ispunct(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_ispunct(int character) {
+unicode_ispunct(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     // Some punctuation marks aren't listed in the map.
     // Some punctuation marks aren't listed in the map.
-    return (character >= 0 && character < 128 && ispunct(character));
+    return (character < 128 && ispunct(character));
   }
   }
   return entry->_char_type == UnicodeLatinMap::CT_punct;
   return entry->_char_type == UnicodeLatinMap::CT_punct;
 }
 }
@@ -326,7 +326,7 @@ unicode_ispunct(int character) {
  * otherwise.  This is akin to ctype's isupper(), extended to Unicode.
  * otherwise.  This is akin to ctype's isupper(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_isupper(int character) {
+unicode_isupper(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     return false;
     return false;
@@ -339,7 +339,7 @@ unicode_isupper(int character) {
  * otherwise.  This is akin to ctype's isspace(), extended to Unicode.
  * otherwise.  This is akin to ctype's isspace(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_isspace(int character) {
+unicode_isspace(char32_t character) {
   switch (character) {
   switch (character) {
   case ' ':
   case ' ':
   case '\t':
   case '\t':
@@ -356,7 +356,7 @@ unicode_isspace(int character) {
  * otherwise.  This is akin to ctype's islower(), extended to Unicode.
  * otherwise.  This is akin to ctype's islower(), extended to Unicode.
  */
  */
 INLINE bool TextEncoder::
 INLINE bool TextEncoder::
-unicode_islower(int character) {
+unicode_islower(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     return false;
     return false;
@@ -369,7 +369,7 @@ unicode_islower(int character) {
  * akin to ctype's toupper(), extended to Unicode.
  * akin to ctype's toupper(), extended to Unicode.
  */
  */
 INLINE int TextEncoder::
 INLINE int TextEncoder::
-unicode_toupper(int character) {
+unicode_toupper(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     return character;
     return character;
@@ -382,7 +382,7 @@ unicode_toupper(int character) {
  * akin to ctype's tolower(), extended to Unicode.
  * akin to ctype's tolower(), extended to Unicode.
  */
  */
 INLINE int TextEncoder::
 INLINE int TextEncoder::
-unicode_tolower(int character) {
+unicode_tolower(char32_t character) {
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   const UnicodeLatinMap::Entry *entry = UnicodeLatinMap::look_up(character);
   if (entry == nullptr) {
   if (entry == nullptr) {
     return character;
     return character;

+ 10 - 10
dtool/src/dtoolutil/textEncoder.h

@@ -23,7 +23,7 @@ class StringDecoder;
 
 
 /**
 /**
  * This class can be used to convert text between multiple representations,
  * This class can be used to convert text between multiple representations,
- * e.g.  utf-8 to Unicode.  You may use it as a static class object, passing
+ * e.g.  UTF-8 to UTF-16.  You may use it as a static class object, passing
  * the encoding each time, or you may create an instance and use that object,
  * the encoding each time, or you may create an instance and use that object,
  * which will record the current encoding and retain the current string.
  * which will record the current encoding and retain the current string.
  *
  *
@@ -78,21 +78,21 @@ PUBLISHED:
   INLINE void append_unicode_char(char32_t character);
   INLINE void append_unicode_char(char32_t character);
   INLINE size_t get_num_chars() const;
   INLINE size_t get_num_chars() const;
   INLINE int get_unicode_char(size_t index) const;
   INLINE int get_unicode_char(size_t index) const;
-  INLINE void set_unicode_char(size_t index, int character);
+  INLINE void set_unicode_char(size_t index, char32_t character);
   INLINE std::string get_encoded_char(size_t index) const;
   INLINE std::string get_encoded_char(size_t index) const;
   INLINE std::string get_encoded_char(size_t index, Encoding encoding) const;
   INLINE std::string get_encoded_char(size_t index, Encoding encoding) const;
   INLINE std::string get_text_as_ascii() const;
   INLINE std::string get_text_as_ascii() const;
 
 
   INLINE static std::string reencode_text(const std::string &text, Encoding from, Encoding to);
   INLINE static std::string reencode_text(const std::string &text, Encoding from, Encoding to);
 
 
-  INLINE static bool unicode_isalpha(int character);
-  INLINE static bool unicode_isdigit(int character);
-  INLINE static bool unicode_ispunct(int character);
-  INLINE static bool unicode_islower(int character);
-  INLINE static bool unicode_isupper(int character);
-  INLINE static bool unicode_isspace(int character);
-  INLINE static int unicode_toupper(int character);
-  INLINE static int unicode_tolower(int character);
+  INLINE static bool unicode_isalpha(char32_t character);
+  INLINE static bool unicode_isdigit(char32_t character);
+  INLINE static bool unicode_ispunct(char32_t character);
+  INLINE static bool unicode_islower(char32_t character);
+  INLINE static bool unicode_isupper(char32_t character);
+  INLINE static bool unicode_isspace(char32_t character);
+  INLINE static int unicode_toupper(char32_t character);
+  INLINE static int unicode_tolower(char32_t character);
 
 
   INLINE static std::string upper(const std::string &source);
   INLINE static std::string upper(const std::string &source);
   INLINE static std::string upper(const std::string &source, Encoding encoding);
   INLINE static std::string upper(const std::string &source, Encoding encoding);

+ 6 - 1
dtool/src/dtoolutil/textEncoder_ext.cxx

@@ -94,7 +94,12 @@ append_text(PyObject *text) {
 #if PY_VERSION_HEX >= 0x03030000
 #if PY_VERSION_HEX >= 0x03030000
     Py_ssize_t len;
     Py_ssize_t len;
     const char *str = PyUnicode_AsUTF8AndSize(text, &len);
     const char *str = PyUnicode_AsUTF8AndSize(text, &len);
-    _this->append_text(std::string(str, len));
+    std::string text_str(str, len);
+    if (_this->get_encoding() == TextEncoder::E_utf8) {
+      _this->append_text(text_str);
+    } else {
+      _this->append_wtext(TextEncoder::decode_text(text_str, TextEncoder::E_utf8));
+    }
 #else
 #else
     Py_ssize_t len = PyUnicode_GET_SIZE(text);
     Py_ssize_t len = PyUnicode_GET_SIZE(text);
     wchar_t *str = (wchar_t *)alloca(sizeof(wchar_t) * (len + 1));
     wchar_t *str = (wchar_t *)alloca(sizeof(wchar_t) * (len + 1));

+ 1 - 1
dtool/src/dtoolutil/unicodeLatinMap.cxx

@@ -1378,7 +1378,7 @@ static const wchar_t combining_accent_map[] = {
  * Returns the Entry associated with the indicated character, if there is one.
  * Returns the Entry associated with the indicated character, if there is one.
  */
  */
 const UnicodeLatinMap::Entry *UnicodeLatinMap::
 const UnicodeLatinMap::Entry *UnicodeLatinMap::
-look_up(wchar_t character) {
+look_up(char32_t character) {
   if (!_initialized) {
   if (!_initialized) {
     init();
     init();
   }
   }

+ 5 - 5
dtool/src/dtoolutil/unicodeLatinMap.h

@@ -112,17 +112,17 @@ public:
 
 
   class Entry {
   class Entry {
   public:
   public:
-    wchar_t _character;
+    char32_t _character;
     CharType _char_type;
     CharType _char_type;
     char _ascii_equiv;
     char _ascii_equiv;
     char _ascii_additional;
     char _ascii_additional;
-    wchar_t _tolower_character;
-    wchar_t _toupper_character;
+    char32_t _tolower_character;
+    char32_t _toupper_character;
     AccentType _accent_type;
     AccentType _accent_type;
     int _additional_flags;
     int _additional_flags;
   };
   };
 
 
-  static const Entry *look_up(wchar_t character);
+  static const Entry *look_up(char32_t character);
 
 
   static wchar_t get_combining_accent(AccentType accent);
   static wchar_t get_combining_accent(AccentType accent);
 
 
@@ -130,7 +130,7 @@ private:
   static void init();
   static void init();
   static bool _initialized;
   static bool _initialized;
 
 
-  typedef phash_map<wchar_t, const Entry *, integer_hash<wchar_t> > ByCharacter;
+  typedef phash_map<char32_t, const Entry *, integer_hash<char32_t> > ByCharacter;
   static ByCharacter *_by_character;
   static ByCharacter *_by_character;
   enum { max_direct_chars = 256 };
   enum { max_direct_chars = 256 };
   static const Entry *_direct_chars[max_direct_chars];
   static const Entry *_direct_chars[max_direct_chars];

+ 9 - 1
dtool/src/interrogatedb/py_panda.cxx

@@ -722,7 +722,10 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
 
 
     // Extract the __file__ attribute, if present.
     // Extract the __file__ attribute, if present.
     Filename main_dir;
     Filename main_dir;
-    PyObject *file_attr = PyObject_GetAttrString(main_module, "__file__");
+    PyObject *file_attr = nullptr;
+    if (main_module != nullptr) {
+      file_attr = PyObject_GetAttrString(main_module, "__file__");
+    }
     if (file_attr == nullptr) {
     if (file_attr == nullptr) {
       // Must be running in the interactive interpreter.  Use the CWD.
       // Must be running in the interactive interpreter.  Use the CWD.
       main_dir = ExecutionEnvironment::get_cwd();
       main_dir = ExecutionEnvironment::get_cwd();
@@ -752,6 +755,11 @@ PyObject *Dtool_PyModuleInitHelper(LibraryDef *defs[], const char *modulename) {
     ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific());
     ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific());
     PyErr_Clear();
     PyErr_Clear();
     initialized_main_dir = true;
     initialized_main_dir = true;
+
+    // Also, while we are at it, initialize the thread swap hook.
+#if defined(HAVE_THREADS) && defined(SIMPLE_THREADS)
+    global_thread_state_swap = PyThreadState_Swap;
+#endif
   }
   }
 
 
   PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1);
   PyModule_AddIntConstant(module, "Dtool_PyNativeInterface", 1);

+ 1 - 1
dtool/src/parser-inc/Python.h

@@ -28,7 +28,7 @@ typedef _typeobject PyTypeObject;
 typedef struct {} PyStringObject;
 typedef struct {} PyStringObject;
 typedef struct {} PyUnicodeObject;
 typedef struct {} PyUnicodeObject;
 
 
-class PyThreadState;
+typedef struct _ts PyThreadState;
 typedef int Py_ssize_t;
 typedef int Py_ssize_t;
 typedef struct bufferinfo Py_buffer;
 typedef struct bufferinfo Py_buffer;
 
 

+ 0 - 20
dtool/src/prc/notifyCategory.I

@@ -82,26 +82,6 @@ is_debug() const {
   // Instruct the compiler to optimize for the usual case.
   // Instruct the compiler to optimize for the usual case.
   return UNLIKELY(is_on(NS_debug));
   return UNLIKELY(is_on(NS_debug));
 }
 }
-#else
-/**
- * When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or
- * "debug" severities, and these methods are redefined to be static to make it
- * more obvious to the compiler.
- */
-constexpr bool NotifyCategory::
-is_spam() {
-  return false;
-}
-
-/**
- * When NOTIFY_DEBUG is not defined, the categories are never set to "spam" or
- * "debug" severities, and these methods are redefined to be static to make it
- * more obvious to the compiler.
- */
-constexpr bool NotifyCategory::
-is_debug() {
-  return false;
-}
 #endif
 #endif
 
 
 /**
 /**

+ 2 - 2
dtool/src/prc/notifyCategory.h

@@ -55,8 +55,8 @@ PUBLISHED:
   INLINE bool is_spam() const;
   INLINE bool is_spam() const;
   INLINE bool is_debug() const;
   INLINE bool is_debug() const;
 #else
 #else
-  constexpr static bool is_spam();
-  constexpr static bool is_debug();
+  constexpr static bool is_spam() { return false; }
+  constexpr static bool is_debug() { return false; }
 #endif
 #endif
   INLINE bool is_info() const;
   INLINE bool is_info() const;
   INLINE bool is_warning() const;
   INLINE bool is_warning() const;

+ 0 - 12
dtool/src/prc/notifyCategoryProxy.I

@@ -72,12 +72,6 @@ is_spam() {
   // Instruct the compiler to optimize for the usual case.
   // Instruct the compiler to optimize for the usual case.
   return UNLIKELY(get_unsafe_ptr()->is_spam());
   return UNLIKELY(get_unsafe_ptr()->is_spam());
 }
 }
-#else
-template<class GetCategory>
-constexpr bool NotifyCategoryProxy<GetCategory>::
-is_spam() {
-  return false;
-}
 #endif
 #endif
 
 
 /**
 /**
@@ -90,12 +84,6 @@ is_debug() {
   // Instruct the compiler to optimize for the usual case.
   // Instruct the compiler to optimize for the usual case.
   return UNLIKELY(get_unsafe_ptr()->is_debug());
   return UNLIKELY(get_unsafe_ptr()->is_debug());
 }
 }
-#else
-template<class GetCategory>
-constexpr bool NotifyCategoryProxy<GetCategory>::
-is_debug() {
-  return false;
-}
 #endif
 #endif
 
 
 /**
 /**

+ 2 - 2
dtool/src/prc/notifyCategoryProxy.h

@@ -75,8 +75,8 @@ public:
   INLINE bool is_spam();
   INLINE bool is_spam();
   INLINE bool is_debug();
   INLINE bool is_debug();
 #else
 #else
-  constexpr static bool is_spam();
-  constexpr static bool is_debug();
+  constexpr static bool is_spam() { return false; }
+  constexpr static bool is_debug() { return false; }
 #endif
 #endif
   INLINE bool is_info();
   INLINE bool is_info();
   INLINE bool is_warning();
   INLINE bool is_warning();

+ 36 - 46
makepanda/makepanda.py

@@ -680,6 +680,9 @@ if (COMPILER == "MSVC"):
         IncDirectory("FCOLLADA", GetThirdpartyDir() + "fcollada/include/FCollada")
         IncDirectory("FCOLLADA", GetThirdpartyDir() + "fcollada/include/FCollada")
     if (PkgSkip("ASSIMP")==0):
     if (PkgSkip("ASSIMP")==0):
         LibName("ASSIMP", GetThirdpartyDir() + "assimp/lib/assimp.lib")
         LibName("ASSIMP", GetThirdpartyDir() + "assimp/lib/assimp.lib")
+        path = GetThirdpartyDir() + "assimp/lib/IrrXML.lib"
+        if os.path.isfile(path):
+            LibName("ASSIMP", GetThirdpartyDir() + "assimp/lib/IrrXML.lib")
         IncDirectory("ASSIMP", GetThirdpartyDir() + "assimp/include/assimp")
         IncDirectory("ASSIMP", GetThirdpartyDir() + "assimp/include/assimp")
     if (PkgSkip("SQUISH")==0):
     if (PkgSkip("SQUISH")==0):
         if GetOptimize() <= 2:
         if GetOptimize() <= 2:
@@ -946,8 +949,6 @@ if (COMPILER=="GCC"):
 
 
     if GetTarget() == 'darwin':
     if GetTarget() == 'darwin':
         LibName("ALWAYS", "-framework AppKit")
         LibName("ALWAYS", "-framework AppKit")
-        if (PkgSkip("OPENCV")==0):
-            LibName("OPENCV", "-framework QuickTime")
         LibName("AGL", "-framework AGL")
         LibName("AGL", "-framework AGL")
         LibName("CARBON", "-framework Carbon")
         LibName("CARBON", "-framework Carbon")
         LibName("COCOA", "-framework Cocoa")
         LibName("COCOA", "-framework Cocoa")
@@ -1334,9 +1335,10 @@ def CompileCxx(obj,src,opts):
                     # Work around Apple compiler bug.
                     # Work around Apple compiler bug.
                     cmd += " -U__EXCEPTIONS"
                     cmd += " -U__EXCEPTIONS"
 
 
-            if 'RTTI' not in opts:
+            target = GetTarget()
+            if 'RTTI' not in opts and target != "darwin":
                 # We always disable RTTI on Android for memory usage reasons.
                 # We always disable RTTI on Android for memory usage reasons.
-                if optlevel >= 4 or GetTarget() == "android":
+                if optlevel >= 4 or target == "android":
                     cmd += " -fno-rtti"
                     cmd += " -fno-rtti"
 
 
         if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm") and arch != 'aarch64':
         if ('SSE2' in opts or not PkgSkip("SSE2")) and not arch.startswith("arm") and arch != 'aarch64':
@@ -1596,6 +1598,8 @@ def CompileLib(lib, obj, opts):
         else:
         else:
             cmd = GetAR() + ' cru ' + BracketNameWithQuotes(lib)
             cmd = GetAR() + ' cru ' + BracketNameWithQuotes(lib)
         for x in obj:
         for x in obj:
+            if GetLinkAllStatic() and x.endswith('.a'):
+                continue
             cmd += ' ' + BracketNameWithQuotes(x)
             cmd += ' ' + BracketNameWithQuotes(x)
         oscmd(cmd)
         oscmd(cmd)
 
 
@@ -3159,10 +3163,10 @@ CopyAllHeaders('panda/src/movies')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraphnodes')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/pgraph')
 CopyAllHeaders('panda/src/cull')
 CopyAllHeaders('panda/src/cull')
+CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/chan')
 CopyAllHeaders('panda/src/char')
 CopyAllHeaders('panda/src/char')
 CopyAllHeaders('panda/src/dgraph')
 CopyAllHeaders('panda/src/dgraph')
-CopyAllHeaders('panda/src/display')
 CopyAllHeaders('panda/src/device')
 CopyAllHeaders('panda/src/device')
 CopyAllHeaders('panda/src/pnmtext')
 CopyAllHeaders('panda/src/pnmtext')
 CopyAllHeaders('panda/src/text')
 CopyAllHeaders('panda/src/text')
@@ -3295,7 +3299,6 @@ if (PkgSkip("PANDATOOL")==0):
     CopyAllHeaders('pandatool/src/ptloader')
     CopyAllHeaders('pandatool/src/ptloader')
     CopyAllHeaders('pandatool/src/miscprogs')
     CopyAllHeaders('pandatool/src/miscprogs')
     CopyAllHeaders('pandatool/src/pstatserver')
     CopyAllHeaders('pandatool/src/pstatserver')
-    CopyAllHeaders('pandatool/src/softprogs')
     CopyAllHeaders('pandatool/src/text-stats')
     CopyAllHeaders('pandatool/src/text-stats')
     CopyAllHeaders('pandatool/src/vrmlprogs')
     CopyAllHeaders('pandatool/src/vrmlprogs')
     CopyAllHeaders('pandatool/src/win-stats')
     CopyAllHeaders('pandatool/src/win-stats')
@@ -3816,7 +3819,7 @@ if (not RUNTIME):
 if (not RUNTIME):
 if (not RUNTIME):
   OPTS=['DIR:panda/src/gobj', 'BUILDING:PANDA',  'NVIDIACG', 'ZLIB', 'SQUISH']
   OPTS=['DIR:panda/src/gobj', 'BUILDING:PANDA',  'NVIDIACG', 'ZLIB', 'SQUISH']
   TargetAdd('p3gobj_composite1.obj', opts=OPTS, input='p3gobj_composite1.cxx')
   TargetAdd('p3gobj_composite1.obj', opts=OPTS, input='p3gobj_composite1.cxx')
-  TargetAdd('p3gobj_composite2.obj', opts=OPTS, input='p3gobj_composite2.cxx')
+  TargetAdd('p3gobj_composite2.obj', opts=OPTS+['BIGOBJ'], input='p3gobj_composite2.cxx')
 
 
   OPTS=['DIR:panda/src/gobj', 'NVIDIACG', 'ZLIB', 'SQUISH', 'PYTHON']
   OPTS=['DIR:panda/src/gobj', 'NVIDIACG', 'ZLIB', 'SQUISH', 'PYTHON']
   IGATEFILES=GetDirectoryContents('panda/src/gobj', ["*.h", "*_composite*.cxx"])
   IGATEFILES=GetDirectoryContents('panda/src/gobj', ["*.h", "*_composite*.cxx"])
@@ -3875,6 +3878,31 @@ if (not RUNTIME):
   TargetAdd('libp3cull.in', opts=['IMOD:panda3d.core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull'])
   TargetAdd('libp3cull.in', opts=['IMOD:panda3d.core', 'ILIB:libp3cull', 'SRCDIR:panda/src/cull'])
   TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"])
   TargetAdd('libp3cull_igate.obj', input='libp3cull.in', opts=["DEPENDENCYONLY"])
 
 
+#
+# DIRECTORY: panda/src/display/
+#
+
+if (not RUNTIME):
+  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
+  TargetAdd('p3display_graphicsStateGuardian.obj', opts=OPTS, input='graphicsStateGuardian.cxx')
+  TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
+  TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
+
+  OPTS=['DIR:panda/src/display', 'PYTHON']
+  IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
+  IGATEFILES.remove("renderBuffer.h")
+  TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
+  TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
+  TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
+  TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
+  TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
+  TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
+
+  if RTDIST and GetTarget() == 'darwin':
+    OPTS=['DIR:panda/src/display']
+    TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
+    TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
+
 #
 #
 # DIRECTORY: panda/src/chan/
 # DIRECTORY: panda/src/chan/
 #
 #
@@ -3922,30 +3950,6 @@ if (not RUNTIME):
   TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
   TargetAdd('libp3dgraph.in', opts=['IMOD:panda3d.core', 'ILIB:libp3dgraph', 'SRCDIR:panda/src/dgraph'])
   TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
   TargetAdd('libp3dgraph_igate.obj', input='libp3dgraph.in', opts=["DEPENDENCYONLY"])
 
 
-#
-# DIRECTORY: panda/src/display/
-#
-
-if (not RUNTIME):
-  OPTS=['DIR:panda/src/display', 'BUILDING:PANDA']
-  TargetAdd('p3display_composite1.obj', opts=OPTS, input='p3display_composite1.cxx')
-  TargetAdd('p3display_composite2.obj', opts=OPTS, input='p3display_composite2.cxx')
-
-  OPTS=['DIR:panda/src/display', 'PYTHON']
-  IGATEFILES=GetDirectoryContents('panda/src/display', ["*.h", "*_composite*.cxx"])
-  IGATEFILES.remove("renderBuffer.h")
-  TargetAdd('libp3display.in', opts=OPTS, input=IGATEFILES)
-  TargetAdd('libp3display.in', opts=['IMOD:panda3d.core', 'ILIB:libp3display', 'SRCDIR:panda/src/display'])
-  TargetAdd('libp3display_igate.obj', input='libp3display.in', opts=["DEPENDENCYONLY"])
-  TargetAdd('p3display_graphicsStateGuardian_ext.obj', opts=OPTS, input='graphicsStateGuardian_ext.cxx')
-  TargetAdd('p3display_graphicsWindow_ext.obj', opts=OPTS, input='graphicsWindow_ext.cxx')
-  TargetAdd('p3display_pythonGraphicsWindowProc.obj', opts=OPTS, input='pythonGraphicsWindowProc.cxx')
-
-  if RTDIST and GetTarget() == 'darwin':
-    OPTS=['DIR:panda/src/display']
-    TargetAdd('subprocessWindowBuffer.obj', opts=OPTS, input='subprocessWindowBuffer.cxx')
-    TargetAdd('libp3subprocbuffer.ilb', input='subprocessWindowBuffer.obj')
-
 #
 #
 # DIRECTORY: panda/src/device/
 # DIRECTORY: panda/src/device/
 #
 #
@@ -4167,6 +4171,7 @@ if (not RUNTIME):
   TargetAdd('libpanda.dll', input='p3device_composite2.obj')
   TargetAdd('libpanda.dll', input='p3device_composite2.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite1.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite1.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite2.obj')
   TargetAdd('libpanda.dll', input='p3dgraph_composite2.obj')
+  TargetAdd('libpanda.dll', input='p3display_graphicsStateGuardian.obj')
   TargetAdd('libpanda.dll', input='p3display_composite1.obj')
   TargetAdd('libpanda.dll', input='p3display_composite1.obj')
   TargetAdd('libpanda.dll', input='p3display_composite2.obj')
   TargetAdd('libpanda.dll', input='p3display_composite2.obj')
   TargetAdd('libpanda.dll', input='p3pipeline_composite1.obj')
   TargetAdd('libpanda.dll', input='p3pipeline_composite1.obj')
@@ -6346,21 +6351,6 @@ if (PkgSkip("PANDATOOL")==0):
     TargetAdd('p3pstatserver_composite1.obj', opts=OPTS, input='p3pstatserver_composite1.cxx')
     TargetAdd('p3pstatserver_composite1.obj', opts=OPTS, input='p3pstatserver_composite1.cxx')
     TargetAdd('libp3pstatserver.lib', input='p3pstatserver_composite1.obj')
     TargetAdd('libp3pstatserver.lib', input='p3pstatserver_composite1.obj')
 
 
-#
-# DIRECTORY: pandatool/src/softprogs/
-#
-
-if (PkgSkip("PANDATOOL")==0):
-    OPTS=['DIR:pandatool/src/softprogs', 'OPENSSL']
-    TargetAdd('softcvs_softCVS.obj', opts=OPTS, input='softCVS.cxx')
-    TargetAdd('softcvs_softFilename.obj', opts=OPTS, input='softFilename.cxx')
-    TargetAdd('softcvs.exe', input='softcvs_softCVS.obj')
-    TargetAdd('softcvs.exe', input='softcvs_softFilename.obj')
-    TargetAdd('softcvs.exe', input='libp3progbase.lib')
-    TargetAdd('softcvs.exe', input='libp3pandatoolbase.lib')
-    TargetAdd('softcvs.exe', input=COMMON_PANDA_LIBS)
-    TargetAdd('softcvs.exe', opts=['ADVAPI'])
-
 #
 #
 # DIRECTORY: pandatool/src/text-stats/
 # DIRECTORY: pandatool/src/text-stats/
 #
 #

+ 0 - 20
makepanda/makepanda.vcproj

@@ -4770,12 +4770,6 @@
 				<File RelativePath="..\pandatool\src\ptloader\config_ptloader.h"></File>
 				<File RelativePath="..\pandatool\src\ptloader\config_ptloader.h"></File>
 				<File RelativePath="..\pandatool\src\ptloader\loaderFileTypePandatool.h"></File>
 				<File RelativePath="..\pandatool\src\ptloader\loaderFileTypePandatool.h"></File>
 			</Filter>
 			</Filter>
-			<Filter Name="softprogs">
-				<File RelativePath="..\pandatool\src\softprogs\softCVS.cxx"></File>
-				<File RelativePath="..\pandatool\src\softprogs\softFilename.h"></File>
-				<File RelativePath="..\pandatool\src\softprogs\softCVS.h"></File>
-				<File RelativePath="..\pandatool\src\softprogs\softFilename.cxx"></File>
-			</Filter>
 			<Filter Name="imageprogs">
 			<Filter Name="imageprogs">
 				<File RelativePath="..\pandatool\src\imageprogs\imageTrans.h"></File>
 				<File RelativePath="..\pandatool\src\imageprogs\imageTrans.h"></File>
 				<File RelativePath="..\pandatool\src\imageprogs\imageTransformColors.cxx"></File>
 				<File RelativePath="..\pandatool\src\imageprogs\imageTransformColors.cxx"></File>
@@ -5305,20 +5299,6 @@
 				<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockImage.h"></File>
 				<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockImage.h"></File>
 				<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockCoordSys.cxx"></File>
 				<File RelativePath="..\pandatool\src\lwo\lwoSurfaceBlockCoordSys.cxx"></File>
 			</Filter>
 			</Filter>
-			<Filter Name="softegg">
-				<File RelativePath="..\pandatool\src\softegg\soft2Egg.c"></File>
-				<File RelativePath="..\pandatool\src\softegg\softNodeTree.cxx"></File>
-				<File RelativePath="..\pandatool\src\softegg\softNodeDesc.h"></File>
-				<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.cxx"></File>
-				<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.I"></File>
-				<File RelativePath="..\pandatool\src\softegg\config_softegg.cxx"></File>
-				<File RelativePath="..\pandatool\src\softegg\softToEggConverter.cxx"></File>
-				<File RelativePath="..\pandatool\src\softegg\softNodeTree.h"></File>
-				<File RelativePath="..\pandatool\src\softegg\config_softegg.h"></File>
-				<File RelativePath="..\pandatool\src\softegg\softNodeDesc.cxx"></File>
-				<File RelativePath="..\pandatool\src\softegg\softToEggConverter.h"></File>
-				<File RelativePath="..\pandatool\src\softegg\softEggGroupUserData.h"></File>
-			</Filter>
 			<Filter Name="xfileprogs">
 			<Filter Name="xfileprogs">
 				<File RelativePath="..\pandatool\src\xfileprogs\eggToX.cxx"></File>
 				<File RelativePath="..\pandatool\src\xfileprogs\eggToX.cxx"></File>
 				<File RelativePath="..\pandatool\src\xfileprogs\xFileTrans.cxx"></File>
 				<File RelativePath="..\pandatool\src\xfileprogs\xFileTrans.cxx"></File>

+ 2 - 2
panda/src/chan/animControl.cxx

@@ -32,14 +32,14 @@ AnimControl(const std::string &name, PartBundle *part,
   Namable(name),
   Namable(name),
   _pending_lock(name),
   _pending_lock(name),
   _pending_cvar(_pending_lock),
   _pending_cvar(_pending_lock),
-  _bound_joints(BitArray::all_on())
+  _bound_joints(BitArray::all_on()),
+  _part(part)
 {
 {
 #ifdef DO_MEMORY_USAGE
 #ifdef DO_MEMORY_USAGE
   MemoryUsage::update_type(this, get_class_type());
   MemoryUsage::update_type(this, get_class_type());
 #endif
 #endif
 
 
   _pending = true;
   _pending = true;
-  _part = part;
   _anim = nullptr;
   _anim = nullptr;
   _channel_index = -1;
   _channel_index = -1;
   set_frame_rate(frame_rate);
   set_frame_rate(frame_rate);

+ 3 - 1
panda/src/chan/animControl.h

@@ -39,6 +39,8 @@ class EXPCL_PANDA_CHAN AnimControl : public TypedReferenceCount, public AnimInte
 public:
 public:
   AnimControl(const std::string &name, PartBundle *part,
   AnimControl(const std::string &name, PartBundle *part,
               double frame_rate, int num_frames);
               double frame_rate, int num_frames);
+  AnimControl(const AnimControl &copy) = delete;
+
   void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
   void setup_anim(PartBundle *part, AnimBundle *anim, int channel_index,
                   const BitArray &bound_joints);
                   const BitArray &bound_joints);
   void set_bound_joints(const BitArray &bound_joints);
   void set_bound_joints(const BitArray &bound_joints);
@@ -82,7 +84,7 @@ private:
   // This is a PT(PartGroup) instead of a PT(PartBundle), just because we
   // This is a PT(PartGroup) instead of a PT(PartBundle), just because we
   // can't include partBundle.h for circular reasons.  But it actually keeps a
   // can't include partBundle.h for circular reasons.  But it actually keeps a
   // pointer to a PartBundle.
   // pointer to a PartBundle.
-  PT(PartGroup) _part;
+  const PT(PartGroup) _part;
   PT(AnimBundle) _anim;
   PT(AnimBundle) _anim;
   int _channel_index;
   int _channel_index;
 
 

+ 7 - 0
panda/src/chan/partBundle.cxx

@@ -556,8 +556,15 @@ control_removed(AnimControl *control) {
     CDStageWriter cdata(_cycler, pipeline_stage);
     CDStageWriter cdata(_cycler, pipeline_stage);
     ChannelBlend::iterator cbi = cdata->_blend.find(control);
     ChannelBlend::iterator cbi = cdata->_blend.find(control);
     if (cbi != cdata->_blend.end()) {
     if (cbi != cdata->_blend.end()) {
+      cdata->_net_blend -= cbi->second;
       cdata->_blend.erase(cbi);
       cdata->_blend.erase(cbi);
       cdata->_anim_changed = true;
       cdata->_anim_changed = true;
+
+      // We need to make sure that any _effective_channel pointers that point
+      // to this control are cleared.
+      if (pipeline_stage == 0) {
+        determine_effective_channels(cdata);
+      }
     }
     }
   }
   }
   CLOSE_ITERATE_ALL_STAGES(_cycler);
   CLOSE_ITERATE_ALL_STAGES(_cycler);

+ 1 - 1
panda/src/collide/collisionTraverser.cxx

@@ -1254,7 +1254,7 @@ compare_collider_to_geom(CollisionEntry &entry, const Geom *geom,
 
 
     if (geom->get_primitive_type() == Geom::PT_polygons) {
     if (geom->get_primitive_type() == Geom::PT_polygons) {
       Thread *current_thread = Thread::get_current_thread();
       Thread *current_thread = Thread::get_current_thread();
-      CPT(GeomVertexData) data = geom->get_vertex_data()->animate_vertices(true, current_thread);
+      CPT(GeomVertexData) data = geom->get_animated_vertex_data(true, current_thread);
       GeomVertexReader vertex(data, InternalName::get_vertex());
       GeomVertexReader vertex(data, InternalName::get_vertex());
 
 
       int num_primitives = geom->get_num_primitives();
       int num_primitives = geom->get_num_primitives();

+ 5 - 5
panda/src/display/graphicsEngine.cxx

@@ -753,7 +753,7 @@ render_frame() {
         // frames, so we won't have to recompute it each frame.
         // frames, so we won't have to recompute it each frame.
         int num_drs = win->get_num_active_display_regions();
         int num_drs = win->get_num_active_display_regions();
         for (int i = 0; i < num_drs; ++i) {
         for (int i = 0; i < num_drs; ++i) {
-          DisplayRegion *dr = win->get_active_display_region(i);
+          PT(DisplayRegion) dr = win->get_active_display_region(i);
           if (dr != nullptr) {
           if (dr != nullptr) {
             NodePath camera_np = dr->get_camera(current_thread);
             NodePath camera_np = dr->get_camera(current_thread);
             if (!camera_np.is_empty()) {
             if (!camera_np.is_empty()) {
@@ -1359,7 +1359,7 @@ is_scene_root(const PandaNode *node) {
     if (win->is_active() && win->get_gsg()->is_active()) {
     if (win->is_active() && win->get_gsg()->is_active()) {
       int num_display_regions = win->get_num_active_display_regions();
       int num_display_regions = win->get_num_active_display_regions();
       for (int i = 0; i < num_display_regions; i++) {
       for (int i = 0; i < num_display_regions; i++) {
-        DisplayRegion *dr = win->get_active_display_region(i);
+        PT(DisplayRegion) dr = win->get_active_display_region(i);
         if (dr != nullptr) {
         if (dr != nullptr) {
           NodePath camera = dr->get_camera();
           NodePath camera = dr->get_camera();
           if (camera.is_empty()) {
           if (camera.is_empty()) {
@@ -1435,7 +1435,7 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
 
 
         int num_display_regions = win->get_num_active_display_regions();
         int num_display_regions = win->get_num_active_display_regions();
         for (int i = 0; i < num_display_regions; i++) {
         for (int i = 0; i < num_display_regions; i++) {
-          DisplayRegion *dr = win->get_active_display_region(i);
+          PT(DisplayRegion) dr = win->get_active_display_region(i);
           if (dr != nullptr) {
           if (dr != nullptr) {
             cull_and_draw_together(win, dr, current_thread);
             cull_and_draw_together(win, dr, current_thread);
           }
           }
@@ -1539,7 +1539,7 @@ cull_to_bins(GraphicsEngine::Windows wlist, Thread *current_thread) {
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       int num_display_regions = win->get_num_active_display_regions();
       int num_display_regions = win->get_num_active_display_regions();
       for (int i = 0; i < num_display_regions; ++i) {
       for (int i = 0; i < num_display_regions; ++i) {
-        DisplayRegion *dr = win->get_active_display_region(i);
+        PT(DisplayRegion) dr = win->get_active_display_region(i);
         if (dr != nullptr) {
         if (dr != nullptr) {
           PT(SceneSetup) scene_setup;
           PT(SceneSetup) scene_setup;
           PT(CullResult) cull_result;
           PT(CullResult) cull_result;
@@ -1659,7 +1659,7 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
           }
           }
           int num_display_regions = win->get_num_active_display_regions();
           int num_display_regions = win->get_num_active_display_regions();
           for (int i = 0; i < num_display_regions; ++i) {
           for (int i = 0; i < num_display_regions; ++i) {
-            DisplayRegion *dr = win->get_active_display_region(i);
+            PT(DisplayRegion) dr = win->get_active_display_region(i);
             if (dr != nullptr) {
             if (dr != nullptr) {
               do_draw(win, gsg, dr, current_thread);
               do_draw(win, gsg, dr, current_thread);
             }
             }

+ 13 - 13
panda/src/display/graphicsOutput.cxx

@@ -697,9 +697,6 @@ void GraphicsOutput::
 remove_all_display_regions() {
 remove_all_display_regions() {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
 
 
-  CDWriter cdata(_cycler, true);
-  cdata->_active_display_regions_stale = true;
-
   TotalDisplayRegions::iterator dri;
   TotalDisplayRegions::iterator dri;
   for (dri = _total_display_regions.begin();
   for (dri = _total_display_regions.begin();
        dri != _total_display_regions.end();
        dri != _total_display_regions.end();
@@ -713,6 +710,12 @@ remove_all_display_regions() {
   }
   }
   _total_display_regions.clear();
   _total_display_regions.clear();
   _total_display_regions.push_back(_overlay_display_region);
   _total_display_regions.push_back(_overlay_display_region);
+
+  OPEN_ITERATE_ALL_STAGES(_cycler) {
+    CDStageWriter cdata(_cycler, pipeline_stage);
+    cdata->_active_display_regions_stale = true;
+  }
+  CLOSE_ITERATE_ALL_STAGES(_cycler);
 }
 }
 
 
 /**
 /**
@@ -740,13 +743,8 @@ set_overlay_display_region(DisplayRegion *display_region) {
  */
  */
 int GraphicsOutput::
 int GraphicsOutput::
 get_num_display_regions() const {
 get_num_display_regions() const {
-  determine_display_regions();
-  int result;
-  {
-    LightMutexHolder holder(_lock);
-    result = _total_display_regions.size();
-  }
-  return result;
+  LightMutexHolder holder(_lock);
+  return _total_display_regions.size();
 }
 }
 
 
 /**
 /**
@@ -1504,13 +1502,15 @@ do_remove_display_region(DisplayRegion *display_region) {
     find(_total_display_regions.begin(), _total_display_regions.end(), drp);
     find(_total_display_regions.begin(), _total_display_regions.end(), drp);
   if (dri != _total_display_regions.end()) {
   if (dri != _total_display_regions.end()) {
     // Let's aggressively clean up the display region too.
     // Let's aggressively clean up the display region too.
-    CDWriter cdata(_cycler, true);
     display_region->cleanup();
     display_region->cleanup();
     display_region->_window = nullptr;
     display_region->_window = nullptr;
     _total_display_regions.erase(dri);
     _total_display_regions.erase(dri);
 
 
-    cdata->_active_display_regions_stale = true;
-
+    OPEN_ITERATE_ALL_STAGES(_cycler) {
+      CDStageWriter cdata(_cycler, pipeline_stage);
+      cdata->_active_display_regions_stale = true;
+    }
+    CLOSE_ITERATE_ALL_STAGES(_cycler);
     return true;
     return true;
   }
   }
 
 

+ 1 - 0
panda/src/display/graphicsOutput.h

@@ -394,6 +394,7 @@ protected:
   typedef CycleDataLockedReader<CData> CDLockedReader;
   typedef CycleDataLockedReader<CData> CDLockedReader;
   typedef CycleDataReader<CData> CDReader;
   typedef CycleDataReader<CData> CDReader;
   typedef CycleDataWriter<CData> CDWriter;
   typedef CycleDataWriter<CData> CDWriter;
+  typedef CycleDataStageWriter<CData> CDStageWriter;
 
 
 protected:
 protected:
   int _creation_flags;
   int _creation_flags;

+ 14 - 28
panda/src/display/graphicsPipeSelection.cxx

@@ -18,7 +18,6 @@
 #include "load_dso.h"
 #include "load_dso.h"
 #include "config_display.h"
 #include "config_display.h"
 #include "typeRegistry.h"
 #include "typeRegistry.h"
-#include "pset.h"
 #include "config_putil.h"
 #include "config_putil.h"
 
 
 #include <algorithm>
 #include <algorithm>
@@ -61,8 +60,8 @@ GraphicsPipeSelection() : _lock("GraphicsPipeSelection") {
 
 
   // Also get the set of modules named in the various aux-display Config
   // Also get the set of modules named in the various aux-display Config
   // variables.  We'll want to know this when we call load_modules() later.
   // variables.  We'll want to know this when we call load_modules() later.
-  int num_aux = aux_display.get_num_unique_values();
-  for (int i = 0; i < num_aux; i++) {
+  size_t num_aux = aux_display.get_num_unique_values();
+  for (size_t i = 0; i < num_aux; ++i) {
     string name = aux_display.get_unique_value(i);
     string name = aux_display.get_unique_value(i);
     if (name != _default_display_module) {
     if (name != _default_display_module) {
       _display_modules.push_back(name);
       _display_modules.push_back(name);
@@ -124,9 +123,7 @@ print_pipe_types() const {
 
 
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
   nout << "Known pipe types:" << std::endl;
   nout << "Known pipe types:" << std::endl;
-  PipeTypes::const_iterator pi;
-  for (pi = _pipe_types.begin(); pi != _pipe_types.end(); ++pi) {
-    const PipeType &pipe_type = (*pi);
+  for (const PipeType &pipe_type : _pipe_types) {
     nout << "  " << pipe_type._type << "\n";
     nout << "  " << pipe_type._type << "\n";
   }
   }
   if (_display_modules.empty()) {
   if (_display_modules.empty()) {
@@ -187,11 +184,9 @@ make_pipe(const string &type_name, const string &module_name) {
 PT(GraphicsPipe) GraphicsPipeSelection::
 PT(GraphicsPipe) GraphicsPipeSelection::
 make_pipe(TypeHandle type) {
 make_pipe(TypeHandle type) {
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
 
 
   // First, look for an exact match of the requested type.
   // First, look for an exact match of the requested type.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type == type) {
     if (ptype._type == type) {
       // Here's an exact match.
       // Here's an exact match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -202,8 +197,7 @@ make_pipe(TypeHandle type) {
   }
   }
 
 
   // Now look for a more-specific type.
   // Now look for a more-specific type.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type.is_derived_from(type)) {
     if (ptype._type.is_derived_from(type)) {
       // Here's an approximate match.
       // Here's an approximate match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -215,8 +209,7 @@ make_pipe(TypeHandle type) {
 
 
   // Couldn't find any match; load the default module and try again.
   // Couldn't find any match; load the default module and try again.
   load_default_module();
   load_default_module();
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type.is_derived_from(type)) {
     if (ptype._type.is_derived_from(type)) {
       // Here's an approximate match.
       // Here's an approximate match.
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
       PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -260,13 +253,11 @@ make_default_pipe() {
   load_default_module();
   load_default_module();
 
 
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
 
 
   if (!_default_pipe_name.empty()) {
   if (!_default_pipe_name.empty()) {
     // First, look for an exact match of the default type name from the
     // First, look for an exact match of the default type name from the
     // Configrc file (excepting case and hyphenunderscore).
     // Configrc file (excepting case and hyphenunderscore).
-    for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-      const PipeType &ptype = (*ti);
+    for (const PipeType &ptype : _pipe_types) {
       if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
       if (cmp_nocase_uh(ptype._type.get_name(), _default_pipe_name) == 0) {
         // Here's an exact match.
         // Here's an exact match.
         PT(GraphicsPipe) pipe = (*ptype._constructor)();
         PT(GraphicsPipe) pipe = (*ptype._constructor)();
@@ -278,8 +269,7 @@ make_default_pipe() {
 
 
     // No match; look for a substring match.
     // No match; look for a substring match.
     string preferred_name = downcase(_default_pipe_name);
     string preferred_name = downcase(_default_pipe_name);
-    for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-      const PipeType &ptype = (*ti);
+    for (const PipeType &ptype : _pipe_types) {
       string ptype_name = downcase(ptype._type.get_name());
       string ptype_name = downcase(ptype._type.get_name());
       if (ptype_name.find(preferred_name) != string::npos) {
       if (ptype_name.find(preferred_name) != string::npos) {
         // Here's a substring match.
         // Here's a substring match.
@@ -292,8 +282,7 @@ make_default_pipe() {
   }
   }
 
 
   // Couldn't find a matching pipe type; choose the first one on the list.
   // Couldn't find a matching pipe type; choose the first one on the list.
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     PT(GraphicsPipe) pipe = (*ptype._constructor)();
     PT(GraphicsPipe) pipe = (*ptype._constructor)();
     if (pipe != nullptr) {
     if (pipe != nullptr) {
       return pipe;
       return pipe;
@@ -310,9 +299,8 @@ make_default_pipe() {
  */
  */
 void GraphicsPipeSelection::
 void GraphicsPipeSelection::
 load_aux_modules() {
 load_aux_modules() {
-  DisplayModules::iterator di;
-  for (di = _display_modules.begin(); di != _display_modules.end(); ++di) {
-    load_named_module(*di);
+  for (const string &module : _display_modules) {
+    load_named_module(module);
   }
   }
 
 
   _display_modules.clear();
   _display_modules.clear();
@@ -337,9 +325,7 @@ add_pipe_type(TypeHandle type, PipeConstructorFunc *func) {
 
 
   // First, make sure we don't already have a GraphicsPipe of this type.
   // First, make sure we don't already have a GraphicsPipe of this type.
   LightMutexHolder holder(_lock);
   LightMutexHolder holder(_lock);
-  PipeTypes::const_iterator ti;
-  for (ti = _pipe_types.begin(); ti != _pipe_types.end(); ++ti) {
-    const PipeType &ptype = (*ti);
+  for (const PipeType &ptype : _pipe_types) {
     if (ptype._type == type) {
     if (ptype._type == type) {
       display_cat->warning()
       display_cat->warning()
         << "Attempt to register GraphicsPipe type " << type
         << "Attempt to register GraphicsPipe type " << type
@@ -375,8 +361,8 @@ do_load_default_module() {
   load_named_module(_default_display_module);
   load_named_module(_default_display_module);
 
 
   DisplayModules::iterator di =
   DisplayModules::iterator di =
-    find(_display_modules.begin(), _display_modules.end(),
-         _default_display_module);
+    std::find(_display_modules.begin(), _display_modules.end(),
+              _default_display_module);
   if (di != _display_modules.end()) {
   if (di != _display_modules.end()) {
     _display_modules.erase(di);
     _display_modules.erase(di);
   }
   }

+ 47 - 39
panda/src/display/graphicsStateGuardian.cxx

@@ -24,7 +24,6 @@
 #include "renderBuffer.h"
 #include "renderBuffer.h"
 #include "light.h"
 #include "light.h"
 #include "planeNode.h"
 #include "planeNode.h"
-#include "ambientLight.h"
 #include "throw_event.h"
 #include "throw_event.h"
 #include "clockObject.h"
 #include "clockObject.h"
 #include "pStatTimer.h"
 #include "pStatTimer.h"
@@ -60,7 +59,6 @@
 #include "fogAttrib.h"
 #include "fogAttrib.h"
 #include "config_pstatclient.h"
 #include "config_pstatclient.h"
 
 
-#include <algorithm>
 #include <limits.h>
 #include <limits.h>
 
 
 using std::string;
 using std::string;
@@ -932,12 +930,12 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
   }
   }
   case Shader::SMO_frame_time: {
   case Shader::SMO_frame_time: {
     PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
     PN_stdfloat time = ClockObject::get_global_clock()->get_frame_time();
-    t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_frame_delta: {
   case Shader::SMO_frame_delta: {
     PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
     PN_stdfloat dt = ClockObject::get_global_clock()->get_dt();
-    t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_texpad_x: {
   case Shader::SMO_texpad_x: {
@@ -949,7 +947,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     double cx = (sx * 0.5) / tex->get_x_size();
     double cx = (sx * 0.5) / tex->get_x_size();
     double cy = (sy * 0.5) / tex->get_y_size();
     double cy = (sy * 0.5) / tex->get_y_size();
     double cz = (sz * 0.5) / tex->get_z_size();
     double cz = (sz * 0.5) / tex->get_z_size();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cx,cy,cz,0);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cx, cy, cz, 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_texpix_x: {
   case Shader::SMO_texpix_x: {
@@ -958,7 +956,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     double px = 1.0 / tex->get_x_size();
     double px = 1.0 / tex->get_x_size();
     double py = 1.0 / tex->get_y_size();
     double py = 1.0 / tex->get_y_size();
     double pz = 1.0 / tex->get_z_size();
     double pz = 1.0 / tex->get_z_size();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,px,py,pz,0);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, px, py, pz, 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_material: {
   case Shader::SMO_attr_material: {
@@ -966,7 +964,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
     // Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
     if (target_material->is_off()) {
     if (target_material->is_off()) {
-      t = LMatrix4(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0);
+      t.set(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     }
     }
     Material *m = target_material->get_material();
     Material *m = target_material->get_material();
@@ -975,17 +973,17 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     LVecBase4 const &emm = m->get_emission();
     LVecBase4 const &emm = m->get_emission();
     LVecBase4 spc = m->get_specular();
     LVecBase4 spc = m->get_specular();
     spc[3] = m->get_shininess();
     spc[3] = m->get_shininess();
-    t = LMatrix4(amb[0],amb[1],amb[2],amb[3],
-                  dif[0],dif[1],dif[2],dif[3],
-                  emm[0],emm[1],emm[2],emm[3],
-                  spc[0],spc[1],spc[2],spc[3]);
+    t.set(amb[0], amb[1], amb[2], amb[3],
+          dif[0], dif[1], dif[2], dif[3],
+          emm[0], emm[1], emm[2], emm[3],
+          spc[0], spc[1], spc[2], spc[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_material2: {
   case Shader::SMO_attr_material2: {
     const MaterialAttrib *target_material = (const MaterialAttrib *)
     const MaterialAttrib *target_material = (const MaterialAttrib *)
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
       _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
     if (target_material->is_off()) {
     if (target_material->is_off()) {
-      t = LMatrix4(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
       return &t;
       return &t;
     }
     }
     Material *m = target_material->get_material();
     Material *m = target_material->get_material();
@@ -1000,7 +998,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 c = target_color->get_color();
     LVecBase4 c = target_color->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_colorscale: {
   case Shader::SMO_attr_colorscale: {
@@ -1010,7 +1008,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 cs = target_color->get_scale();
     LVecBase4 cs = target_color->get_scale();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,cs[0],cs[1],cs[2],cs[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cs[0], cs[1], cs[2], cs[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_fog: {
   case Shader::SMO_attr_fog: {
@@ -1022,7 +1020,8 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     }
     }
     PN_stdfloat start, end;
     PN_stdfloat start, end;
     fog->get_linear_range(start, end);
     fog->get_linear_range(start, end);
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,fog->get_exp_density(),start,end,1.0f/(end-start));
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+          fog->get_exp_density(), start, end, 1.0f / (end - start));
     return &t;
     return &t;
   }
   }
   case Shader::SMO_attr_fogcolor: {
   case Shader::SMO_attr_fogcolor: {
@@ -1033,7 +1032,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       return &LMatrix4::ones_mat();
       return &LMatrix4::ones_mat();
     }
     }
     LVecBase4 c = fog->get_color();
     LVecBase4 c = fog->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_alight_x: {
   case Shader::SMO_alight_x: {
@@ -1042,7 +1041,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     AmbientLight *lt;
     AmbientLight *lt;
     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
     DCAST_INTO_R(lt, np.node(), &LMatrix4::zeros_mat());
     LColor const &c = lt->get_color();
     LColor const &c = lt->get_color();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,c[0],c[1],c[2],c[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_satten_x: {
   case Shader::SMO_satten_x: {
@@ -1052,7 +1051,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
     DCAST_INTO_R(lt, np.node(), &LMatrix4::ones_mat());
     LVecBase3 const &a = lt->get_attenuation();
     LVecBase3 const &a = lt->get_attenuation();
     PN_stdfloat x = lt->get_exponent();
     PN_stdfloat x = lt->get_exponent();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,a[0],a[1],a[2],x);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_dlight_x: {
   case Shader::SMO_dlight_x: {
@@ -1069,7 +1068,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     d.normalize();
     d.normalize();
     LVecBase3 h = d + LVecBase3(0,-1,0);
     LVecBase3 h = d + LVecBase3(0,-1,0);
     h.normalize();
     h.normalize();
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],c[3],d[0],d[1],d[2],0,h[0],h[1],h[2],0);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], c[3],
+          d[0], d[1], d[2], 0,
+          h[0], h[1], h[2], 0);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_plight_x: {
   case Shader::SMO_plight_x: {
@@ -1087,7 +1089,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     Lens *lens = lt->get_lens(0);
     Lens *lens = lt->get_lens(0);
     PN_stdfloat lnear = lens->get_near();
     PN_stdfloat lnear = lens->get_near();
     PN_stdfloat lfar = lens->get_far();
     PN_stdfloat lfar = lens->get_far();
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],lnear,a[0],a[1],a[2],lfar);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], s[3],
+          p[0], p[1], p[2], lnear,
+          a[0], a[1], a[2], lfar);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_slight_x: {
   case Shader::SMO_slight_x: {
@@ -1105,7 +1110,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       _scene_setup->get_world_transform()->get_mat();
       _scene_setup->get_world_transform()->get_mat();
     LVecBase3 p = t.xform_point(lens->get_nodal_point());
     LVecBase3 p = t.xform_point(lens->get_nodal_point());
     LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
     LVecBase3 d = -(t.xform_vec(lens->get_view_vector()));
-    t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
+    t.set(c[0], c[1], c[2], c[3],
+          s[0], s[1], s[2], s[3],
+          p[0], p[1], p[2], 0,
+          d[0], d[1], d[2], cutoff);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_light_ambient: {
   case Shader::SMO_light_ambient: {
@@ -1149,7 +1157,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
     if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
         index < ta->get_num_on_stages()) {
         index < ta->get_num_on_stages()) {
       LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
       LVecBase3 scale = tma->get_transform(ta->get_on_stage(index))->get_scale();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,scale[0],scale[1],scale[2],0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
       return &t;
       return &t;
     } else {
     } else {
       return &LMatrix4::ident_mat();
       return &LMatrix4::ident_mat();
@@ -1173,7 +1181,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
         index < ta->get_num_on_stages()) {
         index < ta->get_num_on_stages()) {
       TextureStage *ts = ta->get_on_stage(index);
       TextureStage *ts = ta->get_on_stage(index);
       PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
       PN_stdfloat v = (ta->get_on_texture(ts)->get_format() == Texture::F_alpha);
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,v,v,v,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
       return &t;
       return &t;
     } else {
     } else {
       return &LMatrix4::zeros_mat();
       return &LMatrix4::zeros_mat();
@@ -1185,7 +1193,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
     const PlaneNode *plane_node;
     const PlaneNode *plane_node;
     DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
     DCAST_INTO_R(plane_node, np.node(), &LMatrix4::zeros_mat());
     LPlane p = plane_node->get_plane();
     LPlane p = plane_node->get_plane();
-    t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,p[0],p[1],p[2],p[3]);
+    t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_clipplane_x: {
   case Shader::SMO_clipplane_x: {
@@ -1235,10 +1243,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
   case Shader::SMO_vec_constant_x: {
   case Shader::SMO_vec_constant_x: {
     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
     const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
     const PN_stdfloat *data = input.get_data();
     const PN_stdfloat *data = input.get_data();
-    t = LMatrix4(data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3],
-                 data[0],data[1],data[2],data[3]);
+    t.set(data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3],
+          data[0], data[1], data[2], data[3]);
     return &t;
     return &t;
   }
   }
   case Shader::SMO_world_to_view: {
   case Shader::SMO_world_to_view: {
@@ -1394,10 +1402,10 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
       // There is an input specifying precisely this whole thing, with dot and
       // There is an input specifying precisely this whole thing, with dot and
       // all.  Support this, even if only for backward compatibility.
       // all.  Support this, even if only for backward compatibility.
       const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
       const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
-      t = LMatrix4(data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3],
-                   data[0],data[1],data[2],data[3]);
+      t.set(data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3],
+            data[0], data[1], data[2], data[3]);
       return &t;
       return &t;
     }
     }
 
 
@@ -1578,11 +1586,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
 
 
   } else if (attrib == IN_position) {
   } else if (attrib == IN_position) {
     if (np.is_empty()) {
     if (np.is_empty()) {
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
       return &t;
       return &t;
     } else if (node->is_ambient_light()) {
     } else if (node->is_ambient_light()) {
       // Ambient light has no position.
       // Ambient light has no position.
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
       DirectionalLight *light;
       DirectionalLight *light;
@@ -1591,7 +1599,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
       CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
       LVector3 dir = -(light->get_direction() * transform->get_mat());
       LVector3 dir = -(light->get_direction() * transform->get_mat());
       dir *= _scene_setup->get_cs_world_transform()->get_mat();
       dir *= _scene_setup->get_cs_world_transform()->get_mat();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
       return &t;
       return &t;
     } else {
     } else {
       LightLensNode *light;
       LightLensNode *light;
@@ -1611,11 +1619,11 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
 
 
   } else if (attrib == IN_halfVector) {
   } else if (attrib == IN_halfVector) {
     if (np.is_empty()) {
     if (np.is_empty()) {
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
       return &t;
       return &t;
     } else if (node->is_ambient_light()) {
     } else if (node->is_ambient_light()) {
       // Ambient light has no half-vector.
       // Ambient light has no half-vector.
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
       return &t;
       return &t;
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
     } else if (node->is_of_type(DirectionalLight::get_class_type())) {
       DirectionalLight *light;
       DirectionalLight *light;
@@ -1627,7 +1635,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       dir.normalize();
       dir.normalize();
       dir += LVector3(0, 0, 1);
       dir += LVector3(0, 0, 1);
       dir.normalize();
       dir.normalize();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
       return &t;
       return &t;
     } else {
     } else {
       LightLensNode *light;
       LightLensNode *light;
@@ -1644,7 +1652,7 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LMatrix4 &t)
       pos.normalize();
       pos.normalize();
       pos += LVector3(0, 0, 1);
       pos += LVector3(0, 0, 1);
       pos.normalize();
       pos.normalize();
-      t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,pos[0],pos[1],pos[2],1);
+      t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
       return &t;
       return &t;
     }
     }
 
 

+ 0 - 1
panda/src/display/p3display_composite2.cxx

@@ -1,5 +1,4 @@
 #include "graphicsPipeSelection.cxx"
 #include "graphicsPipeSelection.cxx"
-#include "graphicsStateGuardian.cxx"
 #include "graphicsThreadingModel.cxx"
 #include "graphicsThreadingModel.cxx"
 #include "graphicsWindow.cxx"
 #include "graphicsWindow.cxx"
 #include "graphicsWindowProc.cxx"
 #include "graphicsWindowProc.cxx"

+ 3 - 5
panda/src/distort/projectionScreen.cxx

@@ -484,8 +484,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
   const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
   const LMatrix4 &to_uv = _invert_uvs ? lens_to_uv_inverted : lens_to_uv;
 
 
   // Iterate through all the vertices in the Geom.
   // Iterate through all the vertices in the Geom.
-  CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
-  vdata = vdata->animate_vertices(true, current_thread);
+  CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(true, current_thread);
 
 
   CPT(GeomVertexFormat) vformat = vdata->get_format();
   CPT(GeomVertexFormat) vformat = vdata->get_format();
   if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
   if (!vformat->has_column(_texcoord_name) || (_texcoord_3d && vformat->get_column(_texcoord_name)->get_num_components() < 3)) {
@@ -507,7 +506,7 @@ recompute_geom(Geom *geom, const LMatrix4 &rel_mat) {
   PT(GeomVertexData) modify_vdata = geom->modify_vertex_data();
   PT(GeomVertexData) modify_vdata = geom->modify_vertex_data();
 
 
   // Maybe the vdata has animation that we should consider.
   // Maybe the vdata has animation that we should consider.
-  CPT(GeomVertexData) animated_vdata = geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread);
+  CPT(GeomVertexData) animated_vdata = geom->get_animated_vertex_data(true, current_thread);
 
 
   GeomVertexWriter texcoord(modify_vdata, _texcoord_name, current_thread);
   GeomVertexWriter texcoord(modify_vdata, _texcoord_name, current_thread);
   GeomVertexWriter color(modify_vdata, current_thread);
   GeomVertexWriter color(modify_vdata, current_thread);
@@ -674,9 +673,8 @@ make_mesh_geom(const Geom *geom, Lens *lens, LMatrix4 &rel_mat) {
 
 
   Thread *current_thread = Thread::get_current_thread();
   Thread *current_thread = Thread::get_current_thread();
   PT(Geom) new_geom = geom->make_copy();
   PT(Geom) new_geom = geom->make_copy();
+  new_geom->set_vertex_data(new_geom->get_animated_vertex_data(false, current_thread));
   PT(GeomVertexData) vdata = new_geom->modify_vertex_data();
   PT(GeomVertexData) vdata = new_geom->modify_vertex_data();
-  new_geom->set_vertex_data(vdata->animate_vertices(false, current_thread));
-  vdata = new_geom->modify_vertex_data();
   GeomVertexRewriter vertex(vdata, InternalName::get_vertex());
   GeomVertexRewriter vertex(vdata, InternalName::get_vertex());
   while (!vertex.is_at_end()) {
   while (!vertex.is_at_end()) {
     LVertex vert = vertex.get_data3();
     LVertex vert = vertex.get_data3();

+ 5 - 5
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -5240,9 +5240,9 @@ calc_fb_properties(DWORD cformat, DWORD dformat,
 #define GAMMA_1 (255.0 * 256.0)
 #define GAMMA_1 (255.0 * 256.0)
 
 
 static bool _gamma_table_initialized = false;
 static bool _gamma_table_initialized = false;
-static unsigned short _orignial_gamma_table [256 * 3];
+static unsigned short _original_gamma_table [256 * 3];
 
 
-void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
+void _create_gamma_table_dx9 (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
   int i;
   int i;
   double gamma_correction;
   double gamma_correction;
 
 
@@ -5304,7 +5304,7 @@ get_gamma_table(void) {
     HDC hdc = GetDC(nullptr);
     HDC hdc = GetDC(nullptr);
 
 
     if (hdc) {
     if (hdc) {
-      if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
+      if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
         _gamma_table_initialized = true;
         _gamma_table_initialized = true;
         get = true;
         get = true;
       }
       }
@@ -5329,10 +5329,10 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
     unsigned short ramp [256 * 3];
     unsigned short ramp [256 * 3];
 
 
     if (restore && _gamma_table_initialized) {
     if (restore && _gamma_table_initialized) {
-      _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
+      _create_gamma_table_dx9 (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
     }
     }
     else {
     else {
-      _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
+      _create_gamma_table_dx9 (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
     }
     }
 
 
     if (SetDeviceGammaRamp (hdc, ramp)) {
     if (SetDeviceGammaRamp (hdc, ramp)) {

+ 1 - 1
panda/src/gles2gsg/gles2gsg.h

@@ -51,7 +51,7 @@
 // OpenGL ES 2 has no fixed-function pipeline.
 // OpenGL ES 2 has no fixed-function pipeline.
 #undef SUPPORT_FIXED_FUNCTION
 #undef SUPPORT_FIXED_FUNCTION
 
 
-#ifdef IS_OSX
+#ifdef BUILD_IPHONE
   #include <OpenGLES/ES2/gl.h>
   #include <OpenGLES/ES2/gl.h>
 // #include <OpenGLESES2glext.h>
 // #include <OpenGLESES2glext.h>
 #else
 #else

+ 1 - 1
panda/src/glesgsg/glesgsg.h

@@ -54,7 +54,7 @@
 #define __glext_h_
 #define __glext_h_
 #define ES1_GLEXT_H_GUARD
 #define ES1_GLEXT_H_GUARD
 
 
-#ifdef IS_OSX
+#ifdef BUILD_IPHONE
   #include <OpenGLES/ES1/gl.h>
   #include <OpenGLES/ES1/gl.h>
 // #include <OpenGLESES1glext.h>
 // #include <OpenGLESES1glext.h>
 #else
 #else

+ 11 - 9
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -226,12 +226,14 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
         if (!resource) {
         if (!resource) {
           resource = "unknown";
           resource = "unknown";
         }
         }
-        GLCAT.error()
-          << "Could not find Cg varying " << cgGetParameterName(p);
-        if (attribname) {
-          GLCAT.error(false) << " : " << attribname;
+        if (GLCAT.is_debug()) {
+          GLCAT.debug()
+            << "Could not find Cg varying " << cgGetParameterName(p);
+          if (attribname) {
+            GLCAT.debug(false) << " : " << attribname;
+          }
+          GLCAT.debug(false) << " (" << resource << ") in the compiled GLSL program.\n";
         }
         }
-        GLCAT.error(false) << " (" << resource << ") in the compiled GLSL program.\n";
 
 
       } else if (loc != 0 && bind._id._name == "vtx_position") {
       } else if (loc != 0 && bind._id._name == "vtx_position") {
         // We really have to bind the vertex position to attribute 0, since
         // We really have to bind the vertex position to attribute 0, since
@@ -312,10 +314,10 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
         GLCAT.debug(false)
         GLCAT.debug(false)
           << " is bound to a conventional attribute (" << resource << ")\n";
           << " is bound to a conventional attribute (" << resource << ")\n";
       }
       }
-    }
-    if (loc == CA_unknown) {
-      // Suggest fix to developer.
-      GLCAT.error() << "Try using a different semantic.\n";
+      if (loc == CA_unknown) {
+        // Suggest fix to developer.
+        GLCAT.debug() << "Try using a different semantic.\n";
+      }
     }
     }
 #endif
 #endif
 
 

+ 9 - 0
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -1097,6 +1097,15 @@ bind_slot_multisample(bool rb_resize, Texture **attach, RenderTexturePlane slot,
 #endif
 #endif
       glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
       glgsg->_glBindRenderbuffer(GL_RENDERBUFFER_EXT, _rbm[slot]);
       GLuint format = GL_DEPTH_COMPONENT;
       GLuint format = GL_DEPTH_COMPONENT;
+#ifndef OPENGLES
+      if (_fb_properties.get_float_depth()) {
+        if (!glgsg->_use_remapped_depth_range) {
+          format = GL_DEPTH_COMPONENT32F;
+        } else {
+          format = GL_DEPTH_COMPONENT32F_NV;
+        }
+      } else
+#endif
       if (tex) {
       if (tex) {
         switch (tex->get_format()) {
         switch (tex->get_format()) {
           case Texture::F_depth_component16:
           case Texture::F_depth_component16:

+ 3 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -8925,6 +8925,9 @@ get_panda_wrap_mode(GLenum wm) {
   case GL_REPEAT:
   case GL_REPEAT:
     return SamplerState::WM_repeat;
     return SamplerState::WM_repeat;
 
 
+  case GL_MIRRORED_REPEAT:
+    return SamplerState::WM_mirror;
+
 #ifndef OPENGLES
 #ifndef OPENGLES
   case GL_MIRROR_CLAMP_EXT:
   case GL_MIRROR_CLAMP_EXT:
   case GL_MIRROR_CLAMP_TO_EDGE_EXT:
   case GL_MIRROR_CLAMP_TO_EDGE_EXT:

+ 23 - 2
panda/src/gobj/geom.cxx

@@ -286,6 +286,28 @@ make_nonindexed(bool composite_only) {
   return num_changed;
   return num_changed;
 }
 }
 
 
+/**
+ * Returns a GeomVertexData that represents the results of computing the
+ * vertex animation on the CPU for this Geom's vertex data.
+ *
+ * If there is no CPU-defined vertex animation on this object, this just
+ * returns the original object.
+ *
+ * If there is vertex animation, but the VertexTransform values have not
+ * changed since last time, this may return the same pointer it returned
+ * previously.  Even if the VertexTransform values have changed, it may still
+ * return the same pointer, but with its contents modified (this is preferred,
+ * since it allows the graphics backend to update vertex buffers optimally).
+ *
+ * If force is false, this method may return immediately with stale data, if
+ * the vertex data is not completely resident.  If force is true, this method
+ * will never return stale data, but may block until the data is available.
+ */
+CPT(GeomVertexData) Geom::
+get_animated_vertex_data(bool force, Thread *current_thread) const {
+  return get_vertex_data()->animate_vertices(force, current_thread);
+}
+
 /**
 /**
  * Replaces the ith GeomPrimitive object stored within the Geom with the new
  * Replaces the ith GeomPrimitive object stored within the Geom with the new
  * object.
  * object.
@@ -1311,8 +1333,7 @@ compute_internal_bounds(Geom::CData *cdata, Thread *current_thread) const {
   int num_vertices = 0;
   int num_vertices = 0;
 
 
   // Get the vertex data, after animation.
   // Get the vertex data, after animation.
-  CPT(GeomVertexData) vertex_data = cdata->_data.get_read_pointer(current_thread);
-  vertex_data = vertex_data->animate_vertices(true, current_thread);
+  CPT(GeomVertexData) vertex_data = get_animated_vertex_data(true, current_thread);
 
 
   // Now actually compute the bounding volume.  We do this by using
   // Now actually compute the bounding volume.  We do this by using
   // calc_tight_bounds to determine our box first.
   // calc_tight_bounds to determine our box first.

+ 2 - 0
panda/src/gobj/geom.h

@@ -85,6 +85,8 @@ PUBLISHED:
   void offset_vertices(const GeomVertexData *data, int offset);
   void offset_vertices(const GeomVertexData *data, int offset);
   int make_nonindexed(bool composite_only);
   int make_nonindexed(bool composite_only);
 
 
+  CPT(GeomVertexData) get_animated_vertex_data(bool force, Thread *current_thread) const;
+
   INLINE bool is_empty() const;
   INLINE bool is_empty() const;
 
 
   INLINE size_t get_num_primitives() const;
   INLINE size_t get_num_primitives() const;

+ 3 - 1
panda/src/gobj/geomVertexArrayData.I

@@ -45,7 +45,9 @@ has_column(const InternalName *name) const {
  */
  */
 INLINE int GeomVertexArrayData::
 INLINE int GeomVertexArrayData::
 get_num_rows() const {
 get_num_rows() const {
-  return get_handle()->get_num_rows();
+  CDReader cdata(_cycler);
+  nassertr(_array_format->get_stride() != 0, 0);
+  return cdata->_buffer.get_size() / _array_format->get_stride();
 }
 }
 
 
 /**
 /**

+ 16 - 3
panda/src/gobj/geomVertexData.I

@@ -60,9 +60,20 @@ has_column(const InternalName *name) const {
  */
  */
 INLINE int GeomVertexData::
 INLINE int GeomVertexData::
 get_num_rows() const {
 get_num_rows() const {
-  GeomVertexDataPipelineReader reader(this, Thread::get_current_thread());
-  reader.check_array_readers();
-  return reader.get_num_rows();
+  CPT(GeomVertexArrayData) array;
+  {
+    CDReader cdata(_cycler);
+    nassertr(cdata->_format->get_num_arrays() == cdata->_arrays.size(), 0);
+
+    if (cdata->_arrays.size() == 0) {
+      // No arrays means no rows.  Weird but legal.
+      return 0;
+    }
+
+    array = cdata->_arrays[0].get_read_pointer();
+  }
+
+  return array->get_num_rows();
 }
 }
 
 
 /**
 /**
@@ -761,7 +772,9 @@ set_object(const GeomVertexData *object) {
   _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
   _cdata = (GeomVertexData::CData *)_object->_cycler.read_unlocked(_current_thread);
   _got_array_readers = false;
   _got_array_readers = false;
 
 
+#ifdef DO_PIPELINING
   _cdata->ref();
   _cdata->ref();
+#endif  // DO_PIPELINING
 }
 }
 
 
 /**
 /**

+ 18 - 5
panda/src/gobj/geomVertexData.cxx

@@ -621,13 +621,26 @@ copy_from(const GeomVertexData *source, bool keep_data_objects,
             const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
             const TransformBlend &blend = blend_table->get_blend(from.get_data1i());
             LVecBase4 weights = LVecBase4::zero();
             LVecBase4 weights = LVecBase4::zero();
             LVecBase4i indices(0, 0, 0, 0);
             LVecBase4i indices(0, 0, 0, 0);
-            nassertv(blend.get_num_transforms() <= 4);
 
 
-            for (size_t i = 0; i < blend.get_num_transforms(); i++) {
-              weights[i] = blend.get_weight(i);
-              indices[i] = add_transform(transform_table, blend.get_transform(i),
-                                         already_added);
+            if (blend.get_num_transforms() <= 4) {
+              for (size_t i = 0; i < blend.get_num_transforms(); i++) {
+                weights[i] = blend.get_weight(i);
+                indices[i] = add_transform(transform_table, blend.get_transform(i),
+                                           already_added);
+              }
+            } else {
+              // Limit the number of blends to the four with highest weights.
+              TransformBlend blend2(blend);
+              blend2.limit_transforms(4);
+              blend2.normalize_weights();
+
+              for (size_t i = 0; i < 4; i++) {
+                weights[i] = blend2.get_weight(i);
+                indices[i] = add_transform(transform_table, blend2.get_transform(i),
+                                           already_added);
+              }
             }
             }
+
             if (weight.has_column()) {
             if (weight.has_column()) {
               weight.set_data4(weights);
               weight.set_data4(weights);
             }
             }

+ 2 - 2
panda/src/gobj/preparedGraphicsObjects.cxx

@@ -1619,8 +1619,8 @@ begin_frame(GraphicsStateGuardianBase *gsg, Thread *current_thread) {
        ++qsi) {
        ++qsi) {
     Shader *shader = qsi->first;
     Shader *shader = qsi->first;
     ShaderContext *sc = shader->prepare_now(this, gsg);
     ShaderContext *sc = shader->prepare_now(this, gsg);
-    if (qti->second != nullptr) {
-      qti->second->set_result(sc);
+    if (qsi->second != nullptr) {
+      qsi->second->set_result(sc);
     }
     }
   }
   }
 
 

+ 1 - 1
panda/src/gobj/textureReloadRequest.cxx

@@ -40,7 +40,7 @@ do_task() {
       // become a kind of a leak (if the texture is never rendered again on
       // become a kind of a leak (if the texture is never rendered again on
       // this GSG, we'll just end up carrying the texture memory in RAM
       // this GSG, we'll just end up carrying the texture memory in RAM
       // forever, instead of dumping it as soon as it gets prepared).
       // forever, instead of dumping it as soon as it gets prepared).
-      _texture->prepare(_pgo);
+      _pgo->enqueue_texture(_texture);
     }
     }
   }
   }
 
 

+ 1 - 1
panda/src/grutil/multitexReducer.cxx

@@ -866,7 +866,7 @@ transfer_geom(GeomNode *geom_node, const InternalName *texcoord_name,
     PT(Geom) geom = orig_geom->make_copy();
     PT(Geom) geom = orig_geom->make_copy();
 
 
     // Ensure that any vertex animation has been applied.
     // Ensure that any vertex animation has been applied.
-    geom->set_vertex_data(geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread));
+    geom->set_vertex_data(geom->get_animated_vertex_data(true, current_thread));
 
 
     // Now get a modifiable pointer to the vertex data in the new Geom.  This
     // Now get a modifiable pointer to the vertex data in the new Geom.  This
     // will actually perform a deep copy of the vertex data.
     // will actually perform a deep copy of the vertex data.

+ 1 - 1
panda/src/net/connection.cxx

@@ -445,7 +445,7 @@ do_flush() {
     if (data_sent > 0) {
     if (data_sent > 0) {
       total_sent += data_sent;
       total_sent += data_sent;
     }
     }
-    double last_report = 0;
+
     while (!okflag && tcp->Active() &&
     while (!okflag && tcp->Active() &&
            (data_sent > 0 || tcp->GetLastError() == LOCAL_BLOCKING_ERROR)) {
            (data_sent > 0 || tcp->GetLastError() == LOCAL_BLOCKING_ERROR)) {
       if (data_sent == 0) {
       if (data_sent == 0) {

+ 3 - 0
panda/src/pgraph/cullTraverserData.cxx

@@ -54,6 +54,9 @@ apply_transform_and_state(CullTraverser *trav) {
     CPT(TransformState) node_transform = _node_reader.get_transform();
     CPT(TransformState) node_transform = _node_reader.get_transform();
     node_effects->cull_callback(trav, *this, node_transform, node_state);
     node_effects->cull_callback(trav, *this, node_transform, node_state);
     apply_transform(node_transform);
     apply_transform(node_transform);
+
+    // The cull callback may have changed the node properties.
+    _node_reader.check_cached(false);
   }
   }
 
 
   if (!node_state->is_empty()) {
   if (!node_state->is_empty()) {

+ 2 - 3
panda/src/pgraph/geomNode.cxx

@@ -376,8 +376,7 @@ r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state,
     geom = transformer.premunge_geom(geom, munger);
     geom = transformer.premunge_geom(geom, munger);
 
 
     // Prepare each of the vertex arrays in the munged Geom.
     // Prepare each of the vertex arrays in the munged Geom.
-    CPT(GeomVertexData) vdata = geom->get_vertex_data(current_thread);
-    vdata = vdata->animate_vertices(false, current_thread);
+    CPT(GeomVertexData) vdata = geom->get_animated_vertex_data(false, current_thread);
     GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
     GeomVertexDataPipelineReader vdata_reader(vdata, current_thread);
     int num_arrays = vdata_reader.get_num_arrays();
     int num_arrays = vdata_reader.get_num_arrays();
     for (int i = 0; i < num_arrays; ++i) {
     for (int i = 0; i < num_arrays; ++i) {
@@ -474,7 +473,7 @@ calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
   for (gi = geoms->begin(); gi != geoms->end(); ++gi) {
     CPT(Geom) geom = (*gi)._geom.get_read_pointer();
     CPT(Geom) geom = (*gi)._geom.get_read_pointer();
     geom->calc_tight_bounds(min_point, max_point, found_any,
     geom->calc_tight_bounds(min_point, max_point, found_any,
-                            geom->get_vertex_data(current_thread)->animate_vertices(true, current_thread),
+                            geom->get_animated_vertex_data(true, current_thread),
                             !next_transform->is_identity(), mat,
                             !next_transform->is_identity(), mat,
                             current_thread);
                             current_thread);
   }
   }

+ 4 - 1
panda/src/pgraph/renderAttrib.cxx

@@ -211,7 +211,7 @@ garbage_collect() {
   }
   }
 
 
   num_this_pass = std::min(num_this_pass, size);
   num_this_pass = std::min(num_this_pass, size);
-  size_t stop_at_element = (_garbage_index + num_this_pass) % size;
+  size_t stop_at_element = (si + num_this_pass) % size;
 
 
   do {
   do {
     RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
     RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si);
@@ -229,6 +229,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 3 - 0
panda/src/pgraph/renderState.cxx

@@ -950,6 +950,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 3 - 0
panda/src/pgraph/transformState.cxx

@@ -1216,6 +1216,9 @@ garbage_collect() {
       // still need to visit.
       // still need to visit.
       --size;
       --size;
       --si;
       --si;
+      if (stop_at_element > 0) {
+        --stop_at_element;
+      }
     }
     }
 
 
     si = (si + 1) % size;
     si = (si + 1) % size;

+ 0 - 8
panda/src/pipeline/blockerSimple.I

@@ -11,14 +11,6 @@
  * @date 2007-06-20
  * @date 2007-06-20
  */
  */
 
 
-/**
- *
- */
-INLINE BlockerSimple::
-BlockerSimple() {
-  _flags = 0;
-}
-
 /**
 /**
  *
  *
  */
  */

+ 2 - 2
panda/src/pipeline/blockerSimple.h

@@ -28,7 +28,7 @@
  */
  */
 class EXPCL_PANDA_PIPELINE BlockerSimple {
 class EXPCL_PANDA_PIPELINE BlockerSimple {
 protected:
 protected:
-  INLINE BlockerSimple();
+  constexpr BlockerSimple() = default;
   INLINE ~BlockerSimple();
   INLINE ~BlockerSimple();
 
 
 protected:
 protected:
@@ -38,7 +38,7 @@ protected:
     F_has_waiters  = 0x40000000,
     F_has_waiters  = 0x40000000,
   };
   };
 
 
-  unsigned int _flags;
+  unsigned int _flags = 0;
 
 
   friend class ThreadSimpleManager;
   friend class ThreadSimpleManager;
 };
 };

+ 3 - 0
panda/src/pipeline/config_pipeline.cxx

@@ -71,7 +71,10 @@ init_libpipeline() {
   }
   }
   initialized = true;
   initialized = true;
 
 
+#ifdef DO_PIPELINING
   CycleData::init_type();
   CycleData::init_type();
+#endif
+
   MainThread::init_type();
   MainThread::init_type();
   ExternalThread::init_type();
   ExternalThread::init_type();
   GenericThread::init_type();
   GenericThread::init_type();

+ 9 - 10
panda/src/pipeline/contextSwitch_longjmp_src.c

@@ -1,8 +1,4 @@
-/* Filename: contextSwitch_longjmp_src.c
- * Created by:  drose (15Apr10)
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
+/**
  * PANDA 3D SOFTWARE
  * PANDA 3D SOFTWARE
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  *
  *
@@ -10,7 +6,10 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ * @file contextSwitch_longjmp_src.c
+ * @author drose
+ * @date 2010-04-15
+ */
 
 
 /* This is the implementation of user-space context switching using
 /* This is the implementation of user-space context switching using
    setmp() / longjmp().  This is the hackier implementation,
    setmp() / longjmp().  This is the hackier implementation,
@@ -90,14 +89,14 @@ void
 cs_longjmp(cs_jmp_buf env) {
 cs_longjmp(cs_jmp_buf env) {
   _asm {
   _asm {
     mov eax, env;
     mov eax, env;
-    
+
     mov ebx, [eax + 0];
     mov ebx, [eax + 0];
     mov edi, [eax + 4];
     mov edi, [eax + 4];
     mov esi, [eax + 8];
     mov esi, [eax + 8];
     mov ebp, [eax + 12];
     mov ebp, [eax + 12];
     mov esp, [eax + 16];
     mov esp, [eax + 16];
     mov edx, [eax + 20];
     mov edx, [eax + 20];
-    
+
     frstor [eax + 24];  /* restore floating-point state */
     frstor [eax + 24];  /* restore floating-point state */
 
 
     mov eax, 1;   /* return 1 from setjmp: pass 2 return */
     mov eax, 1;   /* return 1 from setjmp: pass 2 return */
@@ -251,7 +250,7 @@ setup_context_1(void) {
 }
 }
 
 
 void
 void
-init_thread_context(struct ThreadContext *context, 
+init_thread_context(struct ThreadContext *context,
                     unsigned char *stack, size_t stack_size,
                     unsigned char *stack, size_t stack_size,
                     ThreadFunction *thread_func, void *data) {
                     ThreadFunction *thread_func, void *data) {
   /* Copy all of the input parameters to static variables, then begin
   /* Copy all of the input parameters to static variables, then begin
@@ -263,7 +262,7 @@ init_thread_context(struct ThreadContext *context,
   st_data = data;
   st_data = data;
 
 
   setup_context_1();
   setup_context_1();
-}  
+}
 
 
 void
 void
 save_thread_context(struct ThreadContext *context,
 save_thread_context(struct ThreadContext *context,

+ 14 - 15
panda/src/pipeline/contextSwitch_posix_src.c

@@ -1,8 +1,4 @@
-/* Filename: contextSwitch_posix_src.c
- * Created by:  drose (15Apr10)
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
+/**
  * PANDA 3D SOFTWARE
  * PANDA 3D SOFTWARE
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  *
  *
@@ -10,7 +6,10 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ * @file contextSwitch_posix_src.c
+ * @author drose
+ * @date 2010-04-15
+ */
 
 
 /* This is the implementation of user-space context switching using
 /* This is the implementation of user-space context switching using
    posix threads to manage the different execution contexts.  This
    posix threads to manage the different execution contexts.  This
@@ -44,7 +43,7 @@ struct ThreadContext {
   pthread_mutex_t _ready_mutex;
   pthread_mutex_t _ready_mutex;
   pthread_cond_t _ready_cvar;
   pthread_cond_t _ready_cvar;
   int _ready_flag;
   int _ready_flag;
-  
+
   /* This is set FALSE while the thread is alive, and TRUE if the
   /* This is set FALSE while the thread is alive, and TRUE if the
      thread is to be terminated when it next wakes up. */
      thread is to be terminated when it next wakes up. */
   int _terminated;
   int _terminated;
@@ -83,19 +82,19 @@ thread_main(void *data) {
 }
 }
 
 
 void
 void
-init_thread_context(struct ThreadContext *context, 
+init_thread_context(struct ThreadContext *context,
                     unsigned char *stack, size_t stack_size,
                     unsigned char *stack, size_t stack_size,
                     ThreadFunction *thread_func, void *data) {
                     ThreadFunction *thread_func, void *data) {
   context->_thread_func = thread_func;
   context->_thread_func = thread_func;
   context->_data = data;
   context->_data = data;
 
 
-  pthread_attr_t attr; 
-  pthread_attr_init(&attr); 
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
   pthread_attr_setstacksize(&attr, stack_size);
   pthread_attr_setstacksize(&attr, stack_size);
-  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); 
+  pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
 
 
-  pthread_create(&(context->_thread), &attr, thread_main, context); 
-  pthread_attr_destroy(&attr); 
+  pthread_create(&(context->_thread), &attr, thread_main, context);
+  pthread_attr_destroy(&attr);
 }
 }
 
 
 void
 void
@@ -142,7 +141,7 @@ switch_to_thread_context(struct ThreadContext *from_context,
     /* We've been rudely terminated.  Exit gracefully. */
     /* We've been rudely terminated.  Exit gracefully. */
     pthread_exit(NULL);
     pthread_exit(NULL);
   }
   }
-  
+
   /* Now we have been signaled again, and we're ready to resume the
   /* Now we have been signaled again, and we're ready to resume the
      thread. */
      thread. */
   longjmp(from_context->_jmp_context, 1);
   longjmp(from_context->_jmp_context, 1);
@@ -164,7 +163,7 @@ alloc_thread_context() {
   pthread_mutexattr_init(&attr);
   pthread_mutexattr_init(&attr);
   // The symbol PTHREAD_MUTEX_DEFAULT isn't always available?
   // The symbol PTHREAD_MUTEX_DEFAULT isn't always available?
   //  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
   //  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
-  int result = pthread_mutex_init(&context->_ready_mutex, &attr);
+  pthread_mutex_init(&context->_ready_mutex, &attr);
   pthread_mutexattr_destroy(&attr);
   pthread_mutexattr_destroy(&attr);
 
 
   pthread_cond_init(&context->_ready_cvar, NULL);
   pthread_cond_init(&context->_ready_cvar, NULL);

+ 6 - 7
panda/src/pipeline/contextSwitch_ucontext_src.c

@@ -1,8 +1,4 @@
-/* Filename: contextSwitch_ucontext_src.c
- * Created by:  drose (15Apr10)
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
+/**
  * PANDA 3D SOFTWARE
  * PANDA 3D SOFTWARE
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  *
  *
@@ -10,7 +6,10 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ * @file contextSwitch_ucontext_src.c
+ * @author drose
+ * @date 2010-04-15
+ */
 
 
 /* This is the implementation of user-space context switching using
 /* This is the implementation of user-space context switching using
    getcontext() / setcontext().  This is the preferred implementation,
    getcontext() / setcontext().  This is the preferred implementation,
@@ -43,7 +42,7 @@ begin_context(ThreadFunction *thread_func, void *data) {
 }
 }
 
 
 void
 void
-init_thread_context(struct ThreadContext *context, 
+init_thread_context(struct ThreadContext *context,
                     unsigned char *stack, size_t stack_size,
                     unsigned char *stack, size_t stack_size,
                     ThreadFunction *thread_func, void *data) {
                     ThreadFunction *thread_func, void *data) {
   if (getcontext(&context->_ucontext) != 0) {
   if (getcontext(&context->_ucontext) != 0) {

+ 9 - 10
panda/src/pipeline/contextSwitch_windows_src.c

@@ -1,8 +1,4 @@
-/* Filename: contextSwitch_windows_src.c
- * Created by:  drose (15Apr10)
- *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- *
+/**
  * PANDA 3D SOFTWARE
  * PANDA 3D SOFTWARE
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  * Copyright (c) Carnegie Mellon University.  All rights reserved.
  *
  *
@@ -10,7 +6,10 @@
  * license.  You should have received a copy of this license along
  * license.  You should have received a copy of this license along
  * with this source code in a file named "LICENSE."
  * with this source code in a file named "LICENSE."
  *
  *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ * @file contextSwitch_windows_src.c
+ * @author drose
+ * @date 2010-04-15
+ */
 
 
 /* This is the implementation of user-space context switching using
 /* This is the implementation of user-space context switching using
    native Windows threading constructs to manage the different
    native Windows threading constructs to manage the different
@@ -37,7 +36,7 @@ struct ThreadContext {
   /* This event is in the signaled state when the thread is ready to
   /* This event is in the signaled state when the thread is ready to
      roll. */
      roll. */
   HANDLE _ready;
   HANDLE _ready;
-  
+
   /* This is set FALSE while the thread is alive, and TRUE if the
   /* This is set FALSE while the thread is alive, and TRUE if the
      thread is to be terminated when it next wakes up. */
      thread is to be terminated when it next wakes up. */
   int _terminated;
   int _terminated;
@@ -71,13 +70,13 @@ thread_main(LPVOID data) {
 }
 }
 
 
 void
 void
-init_thread_context(struct ThreadContext *context, 
+init_thread_context(struct ThreadContext *context,
                     unsigned char *stack, size_t stack_size,
                     unsigned char *stack, size_t stack_size,
                     ThreadFunction *thread_func, void *data) {
                     ThreadFunction *thread_func, void *data) {
   context->_thread_func = thread_func;
   context->_thread_func = thread_func;
   context->_data = data;
   context->_data = data;
 
 
-  context->_thread = CreateThread(NULL, stack_size, 
+  context->_thread = CreateThread(NULL, stack_size,
                                   thread_main, context, 0, NULL);
                                   thread_main, context, 0, NULL);
 }
 }
 
 
@@ -117,7 +116,7 @@ switch_to_thread_context(struct ThreadContext *from_context,
     /* We've been rudely terminated.  Exit gracefully. */
     /* We've been rudely terminated.  Exit gracefully. */
     ExitThread(1);
     ExitThread(1);
   }
   }
-  
+
   /* Now we have been signaled again, and we're ready to resume the
   /* Now we have been signaled again, and we're ready to resume the
      thread. */
      thread. */
   longjmp(from_context->_jmp_context, 1);
   longjmp(from_context->_jmp_context, 1);

+ 3 - 0
panda/src/pipeline/cycleData.h

@@ -54,6 +54,9 @@ public:
   INLINE CycleData(const CycleData &copy) = default;
   INLINE CycleData(const CycleData &copy) = default;
   virtual ~CycleData();
   virtual ~CycleData();
 
 
+  CycleData &operator = (CycleData &&from) = default;
+  CycleData &operator = (const CycleData &copy) = default;
+
   virtual CycleData *make_copy() const=0;
   virtual CycleData *make_copy() const=0;
 
 
   virtual void write_datagram(BamWriter *, Datagram &) const;
   virtual void write_datagram(BamWriter *, Datagram &) const;

+ 25 - 13
panda/src/pipeline/cycleDataLockedReader.I

@@ -45,6 +45,19 @@ CycleDataLockedReader(const CycleDataLockedReader<CycleDataType> &copy) :
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataLockedReader<CycleDataType>::
+CycleDataLockedReader(CycleDataLockedReader<CycleDataType> &&from) noexcept :
+  _cycler(from._cycler),
+  _current_thread(from._current_thread),
+  _pointer(from._pointer)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -61,19 +74,6 @@ operator = (const CycleDataLockedReader<CycleDataType> &copy) {
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
-/**
- *
- */
-template<class CycleDataType>
-INLINE CycleDataLockedReader<CycleDataType>::
-CycleDataLockedReader(CycleDataLockedReader<CycleDataType> &&from) noexcept :
-  _cycler(from._cycler),
-  _current_thread(from._current_thread),
-  _pointer(from._pointer)
-{
-  from._pointer = nullptr;
-}
-
 /**
 /**
  *
  *
  */
  */
@@ -177,6 +177,18 @@ operator = (const CycleDataLockedReader<CycleDataType> &copy) {
   _pointer = copy._pointer;
   _pointer = copy._pointer;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataLockedReader<CycleDataType>::
+operator = (CycleDataLockedReader<CycleDataType> &&from) noexcept {
+  nassertv(_pointer == nullptr);
+
+  _pointer = from._pointer;
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 37 - 14
panda/src/pipeline/cycleDataLockedStageReader.I

@@ -47,6 +47,20 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> &copy
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataLockedStageReader<CycleDataType>::
+CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
+  _cycler(from._cycler),
+  _current_thread(from._current_thread),
+  _pointer(from._pointer),
+  _stage(from._stage)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -64,20 +78,6 @@ operator = (const CycleDataLockedStageReader<CycleDataType> &copy) {
   _cycler->increment_read(_pointer);
   _cycler->increment_read(_pointer);
 }
 }
 
 
-/**
- *
- */
-template<class CycleDataType>
-INLINE CycleDataLockedStageReader<CycleDataType>::
-CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
-  _cycler(from._cycler),
-  _current_thread(from._current_thread),
-  _pointer(from._pointer),
-  _stage(from._stage)
-{
-  from._pointer = nullptr;
-}
-
 /**
 /**
  *
  *
  */
  */
@@ -174,6 +174,17 @@ CycleDataLockedStageReader(const CycleDataLockedStageReader<CycleDataType> &copy
 {
 {
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataLockedStageReader<CycleDataType>::
+CycleDataLockedStageReader(CycleDataLockedStageReader<CycleDataType> &&from) noexcept :
+  _pointer(from._cycler)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -183,6 +194,18 @@ operator = (const CycleDataLockedStageReader<CycleDataType> &copy) {
   _pointer = copy._pointer;
   _pointer = copy._pointer;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataLockedStageReader<CycleDataType>::
+operator = (CycleDataLockedStageReader<CycleDataType> &&from) noexcept {
+  nassertv(_pointer == nullptr);
+
+  _pointer = from._pointer;
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */

+ 40 - 17
panda/src/pipeline/cycleDataStageWriter.I

@@ -62,23 +62,6 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
   _cycler->increment_write(_pointer);
   _cycler->increment_write(_pointer);
 }
 }
 
 
-/**
- *
- */
-template<class CycleDataType>
-INLINE void CycleDataStageWriter<CycleDataType>::
-operator = (const CycleDataStageWriter<CycleDataType> &copy) {
-  nassertv(_pointer == nullptr);
-  nassertv(_current_thread == copy._current_thread);
-
-  _cycler = copy._cycler;
-  _pointer = copy._pointer;
-  _stage = copy._stage;
-
-  nassertv(_pointer != nullptr);
-  _cycler->increment_write(_pointer);
-}
-
 /**
 /**
  * This flavor of the constructor elevates the pointer from the
  * This flavor of the constructor elevates the pointer from the
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
@@ -128,6 +111,23 @@ CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
   from._pointer = nullptr;
   from._pointer = nullptr;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataStageWriter<CycleDataType>::
+operator = (const CycleDataStageWriter<CycleDataType> &copy) {
+  nassertv(_pointer == nullptr);
+  nassertv(_current_thread == copy._current_thread);
+
+  _cycler = copy._cycler;
+  _pointer = copy._pointer;
+  _stage = copy._stage;
+
+  nassertv(_pointer != nullptr);
+  _cycler->increment_write(_pointer);
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -227,6 +227,17 @@ CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
 {
 {
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE CycleDataStageWriter<CycleDataType>::
+CycleDataStageWriter(CycleDataStageWriter<CycleDataType> &&from) noexcept :
+  _pointer(from._pointer)
+{
+  from._pointer = nullptr;
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -236,6 +247,18 @@ operator = (const CycleDataStageWriter<CycleDataType> &copy) {
   _pointer = copy._pointer;
   _pointer = copy._pointer;
 }
 }
 
 
+/**
+ *
+ */
+template<class CycleDataType>
+INLINE void CycleDataStageWriter<CycleDataType>::
+operator = (CycleDataStageWriter<CycleDataType> &&from) noexcept {
+  nassertv(_pointer == nullptr);
+
+  _pointer = from._pointer;
+  from._pointer = nullptr;
+}
+
 /**
 /**
  * This flavor of the constructor elevates the pointer from the
  * This flavor of the constructor elevates the pointer from the
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates
  * CycleDataLockedStageReader from a read to a write pointer (and invalidates

+ 1 - 1
panda/src/pipeline/pythonThread.cxx

@@ -225,7 +225,7 @@ call_python_func(PyObject *function, PyObject *args) {
 
 
     } else {
     } else {
       // No exception.  Restore the thread state normally.
       // No exception.  Restore the thread state normally.
-      PyThreadState *state = PyThreadState_Swap(orig_thread_state);
+      PyThreadState_Swap(orig_thread_state);
       thread_states.push_back(new_thread_state);
       thread_states.push_back(new_thread_state);
       // PyThreadState_Clear(new_thread_state);
       // PyThreadState_Clear(new_thread_state);
       // PyThreadState_Delete(new_thread_state);
       // PyThreadState_Delete(new_thread_state);

+ 0 - 8
panda/src/pipeline/threadSimpleImpl.I

@@ -51,14 +51,6 @@ is_threading_supported() {
   return true;
   return true;
 }
 }
 
 
-/**
- *
- */
-INLINE bool ThreadSimpleImpl::
-is_true_threads() {
-  return (is_os_threads != 0);
-}
-
 /**
 /**
  *
  *
  */
  */

+ 11 - 3
panda/src/pipeline/threadSimpleImpl.cxx

@@ -141,8 +141,8 @@ start(ThreadPriority priority, bool joinable) {
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   // Query the current Python thread state.
   // Query the current Python thread state.
-  _python_state = PyThreadState_Swap(nullptr);
-  PyThreadState_Swap(_python_state);
+  _python_state = thread_state_swap(nullptr);
+  thread_state_swap(_python_state);
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
   init_thread_context(_context, _stack, _stack_size, st_begin_thread, this);
   init_thread_context(_context, _stack, _stack_size, st_begin_thread, this);
@@ -201,6 +201,14 @@ prepare_for_exit() {
   manager->prepare_for_exit();
   manager->prepare_for_exit();
 }
 }
 
 
+/**
+ *
+ */
+bool ThreadSimpleImpl::
+is_true_threads() {
+  return (is_os_threads != 0);
+}
+
 /**
 /**
  *
  *
  */
  */
@@ -238,7 +246,7 @@ st_begin_thread(void *data) {
 void ThreadSimpleImpl::
 void ThreadSimpleImpl::
 begin_thread() {
 begin_thread() {
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
-  PyThreadState_Swap(_python_state);
+  thread_state_swap(_python_state);
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
 #ifdef HAVE_POSIX_THREADS
 #ifdef HAVE_POSIX_THREADS

+ 1 - 1
panda/src/pipeline/threadSimpleImpl.h

@@ -63,7 +63,7 @@ public:
 
 
   INLINE static void bind_thread(Thread *thread);
   INLINE static void bind_thread(Thread *thread);
   INLINE static bool is_threading_supported();
   INLINE static bool is_threading_supported();
-  INLINE static bool is_true_threads();
+  static bool is_true_threads();
   INLINE static bool is_simple_threads();
   INLINE static bool is_simple_threads();
   INLINE static void sleep(double seconds);
   INLINE static void sleep(double seconds);
   INLINE static void yield();
   INLINE static void yield();

+ 5 - 13
panda/src/pipeline/threadSimpleManager.cxx

@@ -20,7 +20,9 @@
 #include "mainThread.h"
 #include "mainThread.h"
 
 
 #ifdef WIN32
 #ifdef WIN32
-#define WIN32_LEAN_AND_MEAN
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN 1
+#endif
 #include <windows.h>
 #include <windows.h>
 #endif
 #endif
 
 
@@ -235,7 +237,7 @@ next_context() {
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
   // Save the current Python thread state.
   // Save the current Python thread state.
-  _current_thread->_python_state = PyThreadState_Swap(nullptr);
+  _current_thread->_python_state = thread_state_swap(nullptr);
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 
 
 #ifdef DO_PSTATS
 #ifdef DO_PSTATS
@@ -256,7 +258,7 @@ next_context() {
 #endif  // DO_PSTATS
 #endif  // DO_PSTATS
 
 
 #ifdef HAVE_PYTHON
 #ifdef HAVE_PYTHON
-  PyThreadState_Swap(_current_thread->_python_state);
+  thread_state_swap(_current_thread->_python_state);
 #endif  // HAVE_PYTHON
 #endif  // HAVE_PYTHON
 }
 }
 
 
@@ -468,16 +470,6 @@ init_pointers() {
     _pointers_initialized = true;
     _pointers_initialized = true;
     _global_ptr = new ThreadSimpleManager;
     _global_ptr = new ThreadSimpleManager;
     Thread::get_main_thread();
     Thread::get_main_thread();
-
-#ifdef HAVE_PYTHON
-    // Ensure that the Python threading system is initialized and ready to go.
-
-#if PY_VERSION_HEX >= 0x03020000
-    Py_Initialize();
-#endif
-
-    PyEval_InitThreads();
-#endif
   }
   }
 }
 }
 
 

+ 1 - 1
panda/src/text/textNode.cxx

@@ -291,8 +291,8 @@ output(std::ostream &out) const {
  */
  */
 void TextNode::
 void TextNode::
 write(std::ostream &out, int indent_level) const {
 write(std::ostream &out, int indent_level) const {
-  MutexHolder holder(_lock);
   PandaNode::write(out, indent_level);
   PandaNode::write(out, indent_level);
+  MutexHolder holder(_lock);
   TextProperties::write(out, indent_level + 2);
   TextProperties::write(out, indent_level + 2);
   indent(out, indent_level + 2)
   indent(out, indent_level + 2)
     << "transform is: " << *TransformState::make_mat(_transform) << "\n";
     << "transform is: " << *TransformState::make_mat(_transform) << "\n";

+ 5 - 5
panda/src/wgldisplay/wglGraphicsStateGuardian.cxx

@@ -778,9 +778,9 @@ register_twindow_class() {
 #define GAMMA_1 (255.0 * 256.0)
 #define GAMMA_1 (255.0 * 256.0)
 
 
 static bool _gamma_table_initialized = false;
 static bool _gamma_table_initialized = false;
-static unsigned short _orignial_gamma_table [256 * 3];
+static unsigned short _original_gamma_table [256 * 3];
 
 
-void _create_gamma_table (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
+void _create_gamma_table_wgl (PN_stdfloat gamma, unsigned short *original_red_table, unsigned short *original_green_table, unsigned short *original_blue_table, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table) {
   int i;
   int i;
   double gamma_correction;
   double gamma_correction;
 
 
@@ -842,7 +842,7 @@ get_gamma_table(void) {
     HDC hdc = GetDC(nullptr);
     HDC hdc = GetDC(nullptr);
 
 
     if (hdc) {
     if (hdc) {
-      if (GetDeviceGammaRamp (hdc, (LPVOID) _orignial_gamma_table)) {
+      if (GetDeviceGammaRamp (hdc, (LPVOID) _original_gamma_table)) {
         _gamma_table_initialized = true;
         _gamma_table_initialized = true;
         get = true;
         get = true;
       }
       }
@@ -867,10 +867,10 @@ static_set_gamma(bool restore, PN_stdfloat gamma) {
     unsigned short ramp [256 * 3];
     unsigned short ramp [256 * 3];
 
 
     if (restore && _gamma_table_initialized) {
     if (restore && _gamma_table_initialized) {
-      _create_gamma_table (gamma, &_orignial_gamma_table [0], &_orignial_gamma_table [256], &_orignial_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
+      _create_gamma_table_wgl (gamma, &_original_gamma_table [0], &_original_gamma_table [256], &_original_gamma_table [512], &ramp [0], &ramp [256], &ramp [512]);
     }
     }
     else {
     else {
-      _create_gamma_table (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
+      _create_gamma_table_wgl (gamma, 0, 0, 0, &ramp [0], &ramp [256], &ramp [512]);
     }
     }
 
 
     if (SetDeviceGammaRamp (hdc, ramp)) {
     if (SetDeviceGammaRamp (hdc, ramp)) {

+ 19 - 3
panda/src/windisplay/winGraphicsWindow.cxx

@@ -293,13 +293,29 @@ set_properties_now(WindowProperties &properties) {
       _properties.set_fixed_size(properties.get_fixed_size());
       _properties.set_fixed_size(properties.get_fixed_size());
       properties.clear_fixed_size();
       properties.clear_fixed_size();
     }
     }
+    // When switching undecorated mode, Windows will keep the window at the
+    // current outer size, whereas we want to keep it with the configured
+    // inner size.  Store the current size and origin.
+    LPoint2i top_left = _properties.get_origin();
+    LPoint2i bottom_right = top_left + _properties.get_size();
+
     DWORD window_style = make_style(_properties);
     DWORD window_style = make_style(_properties);
     SetWindowLong(_hWnd, GWL_STYLE, window_style);
     SetWindowLong(_hWnd, GWL_STYLE, window_style);
 
 
+    // Now calculate the proper size and origin with the new window style.
+    RECT view_rect;
+    SetRect(&view_rect, top_left[0], top_left[1],
+            bottom_right[0], bottom_right[1]);
+    WINDOWINFO wi;
+    GetWindowInfo(_hWnd, &wi);
+    AdjustWindowRectEx(&view_rect, wi.dwStyle, FALSE, wi.dwExStyle);
+
     // We need to call this to ensure that the style change takes effect.
     // We need to call this to ensure that the style change takes effect.
-    SetWindowPos(_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
-      SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE |
-      SWP_FRAMECHANGED | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
+    SetWindowPos(_hWnd, HWND_NOTOPMOST, view_rect.left, view_rect.top,
+                 view_rect.right - view_rect.left,
+                 view_rect.bottom - view_rect.top,
+                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED |
+                 SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
   }
   }
 
 
   if (properties.has_title()) {
   if (properties.has_title()) {

+ 2 - 0
pandatool/src/eggcharbase/eggBackPointer.cxx

@@ -13,6 +13,8 @@
 
 
 #include "eggBackPointer.h"
 #include "eggBackPointer.h"
 
 
+#include "pnotify.h"
+
 
 
 TypeHandle EggBackPointer::_type_handle;
 TypeHandle EggBackPointer::_type_handle;
 
 

+ 1 - 0
pandatool/src/eggcharbase/eggCharacterDb.h

@@ -29,6 +29,7 @@
 */
 */
 
 
 class EggJointPointer;
 class EggJointPointer;
+class LMatrix4d;
 
 
 /**
 /**
  * This class is used during joint optimization or restructuring to store the
  * This class is used during joint optimization or restructuring to store the

+ 2 - 0
pandatool/src/eggcharbase/eggJointData.cxx

@@ -12,6 +12,8 @@
  */
  */
 
 
 #include "eggJointData.h"
 #include "eggJointData.h"
+
+#include "eggCharacterDb.h"
 #include "eggJointNodePointer.h"
 #include "eggJointNodePointer.h"
 #include "eggMatrixTablePointer.h"
 #include "eggMatrixTablePointer.h"
 #include "pvector.h"
 #include "pvector.h"

+ 2 - 1
pandatool/src/eggcharbase/eggJointNodePointer.cxx

@@ -14,8 +14,9 @@
 #include "eggJointNodePointer.h"
 #include "eggJointNodePointer.h"
 
 
 #include "dcast.h"
 #include "dcast.h"
-#include "eggObject.h"
+#include "eggCharacterDb.h"
 #include "eggGroup.h"
 #include "eggGroup.h"
+#include "eggObject.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 
 
 
 

+ 2 - 0
pandatool/src/eggcharbase/eggMatrixTablePointer.cxx

@@ -12,7 +12,9 @@
  */
  */
 
 
 #include "eggMatrixTablePointer.h"
 #include "eggMatrixTablePointer.h"
+
 #include "dcast.h"
 #include "dcast.h"
+#include "eggCharacterDb.h"
 #include "eggSAnimData.h"
 #include "eggSAnimData.h"
 #include "eggXfmAnimData.h"
 #include "eggXfmAnimData.h"
 #include "eggXfmSAnim.h"
 #include "eggXfmSAnim.h"

+ 1 - 0
pandatool/src/palettizer/paletteGroup.cxx

@@ -17,6 +17,7 @@
 #include "textureImage.h"
 #include "textureImage.h"
 #include "palettizer.h"
 #include "palettizer.h"
 #include "paletteImage.h"
 #include "paletteImage.h"
+#include "sourceTextureImage.h"
 
 
 #include "indent.h"
 #include "indent.h"
 #include "datagram.h"
 #include "datagram.h"

+ 0 - 55
pandatool/src/softegg/config_softegg.cxx

@@ -1,55 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_softegg.cxx
- * @author masad
- * @date 2003-09-25
- */
-
-#include "config_softegg.h"
-#include "softEggGroupUserData.h"
-#include "softNodeDesc.h"
-
-#include "dconfig.h"
-
-Configure(config_softegg);
-NotifyCategoryDef(softegg, ":soft");
-
-ConfigureFn(config_softegg) {
-  init_libsoftegg();
-}
-
-// These control the default behavior of the softegg converter, but not
-// necessarily the default behavior of the soft2egg command-line tool (which
-// has its own defaults).
-
-// Should we respect the Soft?  double-sided flag (true) or ignore it and
-// assume everything is single-sided (false)?
-ConfigVariableBool soft_default_double_sided("soft-default-double-sided", false);
-
-// Should we apply vertex color even when a texture is applied (true) or only
-// when no texture is applied or the vertex-color egg flag is set (false)?
-ConfigVariableBool soft_default_vertex_color("soft-default-vertex-color", true);
-
-/**
- * Initializes the library.  This must be called at least once before any of
- * the functions or classes in this library can be used.  Normally it will be
- * called by the static initializers and need not be called explicitly, but
- * special cases exist.
- */
-void
-init_libsoftegg() {
-  static bool initialized = false;
-  if (initialized) {
-    return;
-  }
-  initialized = true;
-
-  SoftEggGroupUserData::init_type();
-  SoftNodeDesc::init_type();
-}

+ 0 - 28
pandatool/src/softegg/config_softegg.h

@@ -1,28 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file config_softegg.h
- * @author masad
- * @date 2003-09-25
- */
-
-#ifndef CONFIG_SOFTEGG_H
-#define CONFIG_SOFTEGG_H
-
-#include "pandatoolbase.h"
-#include "notifyCategoryProxy.h"
-#include "configVariableBool.h"
-
-NotifyCategoryDeclNoExport(softegg);
-
-extern ConfigVariableBool soft_default_double_sided;
-extern ConfigVariableBool soft_default_vertex_color;
-
-extern void init_libsoftegg();
-
-#endif

+ 0 - 4751
pandatool/src/softegg/soft2Egg.c

@@ -1,4751 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file soft2Egg.c
- * @author masad
- * @date 2003-09-26
- */
-
-#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;
-
-    std::ofstream eggFile;
-    std::ofstream animFile;
-    std::ofstream texFile;
-};
-
-
-/**
- * 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();
-}
-
-/**
- * Displays the usage message.
- */
-void soft2egg::
-Usage() {
-  cerr << "\nUsage:\n"
-       << _commandName << " [opts] (must specify -m or -s)\n\n"
-       << "Options:\n";
-
-  ShowOpts();
-  cerr << "\n";
-}
-
-
-
-/**
- * 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 'fulufssoft371_mips23Drsrc'.\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();
-}
-
-
-/**
- *
- */
-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);
-}
-
-
-
-/**
- * Take a float and make sure it is of the body.
- */
-int soft2egg::
-isNum( float num )
-{
-    return( ( num < HUGE_VAL ) && finite( num ) );
-}
-
-
-/**
- * Given a string, return a copy of the string up to the first occurrence 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 );
-}
-
-
-/**
- * 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 );
-}
-
-/**
- * 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 );
-}
-
-/**
- * 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;
-}
-
-/**
- * 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();
-}
-
-/**
- * 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;
-}
-
-
-/**
- * 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();
-}
-
-/**
- * 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 );
-}
-
-
-/**
- * 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 );
-}
-
-
-/**
- * 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 );
-  }
-}
-
-/**
- * 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 );
-}
-
-
-/**
- * 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 );
-}
-
-/**
- * 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 );
-}
-
-
-/**
- * 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 1199
-                // 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";
-        }
-    }
-
-}
-
-/**
- * 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 1199 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 1199 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 );
-}
-
-
-/**
- * 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 );
-}
-
-/**
- * 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 );
-}
-
-/**
- * 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, &degree );
-    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 );
-}
-
-/**
- * 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] );
-    }
-}
-
-/**
- * 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;
-}
-
-
-/**
- * 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 4799 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" );
-}
-
-
-/**
- * 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
-    // fulrndpubvrmlchipchips_adventurecharzone1roomswarehouse_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 );
-    }
-}
-
-/**
- * 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" );
-    }
-}
-
-/**
- * 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].xoriginalVerts[j].w); dy =
-                // shapeVerts[j].y - (originalVerts[j].yoriginalVerts[j].w);
-                // dz = shapeVerts[j].z -
-                // (originalVerts[j].zoriginalVerts[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
-}
-
-
-/**
- * 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 );
-        }
-
-    }
-}
-
-
-/**
- * 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 );
-    }
-
-}
-
-/**
- * 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 );
-        }
-    }
-}
-
-
-/**
- * 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 );
-
-}
-
-
-/**
- * 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
-
-/**
- * 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

+ 0 - 44
pandatool/src/softegg/softEggGroupUserData.I

@@ -1,44 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softEggGroupUserData.I
- * @author masad
- * @date 2003-09-25
- */
-
-/**
- *
- */
-INLINE SoftEggGroupUserData::
-SoftEggGroupUserData() {
-  _vertex_color = false;
-  _double_sided = false;
-}
-
-
-/**
- *
- */
-INLINE SoftEggGroupUserData::
-SoftEggGroupUserData(const SoftEggGroupUserData &copy) :
-  EggUserData(copy),
-  _vertex_color(copy._vertex_color),
-  _double_sided(copy._double_sided)
-{
-}
-
-
-/**
- *
- */
-INLINE void SoftEggGroupUserData::
-operator = (const SoftEggGroupUserData &copy) {
-  EggUserData::operator = (copy);
-  _vertex_color = copy._vertex_color;
-  _double_sided = copy._double_sided;
-}

+ 0 - 16
pandatool/src/softegg/softEggGroupUserData.cxx

@@ -1,16 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softEggGroupUserData.cxx
- * @author masad
- * @date 2003-09-25
- */
-
-#include "softEggGroupUserData.h"
-
-TypeHandle SoftEggGroupUserData::_type_handle;

+ 0 - 53
pandatool/src/softegg/softEggGroupUserData.h

@@ -1,53 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softEggGroupUserData.h
- * @author masad
- * @date 2003-09-25
- */
-
-#ifndef SOFTEGGGROUPUSERDATA_H
-#define SOFTEGGGROUPUSERDATA_H
-
-#include "pandatoolbase.h"
-#include "eggUserData.h"
-
-/**
- * This class contains extra user data which is piggybacked onto EggGroup
- * objects for the purpose of the softimage converter.
- */
-class SoftEggGroupUserData : public EggUserData {
-public:
-  INLINE SoftEggGroupUserData();
-  INLINE SoftEggGroupUserData(const SoftEggGroupUserData &copy);
-  INLINE void operator = (const SoftEggGroupUserData &copy);
-
-  bool _vertex_color;
-  bool _double_sided;
-
-public:
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    EggUserData::init_type();
-    register_type(_type_handle, "SoftEggGroupUserData",
-                  EggUserData::get_class_type());
-  }
-  virtual TypeHandle get_type() const {
-    return get_class_type();
-  }
-  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
-
-private:
-  static TypeHandle _type_handle;
-};
-
-#include "softEggGroupUserData.I"
-
-#endif

+ 0 - 1310
pandatool/src/softegg/softNodeDesc.cxx

@@ -1,1310 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softNodeDesc.cxx
- * @author masad
- * @date 2003-10-03
- */
-
-#include "softNodeDesc.h"
-#include "config_softegg.h"
-#include "eggGroup.h"
-#include "eggXfmSAnim.h"
-#include "eggSAnimData.h"
-#include "softToEggConverter.h"
-#include "dcast.h"
-
-using std::endl;
-
-TypeHandle SoftNodeDesc::_type_handle;
-
-/**
- *
- */
-SoftNodeDesc::
-SoftNodeDesc(SoftNodeDesc *parent, const std::string &name) :
-  Namable(name),
-  _parent(parent)
-{
-  _model = nullptr;
-  _egg_group = nullptr;
-  _egg_table = nullptr;
-  _anim = nullptr;
-  _joint_type = JT_none;
-
-  // Add ourselves to our parent.
-  if (_parent != nullptr) {
-    softegg_cat.spam() << "parent name " << _parent->get_name();
-    _parent->_children.push_back(this);
-  }
-
-  // set the _parentJoint to Null
-  _parentJoint = nullptr;
-
-  fullname = nullptr;
-
-  numTexLoc = 0;
-  numTexGlb = 0;
-
-  uScale = nullptr;
-  vScale = nullptr;
-  uOffset = nullptr;
-  vOffset = nullptr;
-
-  valid;
-  uv_swap;
-  // SAA_Boolean visible;
-  numTexTri = nullptr;
-  textures = nullptr;
-  materials = nullptr;
-  triangles = nullptr;
-  gtype = SAA_GEOM_ORIGINAL;
-}
-
-/**
- *
- */
-SoftNodeDesc::
-~SoftNodeDesc() {
-  // I think it is a mistake to try to delete this.  This was one member of an
-  // entire array allocated at once; you can't delete individual elements of
-  // an array.
-
-  // Screw cleanup, anyway--we'll just let the array leak.
-  /*
-  if (_model != (SAA_Elem *)NULL) {
-    delete _model;
-  }
-  */
-}
-
-/**
- * Indicates an associated between the SoftNodeDesc and some SAA_Elem
- * instance.
- */
-void SoftNodeDesc::
-set_model(SAA_Elem *model) {
-  _model = model;
-}
-
-/**
- * Sometimes, parent is not known at node creation As soon as it is known, set
- * the parent
- */
-void SoftNodeDesc::
-set_parent(SoftNodeDesc *parent) {
-  if (_parent) {
-    softegg_cat.spam() << endl;
-    /*
-    softegg_cat.spam() << " expected _parent to be null!?\n";
-    if (_parent == parent)
-      softegg_cat.spam() << " parent already set\n";
-    else {
-      softegg_cat.spam() << " current parent " << _parent->get_name() << " new parent "
-           << parent << endl;
-    }
-    */
-    return;
-  }
-  _parent = parent;
-  softegg_cat.spam() << " set parent to " << _parent->get_name() << endl;
-
-  // Add ourselves to our parent.
-  _parent->_children.push_back(this);
-}
-
-/**
- * Sometimes, parent is not known at node creation As soon as it is known, set
- * the parent
- */
-void SoftNodeDesc::
-force_set_parent(SoftNodeDesc *parent) {
-  if (_parent)
-    softegg_cat.spam() << " current parent " << _parent->get_name();
-
-  _parent = parent;
-
-  if (_parent)
-    softegg_cat.spam() << " new parent " << _parent->get_name() << endl;
-
-  // Add ourselves to our parent.
-  _parent->_children.push_back(this);
-}
-
-/**
- * Returns true if a Soft dag path has been associated with this node, false
- * otherwise.
- */
-bool SoftNodeDesc::
-has_model() const {
-  return (_model != nullptr);
-}
-
-/**
- * Returns the SAA_Elem * associated with this node.  It is an error to call
- * this unless has_model() returned true.
- */
-SAA_Elem *SoftNodeDesc::
-get_model() const {
-  nassertr(_model != nullptr, _model);
-  return _model;
-}
-
-/**
- * Returns true if the node should be treated as a joint by the converter.
- */
-bool SoftNodeDesc::
-is_joint() const {
-  // return _joint_type == JT_joint || _joint_type == JT_pseudo_joint;
-  return _joint_type == JT_joint;
-}
-
-/**
- * Returns true if the node should be treated as a junk by the converter.
- */
-bool SoftNodeDesc::
-is_junk() const {
-  return _joint_type == JT_junk;
-}
-
-/**
- * sets the _joint_type to JT_joint
- */
-void SoftNodeDesc::
-set_joint() {
-  _joint_type = JT_joint;
-}
-/**
- * Returns true if the node is the parent or ancestor of a joint.
- */
-bool SoftNodeDesc::
-is_joint_parent() const {
-  return _joint_type == JT_joint_parent;
-}
-
-/**
- * Recursively clears the egg pointers from this node and all children.
- */
-void SoftNodeDesc::
-clear_egg() {
-  _egg_group = nullptr;
-  _egg_table = nullptr;
-  _anim = nullptr;
-
-  Children::const_iterator ci;
-  for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    SoftNodeDesc *child = (*ci);
-    child->clear_egg();
-  }
-}
-
-/**
- * Indicates that this node has at least one child that is a joint or a
- * pseudo-joint.
- */
-void SoftNodeDesc::
-mark_joint_parent() {
-  if (_joint_type == JT_none) {
-    _joint_type = JT_joint_parent;
-    softegg_cat.spam() << " marked parent " << get_name();
-  }
-  else
-    softegg_cat.spam() << " ?parent " << get_name() << " joint type " << _joint_type;
-
-  if (_parent != nullptr) {
-    _parent->mark_joint_parent();
-  }
-  softegg_cat.spam() << endl;
-}
-
-/**
- * Walks the hierarchy, if a node is joint, make sure all its parents are
- * marked JT_joint_parent
- */
-void SoftNodeDesc::
-check_joint_parent() {
-  Children::const_iterator ci;
-  for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    SoftNodeDesc *child = (*ci);
-    if (child->is_joint()) {
-      softegg_cat.spam() << "child " << child->get_name();
-      mark_joint_parent();
-    }
-    child->check_joint_parent();
-  }
-}
-
-/**
- * check to see if this is a branch we don't want to descend - this will
- * prevent creating geometry for animation control structures
- */
-void SoftNodeDesc::
-check_junk(bool parent_junk) {
-  const char *name = get_name().c_str();
-
-  if (parent_junk) {
-    _joint_type = JT_junk;
-    softegg_cat.spam() << "junk node " << get_name() << endl;
-  }
-  if ( (strstr(name, "con-") != nullptr) ||
-       (strstr(name, "con_") != nullptr) ||
-       (strstr(name, "fly_") != nullptr) ||
-       (strstr(name, "fly-") != nullptr) ||
-       (strstr(name, "camRIG") != nullptr) ||
-       (strstr(name, "cam_rig") != nullptr) ||
-       (strstr(name, "bars") != nullptr) )
-    {
-      _joint_type = JT_junk;
-      softegg_cat.spam() << "junk node " << get_name() << endl;
-      parent_junk = true;
-      Children::const_iterator ci;
-      for (ci = _children.begin(); ci != _children.end(); ++ci) {
-        SoftNodeDesc *child = (*ci);
-        softegg_cat.spam() << child->get_name() << ",";
-      }
-      softegg_cat.spam() << endl;
-    }
-  Children::const_iterator ci;
-  for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    SoftNodeDesc *child = (*ci);
-    child->check_junk(parent_junk);
-  }
-}
-
-/**
- * check to see if this is a selected branch we want to descend - this will
- * prevent creating geometry for other parts
- */
-bool SoftNodeDesc::
-is_partial(char *search_prefix) {
-  const char *name = fullname;
-
-  // if no search prefix then return false
-  if (!search_prefix)
-    return false;
-  // if name is search_prefix, return false
-  if (strstr(name, search_prefix) != nullptr) {
-    softegg_cat.debug() << "matched " << name << " ";
-    return false;
-  }
-  // if name is not search_prefix, look in its parent
-  if (strstr(name, search_prefix) == nullptr) {
-    softegg_cat.debug() << "node " << name << " ";
-    if (_parent)
-      return _parent->is_partial(search_prefix);
-  }
-  // neither name nor its parent is search_prefix
-  return true;
-}
-
-/**
- * Go through the ancestors and figure out who is the immediate _parentJoint
- * of this node
- */
-void SoftNodeDesc::
-set_parentJoint(SAA_Scene *scene, SoftNodeDesc *lastJoint) {
-  if (is_junk())
-    return;
-  // set its parent joint to the lastJoint
-  _parentJoint = lastJoint;
-  softegg_cat.spam() << get_name() << ": parent joint set to :" << lastJoint;
-  if (lastJoint)
-    softegg_cat.spam() << "(" << lastJoint->get_name() << ")";
-  softegg_cat.spam() << endl;
-
-  // is this node a joint?
-  SAA_Boolean isSkeleton = false;
-  if (has_model())
-    SAA_modelIsSkeleton( scene, get_model(), &isSkeleton );
-
-  // if  already a joint or name has "joint" in it
-  const char *name = get_name().c_str();
-  if (is_joint() || isSkeleton || strstr(name, "joint") != nullptr) {
-    lastJoint = this;
-  }
-  if ( _parentJoint && strstr( _parentJoint->get_name().c_str(), "scale" ) != nullptr ) {
-    // make sure _parentJoint didn't have the name "joint" in it
-    if (strstr(_parentJoint->get_name().c_str(), "joint") == nullptr) {
-      _parentJoint = nullptr;
-      // _parentJoint = lastJoint = NULL;
-      softegg_cat.spam() << "scale joint flag set!\n";
-    }
-  }
-
-  // look in the children
-  Children::const_iterator ci;
-  for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    SoftNodeDesc *child = (*ci);
-    child->set_parentJoint(scene, lastJoint);
-  }
-}
-
-/**
- * Walks the hierarchy, looking for non-joint nodes that are both children and
- * parents of a joint.  These nodes are deemed to be pseudo joints, since the
- * converter must treat them as joints.
- */
-void SoftNodeDesc::
-check_pseudo_joints(bool joint_above) {
-  if (_joint_type == JT_joint_parent && joint_above) {
-    // This is one such node: it is the parent of a joint (JT_joint_parent is
-    // set), and it is the child of a joint (joint_above is set).
-    _joint_type = JT_pseudo_joint;
-    softegg_cat.debug() << "pseudo " << get_name() << " case1\n";
-  }
-
-  if (_joint_type == JT_joint) {
-    // If this node is itself a joint, then joint_above is true for all child
-    // nodes.
-    joint_above = true;
-  }
-
-  // Don't bother traversing further if _joint_type is none or junk, since
-  // that means this node has no joint children.
-  if (_joint_type != JT_none && _joint_type != JT_junk) {
-
-    bool any_joints = false;
-    Children::const_iterator ci;
-    for (ci = _children.begin(); ci != _children.end(); ++ci) {
-      SoftNodeDesc *child = (*ci);
-      child->check_pseudo_joints(joint_above);
-      if (child->is_joint()) {
-        softegg_cat.spam() << get_name() << " any_joint true by " << child->get_name() << endl;
-        any_joints = true;
-      }
-    }
-
-    // If any children qualify as joints, then any sibling nodes that are
-    // parents of joints are also elevated to joints.
-    if (any_joints) {
-      bool all_joints = true;
-      for (ci = _children.begin(); ci != _children.end(); ++ci) {
-        SoftNodeDesc *child = (*ci);
-        if (child->_joint_type == JT_joint_parent) {
-          child->_joint_type = JT_pseudo_joint;
-          softegg_cat.debug() << "pseudo " << child->get_name() << " case2 by parent " << get_name() << "\n";
-        } else if (child->_joint_type == JT_none || child->_joint_type == JT_junk) {
-          all_joints = false;
-        }
-      }
-
-      if (all_joints || any_joints) {
-        // Finally, if all children or at least one is a joint, then we are
-        // too.
-        if (_joint_type == JT_joint_parent) {
-          _joint_type = JT_pseudo_joint;
-          softegg_cat.debug() << "pseudo " << get_name() << " case3\n";
-        }
-      }
-    }
-  }
-  else
-    softegg_cat.spam() << "found null joint " << get_name() << endl;
-}
-
-/**
- * Extracts the transform on the indicated Soft node, and applies it to the
- * corresponding Egg node.
- */
-void SoftNodeDesc::
-get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global) {
-  // Get the model's matrix
-  int scale_joint = 0;
-
-  if (!global && _parentJoint && !stec.flatten && !scale_joint) {
-
-    SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_LOCAL,  matrix );
-    softegg_cat.debug() << get_name() << " using local matrix :parent ";
-
-  } else {
-
-    SAA_modelGetMatrix( scene, get_model(), SAA_COORDSYS_GLOBAL,  matrix );
-    softegg_cat.debug() << get_name() << " using global matrix :parent ";
-
-  }
-
-  if (_parentJoint && !stec.flatten)
-    softegg_cat.debug() << _parentJoint->get_name() << endl;
-  else
-    softegg_cat.debug() << _parentJoint << endl;
-
-
-  softegg_cat.spam() << "model matrix = " << matrix[0][0] << " " << matrix[0][1] << " " << matrix[0][2] << " " << matrix[0][3] << "\n";
-  softegg_cat.spam() << "model matrix = " << matrix[1][0] << " " << matrix[1][1] << " " << matrix[1][2] << " " << matrix[1][3] << "\n";
-  softegg_cat.spam() << "model matrix = " << matrix[2][0] << " " << matrix[2][1] << " " << matrix[2][2] << " " << matrix[2][3] << "\n";
-  softegg_cat.spam() << "model matrix = " << matrix[3][0] << " " << matrix[3][1] << " " << matrix[3][2] << " " << matrix[3][3] << "\n";
-
-  if (!global && is_joint()) {
-    LMatrix4d m4d(matrix[0][0], matrix[0][1], matrix[0][2], matrix[0][3],
-                  matrix[1][0], matrix[1][1], matrix[1][2], matrix[1][3],
-                  matrix[2][0], matrix[2][1], matrix[2][2], matrix[2][3],
-                  matrix[3][0], matrix[3][1], matrix[3][2], matrix[3][3]);
-    if (!m4d.almost_equal(LMatrix4d::ident_mat(), 0.0001)) {
-      egg_group->set_transform3d(m4d);
-      softegg_cat.spam() << "set transform in egg_group\n";
-    }
-  }
-  return;
-}
-
-/**
- * Extracts the transform on the indicated Soft node, as appropriate for a
- * joint in an animated character, and applies it to the indicated node.  This
- * is different from get_transform() in that it does not respect the
- * _transform_type flag, and it does not consider the relative transforms
- * within the egg file.  more added functionality: now fills in components of
- * anim (EffXfmSAnim) class (masad).
- */
-void SoftNodeDesc::
-get_joint_transform(SAA_Scene *scene,  EggGroup *egg_group, EggXfmSAnim *anim, bool global) {
-  // SI_Error result;
-  SAA_Elem *skeletonPart = _model;
-  const char *name = get_name().c_str();
-
-  if ( skeletonPart != nullptr ) {
-    PN_stdfloat i,j,k;
-    PN_stdfloat h,p,r;
-    PN_stdfloat x,y,z;
-    int scale_joint = 0;
-
-    softegg_cat.spam() << "\n\nanimating child " << name << endl;
-
-    if (_parentJoint && !stec.flatten && !scale_joint ) {
-      softegg_cat.debug() << "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 );
-    } else {
-      softegg_cat.debug() << " 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 );
-    }
-
-    softegg_cat.spam() << "\nanim data: " << i << " " << j << " " << k << endl;
-    softegg_cat.spam() << "\t" << p << " " << h << " " << r << endl;
-    softegg_cat.spam() << "\t" << x << " " << y << " " << z << endl;
-
-    // Encode the component multiplication ordering in the egg file.
-    // SoftImage always uses this order, regardless of the setting of temp-
-    // hpr-fix.
-    anim->set_order("sphrt");
-
-    // Add each component by their names
-    anim->add_component_data("i", i);
-    anim->add_component_data("j", j);
-    anim->add_component_data("k", k);
-    anim->add_component_data("p", p);
-    anim->add_component_data("h", h);
-    anim->add_component_data("r", r);
-    anim->add_component_data("x", x);
-    anim->add_component_data("y", y);
-    anim->add_component_data("z", z);
-  }
-  else {
-    softegg_cat.debug() << "Cannot build anim table - no skeleton\n";
-  }
-}
-
-/**
- * Converts the indicated Soft polyset to a bunch of EggPolygons and parents
- * them to the indicated egg group.
- */
-void SoftNodeDesc::
-load_poly_model(SAA_Scene *scene, SAA_ModelType type) {
-  SI_Error result;
-  const char *name = get_name().c_str();
-
-  int i;
-  int id = 0;
-
-  // if making a pose - get deformed geometry
-  if ( stec.make_pose )
-    gtype = SAA_GEOM_DEFORMED;
-
-  // If the model is a PATCH in soft, set its step before tesselating
-  else if ( type == SAA_MPTCH )
-    SAA_patchSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
-
-  // Get the number of triangles
-  result = SAA_modelGetNbTriangles( scene, _model, gtype, id, &numTri);
-  softegg_cat.spam() << "triangles: " << numTri << "\n";
-
-  if ( result != SI_SUCCESS ) {
-    softegg_cat.spam() << "Error: couldn't get number of triangles!\n";
-    softegg_cat.debug() << "\tbailing on model: " << name << "\n";
-    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)
-  softegg_cat.spam() << "is Skeleton? " << isSkeleton << "\n";
-
-  /*************************************************************************************/
-
-  // model is not a null and has no triangles!
-  if ( !numTri ) {
-    softegg_cat.spam() << "no triangles!\n";
-  }
-  else {
-    // allocate array of triangles
-    triangles = (SAA_SubElem *) new SAA_SubElem[numTri];
-    if (!triangles) {
-      softegg_cat.info() << "Not enough Memory for triangles...\n";
-      exit(1);
-    }
-    // triangulate model and read the triangles into array
-    SAA_modelGetTriangles( scene, _model, gtype, id, numTri, triangles );
-    softegg_cat.spam() << "got triangles\n";
-
-    /***********************************************************************************/
-
-    // allocate array of materials (Asad: it gives a warning if try to get one
-    // triangle at a time...investigate later read each triangle's material
-    // into array
-    materials = (SAA_Elem*) new SAA_Elem[numTri];
-    SAA_triangleGetMaterials( scene, _model, numTri, triangles, materials );
-    if (!materials) {
-      softegg_cat.info() << "Not enough Memory for materials...\n";
-      exit(1);
-    }
-    softegg_cat.spam() << "got materials\n";
-
-    /***********************************************************************************/
-
-    // allocate array of textures per triangle
-    numTexTri = new int[numTri];
-    const void *relinfo;
-
-    // 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 ) {
-      softegg_cat.spam() << "numTexLoc = " << numTexLoc << endl;
-
-      // allocate arrays of texture info
-      uScale = new PN_stdfloat[numTri];
-      vScale = new PN_stdfloat[numTri];
-      uOffset = new PN_stdfloat[numTri];
-      vOffset = new PN_stdfloat[numTri];
-      texNameArray = new char *[numTri];
-      uRepeat = new int[numTri];
-      vRepeat = new int[numTri];
-
-      // ASSUME only one texture per material
-      textures = new 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] );
-
-        // initialize the array value
-        texNameArray[i] = nullptr;
-        // initialize the repeats
-        uRepeat[i] = vRepeat[i] = 0;
-
-        // see if this triangle has texture info
-        if (numTexTri[i] == 0)
-          continue;
-
-        // check to see if texture is present
-        result = SAA_elementIsValid( scene, &textures[i], &valid );
-
-        if ( result != SI_SUCCESS )
-          softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
-
-        // texture present - get the name and uv info
-        if ( valid ) {
-          // according to drose, we don't need to convert .pic files to .rgb,
-          // panda can now read the .pic files.
-          texNameArray[i] = stec.GetTextureName(scene, &textures[i]);
-
-          softegg_cat.spam() << " tritex[" << i << "] named: " << texNameArray[i] << endl;
-
-          SAA_texture2DGetUVSwap( scene, &textures[i], &uv_swap );
-
-          if ( uv_swap == TRUE )
-            softegg_cat.spam() << " 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] );
-
-          softegg_cat.spam() << "tritex[" << i << "] uScale: " << uScale[i] << " vScale: " << vScale[i] << endl;
-          softegg_cat.spam() << " uOffset: " << uOffset[i] << " vOffset: " << vOffset[i] << endl;
-
-          SAA_texture2DGetRepeats( scene, &textures[i], &uRepeat[i], &vRepeat[i] );
-          softegg_cat.spam() << "uRepeat = " << uRepeat[i] << ", vRepeat = " << vRepeat[i] << endl;
-        }
-        else {
-          softegg_cat.spam() << "Invalid texture...\n";
-          softegg_cat.spam() << " tritex[" << i << "] named: (null)\n";
-        }
-      }
-    }
-    else { // if no local textures, try to get global textures
-      SAA_modelRelationGetT2DGlbNbElements( scene, _model,
-                                            FALSE, &relinfo, &numTexGlb );
-      if ( numTexGlb ) {
-        // ASSUME only one texture per model
-        textures = new SAA_Elem;
-        // get the referenced texture
-        SAA_modelRelationGetT2DGlbElements( scene, _model,
-                                            TEX_PER_MAT, textures );
-        softegg_cat.spam() << "numTexGlb = " << numTexGlb << endl;
-        // check to see if texture is present
-        SAA_elementIsValid( scene, textures, &valid );
-        if ( valid ) {  // texture present - get the name and uv info
-          SAA_texture2DGetUVSwap( scene, textures, &uv_swap );
-
-          if ( uv_swap == TRUE )
-            softegg_cat.spam() << " swapping u and v...\n";
-
-          // according to drose, we don't need to convert .pic files to .rgb,
-          // panda can now read the .pic files.
-          texNameArray = new char *[1];
-          *texNameArray = stec.GetTextureName(scene, textures);
-
-          uRepeat = new int;
-          vRepeat = new int;
-
-          softegg_cat.spam() << " global tex named: " << *texNameArray << endl;
-
-          // allocate arrays of texture info
-          uScale = new PN_stdfloat;
-          vScale = new PN_stdfloat;
-          uOffset = new PN_stdfloat;
-          vOffset = new PN_stdfloat;
-
-          SAA_texture2DGetUScale( scene, textures, uScale );
-          SAA_texture2DGetVScale( scene, textures, vScale );
-          SAA_texture2DGetUOffset( scene, textures, uOffset );
-          SAA_texture2DGetVOffset( scene, textures, vOffset );
-
-          softegg_cat.spam() << " global tex uScale: " << *uScale << " vScale: " << *vScale << endl;
-          softegg_cat.spam() << "            uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
-
-          SAA_texture2DGetRepeats(  scene, textures, uRepeat, vRepeat );
-          softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
-        }
-        else {
-          softegg_cat.spam() << "Invalid Texture...\n";
-        }
-      }
-    }
-  }
-  softegg_cat.spam() << "got textures" << endl;
-}
-
-/**
- * Converts the indicated Soft polyset to a bunch of EggPolygons and parents
- * them to the indicated egg group.
- */
-void SoftNodeDesc::
-load_nurbs_model(SAA_Scene *scene, SAA_ModelType type) {
-  SI_Error result;
-  const char *name = get_name().c_str();
-
-  // if making a pose - get deformed geometry
-  if ( stec.make_pose )
-    gtype = SAA_GEOM_DEFORMED;
-
-  // If the model is a NURBS in soft, set its step before tesselating
-  if ( type == SAA_MNSRF )
-    SAA_nurbsSurfaceSetStep( scene, _model, stec.nurbs_step, stec.nurbs_step );
-
-  // get the materials
-  /***********************************************************************************/
-  const void *relinfo;
-
-  SAA_modelRelationGetMatNbElements( scene, get_model(), FALSE, &relinfo,
-                                     &numNurbMats );
-
-  softegg_cat.spam() << "nurbs surf has " << numNurbMats << " materials\n";
-
-  if ( numNurbMats ) {
-    materials = new SAA_Elem[numNurbMats];
-    if (!materials) {
-      softegg_cat.info() << "Out Of Memory on allocating materials\n";
-      exit(1);
-    }
-
-    SAA_modelRelationGetMatElements( scene, get_model(), relinfo,
-                                     numNurbMats, materials );
-
-    softegg_cat.spam() << "got materials\n";
-
-    // get the textures
-    /***********************************************************************************/
-    numNurbTexLoc = 0;
-    numNurbTexGlb = 0;
-
-    // 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 ) {
-      softegg_cat.spam() << name << " had " << numNurbTexLoc << " local tex\n";
-      nassertv(numNurbTexLoc == 1);
-
-      textures = new SAA_Elem[numNurbTexLoc];
-
-      // get the referenced texture
-      SAA_materialRelationGetT2DLocElements( scene, &materials[0], TEX_PER_MAT, &textures[0] );
-
-    }
-    // if no locals, try to get globals
-    else {
-      SAA_modelRelationGetT2DGlbNbElements( scene, get_model(), FALSE, &relinfo, &numNurbTexGlb );
-
-      if ( numNurbTexGlb ) {
-        softegg_cat.spam() << name << " had " << numNurbTexGlb << " global tex\n";
-        nassertv(numNurbTexGlb == 1);
-
-        textures = new SAA_Elem[numNurbTexGlb];
-
-        // get the referenced texture
-        SAA_modelRelationGetT2DGlbElements( scene, get_model(), TEX_PER_MAT, &textures[0] );
-      }
-    }
-
-    if ( numNurbTexLoc || numNurbTexGlb) {
-
-      // allocate the texture name array
-      texNameArray = new char *[1];
-      // allocate arrays of texture info
-      uScale = new PN_stdfloat;
-      vScale = new PN_stdfloat;
-      uOffset = new PN_stdfloat;
-      vOffset = new PN_stdfloat;
-      uRepeat = new int;
-      vRepeat = new int;
-
-      // check to see if texture is present
-      result = SAA_elementIsValid( scene, &textures[0], &valid );
-
-      if ( result != SI_SUCCESS )
-        softegg_cat.spam() << "SAA_elementIsValid failed!!!!\n";
-
-      // texture present - get the name and uv info
-      if ( valid ) {
-        // according to drose, we don't need to convert .pic files to .rgb,
-        // panda can now read the .pic files.
-        texNameArray[0] = stec.GetTextureName(scene, &textures[0]);
-
-        softegg_cat.spam() << " tritex[0] named: " << texNameArray[0] << endl;
-
-        SAA_texture2DGetUVSwap( scene, &textures[0], &uv_swap );
-
-        if ( uv_swap == TRUE )
-          softegg_cat.spam() << " swapping u and v...\n" ;
-
-        SAA_texture2DGetUScale( scene, &textures[0], uScale );
-        SAA_texture2DGetVScale( scene, &textures[0], vScale );
-        SAA_texture2DGetUOffset( scene, &textures[0], uOffset );
-        SAA_texture2DGetVOffset( scene, &textures[0], vOffset );
-
-        softegg_cat.spam() << "tritex[0] uScale: " << *uScale << " vScale: " << *vScale << endl;
-        softegg_cat.spam() << " uOffset: " << *uOffset << " vOffset: " << *vOffset << endl;
-
-        SAA_texture2DGetRepeats( scene, &textures[0], uRepeat, vRepeat );
-        softegg_cat.spam() << "uRepeat = " << *uRepeat << ", vRepeat = " << *vRepeat << endl;
-      }
-      else {
-        softegg_cat.spam() << "Invalid texture...\n";
-        softegg_cat.spam() << " tritex[0] named: (null)\n";
-      }
-    }
-
-    softegg_cat.spam() << "got textures\n";
-  }
-}
-
-/**
- * given a vertex, find its corresponding shape vertex and return its index.
- */
-int SoftNodeDesc::
-find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert) {
-  int i, found = 0;
-
-  for (i = 0; i < numVert && !found ; i++) {
-    if ((p3d[0] == vertices[i].x) &&
-        (p3d[1] == vertices[i].y) &&
-        (p3d[2] == vertices[i].z)) {
-      found = 1;
-      softegg_cat.spam() << "found shape vert at index " << i << endl;
-    }
-  }
-
-  if (!found )
-    i = -1;
-  else
-    i--;
-
-  return i;
-}
-
-/**
- * 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 SoftNodeDesc::
-make_vertex_offsets(int numShapes) {
-  int i, j;
-  int offset;
-  int numCV;
-  char tableName[_MAX_PATH];
-  SAA_DVector *shapeVerts = nullptr;
-  SAA_DVector *uniqueVerts = nullptr;
-  SAA_Elem *model = get_model();
-  SAA_Scene *scene = &stec.scene;
-
-  EggVertexPool *vpool = nullptr;
-  std::string vpool_name = get_name() + ".verts";
-  EggNode *t = stec._tree.get_egg_root()->find_child(vpool_name);
-  if (t)
-    DCAST_INTO_V(vpool, t);
-
-  int numOrigVert = (int) vpool->size();
-  EggVertexPool::iterator vi;
-
-  if ((type == SAA_MNSRF) && stec.make_nurbs)
-    SAA_nurbsSurfaceSetStep( scene, model, stec.nurbs_step, stec.nurbs_step );
-
-  SAA_modelGetNbVertices( scene, model, &numCV );
-
-  // get the shape verts
-  uniqueVerts = new SAA_DVector[numCV];
-  SAA_modelGetVertices( scene, model, SAA_GEOM_ORIGINAL, 0,
-                        numCV, uniqueVerts );
-
-  softegg_cat.spam() << numCV << " CV's\n";
-
-  for ( i = 0; i < numCV; i++ )
-    // convert vertices to global
-    _VCT_X_MAT( uniqueVerts[i], uniqueVerts[i], matrix);
-    softegg_cat.spam() << "uniqueVerts[" << i << "] = " << uniqueVerts[i].x << " " << uniqueVerts[i].y
-         << " " << uniqueVerts[i].z << " " << uniqueVerts[i].w << endl;
-
-  // iterate through for each key shape (except original)
-  for ( i = 1; i < numShapes; i++ ) {
-
-    sprintf(tableName, "%s.%d", get_name().c_str(), i);
-
-    softegg_cat.spam() << "\nMaking geometry offsets for " << tableName << "...\n";
-
-    if ((type == SAA_MNSRF) && stec.make_nurbs)
-      softegg_cat.spam() << "calculating NURBS morphs...\n";
-    else
-      softegg_cat.spam() << "calculating triangle morphs...\n";
-
-    // get the shape verts
-    shapeVerts = new SAA_DVector[numCV];
-    SAA_modelGetVertices( scene, model, SAA_GEOM_SHAPE, i+1, numCV, shapeVerts );
-
-    for ( j=0; j < numCV; j++ ) {
-      // convert vertices to global
-      _VCT_X_MAT( shapeVerts[j], shapeVerts[j], matrix);
-
-      softegg_cat.spam() << "shapeVerts[" << j << "] = " << shapeVerts[j].x << " "
-           << shapeVerts[j].y << " " << shapeVerts[j].z << endl;
-    }
-    softegg_cat.spam() << endl;
-
-    // for every original vertex, compare to the corresponding key shape
-    // vertex and see if a vertex offset is needed
-    j = 0;
-    for (vi = vpool->begin(); vi != vpool->end(); ++vi, ++j) {
-
-      double dx, dy, dz;
-      EggVertex *vert = (*vi);
-      LPoint3d p3d = vert->get_pos3();
-
-      softegg_cat.spam() << "oVert[" << j << "] = " <<  p3d[0] << " " <<  p3d[1] << " " <<  p3d[2] << endl;
-      if ((type == SAA_MNSRF) && stec.make_nurbs) {
-        dx = shapeVerts[j].x - p3d[0];
-        dy = shapeVerts[j].y - p3d[1];
-        dz = shapeVerts[j].z - p3d[2];
-
-        softegg_cat.spam() << "global shapeVerts[" << j << "] = " << shapeVerts[j].x << " "
-             << shapeVerts[j].y << " " << shapeVerts[j].z << " " << shapeVerts[j].w << endl;
-      }
-      else {
-        // we need to map from original vertices to triangle shape vertices
-        // here
-        offset = find_shape_vert(p3d, uniqueVerts, numCV);
-
-        dx = shapeVerts[offset].x - p3d[0];
-        dy = shapeVerts[offset].y - p3d[1];
-        dz = shapeVerts[offset].z - p3d[2];
-
-        softegg_cat.spam() << "global shapeVerts[" << offset << "] = " << shapeVerts[offset].x << " "
-             << shapeVerts[offset].y << " " << shapeVerts[offset].z << endl;
-      }
-
-      softegg_cat.spam() << j << ": dx = " << dx << ", dy = " << dy << ", dz = " << dz << endl;
-
-      // if change isn't negligible, make a morph vertex entry
-      double total = fabs(dx)+fabs(dy)+fabs(dz);
-      if ( total > 0.00001 ) {
-        if ( vpool != nullptr ) {
-          // create offset
-          LVector3d p(dx, dy, dz);
-          EggMorphVertex *dxyz = new EggMorphVertex(tableName, p);
-          // add the offset to the vertex
-          vert->_dxyzs.insert(*dxyz);
-        }
-        else
-          softegg_cat.spam() << "Error: couldn't find vertex pool " << vpool_name << endl;
-
-      } // if total
-    } //for j
-  } //for i
-}
-
-/**
- * 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 SoftNodeDesc::
-make_morph_table(  PN_stdfloat time ) {
-  int numShapes;
-  SAA_Elem *model = nullptr;
-  SAA_AnimInterpType type;
-  SAA_Scene *scene = &stec.scene;
-
-  if (has_model())
-    model = get_model();
-  else
-    return;
-
-  // Get the number of key shapes
-  SAA_modelGetNbShapes( scene, model, &numShapes );
-
-  if ( numShapes <= 0 ) {
-    return;
-  }
-
-  stec.has_morph = true;
-
-  softegg_cat.spam() << "make_morph_table: " << get_name() << " : num shapes: " << numShapes << endl;
-
-  SAA_modelGetShapeInterpolation( scene, model, &type );
-
-  if ( type == SAA_ANIM_LINEAR || type == SAA_ANIM_CARDINAL ) {
-    softegg_cat.spam() << "linear morph" << endl;
-    make_linear_morph_table( numShapes, time );
-  }
-  else {    // must be weighted...
-    // check first for expressions
-    softegg_cat.spam() << "expression morph" << endl;
-    make_expression_morph_table( numShapes, time );
-  }
-}
-
-/**
- * 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 SoftNodeDesc::
-make_linear_morph_table(int numShapes, PN_stdfloat time) {
-  int i;
-  PN_stdfloat curveVal;
-  char tableName[_MAX_PATH];
-  SAA_Elem fcurve;
-  // SAnimTable *thisTable;
-  EggSAnimData *anim;
-  SAA_Elem *model = get_model();
-  SAA_Scene *scene = &stec.scene;
-
-  softegg_cat.spam() << "linear interp, getting fcurve\n";
-
-  SAA_modelFcurveGetShape( scene, model, &fcurve );
-
-  SAA_fcurveEval( scene, &fcurve, time, &curveVal );
-
-  softegg_cat.spam() << "at time " << time << ", fcurve for " << get_name() << " = " << curveVal << endl;
-
-  PN_stdfloat nextVal = 0.0f;
-
-  // populate morph table values for this frame
-  for ( i = 1; i < numShapes; i++ ) {
-    // derive table name from the model name
-    sprintf(tableName, "%s.%d", get_name().c_str(), i);
-
-    softegg_cat.spam() << "Linear: looking for table '" << tableName << "'\n";
-
-    // find the morph table associated with this key shape
-    anim = stec.find_morph_table(tableName);
-
-    if ( anim != nullptr ) {
-      if ( i == (int)curveVal ) {
-        if ( curveVal - i == 0 ) {
-          anim->add_data(1.0f );
-          softegg_cat.spam() << "adding element 1.0f\n";
-        }
-        else {
-          anim->add_data(1.0f - (curveVal - i));
-          nextVal = curveVal - i;
-          softegg_cat.spam() << "adding element " << 1.0f - (curveVal - i) << endl;
-        }
-      }
-      else {
-        if ( nextVal ) {
-          anim->add_data(nextVal );
-          nextVal = 0.0f;
-          softegg_cat.spam() << "adding element " << nextVal << endl;
-        }
-        else {
-          anim->add_data(0.0f);
-          softegg_cat.spam() << "adding element 0.0f\n";
-        }
-      }
-
-      softegg_cat.spam() <<" to '" << tableName << "'\n";
-    }
-    else
-      softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
-  }
-}
-
-/**
- * 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 SoftNodeDesc::
-make_weighted_morph_table(int numShapes, PN_stdfloat time) {
-  PN_stdfloat curveVal;
-  SI_Error result;
-  char tableName[_MAX_PATH];
-  SAA_Elem *weightCurves;
-  // SAnimTable *thisTable;
-  EggSAnimData *anim;
-  SAA_Elem *model = get_model();
-  SAA_Scene *scene = &stec.scene;
-
-  // allocate array of weight curves (one for each shape)
-  weightCurves = new 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;
-
-      softegg_cat.spam() << "at time " << time << ", weightCurve[" << i << "] for " << get_name() << " = " << curveVal << endl;
-
-      // derive table name from the model name
-      sprintf(tableName, "%s.%d", get_name().c_str(), i);
-
-      // find and populate shape table
-      softegg_cat.spam() << "Weight: looking for table '" << tableName << "'\n";
-
-      // find the morph table associated with this key shape
-      anim = stec.find_morph_table(tableName);
-
-      if ( anim != nullptr ) {
-        anim->add_data(curveVal);
-        softegg_cat.spam() << "adding element " << curveVal << endl;
-      }
-      else
-        softegg_cat.spam() << i << " : Couldn't find table '" << tableName << "'\n";
-    }
-  }
-}
-
-/**
- * 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 SoftNodeDesc::
-make_expression_morph_table(int numShapes, PN_stdfloat time)
-{
-  // int j;
-  int numExp;
-  char *track;
-  // PN_stdfloat expVal; PN_stdfloat sliderVal; char *tableName; char
-  // *sliderName; SAnimTable *thisTable;
-  SAA_Elem *expressions;
-  SI_Error result;
-
-  SAA_Elem *model = get_model();
-  SAA_Scene *scene = &stec.scene;
-
-  // populate morph table values for this frame
-
-  // compose track name
-  track = nullptr;
-
-  // find how many expressions for this shape
-  SAA_elementGetNbExpressions( scene, model, track, FALSE, &numExp );
-
-  softegg_cat.spam() << get_name() << " has " << numExp << " RHS expressions\n";
-
-  if ( numExp ) {
-    // get the expressions for this shape
-    expressions = new SAA_Elem[numExp];
-    softegg_cat.spam() << "getting " << numExp << " RHS expressions...\n";
-
-    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
-                anim = (SAnimTable *)
-                    (morphRoot->FindDescendent( tableName ));
-
-                if ( anim != NULL )
-                {
-                    anim->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 {
-    softegg_cat.spam() << "weighted morph" << endl;
-    // no expression, use weight curves
-    make_weighted_morph_table(numShapes, time );
-  }
-}

+ 0 - 159
pandatool/src/softegg/softNodeDesc.h

@@ -1,159 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softNodeDesc.h
- * @author masad
- * @date 2003-10-03
- */
-
-#ifndef SOFTNODEDESC_H
-#define SOFTNODEDESC_H
-
-#ifdef _MIN
-#undef _MIN
-#endif
-#ifdef _MAX
-#undef _MAX
-#endif
-
-#include "pandatoolbase.h"
-
-#include "eggVertex.h"
-#include "eggVertexPool.h"
-#include "referenceCount.h"
-#include "pointerTo.h"
-#include "namable.h"
-
-#include <SAA.h>
-
-class EggGroup;
-class EggTable;
-class EggXfmSAnim;
-
-/**
- * Describes a single instance of a node aka element in the Soft scene graph,
- * relating it to the corresponding egg structures (e.g.  node, group, or
- * table entry) that will be created.
- */
-class SoftNodeDesc : public ReferenceCount, public Namable {
-public:
-  SoftNodeDesc(SoftNodeDesc *parent=nullptr, const std::string &name = std::string());
-  ~SoftNodeDesc();
-
-  void set_parent(SoftNodeDesc *parent);
-  void force_set_parent(SoftNodeDesc *parent);
-  void set_model(SAA_Elem *model);
-  bool has_model() const;
-  SAA_Elem *get_model() const;
-
-  bool is_joint() const;
-  bool is_junk() const;
-  void set_joint();
-  bool is_joint_parent() const;
-  bool is_partial(char *search_prefix);
-
-  SoftNodeDesc *_parent;
-  SoftNodeDesc *_parentJoint; // keep track of who is your parent joint
-  typedef pvector< PT(SoftNodeDesc) > Children;
-  Children _children;
-
-private:
-  void clear_egg();
-  void mark_joint_parent();
-  void check_joint_parent();
-  void check_junk(bool parent_junk);
-  void check_pseudo_joints(bool joint_above);
-
-  void set_parentJoint(SAA_Scene *scene, SoftNodeDesc *lastJoint);
-
-  SAA_ModelType type;
-
-  SAA_Elem *_model;
-
-  EggGroup *_egg_group;
-  EggTable *_egg_table;
-  EggXfmSAnim *_anim;
-
-  enum JointType {
-    JT_none,         // Not a joint.
-    JT_joint,        // An actual joint in Soft.
-    JT_pseudo_joint, // Not a joint in Soft, but treated just like a
-                     // joint for the purposes of the converter.
-    JT_joint_parent, // A parent or ancestor of a joint or pseudo joint.
-    JT_junk,         // originated from con-/fly-/car_rig/bars etc.
-  };
-  JointType _joint_type;
-
-public:
-
-  char **texNameArray;
-  int *uRepeat, *vRepeat;
-  PN_stdfloat matrix[4][4];
-
-  const char *fullname;
-
-  int numTri;
-  // int numShapes;
-  int numTexLoc;
-  int numTexGlb;
-  int *numTexTri;
-
-  // if the node is a MNSRF
-  int numNurbTexLoc;
-  int numNurbTexGlb;
-  int numNurbMats;
-
-  PN_stdfloat *uScale;
-  PN_stdfloat *vScale;
-  PN_stdfloat *uOffset;
-  PN_stdfloat *vOffset;
-
-  SAA_Boolean valid;
-  SAA_Boolean uv_swap;
-  // SAA_Boolean visible;
-  SAA_Elem *textures;
-  SAA_Elem *materials;
-  SAA_SubElem *triangles;
-  SAA_GeomType gtype;
-
-  EggGroup *get_egg_group()const {return _egg_group;}
-
-  void get_transform(SAA_Scene *scene, EggGroup *egg_group, bool global);
-  void get_joint_transform(SAA_Scene *scene, EggGroup *egg_group, EggXfmSAnim *anim, bool global);
-  void load_poly_model(SAA_Scene *scene, SAA_ModelType type);
-  void load_nurbs_model(SAA_Scene *scene, SAA_ModelType type);
-
-  void make_morph_table(PN_stdfloat time);
-  void make_linear_morph_table(int numShapes, PN_stdfloat time);
-  void make_weighted_morph_table(int numShapes, PN_stdfloat time);
-  void make_expression_morph_table(int numShapes, PN_stdfloat time);
-
-  void make_vertex_offsets(int numShapes);
-  int find_shape_vert(LPoint3d p3d, SAA_DVector *vertices, int numVert);
-
-  static TypeHandle get_class_type() {
-    return _type_handle;
-  }
-  static void init_type() {
-    ReferenceCount::init_type();
-    Namable::init_type();
-    register_type(_type_handle, "SoftNodeDesc",
-                  ReferenceCount::get_class_type(),
-                  Namable::get_class_type());
-  }
-
-private:
-  static TypeHandle _type_handle;
-
-  friend class SoftNodeTree;
-};
-
-class SoftToEggConverter;
-extern SoftToEggConverter stec;
-
-#endif

+ 0 - 561
pandatool/src/softegg/softNodeTree.cxx

@@ -1,561 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softNodeTree.cxx
- * @author masad
- * @date 2003-09-26
- */
-
-// Includes
-
-#include "softNodeTree.h"
-#include "softEggGroupUserData.h"
-#include "config_softegg.h"
-#include "eggGroup.h"
-#include "eggTable.h"
-#include "eggXfmSAnim.h"
-#include "eggData.h"
-#include "softToEggConverter.h"
-#include "dcast.h"
-
-#include <SAA.h>
-
-using std::endl;
-
-/**
- *
- */
-SoftNodeTree::
-SoftNodeTree() {
-  _root = new SoftNodeDesc(nullptr, "----root");
-  _root->fullname = "----root";
-  _fps = 0.0;
-  _use_prefix = 0;
-  _search_prefix = nullptr;
-  _egg_data = nullptr;
-  _egg_root = nullptr;
-  _skeleton_node = nullptr;
-}
-/**
- * Given an element, return a copy of the element's name WITHOUT prefix.
- */
-char *SoftNodeTree::
-GetName( SAA_Scene *scene, SAA_Elem *element ) {
-  int nameLen;
-  char *name;
-
-  // get the name
-  SAA_elementGetNameLength( scene, element, &nameLen );
-  name = new char[++nameLen];
-  SAA_elementGetName( scene, element, nameLen, name );
-
-  return name;
-}
-
-/**
- * Given an element, return a copy of the element's name complete with prefix.
- */
-char *SoftNodeTree::
-GetFullName( SAA_Scene *scene, SAA_Elem *element )
-{
-  int nameLen, prefixLen;
-  char *name, *prefix;
-
-  // get the name length
-  SAA_elementGetNameLength( scene, element, &nameLen );
-  // get the prefix length
-  SAA_elementGetPrefixLength( scene, element, &prefixLen );
-  // allocate the array to hold name
-  name = new char[++nameLen];
-  // allocate the array to hold prefix and length + hyphen
-  prefix = new char[++prefixLen + nameLen + 4];
-  // get the name
-  SAA_elementGetName( scene, element, nameLen, name );
-  // get the prefix
-  SAA_elementGetPrefix( scene, element, prefixLen, prefix );
-  // add 'em together
-  strcat(prefix, "-");
-  strcat(prefix, name);
-
-  // return string
-  return prefix;
-}
-
-/**
- * Given an element, return a string containing the contents of its MODEL NOTE
- * entry
- */
-char *SoftNodeTree::
-GetModelNoteInfo( SAA_Scene *scene, SAA_Elem *model ) {
-  int size;
-  char *modelNote = nullptr;
-  SAA_Boolean bigEndian;
-
-  SAA_elementGetUserDataSize( scene, model, "MNOT", &size );
-
-  if ( size != 0 ) {
-    // allocate modelNote string
-    modelNote = new 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 = (char *)memchr( modelNote, '\n', size );
-    if ( eol != nullptr)
-      *eol = '\0';
-    else
-      modelNote[size] = '\0';
-
-    softegg_cat.spam() << "\nmodelNote = " << modelNote << endl;
-  }
-
-  return modelNote;
-}
-
-/**
- * Given a string, return a copy of the string up to the first occurence of
- * '-'.
- */
-char *SoftNodeTree::
-GetRootName( const char *name ) {
-  const char *hyphen;
-  char *root;
-  int len;
-
-  hyphen = strchr( name, '-' );
-  len = hyphen-name;
-
-  if ( (hyphen != nullptr) && len ) {
-    root = new char[len+1];
-    strncpy( root, name, len );
-    root[len] = '\0';
-  }
-  else {
-    root = new char[strlen(name)+1];
-    strcpy( root, name );
-  }
-  return( root );
-}
-
-/**
- * Walks through the complete Soft hierarchy and builds up the corresponding
- * tree.
- */
-bool SoftNodeTree::
-build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database) {
-  SI_Error status;
-  SoftNodeDesc *node;
-
-  // Get the entire Soft scene.
-  int numModels;
-  SAA_Elem *models;
-
-  SAA_sceneGetNbModels( &scene, &numModels );
-  softegg_cat.spam() << "Scene has " << numModels << " model(s)...\n";
-
-  // This while loop walks through the entire Soft hierarchy, one node at a
-  // time.
-  bool all_ok = true;
-  if ( numModels ) {
-    // allocate array of models
-    models = (SAA_Elem *) new SAA_Elem[numModels];
-    if ( models != nullptr ) {
-      if ((status = SAA_sceneGetModels( &scene, numModels, models )) != SI_SUCCESS) {
-        return false;
-      }
-      for ( int i = 0; i < numModels; i++ ) {
-        int level;
-        status = SAA_elementGetHierarchyLevel( &scene, &models[i], &level );
-        softegg_cat.spam() << "model[" << i << "]" << endl;
-        softegg_cat.spam() << " level " << level << endl;
-        softegg_cat.spam() << " status is " << status << "\n";
-
-        node = build_node(&scene, &models[i]);
-        if (!level && node)
-          node->set_parent(_root);
-      }
-    }
-  }
-
-  softegg_cat.spam() << "jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\n";
-
-  // check the nodes that are junk for animationartist control purposes
-  _root->check_junk(false);
-
-  softegg_cat.spam() << "jpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjpjp\n";
-
-  // check the nodes that are parent of ancestors of a joint
-  _root->check_joint_parent();
-
-  softegg_cat.spam() << "pppppppppppppppppppppppppppppppppppppppppppppppppppppppp\n";
-
-  // check the nodes that are pseudo joints
-  _root->check_pseudo_joints(false);
-
-  softegg_cat.spam() << "========================================================\n";
-
-  // find _parentJoint for each node
-  _root->set_parentJoint(&scene, nullptr);
-
-  return all_ok;
-}
-#if 0
-/**
- * Walks through the selected subset of the Soft hierarchy (or the complete
- * hierarchy, if nothing is selected) and builds up the corresponding tree.
- */
-bool SoftNodeTree::
-build_selected_hierarchy(char *scene_name) {
-  MStatus status;
-
-  MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
-  if (!status) {
-    status.perror("MItDag constructor");
-    return false;
-  }
-
-  // Get only the selected geometry.
-  MSelectionList selection;
-  status = MGlobal::getActiveSelectionList(selection);
-  if (!status) {
-    status.perror("MGlobal::getActiveSelectionList");
-    return false;
-  }
-
-  // Get the selected geometry only if the selection is nonempty; otherwise,
-  // get the whole scene anyway.
-  if (selection.isEmpty()) {
-    softegg_cat.info()
-      << "Selection list is empty.\n";
-    return build_complete_hierarchy();
-  }
-
-  bool all_ok = true;
-  unsigned int length = selection.length();
-  for (unsigned int i = 0; i < length; i++) {
-    MDagPath root_path;
-    status = selection.getDagPath(i, root_path);
-    if (!status) {
-      status.perror("MSelectionList::getDagPath");
-    } else {
-      // Now traverse through the selected dag path and all nested dag paths.
-      dag_iterator.reset(root_path);
-      while (!dag_iterator.isDone()) {
-        MDagPath dag_path;
-        status = dag_iterator.getPath(dag_path);
-        if (!status) {
-          status.perror("MItDag::getPath");
-        } else {
-          build_node(dag_path);
-        }
-
-        dag_iterator.next();
-      }
-    }
-  }
-
-  if (all_ok) {
-    _root->check_pseudo_joints(false);
-  }
-
-  return all_ok;
-}
-#endif
-/**
- * Returns the total number of nodes in the hierarchy, not counting the root
- * node.
- */
-int SoftNodeTree::
-get_num_nodes() const {
-  return _nodes.size();
-}
-
-/**
- * Returns the nth node in the hierarchy, in an arbitrary ordering.
- */
-SoftNodeDesc *SoftNodeTree::
-get_node(int n) const {
-  nassertr(n >= 0 && n < (int)_nodes.size(), nullptr);
-  return _nodes[n];
-}
-
-/**
- * Returns the node named 'name' in the hierarchy, in an arbitrary ordering.
- */
-SoftNodeDesc *SoftNodeTree::
-get_node(std::string name) const {
-  NodesByName::const_iterator ni = _nodes_by_name.find(name);
-  if (ni != _nodes_by_name.end())
-    return (*ni).second;
-  return nullptr;
-}
-
-/**
- * Removes all of the references to generated egg structures from the tree,
- * and prepares the tree for generating new egg structures.
- */
-void SoftNodeTree::
-clear_egg(EggData *egg_data, EggGroupNode *egg_root,
-          EggGroupNode *skeleton_node) {
-  _root->clear_egg();
-  _egg_data = egg_data;
-  _egg_root = egg_root;
-  _skeleton_node = skeleton_node;
-}
-
-/**
- * Returns the EggGroupNode corresponding to the group or joint for the
- * indicated node.  Creates the group node if it has not already been created.
- */
-EggGroup *SoftNodeTree::
-get_egg_group(SoftNodeDesc *node_desc) {
-  nassertr(_egg_root != nullptr, nullptr);
-
-  // lets print some relationship
-  softegg_cat.spam() << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
-  if (node_desc->_parent)
-    softegg_cat.spam() << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
-  else
-    softegg_cat.spam() << " parent " << node_desc->_parent;
-  softegg_cat.spam() << endl;
-
-  if (node_desc->_egg_group == nullptr) {
-    // We need to make a new group node.
-    EggGroup *egg_group;
-
-    egg_group = new EggGroup(node_desc->get_name());
-    if (node_desc->is_joint()) {
-      egg_group->set_group_type(EggGroup::GT_joint);
-    }
-
-    if (stec.flatten || (!node_desc->_parentJoint || node_desc->_parentJoint == _root)) {
-      // The parent is the root.
-      softegg_cat.spam() << "came hereeeee\n";
-      _egg_root->add_child(egg_group);
-    } else {
-      // The parent is another node.
-      EggGroup *parent_egg_group = get_egg_group(node_desc->_parentJoint);
-      parent_egg_group->add_child(egg_group);
-    }
-
-    node_desc->_egg_group = egg_group;
-  }
-
-  return node_desc->_egg_group;
-}
-
-/**
- * Returns the EggTable corresponding to the joint for the indicated node.
- * Creates the table node if it has not already been created.
- */
-EggTable *SoftNodeTree::
-get_egg_table(SoftNodeDesc *node_desc) {
-  nassertr(_skeleton_node != nullptr, nullptr);
-  nassertr(node_desc->is_joint(), nullptr);
-
-  // lets print some relationship
-  softegg_cat.spam() << " group " << node_desc->get_name() << "(" << node_desc->_egg_group << ")";
-  if (node_desc->_parent)
-    softegg_cat.spam() << " parent " << node_desc->_parent->get_name() << "(" << node_desc->_parent << ")";
-  else
-    softegg_cat.spam() << " parent " << node_desc->_parent;
-  softegg_cat.spam() << endl;
-
-  if (node_desc->_egg_table == nullptr) {
-    softegg_cat.spam() << "creating a new table\n";
-    // We need to make a new table node.  nassertr(node_desc->_parent !=
-    // (SoftNodeDesc *)NULL, NULL);
-
-    EggTable *egg_table = new EggTable(node_desc->get_name());
-    node_desc->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system());
-    node_desc->_anim->set_fps(_fps);
-    egg_table->add_child(node_desc->_anim);
-
-    if (stec.flatten || (!node_desc->_parentJoint || node_desc->_parentJoint == _root)) {
-      // if (!node_desc->_parent->is_joint()) { The parent is not a joint; put
-      // it at the top.
-      _skeleton_node->add_child(egg_table);
-    } else {
-      // The parent is another joint.
-      EggTable *parent_egg_table = get_egg_table(node_desc->_parentJoint);
-      parent_egg_table->add_child(egg_table);
-    }
-
-    node_desc->_egg_table = egg_table;
-  }
-
-  return node_desc->_egg_table;
-}
-
-/**
- * Returns the anim table corresponding to the joint for the indicated node.
- * Creates the table node if it has not already been created.
- */
-EggXfmSAnim *SoftNodeTree::
-get_egg_anim(SoftNodeDesc *node_desc) {
-  get_egg_table(node_desc);
-  return node_desc->_anim;
-}
-
-/**
- * Sets joint information for MNILL node
- */
-void SoftNodeTree::
-handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, const char *node_name) {
-  const char *name = node_name;
-  SAA_AlgorithmType    algo;
-  SAA_Elem *model = node_desc->get_model();
-
-  SAA_modelGetAlgorithm( scene, model, &algo );
-  softegg_cat.spam() << " null algorithm: " << algo << endl;
-
-  if ( algo == SAA_ALG_INV_KIN ) {
-    // MakeJoint( &scene, lastJoint, lastAnim,  model, name );
-    node_desc->set_joint();
-    softegg_cat.spam() << " encountered IK root: " << name << endl;
-  }
-  else if ( algo == SAA_ALG_INV_KIN_LEAF ) {
-    // MakeJoint( &scene, lastJoint, lastAnim, model, name );
-    node_desc->set_joint();
-    softegg_cat.spam() << " encountered IK leaf: " << name << endl;
-  }
-  else if ( algo == SAA_ALG_STANDARD ) {
-    SAA_Boolean isSkeleton = FALSE;
-    softegg_cat.spam() << " encountered Standard null: " << name << endl;
-
-    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" ) != nullptr) ) {
-      // MakeJoint( &scene, lastJoint, lastAnim, model, name );
-      node_desc->set_joint();
-      softegg_cat.spam() << " animating Standard null!!!\n";
-      softegg_cat.spam() << "isSkeleton: " << isSkeleton << endl;
-    }
-  }
-  else
-    softegg_cat.spam() << " encountered some other NULL: " << algo << endl;
-}
-
-/**
- * Returns a pointer to the node corresponding to the indicated dag_path
- * object, creating it first if necessary.
- */
-SoftNodeDesc *SoftNodeTree::
-build_node(SAA_Scene *scene, SAA_Elem *model) {
-  char *name, *fullname;
-  std::string node_name;
-  int numChildren;
-  int thisChild;
-  SAA_Elem *children;
-  SAA_ModelType type;
-  SAA_Boolean isSkeleton = FALSE;
-
-  fullname = GetFullName(scene, model);
-  if (_use_prefix)
-    name = fullname;
-  else
-    name = GetName(scene, model);
-
-  node_name = name;
-
-  SoftNodeDesc *node_desc = r_build_node(nullptr, node_name);
-
-  node_desc->fullname = fullname;
-  node_desc->set_model(model);
-  SAA_modelIsSkeleton( scene, model, &isSkeleton );
-
-  // find out what type of node we're dealing with
-  SAA_modelGetType( scene, node_desc->get_model(), &type );
-
-  if (type == SAA_MJNT || isSkeleton || (strstr(node_desc->get_name().c_str(), "joint") != nullptr))
-    node_desc->set_joint();
-
-  // treat the MNILL differently, because it needs to detect and set some
-  // joints
-  if (type == SAA_MNILL)
-    handle_null(scene, node_desc, name);
-
-  if (node_desc->is_joint())
-    softegg_cat.spam() << "type: " << type << " isSkeleton: " << isSkeleton << endl;
-
-  // get to the children
-  SAA_modelGetNbChildren( scene, model, &numChildren );
-  softegg_cat.spam() << " Model " << node_name << " children: " << numChildren << endl;
-
-  if ( numChildren ) {
-    children = new SAA_Elem[numChildren];
-    SAA_modelGetChildren( scene, model, numChildren, children );
-    if (!children)
-      softegg_cat.info() << "Not enough Memory for children...\n";
-
-    for ( thisChild = 0; thisChild < numChildren; thisChild++ ) {
-      fullname = GetFullName(scene, &children[thisChild]);
-      if (_use_prefix)
-        node_name = fullname;
-      else
-        node_name = GetName(scene, &children[thisChild]);
-
-      softegg_cat.spam() << " building child " << thisChild << "...";
-
-      SoftNodeDesc *node_child = r_build_node(node_desc, node_name);
-
-      node_child->fullname = fullname;
-      node_child->set_model(&children[thisChild]);
-      SAA_modelIsSkeleton( scene, &children[thisChild], &isSkeleton );
-
-      // find out what type of node we're dealing with
-      SAA_modelGetType( scene, node_child->get_model(), &type );
-
-      if (type == SAA_MJNT || isSkeleton || (strstr(node_child->get_name().c_str(), "joint") != nullptr))
-        node_child->set_joint();
-
-      // treat the MNILL differently, because it needs to detect and set some
-      // joints
-      if (type == SAA_MNILL)
-        handle_null(scene, node_child, node_name.c_str());
-
-      if (node_child->is_joint())
-        softegg_cat.spam() << "type: " << type << " isSkeleton: " << isSkeleton << endl;
-    }
-  }
-  return node_desc;
-}
-
-/**
- * The recursive implementation of build_node().
- */
-SoftNodeDesc *SoftNodeTree::
-r_build_node(SoftNodeDesc *parent_node, const std::string &name) {
-  SoftNodeDesc *node_desc;
-
-  // If we have already encountered this pathname, return the corresponding
-  // SoftNodeDesc immediately.
-  NodesByName::const_iterator ni = _nodes_by_name.find(name);
-  if (ni != _nodes_by_name.end()) {
-    softegg_cat.spam() << "  already built node " << (*ni).first;
-    node_desc = (*ni).second;
-    node_desc->set_parent(parent_node);
-    return node_desc;
-  }
-
-  // Otherwise, we have to create it.  Do this recursively, so we create each
-  // node along the path.
-  node_desc = new SoftNodeDesc(parent_node, name);
-
-  softegg_cat.spam() << " node name : " << name << endl;
-  _nodes.push_back(node_desc);
-
-  _nodes_by_name.insert(NodesByName::value_type(name, node_desc));
-
-  return node_desc;
-}

+ 0 - 78
pandatool/src/softegg/softNodeTree.h

@@ -1,78 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softNodeTree.h
- * @author masad
- * @date 2003-10-03
- */
-
-#ifndef SOFTNODETREE_H
-#define SOFTNODETREE_H
-
-#include "pandatoolbase.h"
-#include "softNodeDesc.h"
-
-#include <SAA.h>
-
-class EggGroup;
-class EggTable;
-class EggXfmSAnim;
-class EggData;
-class EggGroupNode;
-
-
-/**
- * Describes a complete tree of soft nodes for conversion.
- */
-class SoftNodeTree {
-public:
-  SoftNodeTree();
-  SoftNodeDesc *build_node(SAA_Scene *scene, SAA_Elem *model);
-  bool build_complete_hierarchy(SAA_Scene &scene, SAA_Database &database);
-  void handle_null(SAA_Scene *scene, SoftNodeDesc *node_desc, const char *node_name);
-  // bool build_selected_hierarchy(SAA_Scene *s, SAA_Database *d, char
-  // *scene_name);
-
-  int get_num_nodes() const;
-  SoftNodeDesc *get_node(int n) const;
-  SoftNodeDesc *get_node(std::string name) const;
-
-  char *GetRootName(const char *);
-  char *GetModelNoteInfo(SAA_Scene *, SAA_Elem *);
-  char *GetName(SAA_Scene *scene, SAA_Elem *element);
-  char *GetFullName(SAA_Scene *scene, SAA_Elem *element);
-
-  EggGroupNode *get_egg_root() {return _egg_root;}
-  EggGroup *get_egg_group(SoftNodeDesc *node_desc);
-  EggTable *get_egg_table(SoftNodeDesc *node_desc);
-  EggXfmSAnim *get_egg_anim(SoftNodeDesc *node_desc);
-
-  void clear_egg(EggData *egg_data, EggGroupNode *egg_root, EggGroupNode *skeleton_node);
-
-  PT(SoftNodeDesc) _root;
-  PN_stdfloat _fps;
-  int _use_prefix;
-  char *_search_prefix;
-
-
-private:
-
-  EggData *_egg_data;
-  EggGroupNode *_egg_root;
-  EggGroupNode *_skeleton_node;
-
-  SoftNodeDesc *r_build_node(SoftNodeDesc *parent_node, const std::string &path);
-
-  typedef pmap<std::string, SoftNodeDesc *> NodesByName;
-  NodesByName _nodes_by_name;
-
-  typedef pvector<SoftNodeDesc *> Nodes;
-  Nodes _nodes;
-};
-
-#endif

+ 0 - 2122
pandatool/src/softegg/softToEggConverter.cxx

@@ -1,2122 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softToEggConverter.cxx
- * @author masad
- * @date 2003-09-25
- */
-
-#include "softToEggConverter.h"
-#include "config_softegg.h"
-#include "softEggGroupUserData.h"
-
-#include "eggData.h"
-#include "eggGroup.h"
-#include "eggTable.h"
-#include "eggVertex.h"
-#include "eggComment.h"
-#include "eggVertexPool.h"
-#include "eggNurbsSurface.h"
-#include "eggNurbsCurve.h"
-#include "eggPolygon.h"
-#include "eggPrimitive.h"
-#include "eggTexture.h"
-#include "eggTextureCollection.h"
-#include "eggXfmSAnim.h"
-#include "eggSAnimData.h"
-#include "string_utils.h"
-#include "dcast.h"
-
-using std::endl;
-using std::string;
-
-SoftToEggConverter stec;
-
-const int    TEX_PER_MAT = 1;
-
-/**
- *
- */
-SoftToEggConverter::
-SoftToEggConverter(const string &program_name) :
-  _program_name(program_name)
-{
-  _from_selection = false;
-  _polygon_output = false;
-  _polygon_tolerance = 0.01;
-  /*
-  _respect_maya_double_sided = maya_default_double_sided;
-  _always_show_vertex_color = maya_default_vertex_color;
-  */
-  _transform_type = TT_model;
-
-  database_name = nullptr;
-  scene_name = nullptr;
-  model_name = nullptr;
-  animFileName = nullptr;
-  eggFileName = nullptr;
-  tex_path = nullptr;
-  eggGroupName = nullptr;
-  tex_filename = nullptr;
-  search_prefix = nullptr;
-  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;
-}
-
-/**
- *
- */
-SoftToEggConverter::
-SoftToEggConverter(const SoftToEggConverter &copy) :
-  _from_selection(copy._from_selection),
-  /*
-  _maya(copy._maya),
-  */
-  _polygon_output(copy._polygon_output),
-  _polygon_tolerance(copy._polygon_tolerance),
-  /*
-  _respect_maya_double_sided(copy._respect_maya_double_sided),
-  _always_show_vertex_color(copy._always_show_vertex_color),
-  */
-  _transform_type(copy._transform_type)
-{
-}
-
-/**
- *
- */
-SoftToEggConverter::
-~SoftToEggConverter() {
-  /*
-  close_api();
-  */
-}
-/**
- * Displays the "what is this program" message, along with the usage message.
- * Should be overridden in base classes to describe the current program.
- */
-void SoftToEggConverter::
-Help()
-{
-    softegg_cat.info() <<
-      "soft2egg takes a SoftImage scene or model\n"
-      "and outputs its contents as an egg file\n";
-
-    Usage();
-}
-
-/**
- * Displays the usage message.
- */
-void SoftToEggConverter::
-Usage() {
-  softegg_cat.info()
-    << "\nUsage:\n"
-    // << _commandName << " [opts] (must specify -m or -s)\n\n"
-    << "soft" << " [opts] (must specify -m or -s)\n\n"
-    << "Options:\n";
-
-  ShowOpts();
-  softegg_cat.info() << "\n";
-}
-
-/**
- * Displays the valid options.  Should be extended in base classes to show
- * additional options relevant to the current program.
- */
-void SoftToEggConverter::
-ShowOpts()
-{
-  softegg_cat.info() <<
-    "  -r <path>  - Used to provide soft with the resource\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();
-}
-
-/**
- * Calls getopt() to parse the command-line switches.  Calls HandleGetopts()
- * to interpret each switch.  Returns true if the parsing was successful;
- * false if there was an error.  Adjusts argc and argv to remove the switches
- * from the parameter list.
- */
-bool SoftToEggConverter::
-DoGetopts(int &argc, char **&argv) {
-  bool okflag = true;
-  int i = 0;
-  softegg_cat.info() << "argc " << argc << "\n";
-  if (argc <2) {
-    Usage();
-    okflag = false;
-  }
-  while( i < argc ) {
-    strcat(_commandLine, argv[i]);
-    strcat(_commandLine, " ");
-    ++i;
-  }
-  softegg_cat.info() << endl << _commandLine << endl;
-
-  i = 1;
-  while ((i < argc) && (argv[i][0] == '-') && okflag) {
-    softegg_cat.info() << "arg " << i << " is " << argv[i] << "\n";
-    okflag = HandleGetopts(i, argc, argv);
-  }
-  return okflag;
-}
-
-/**
- * increment idx based on what kind of option parsed Supported options are as
- * follows: r:d:s:m:t:P:b:e:f:T:S:M:A:N:v:o:FhknpaxiucCD
- */
-bool SoftToEggConverter::
-HandleGetopts(int &idx, int argc, char **argv)
-{
-  bool okflag = true;
-
-  char flag = argv[idx][1];    // skip the '-' from option
-
-  switch (flag)
-    {
-    case 'r':       // Set the resource path for soft.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        // Get the path.
-        rsrc_path = argv[idx+1];
-        softegg_cat.info() << "using rsrc path " << rsrc_path << "\n";
-      }
-      ++idx;
-      break;
-
-    case 'd':       // Set the database path.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        // Get the path.
-        database_name = argv[idx+1];
-        softegg_cat.info() << "using database " << database_name << "\n";
-      }
-      ++idx;
-      break;
-
-    case 's':     // Check if its a scene.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        // Get scene name.
-        scene_name = argv[idx+1];
-        softegg_cat.info() << "loading scene " << scene_name << "\n";
-      }
-      ++idx;
-      break;
-
-    case 'm':     // Check if its a model.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        // Get model name.
-        model_name = argv[idx+1];
-        softegg_cat.info() << "loading model " <<  model_name << endl;
-      }
-      ++idx;
-      break;
-
-    case 't':     // Get converted texture path.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        // Get tex path name.
-        tex_path = argv[idx+1];
-        softegg_cat.info() << "texture path:  " << tex_path << endl;
-      }
-      ++idx;
-      break;
-
-    case 'T':      // Specify texture list filename.
-      if ( strcmp( argv[idx+1], "") ) {
-        // Get the name.
-        tex_filename = argv[idx+1];
-        softegg_cat.info() << "creating texture list file: " << tex_filename << endl;
-      }
-      ++idx;
-      break;
-
-    case 'S':     // Set NURBS step.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        nurbs_step = atoi(argv[idx+1]);
-        softegg_cat.info() << "NURBS step:  " << nurbs_step << endl;
-      }
-      ++idx;
-      break;
-
-    case 'M':     // Set model output file name.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        eggFileName = argv[idx+1];
-        softegg_cat.info() << "Model output filename:  " << eggFileName << endl;
-      }
-      ++idx;
-      break;
-
-    case 'A':     // Set anim output file name.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        animFileName = argv[idx+1];
-        softegg_cat.info() << "Anim output filename:  " << animFileName << endl;
-      }
-      ++idx;
-      break;
-
-    case 'N':     // Set egg model name.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        eggGroupName = argv[idx+1];
-        softegg_cat.info() << "Egg group name:  " << eggGroupName << endl;
-      }
-      ++idx;
-      break;
-
-    case 'o':     // Set search_prefix.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        search_prefix = argv[idx+1];
-        softegg_cat.info() << "Only converting models with prefix:  " << search_prefix << endl;
-      }
-      ++idx;
-      break;
-
-    case 'h':    // print help message
-      Help();
-      exit(1);
-      break;
-
-    case 'c':    // Cancel morph animation conversion
-      make_morph = FALSE;
-      softegg_cat.info() << "canceling morph conversion\n";
-      break;
-
-    case 'C':    // Cancel uv animation conversion
-      make_duv = FALSE;
-      softegg_cat.info() << "canceling uv animation conversion\n";
-      break;
-
-    case 'D':    // Omit the Dart flag
-      make_dart = FALSE;
-      softegg_cat.info() << "making a non-character model\n";
-      break;
-
-    case 'k':    // Enable soft skinning
-      // make_soft = TRUE; fprintf( outStream, "enabling soft skinning\n" );
-      softegg_cat.info() << "-k flag no longer necessary\n";
-      break;
-
-    case 'n':    // Generate egg NURBS output
-      make_nurbs = TRUE;
-      softegg_cat.info() << "outputting egg NURBS info\n";
-      break;
-
-    case 'p':    // Generate egg polygon output
-      make_poly = TRUE;
-      softegg_cat.info() << "outputting egg polygon info\n";
-      break;
-
-    case 'P':    // Generate static pose from given frame
-      if ( strcmp( argv[idx+1], "" ) ) {
-        make_pose = TRUE;
-        pose_frame = atoi(argv[idx+1]);
-        softegg_cat.info() << "generating static pose from frame " << pose_frame << endl;
-      }
-      ++idx;
-      break;
-
-    case 'a':     // Compile animation tables.
-      make_anim = TRUE;
-      softegg_cat.info() << "attempting to compile anim tables\n";
-      break;
-
-    case 'F':     // Build a flat skeleton.
-      flatten = TRUE;
-      softegg_cat.info() << "building a flat skeleton!!!\n";
-      break;
-
-    case 'x':     // Shift NURBS parameters to preserve Alias textures.
-      shift_textures = TRUE;
-      softegg_cat.info() << "shifting NURBS parameters...\n";
-      break;
-
-    case 'i':     // Ignore Soft uv texture offsets
-      ignore_tex_offsets = TRUE;
-      softegg_cat.info() << "ignoring texture offsets...\n";
-      break;
-
-    case 'u':     // Use Soft prefix in model names
-      use_prefix = TRUE;
-      softegg_cat.info() << "using prefix in model names...\n";
-      break;
-
-
-    case 'v':     // print debug messages.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        verbose = atoi(argv[idx+1]);
-        softegg_cat.info() << "using debug level " << verbose << endl;
-      }
-      ++idx;
-      break;
-
-    case 'b':     // Set animation start frame.
-      anim_start = atoi(argv[idx]+2);
-      softegg_cat.info() << "animation starting at frame:  " << anim_start << endl;
-      break;
-
-    case 'e':     /// Set animation end frame.
-      anim_end = atoi(argv[idx]+2);
-      softegg_cat.info() << "animation ending at frame:  " << anim_end << endl;
-      break;
-
-    case 'f':     /// Set animation frame rate.
-      if ( strcmp( argv[idx+1], "" ) ) {
-        anim_rate = atoi(argv[idx+1]);
-        softegg_cat.info() << "animation frame rate:  " << anim_rate << endl;
-      }
-      ++idx;
-      break;
-
-    default:
-      softegg_cat.info() << flag << " flag not supported\n";
-      okflag = false;
-    }
-  idx++;
-  return (okflag);
-}
-
-/**
- * Allocates and returns a new copy of the converter.
- */
-SomethingToEggConverter *SoftToEggConverter::
-make_copy() {
-  return new SoftToEggConverter(*this);
-}
-
-/**
- * Returns the English name of the file type this converter supports.
- */
-string SoftToEggConverter::
-get_name() const {
-  return "Soft";
-}
-
-/**
- * Returns the common extension of the file type this converter supports.
- */
-string SoftToEggConverter::
-get_extension() const {
-  return "mb";
-}
-
-/**
- * Returns the English name of the file type this converter supports.
- */
-SoftNodeDesc *SoftToEggConverter::
-find_node(string name) {
-  return _tree.get_node(name);
-}
-
-/**
- * Given a texture element, return texture name with given tex_path
- */
-char *SoftToEggConverter::
-GetTextureName( SAA_Scene *scene, SAA_Elem *texture ) {
-  char *fileName = new char[_MAX_PATH];
-  char tempName[_MAX_PATH];
-  SAA_texture2DGetPicName( scene, texture, _MAX_PATH, tempName );
-
-  if (tex_path) {
-    // softegg_cat.spam() << "tempName :" << tempName << endl;
-    strcpy(fileName, tex_path);
-
-    // do some processing on the name string
-    char *tmpName = nullptr;
-    tmpName = strrchr(tempName, '/');
-    if (tmpName)
-      tmpName++;
-    else
-      tmpName = tempName;
-
-    // softegg_cat.spam() << "tmpName : " << tmpName << endl;
-    strcat(fileName, "/");
-    strcat(fileName, tmpName);
-  }
-  else {
-    strcpy(fileName, tempName);
-  }
-
-  strcat(fileName, ".pic");
-  // softegg_cat.spam() << "fileName : " << fileName << endl;
-
-  return fileName;
-}
-
-/**
- * Handles the reading of the input file and converting it to egg.  Returns
- * true if successful, false otherwise.
- *
- * This is designed to be as generic as possible, generally in support of run-
- * time loading.  Also see convert_soft().
- */
-bool SoftToEggConverter::
-convert_file(const Filename &filename) {
-  if (!open_api()) {
-    softegg_cat.error()
-      << "Soft is not available.\n";
-    return false;
-  }
-  if (_character_name.empty()) {
-    _character_name = filename.get_basename_wo_extension();
-  }
-  return convert_soft(false);
-}
-
-/**
- * Fills up the egg_data structure according to the global soft model data.
- * Returns true if successful, false if there is an error.  If from_selection
- * is true, the converted geometry is based on that which is selected;
- * otherwise, it is the entire Soft scene.
- */
-bool SoftToEggConverter::
-convert_soft(bool from_selection) {
-  bool all_ok = true;
-
-  _from_selection = from_selection;
-  _textures.clear();
-
-  PT(EggData) egg_data = new EggData;
-  set_egg_data(egg_data);
-  softegg_cat.spam() << "eggData " << get_egg_data() << "\n";
-
-  // append the command line
-  softegg_cat.info() << _commandLine << endl;
-  get_egg_data()->insert(get_egg_data()->begin(), new EggComment("", _commandLine));
-
-  if (_egg_data->get_coordinate_system() != CS_default) {
-    softegg_cat.spam() << "coordinate system is not default\n";
-    exit(1);
-  }
-
-  _tree._use_prefix = use_prefix;
-  _tree._search_prefix = search_prefix;
-  all_ok = _tree.build_complete_hierarchy(scene, database);
-
-  // Lets see if we have gotten the hierarchy right _tree.print_hierarchy();
-  // exit(1);
-
-  char *root_name = _tree.GetRootName( eggFileName );
-
-  softegg_cat.debug() << "main group name: " << root_name << endl;
-  if (root_name)
-    _character_name = root_name;
-
-  if (make_poly || make_nurbs) {
-    // Specify that the texture names should be relative to the output file.
-    Filename output_filename(eggFileName);
-    _path_replace->_path_store = PS_relative;
-    _path_replace->_path_directory = output_filename.get_dirname();
-
-    if (!convert_char_model()) {
-      all_ok = false;
-    }
-
-    // generate soft skinning assignments if desired
-    if (!make_soft_skin()) {
-      all_ok = false;
-    }
-
-    // sometimes you need to hard assign some vertices
-    if (!cleanup_soft_skin()) {
-      all_ok = false;
-    }
-
-    // reparent_decals(get_egg_data());
-    softegg_cat.info() << "Converted Softimage file\n";
-
-    // write out the egg model file
-    _egg_data->write_egg(output_filename);
-    softegg_cat.info() << "Wrote Egg file " << output_filename << endl;
-  }
-  if (make_anim) {
-    if (!convert_char_chan()) {
-      all_ok = false;
-    }
-
-    // reparent_decals(get_egg_data());
-    softegg_cat.info() << "Converted Softimage file\n";
-
-    // write out the egg model file
-    _egg_data->write_egg(Filename(animFileName));
-    softegg_cat.info() << "Wrote Anim file " << animFileName << endl;
-  }
-  return all_ok;
-}
-
-/**
- * Attempts to open the Soft API if it was not already open, and returns true
- * if successful, or false if there is an error.
- */
-bool SoftToEggConverter::
-open_api() {
-  if ((scene_name == nullptr && model_name == nullptr) || database_name == nullptr) {
-    Usage();
-    exit( 1 );
-  }
-  if ((result = SAA_Init(rsrc_path, FALSE)) != SI_SUCCESS) {
-    softegg_cat.info() << "Error: Couldn't get resource path!\n";
-    exit( 1 );
-  }
-  // cout << "got past init" << endl;
-  if ((result = SAA_databaseLoad(database_name, &database)) != SI_SUCCESS) {
-    softegg_cat.info() << "Error: Couldn't load database!\n";
-    exit( 1 );
-  }
-  // cout << "got past database load" << endl;
-  if ((result = SAA_sceneGetCurrent(&scene)) != SI_SUCCESS) {
-    softegg_cat.info() << "Error: Couldn't get current scene!\n";
-    exit( 1 );
-  }
-  // cout << "got past get current" << endl;
-  if ((result = SAA_sceneLoad( &database, scene_name, &scene )) != SI_SUCCESS) {
-    softegg_cat.info() << "Error: Couldn't load scene " << scene_name << "!\n";
-    exit( 1 );
-  }
-  // cout << "got past scene load" << endl;
-  if ( SAA_updatelistGet( &scene ) == SI_SUCCESS ) {
-    PN_stdfloat time;
-
-    softegg_cat.info() << "setting Scene to frame " << pose_frame << "...\n";
-    // SAA_sceneSetPlayCtrlCurrentFrame( &scene, pose_frame );
-    SAA_frame2Seconds( &scene, pose_frame, &time );
-    SAA_updatelistEvalScene( &scene, time );
-    if ( make_pose )
-      SAA_sceneFreeze(&scene);
-  }
-
-  // if no egg filename specified, make up a name
-  if ( eggFileName == nullptr ) {
-    string madeName;
-    string tempName(scene_name);
-    string::size_type end = tempName.find(".dsc");
-    if (end != string::npos) {
-      madeName.assign(tempName.substr(0,end));
-      if ( make_nurbs )
-        madeName.insert(madeName.size(), "-nurb");
-      madeName.insert(madeName.size(), ".egg" );
-    }
-    eggFileName = new char[madeName.size()+1];
-    strcpy(eggFileName, madeName.c_str());
-
-    // if no anim filename specified, make up a name
-    if ( animFileName == nullptr ) {
-      madeName.assign(tempName.substr(0,end));
-      madeName.insert(madeName.size(), "-chan.egg");
-      animFileName = new char[strlen(scene_name)+ 10];
-      strcpy(animFileName, madeName.c_str());
-    }
-  }
-
-  return true;
-}
-
-/**
- * Closes the Soft API, if it was previously opened.  Caution!  Soft appears
- * to call exit() when its API is closed.
- */
-void SoftToEggConverter::
-close_api() {
-  // don't know yet
-}
-
-/**
- * Converts the file as an animatable character model, with joints and vertex
- * membership.
- */
-bool SoftToEggConverter::
-convert_char_model() {
-  softegg_cat.spam() << "character name " << _character_name << "\n";
-  EggGroup *char_node = new EggGroup(eggGroupName);
-  get_egg_data()->add_child(char_node);
-  char_node->set_dart_type(EggGroup::DT_default);
-
-  return convert_hierarchy(char_node);
-}
-
-/**
- * Given a tablename, it either creates a new eggSAnimData structure (if
- * doesn't exist) or locates it.
- */
-EggSAnimData *SoftToEggConverter::
-find_morph_table(char *name) {
-  EggSAnimData *anim = nullptr;
-  MorphTable::iterator mt;
-  for (mt = _morph_table.begin(); mt != _morph_table.end(); ++mt) {
-    anim = (*mt);
-    if (!strcmp(anim->get_name().c_str(), name))
-      return anim;
-  }
-
-  // create an entry
-  anim = new EggSAnimData(name);
-  anim->set_fps(_tree._fps);
-  _morph_table.push_back(anim);
-  morph_node->add_child(anim);
-  return anim;
-}
-
-/**
- * Converts the animation as a series of tables to apply to the character
- * model, as retrieved earlier via AC_model.
- */
-bool SoftToEggConverter::
-convert_char_chan() {
-  int start_frame = -1;
-  int end_frame = -1;
-  int frame_inc, frame;
-  double output_frame_rate = anim_rate;
-
-  PN_stdfloat time;
-
-  EggTable *root_table_node = new EggTable();
-  get_egg_data()->add_child(root_table_node);
-  EggTable *bundle_node = new EggTable(eggGroupName);
-  bundle_node->set_table_type(EggTable::TT_bundle);
-  root_table_node->add_child(bundle_node);
-  EggTable *skeleton_node = new EggTable("<skeleton>");
-  bundle_node->add_child(skeleton_node);
-
-  morph_node = new EggTable("morph");
-
-  // Set the frame rate before we start asking for anim tables to be created.
-  SAA_sceneGetPlayCtrlStartFrame(&scene, &start_frame);
-  SAA_sceneGetPlayCtrlEndFrame(&scene, &end_frame);
-  SAA_sceneGetPlayCtrlFrameStep( &scene, &frame_inc );
-  if (frame_inc != 1) // Hmmm...some files gave me frame_inc of 0, that can't be good
-    frame_inc = 1;
-
-  softegg_cat.info() << "animation start frame: " << start_frame << " end frame: " << end_frame << endl;
-  softegg_cat.info() << "animation frame inc: " << frame_inc << endl;
-
-  _tree._fps = output_frame_rate / frame_inc;
-  // _tree.clear_egg(get_egg_data(), NULL, root_node);
-  _tree.clear_egg(get_egg_data(), nullptr, skeleton_node);
-
-  // Now we can get the animation data by walking through all of the frames,
-  // one at a time, and getting the joint angles at each frame.
-
-  // This is just a temporary EggGroup to receive the transform for each joint
-  // each frame.
-  PT(EggGroup) tgroup = new EggGroup;
-
-  int num_nodes = _tree.get_num_nodes();
-  int i;
-
-  // MTime frame(start_frame, MTime::uiUnit()); MTime frame_stop(end_frame,
-  // MTime::uiUnit()); start at first frame and go to last
-  if (make_pose) {
-    start_frame = pose_frame;
-    end_frame = pose_frame;
-  }
-  if (anim_start > 0)
-    start_frame = anim_start;
-  if (anim_end > 0)
-    end_frame = anim_end;
-  for ( frame = start_frame; frame <= end_frame; frame += frame_inc) {
-    SAA_frame2Seconds( &scene, frame, &time );
-    // softegg_cat.spam() << "got time " << time << endl;
-    if (!make_pose) {
-      SAA_updatelistEvalScene( &scene, time );
-    }
-    softegg_cat.spam() << "\n> animating frame " << frame << endl;
-
-    // if (softegg_cat.is_debug()) { softegg_cat.debug(false)
-    softegg_cat.info() << "frame " << time << "\n";
-    // } else { We have to write to cerr instead of softegg_cat to allow
-    // flushing without writing a newline.  std::cerr << "." << std::flush; }
-    // MGlobal::viewFrame(frame);
-
-    for (i = 0; i < num_nodes; i++) {
-      SoftNodeDesc *node_desc = _tree.get_node(i);
-
-      if (node_desc->is_partial(search_prefix)) {
-        softegg_cat.debug() << endl;
-        continue;
-      }
-      if (make_morph) {
-        node_desc->make_morph_table(time);
-      }
-      if (node_desc->is_joint()) {
-        softegg_cat.spam() << "-----joint " << node_desc->get_name() << "\n";
-        EggXfmSAnim *anim = _tree.get_egg_anim(node_desc);
-        // following function fills in the anim structure
-        node_desc->get_joint_transform(&scene, tgroup, anim, TRUE);
-      }
-    }
-
-    // frame += frame_inc;
-  }
-
-  if (has_morph)
-    bundle_node->add_child(morph_node);
-
-  // Now optimize all of the tables we just filled up, for no real good
-  // reason, except that it makes the resulting egg file a little easier to
-  // read.
-  for (i = 0; i < num_nodes; i++) {
-    SoftNodeDesc *node_desc = _tree.get_node(i);
-    if (node_desc->is_partial(search_prefix))
-      continue;
-
-    if (node_desc->is_joint()) {
-      _tree.get_egg_anim(node_desc)->optimize();
-    }
-  }
-
-  softegg_cat.info(false)
-    << "\n";
-
-  return true;
-}
-
-/**
- * Generates egg structures for each node in the Soft hierarchy.
- */
-bool SoftToEggConverter::
-convert_hierarchy(EggGroupNode *egg_root) {
-  int num_nodes = _tree.get_num_nodes();
-
-  _tree.clear_egg(get_egg_data(), egg_root, nullptr);
-  softegg_cat.spam() << "num_nodes = " << num_nodes << endl;
-  for (int i = 0; i < num_nodes; i++) {
-    if (!process_model_node(_tree.get_node(i))) {
-      return false;
-    }
-    softegg_cat.debug() << i << endl;
-  }
-  return true;
-}
-
-/**
- * Converts the indicated Soft node (given a MDagPath, similar in concept to
- * Panda's NodePath) to the corresponding Egg structure.  Returns true if
- * successful, false if an error was encountered.
- */
-bool SoftToEggConverter::
-process_model_node(SoftNodeDesc *node_desc) {
-  EggGroup *egg_group = nullptr;
-  const char *name = nullptr;
-  char *fullname = nullptr;
-  SAA_ModelType type;
-
-  name = node_desc->get_name().c_str();
-  softegg_cat.debug() << "element name <" << name << ">\n";
-
-  if (node_desc->is_junk()) {
-    softegg_cat.spam() << "no processing, it is junk\n";
-    return true;
-  }
-
-  // split
-  if (node_desc->is_partial(search_prefix)) {
-    softegg_cat.debug() << endl;
-    return true;
-  }
-  else
-    softegg_cat.debug() << endl << name << ":being processed" << endl;
-
-  egg_group = _tree.get_egg_group(node_desc);
-
-  // find out what type of node we're dealing with
-  SAA_modelGetType( &scene, node_desc->get_model(), &type );
-
-  softegg_cat.debug() << "encountered ";
-  switch(type){
-  case SAA_MNILL:
-    softegg_cat.debug() << "null\n";
-    break;
-  case SAA_MPTCH:
-    softegg_cat.debug() << "patch\n";
-    break;
-  case SAA_MFACE:
-    softegg_cat.debug() << "face\n";
-    // break;
-  case SAA_MSMSH:
-    softegg_cat.debug() << "mesh\n";
-    node_desc->get_transform(&scene, egg_group, TRUE);
-    make_polyset(node_desc, egg_group, type);
-    break;
-  case SAA_MJNT:
-    softegg_cat.debug() << "joint";
-    softegg_cat.debug() << " joint type " << node_desc->is_joint() << endl;
-    break;
-  case SAA_MSPLN:
-    softegg_cat.debug() << "spline\n";
-    break;
-  case SAA_MMETA:
-    softegg_cat.debug() << "meta element\n";
-    break;
-  case SAA_MBALL:
-    softegg_cat.debug() << "meta ball\n";
-    break;
-  case SAA_MNCRV:
-    softegg_cat.debug() << "nurbs curve\n";
-    break;
-  case SAA_MNSRF:
-    softegg_cat.debug() << "nurbs surf\n";
-    node_desc->get_transform(&scene, egg_group, TRUE);
-    make_nurb_surface(node_desc, egg_group, type);
-    break;
-  default:
-    softegg_cat.debug() << "unknown type: " << type << "\n";
-  }
-
-  if (node_desc->is_joint())
-    node_desc->get_transform(&scene, egg_group, FALSE);
-
-  return true;
-}
-
-/**
- * Converts the indicated Soft polyset to a bunch of EggPolygons and parents
- * them to the indicated egg group.
- */
-void SoftToEggConverter::
-make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type) {
-  int id = 0;
-  int i, idx;
-  int numShapes;
-  SAA_Boolean valid;
-  SAA_Boolean visible;
-  PN_stdfloat *uCoords = nullptr;
-  PN_stdfloat *vCoords = nullptr;
-  string name = node_desc->get_name();
-
-  SAA_modelGetNodeVisibility( &scene, node_desc->get_model(), &visible );
-  softegg_cat.spam() << "model visibility: " << visible << endl;
-
-  // 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 )) ))
-       )
-    {
-      // Get the number of key shapes
-      SAA_modelGetNbShapes( &scene, node_desc->get_model(), &numShapes );
-      softegg_cat.spam() << "process_model_node: num shapes: " << numShapes << endl;
-
-      // load all node data from soft for this node_desc
-      node_desc->load_poly_model(&scene, type);
-
-      string vpool_name = name + ".verts";
-      EggVertexPool *vpool = new EggVertexPool(vpool_name);
-      vpool->set_highest_index(0);
-
-      // add the vertices in the _tree._root node, so that they will be
-      // written out first in egg file.  This solves a problem of soft-
-      // skinning trying to access vertex pool before it is defined.
-
-      _tree.get_egg_root()->insert(_tree.get_egg_root()->begin(), vpool);
-
-      // We will need to transform all vertices from world coordinate space
-      // into the vertex space appropriate to this node.  Usually, this is the
-      // same thing as world coordinate space, and this matrix will be
-      // identity; but if the node is under an instance (particularly, for
-      // instance, a billboard) then the vertex space will be different from
-      // world space.
-      LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
-
-      // Asad: change from soft2egg.c.  Here I am trying to get one triangles
-      // vertices not all
-      for (idx=0; idx<node_desc->numTri; ++idx) {
-        EggPolygon *egg_poly = new EggPolygon;
-        egg_group->add_child(egg_poly);
-
-        softegg_cat.spam() << "processing polygon " << idx << endl;
-
-        // Is this a double sided polygon?  meaning check for back face flag
-        char *modelNoteStr = _tree.GetModelNoteInfo( &scene, node_desc->get_model() );
-        if ( modelNoteStr != nullptr ) {
-          if ( strstr( modelNoteStr, "bface" ) != nullptr )
-            egg_poly->set_bface_flag(TRUE);
-        }
-
-        // read each triangle's control vertices into array
-        SAA_SubElem cvertices[3];
-        SAA_triangleGetCtrlVertices( &scene, node_desc->get_model(), node_desc->gtype, id, 1, node_desc->triangles+idx, cvertices );
-
-        // read control vertices in this triangle
-        SAA_DVector cvertPos[3];
-        SAA_ctrlVertexGetPositions( &scene, node_desc->get_model(), 3, cvertices, cvertPos);
-
-        // read indices of each vertices in this triangle
-        int indices[3];
-        indices[0] = indices[1] = indices[2] = 0;
-        SAA_ctrlVertexGetIndices( &scene, node_desc->get_model(), 3, cvertices, indices );
-
-        // read each control vertex's normals into an array
-        SAA_DVector normals[3];
-        SAA_ctrlVertexGetNormals( &scene, node_desc->get_model(), 3, cvertices, normals );
-        for (i=0; i<3; ++i)
-          softegg_cat.spam() << "normals[" << i <<"] = " << normals[i].x << " " <<  normals[i].y
-               << " " << normals[i].z << " " <<  normals[i].w << "\n";
-
-        // allocate arrays for u & v coords
-        if (node_desc->textures) {
-          if (node_desc->numTexLoc && node_desc->numTexTri[idx]) {
-            // allocate arrays for u & v coords I think there are one texture
-            // per triangle hence we need only 3 corrdinates
-            uCoords = new PN_stdfloat[3];
-            vCoords = new PN_stdfloat[3];
-
-            // read the u & v coords into the arrays
-            if ( uCoords != nullptr && vCoords != nullptr) {
-              for ( i = 0; i < 3; i++ )
-                uCoords[i] = vCoords[i] = 0.0f;
-
-              // TODO: investigate the coord_cnt parameter...
-              SAA_ctrlVertexGetUVTxtCoords( &scene, node_desc->get_model(), 3, cvertices,
-                                            3, uCoords, vCoords );
-            }
-            else
-              softegg_cat.info() << "Not enough Memory for texture coords...\n";
-
-#if 1
-            for ( i=0; i<3; i++ )
-              softegg_cat.spam() << "texcoords[" << i << "] = ( " << uCoords[i] << " , " << vCoords[i] <<" )\n";
-#endif
-          }
-          else if (node_desc->numTexGlb) {
-            // allocate arrays for u & v coords
-            uCoords = new PN_stdfloat[node_desc->numTexGlb*3];
-            vCoords = new PN_stdfloat[node_desc->numTexGlb*3];
-
-            for ( i = 0; i < node_desc->numTexGlb*3; i++ ) {
-              uCoords[i] = vCoords[i] = 0.0f;
-            }
-
-            // read the u & v coords into the arrays
-            if ( uCoords != nullptr && vCoords != nullptr) {
-              SAA_triCtrlVertexGetGlobalUVTxtCoords( &scene, node_desc->get_model(), 3, cvertices,
-                                                     node_desc->numTexGlb, node_desc->textures, uCoords, vCoords );
-            }
-            else
-              softegg_cat.info() << "Not enough Memory for texture coords...\n";
-          }
-        }
-
-        for ( i=0; i < 3; i++ ) {
-          EggVertex vert;
-
-          // There are some conversions needed from local matrix to global
-          // coords
-          SAA_DVector local = cvertPos[i];
-          SAA_DVector global = {0};
-
-          _VCT_X_MAT( global, local, node_desc->matrix );
-
-          softegg_cat.spam() << "indices[" << i << "] = " << indices[i] << "\n";
-          softegg_cat.spam() << "cvert[" << i << "] = " << cvertPos[i].x << " " << cvertPos[i].y
-                              << " " << cvertPos[i].z << " " << cvertPos[i].w << "\n";
-          softegg_cat.spam() << " global cvert[" << i << "] = " << global.x << " " << global.y
-                              << " " << global.z << " " << global.w << "\n";
-
-          // LPoint3d p3d(cvertPos[i].x, cvertPos[i].y, cvertPos[i].z);
-          LPoint3d p3d(global.x, global.y, global.z);
-          p3d = p3d * vertex_frame_inv;
-          vert.set_pos(p3d);
-
-          local = normals[i];
-          _VCT_X_MAT( global, local, node_desc->matrix );
-
-          softegg_cat.spam() << "normals[" << i <<"] = " << normals[i].x << " " <<  normals[i].y
-               << " " << normals[i].z << " " <<  normals[i].w << "\n";
-          softegg_cat.spam() << " global normals[" << i <<"] = " << global.x << " " <<  global.y
-               << " " << global.z << " " <<  global.w << "\n";
-
-          LVector3d n3d(global.x, global.y, global.z);
-          n3d = n3d * vertex_frame_inv;
-          vert.set_normal(n3d);
-
-          // if texture present set the texture coordinates
-          if (node_desc->textures) {
-            PN_stdfloat u, v;
-
-            if (uCoords && vCoords) {
-              u = uCoords[i];
-              v = 1.0f - vCoords[i];
-              softegg_cat.spam() << "texcoords[" << i << "] = " << u << " "
-                                 << v << endl;
-
-              vert.set_uv(LTexCoordd(u, v));
-              // vert.set_uv(LTexCoordd(uCoords[i], vCoords[i]));
-            }
-          }
-          vert.set_external_index(indices[i]);
-          egg_poly->add_vertex(vpool->create_unique_vertex(vert));
-
-          // check to see if material is present
-          PN_stdfloat r,g,b,a;
-          SAA_elementIsValid( &scene, &node_desc->materials[idx], &valid );
-          // material present - get the color
-          if ( valid ) {
-            SAA_materialGetDiffuse( &scene, &node_desc->materials[idx], &r, &g, &b );
-            SAA_materialGetTransparency( &scene, &node_desc->materials[idx], &a );
-            egg_poly->set_color(LColor(r, g, b, 1.0f - a));
-            softegg_cat.spam() << "color r = " << r << " g = " << g << " b = " << b << " a = " << 1.0f - a << "\n";
-          }
-          else {     // no material - default to white
-            egg_poly->set_color(LColor(1.0, 1.0, 1.0, 1.0));
-            softegg_cat.spam() << "default color\n";
-          }
-
-          /*
-          // keep a one to one copy in this node's vpool
-          EggVertex *t_vert = new EggVertex(vert);
-          if (!t_vert) {
-            softegg_cat.spam() << "out of memeory " << endl;
-            nassertv(t_vert != NULL);
-          }
-          node_desc->get_vpool()->add_vertex(t_vert, indices[i]);
-          */
-
-          softegg_cat.spam() << "\n";
-        }
-
-        // Now apply the shader.
-        if (node_desc->textures != nullptr) {
-          if (node_desc->numTexLoc && node_desc->numTexTri[idx]) {
-            if (!strstr(node_desc->texNameArray[idx], "noIcon"))
-              set_shader_attributes(node_desc, *egg_poly, idx);
-            else
-              softegg_cat.spam() << "texname :" << node_desc->texNameArray[idx] << endl;
-          }
-          else {
-            if (!strstr(node_desc->texNameArray[0], "noIcon"))
-              set_shader_attributes(node_desc, *egg_poly, 0);
-            else
-              softegg_cat.spam() << "texname :" << node_desc->texNameArray[0] << endl;
-        }
-      }
-      }
-      // if model has key shapes, generate vertex offsets
-      if ( numShapes > 0 && make_morph )
-        node_desc->make_vertex_offsets( numShapes);
-    }
-}
-
-/**
- * Converts the indicated Soft nurbs set to a bunch of EggPolygons and parents
- * them to the indicated egg group.
- */
-void SoftToEggConverter::
-make_nurb_surface(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type) {
-  int id = 0;
-  int i, j, k;
-  int numShapes;
-  SAA_Boolean valid;
-  SAA_Boolean visible;
-  PN_stdfloat *uCoords = nullptr;
-  PN_stdfloat *vCoords = nullptr;
-  string name = node_desc->get_name();
-
-  SAA_modelGetNodeVisibility( &scene, node_desc->get_model(), &visible );
-  softegg_cat.spam() << "model visibility: " << visible << endl;
-  softegg_cat.spam() << "nurbs!!!surface!!!" << endl;
-
-  // check to see if its a nurbs surface
-  if ( (type == SAA_MNSRF) && ( visible ) && (( make_nurbs )
-                                              || ( !make_nurbs && !make_poly &&  make_duv )) )
-    {
-      // Get the number of key shapes
-      SAA_modelGetNbShapes( &scene, node_desc->get_model(), &numShapes );
-      softegg_cat.spam() << "process_model_node: num shapes: " << numShapes << endl;
-
-      // load all node data from soft for this node_desc
-      node_desc->load_nurbs_model(&scene, type);
-
-      string vpool_name = name + ".verts";
-      EggVertexPool *vpool = new EggVertexPool(vpool_name);
-      vpool->set_highest_index(0);
-
-      // add the vertices in the _tree._egg_root node, so that they will be
-      // written out first in egg file.  This solves a problem of soft-
-      // skinning trying to access vertex pool before it is defined.
-
-      // _tree.get_egg_root()->add_child(vpool);
-      _tree.get_egg_root()->insert(_tree.get_egg_root()->begin(), vpool);
-
-      // egg_group->add_child(vpool);
-
-      /*
-      // create a copy of vpool in node_desc which will be used later for
-      // soft_skinning
-      node_desc->create_vpool(vpool_name);
-      */
-
-      int uRows, vRows;
-      int uKnots, vKnots;
-      int uExtra, vExtra;
-      int uDegree, vDegree;
-      int uCurves, vCurves;
-
-      vector <double> Knots;
-
-      EggNurbsSurface *eggNurbs = new EggNurbsSurface( name );
-
-      // create nurbs representation of surface
-      SAA_nurbsSurfaceGetDegree( &scene, node_desc->get_model(), &uDegree, &vDegree );
-      softegg_cat.spam() << "nurbs degree: " << uDegree << " u, " << vDegree << " v\n";
-
-      SAA_nurbsSurfaceGetNbKnots( &scene, node_desc->get_model(), &uKnots, &vKnots );
-      softegg_cat.spam() << "nurbs knots: " << uKnots << " u, " << vKnots << " v\n";
-
-      SAA_Boolean uClosed = FALSE;
-      SAA_Boolean vClosed = FALSE;
-
-      SAA_nurbsSurfaceGetClosed( &scene, node_desc->get_model(), &uClosed, &vClosed);
-
-      uExtra = vExtra = 2;
-      if ( uClosed ) {
-        softegg_cat.spam() << "nurbs is closed in u...\n";
-        uExtra += 4;
-      }
-      if ( vClosed ) {
-        softegg_cat.spam() << "nurbs is closed in v...\n";
-        vExtra += 4;
-      }
-      eggNurbs->setup(uDegree+1, vDegree+1,
-                      uKnots + uExtra, vKnots + vExtra);
-
-      softegg_cat.spam() << "from eggNurbs: num u knots " << eggNurbs->get_num_u_knots() << endl;
-      softegg_cat.spam() << "from eggNurbs: num v knots " << eggNurbs->get_num_v_knots() << endl;
-      softegg_cat.spam() << "from eggNurbs: num u cvs " << eggNurbs->get_num_u_cvs() << endl;
-      softegg_cat.spam() << "from eggNurbs: num v cvs " << eggNurbs->get_num_v_cvs() << endl;
-
-      SAA_nurbsSurfaceGetNbVertices( &scene, node_desc->get_model(), &uRows, &vRows );
-      softegg_cat.spam() << "nurbs vertices: " << uRows << " u, " << vRows << " v\n";
-
-      SAA_nurbsSurfaceGetNbCurves( &scene, node_desc->get_model(), &uCurves, &vCurves );
-      softegg_cat.spam() << "nurbs curves: " << uCurves << " u, " << vCurves << " v\n";
-
-      if ( shift_textures ) {
-        if ( uClosed )
-          // shift starting point on NURBS surface for correct textures
-          SAA_nurbsSurfaceShiftParameterization( &scene, node_desc->get_model(), -2, 0 );
-
-        if ( vClosed )
-          // shift starting point on NURBS surface for correct textures
-          SAA_nurbsSurfaceShiftParameterization( &scene, node_desc->get_model(), 0, -2 );
-      }
-
-      SAA_nurbsSurfaceSetStep( &scene, node_desc->get_model(), nurbs_step, nurbs_step );
-
-      // Is this a double sided polygon?  meaning check for back face flag
-      char *modelNoteStr = _tree.GetModelNoteInfo( &scene, node_desc->get_model() );
-      if ( modelNoteStr != nullptr ) {
-        if ( strstr( modelNoteStr, "bface" ) != nullptr ) {
-          eggNurbs->set_bface_flag(TRUE);
-          softegg_cat.spam() << "Set backface flag\n";
-        }
-      }
-
-      double *uKnotArray = new double[uKnots];
-      double *vKnotArray = new double[vKnots];
-      result = SAA_nurbsSurfaceGetKnots( &scene, node_desc->get_model(), node_desc->gtype, 0,
-                                         uKnots, vKnots, uKnotArray, vKnotArray );
-
-      if (result != SI_SUCCESS) {
-        softegg_cat.spam() << "Couldn't get knots\n";
-        exit(1);
-      }
-
-      // Lets prepare the softimage knots and then assign to eggKnots
-      add_knots( Knots, uKnotArray, uKnots, uClosed, uDegree );
-      softegg_cat.spam() << "u knots: ";
-      for (i = 0; i < (int)Knots.size(); i++) {
-        softegg_cat.spam() << Knots[i] << " ";
-        eggNurbs->set_u_knot(i, Knots[i]);
-      }
-      softegg_cat.spam() << endl;
-
-      Knots.resize(0);
-      add_knots( Knots, vKnotArray, vKnots, vClosed, vDegree );
-      softegg_cat.spam() << "v knots: ";
-      for (i = 0; i < (int)Knots.size(); i++) {
-        softegg_cat.spam() << Knots[i] << " ";
-        eggNurbs->set_v_knot(i, Knots[i]);
-      }
-      softegg_cat.spam() << endl;
-
-      // lets get the number of vertices from softimage
-      int numVert;
-      SAA_modelGetNbVertices( &scene, node_desc->get_model(), &numVert );
-
-      softegg_cat.spam() << numVert << " CV's\n";
-
-      // get the CV's
-      SAA_DVector *vertices = nullptr;
-      vertices = new SAA_DVector[numVert];
-
-      SAA_modelGetVertices( &scene, node_desc->get_model(), node_desc->gtype, 0, numVert, vertices );
-
-      LMatrix4d vertex_frame_inv = egg_group->get_vertex_frame_inv();
-
-      // create the buffer for EggVertices
-      EggVertex *verts = new EggVertex[numVert];
-
-      softegg_cat.spam() << endl << eggNurbs->get_num_cvs() << endl << endl;
-
-      // for ( i = 0; i<eggNurbs->get_num_cvs(); i++ ) {
-      for ( k = 0; k<numVert; k++ ) {
-        SAA_DVector global;
-
-        /*
-        int ui = eggNurbs->get_u_index(i);
-        int vi = eggNurbs->get_v_index(i);
-
-        int k = vRows * ui + vi;
-
-        softegg_cat.spam() << i << ": ui " << ui << ", vi " << vi << ", k " << k << endl;
-
-        softegg_cat.spam() << "original cv[" << k << "] = "
-             << vertices[k].x << " " << vertices[k].y << " "
-             << vertices[k].z << " " << vertices[k].w << endl;
-        */
-
-        // convert to global coords
-        _VCT_X_MAT( global, vertices[k], node_desc->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;
-
-        /*
-        softegg_cat.spam() << "global cv[" << k << "] = "
-             << global.x << " " << global.y << " "
-             << global.x << " " << global.w << endl;
-        */
-
-        LPoint4d p4d(global.x, global.y, global.z, global.w);
-        p4d = p4d * vertex_frame_inv;
-        verts[k].set_pos(p4d);
-
-        // check to see if material is present
-        if (node_desc->numNurbMats) {
-          PN_stdfloat r,g,b,a;
-          SAA_elementIsValid( &scene, &node_desc->materials[0], &valid );
-          // material present - get the color
-          if ( valid ) {
-            SAA_materialGetDiffuse( &scene, &node_desc->materials[0], &r, &g, &b );
-            SAA_materialGetTransparency( &scene, &node_desc->materials[0], &a );
-            verts[k].set_color(LColor(r, g, b, 1.0f - a));
-            // softegg_cat.spam() << "color r = " << r << " g = " << g << " b
-            // = " << b << " a = " << a << "\n";
-          }
-          else {     // no material - default to white
-            verts[k].set_color(LColor(1.0, 1.0, 1.0, 1.0));
-            softegg_cat.spam() << "default color\n";
-          }
-        }
-        vpool->add_vertex(verts+k, k);
-        eggNurbs->add_vertex(vpool->get_vertex(k));
-
-        if ( uClosed ) {
-          // add first uDegree verts to end of row
-          if ( (k % uRows) == ( uRows - 1) ) {
-            for ( i = 0; i < uDegree; i++ ) {
-              // add vref's to NURBS info
-              eggNurbs->add_vertex( vpool->get_vertex(i+((k/uRows)*uRows)) );
-            }
-          }
-        }
-      }
-
-      // 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++ )
-          eggNurbs->add_vertex( vpool->get_vertex(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++ )
-            eggNurbs->add_vertex( vpool->get_vertex(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++ )
-            eggNurbs->add_vertex( vpool->get_vertex(k+(i*uRows)+((k/uRows)*uRows)) );
-        }
-      }
-
-      // We add the NURBS to the group down here, after all of the vpools for
-      // the trim curves have been added.
-      egg_group->add_child(eggNurbs);
-
-      // Now apply the shader.
-      if (node_desc->textures != nullptr) {
-        if (!strstr(node_desc->texNameArray[0], "noIcon"))
-          set_shader_attributes(node_desc, *eggNurbs, 0);
-        else
-          softegg_cat.spam() << "texname :" << node_desc->texNameArray[0] << endl;
-      }
-
-      // if model has key shapes, generate vertex offsets
-      if ( numShapes > 0 && make_morph )
-        node_desc->make_vertex_offsets( numShapes);
-    }
-}
-
-/**
- * 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 SoftToEggConverter::
-add_knots( 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 = new 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] );
-      softegg_cat.spam() << "knots[" << k << "] = " << newKnots[k] << endl;
-    }
-  }
-  else {
-    eggKnots.push_back( knots[k] );
-    softegg_cat.spam() << "knots[" << k << "] = " << knots[k] << endl;
-  }
-
-  // add the regular complement of knots
-  for (k = 0; k < numKnots; k++) {
-    eggKnots.push_back( knots[k] );
-    softegg_cat.spam() << "knots[" << k+1 << "] = " << knots[k] << endl;
-  }
-
-  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]) );
-      softegg_cat.spam() << "knots[" << k << "] = " << lastKnot + (knots[k] - knots[k-1]) << endl;
-      lastKnot = lastKnot + (knots[k] - knots[k-1]);
-    }
-  }
-  else {
-    eggKnots.push_back( knots[k-1] );
-    softegg_cat.spam() << "knots[" << k+1 << "] = " << knots[k-1] << endl;
-  }
-}
-
-/**
- * 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 *SoftToEggConverter::
-FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert ) {
-  int i,j;
-  int *vertMap = nullptr;
-  int vpoolSize = (int)vpool->size();
-  PN_stdfloat closestDist;
-  PN_stdfloat thisDist;
-  int closest;
-
-  vertMap = new int[vpoolSize];
-  i = 0;
-  EggVertexPool::iterator vi;
-  for (vi = vpool->begin(); vi != vpool->end(); ++vi, ++i) {
-    EggVertex *vert = (*vi);
-    softegg_cat.spam() << "vert external index = " << vert->get_external_index() << endl;
-    // softegg_cat.spam() << "found vert " << vert << endl; softegg_cat.spam()
-    // << "vert [" << i << "] " << vpool->get_vertex(i+1);
-    LPoint3d p3d = vert->get_pos3();
-
-    // find closest model vertex
-    for ( j = 0; j < numVert; j++ ) {
-      // calculate distance
-      thisDist = sqrtf(
-                       powf( p3d[0] - vertices[j].x , 2 ) +
-                       powf( p3d[1] - vertices[j].y , 2 ) +
-                       powf( p3d[2] - vertices[j].z , 2 ) );
-
-      // remember this if its the closest so far
-      if ( !j || ( thisDist < closestDist ) ) {
-        closest = j;
-        closestDist = thisDist;
-      }
-    }
-
-    vertMap[i] = closest;
-    softegg_cat.spam() << "mapping v " << i << " of " << vpoolSize-1 << ":( "
-                       << p3d[0] << " "
-                       << p3d[1] << " "
-                       << p3d[2] << ")\n";
-
-    softegg_cat.spam() << "    to cv " << closest << " of " << numVert-1 << ":( "
-                       << vertices[closest].x << " "
-                       << vertices[closest].y << " "
-                       << vertices[closest].z << " )\tdelta = " << closestDist << endl;
-  }
-  return vertMap;
-}
-
-/**
- * make soft skin assignments to the mesh finally call cleanup_soft_skin to
- * clean it up
- */
-bool SoftToEggConverter::
-make_soft_skin() {
-  int num_nodes = _tree.get_num_nodes();
-  SoftNodeDesc *node_desc;
-  SAA_Boolean isSkeleton;
-
-  softegg_cat.spam() << endl << "----------------------------------------------------------------" << endl;
-
-  for (int i = 0; i < num_nodes; i++) {
-    node_desc = _tree.get_node(i);
-    SAA_modelIsSkeleton( &scene, node_desc->get_model(), &isSkeleton );
-
-    softegg_cat.spam() << "??checking node " << node_desc->get_name() << " isSkel " << isSkeleton << " isJoint " << node_desc->is_joint() << endl;
-    if (isSkeleton && node_desc->is_joint()) {
-
-      if (node_desc->is_partial(search_prefix))
-          continue;
-
-      // Now that we've added all the polygons (and created all the vertices),
-      // go back through the vertex pool and set up the appropriate joint
-      // membership for each of the vertices.
-
-      // check for envelops
-      int numEnv;
-      SAA_ModelType type;
-      SAA_Elem *envelopes;
-      SAA_Elem *model = node_desc->get_model();
-      EggGroup *joint = nullptr;
-      EggVertexPool *vpool;
-
-      SAA_skeletonGetNbEnvelopes( &scene, model, &numEnv );
-      if ( numEnv == 0 ) {
-        softegg_cat.spam() << "no soft skinning for joint " << node_desc->get_name() << endl;
-        continue;
-      }
-
-      // it's got envelopes - must be soft skinned
-      softegg_cat.spam() << endl << "found skeleton part( " << node_desc->get_name() << ")!\n";
-      softegg_cat.spam() << "numEnv = " << numEnv << endl;
-      // allocate envelope array
-      envelopes = new SAA_Elem[numEnv];
-      if ( envelopes == nullptr ) {
-        softegg_cat.info() << "Out Of Memory" << endl;
-        exit(1);
-      }
-      int thisEnv;
-      SAA_EnvType envType;
-      bool hasEnvVertices = 0;
-
-      SAA_skeletonGetEnvelopes( &scene, model, numEnv, envelopes );
-      for ( thisEnv = 0; thisEnv < numEnv; thisEnv++ ) {
-        softegg_cat.spam() << "env[" << thisEnv << "]: ";
-        SAA_envelopeGetType( &scene, &envelopes[thisEnv], &envType );
-
-        if ( envType == SAA_ENVTYPE_NONE ) {
-          softegg_cat.spam() << "envType = none\n";
-        }
-        else if ( envType == SAA_ENVTYPE_FLXLCL ) {
-          softegg_cat.spam() << "envType = flexible, local\n";
-          hasEnvVertices = 1;
-        }
-        else if ( envType == SAA_ENVTYPE_FLXGLB ) {
-          softegg_cat.spam() << "envType = flexible, global\n";
-          hasEnvVertices = 1;
-        }
-        else if ( envType == SAA_ENVTYPE_RGDGLB ) {
-          softegg_cat.spam() << "envType = rigid, global\n";
-          hasEnvVertices = 1;
-        }
-        else {
-          softegg_cat.spam() << "envType = unknown\n";
-        }
-
-      }
-      if ( !hasEnvVertices )
-        continue;
-
-      SAA_SubElem *envVertices = nullptr;
-      int *numEnvVertices;
-      int i,j,k;
-
-      numEnvVertices = new int[numEnv];
-
-      if ( numEnvVertices != nullptr ) {
-        SAA_envelopeGetNbCtrlVertices( &scene, model, numEnv, envelopes, numEnvVertices );
-        int totalEnvVertices = 0;
-        for( i = 0; i < numEnv; i++ ) {
-          totalEnvVertices += numEnvVertices[i];
-          softegg_cat.spam() << "numEnvVertices[" << i << "] = " << numEnvVertices[i] << endl;
-        }
-        softegg_cat.spam() << "total env verts = " << totalEnvVertices << endl;
-        if ( totalEnvVertices == 0 )
-          continue;
-
-        envVertices = new SAA_SubElem[totalEnvVertices];
-        if ( envVertices != nullptr ) {
-          result = SAA_envelopeGetCtrlVertices( &scene, model,
-                                                numEnv, envelopes, numEnvVertices, envVertices);
-          if (result != SI_SUCCESS) {
-            softegg_cat.spam() << "error: GetCtrlVertices\n";
-            exit(1);
-          }
-          // loop through for each envelope
-          for ( i = 0; i < numEnv; i++ ) {
-            PN_stdfloat *weights = nullptr;
-            int vertArrayOffset = 0;
-            softegg_cat.spam() << "envelope[" << i << "]: ";
-            weights = new PN_stdfloat[numEnvVertices[i]];
-            if ( weights ) {
-              char *envName;
-              int *vpoolMap = nullptr;
-              for ( j = 0; j < i; j++ )
-                vertArrayOffset += numEnvVertices[j];
-              softegg_cat.spam() << "envVertArray offset = " << vertArrayOffset;
-
-              /*
-              if (vertArrayOffset == totalEnvVertices) {
-                softegg_cat.spam() << endl;                  vpoolMap = FindClosestTriVert( vpool, globalModelVertices, modelNumVert );
-
-                break;
-              }
-              */
-
-              // get the weights of the envelope vertices
-              result = 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 = _tree.GetFullName( &scene, &envelopes[i] );
-              }
-              else {
-                // Get the name of the envelope
-                envName = _tree.GetName( &scene, &envelopes[i] );
-              }
-
-              softegg_cat.spam() << " envelop name is [" << envName << "]" << endl;
-
-              if (result != SI_SUCCESS) {
-                softegg_cat.spam() << "warning: this envelop doesn't have any weights\n";
-                continue;
-              }
-
-              result = SAA_modelGetType( &scene, &envelopes[i], &type );
-              if (result != SI_SUCCESS) {
-                softegg_cat.debug() << "choked on get type\n";
-                exit(1);
-              }
-
-              softegg_cat.spam() << "envelope model type ";
-              if ( type == SAA_MSMSH )
-                softegg_cat.spam() << "MESH\n";
-              else if ( type == SAA_MNSRF )
-                softegg_cat.spam() << "NURBS\n";
-              else
-                softegg_cat.spam() << "OTHER\n";
-
-              int *envVtxIndices = nullptr;
-              envVtxIndices = new int[numEnvVertices[i]];
-
-              // Get the envelope vertex indices
-              result = SAA_ctrlVertexGetIndices( &scene, &envelopes[i], numEnvVertices[i],
-                                                 &envVertices[vertArrayOffset], envVtxIndices );
-
-              if (result != SI_SUCCESS) {
-                softegg_cat.debug() << "error: choked on get indices\n";
-                exit(1);
-              }
-
-              // find out how many vertices the model has
-              int modelNumVert;
-
-              SAA_modelGetNbVertices( &scene, &envelopes[i], &modelNumVert );
-
-              SAA_DVector *modelVertices = nullptr;
-              modelVertices = new 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 = nullptr;
-              globalModelVertices = new SAA_DVector[modelNumVert];
-              PN_stdfloat 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 );
-              }
-
-              // Get the vpool
-              string s_name = envName;
-              SoftNodeDesc *mesh_node = find_node(s_name);
-              if (!mesh_node) {
-                softegg_cat.debug() << "error: node " << s_name << " not found in tree\n";
-                exit(1);
-              }
-              string vpool_name = s_name + ".verts";
-              EggNode *t = _tree.get_egg_root()->find_child(vpool_name);
-              if (t)
-                DCAST_INTO_R(vpool, t, nullptr);
-
-              // find the mapping of the vertices that match this envelop
-              if (vpool) {
-                softegg_cat.spam() << "found vpool of size " << vpool->size() << endl;
-                if ( !make_nurbs || (type == SAA_MSMSH) ) {
-                  vpoolMap = FindClosestTriVert( vpool, globalModelVertices, modelNumVert );
-                }
-              }
-              else {
-                softegg_cat.debug() << "warning: vpool " << vpool_name << " not found\n";
-                continue; // could be because of not visible
-              }
-
-              joint = node_desc->get_egg_group();
-              // 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
-                    EggVertex *vert = vpool->get_vertex(envVtxIndices[j]);
-                    if (!vert) {
-                      softegg_cat.debug() << "possible error: index " << envVtxIndices[j] << ": vert is " << vert << endl;
-                      continue;
-                    }
-                    joint->ref_vertex( vert, scaledWeight );
-                    softegg_cat.spam() << j << ": adding vref to cv " << envVtxIndices[j]
-                         << " with weight " << scaledWeight << endl;
-
-                    /*
-                    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
-                    softegg_cat.spam() << j << "--trying to find " << envVtxIndices[j] << endl;
-                    for ( k = 0; k < (int)vpool->size(); k++ ) {
-                      if ( vpoolMap[k] == envVtxIndices[j] ) {
-                        EggVertex *vert = vpool->get_vertex(k+1);
-                        // EggVertex *vert =
-                        // mesh_node->get_vpool()->get_vertex(vpoolMap[k]+1);
-                        if (!vert) {
-                          softegg_cat.debug() << "possible error: index " << k+1 << ": vert is " << vert << endl;
-                          break;
-                        }
-
-                        joint->ref_vertex(vert, scaledWeight);
-                        softegg_cat.spam() << j << ": adding vref from cv " << envVtxIndices[j]
-                             << " to vert " << k+1 << " with weight " << scaledWeight
-                             << "(vpool)\n";
-                        /*
-                          envPool->Vertex(k)->AddJoint( joint, scaledWeight );
-                          // set flag to show this vertex has been assigned
-                          envPool->Vertex(k)->multipleJoints = 1;
-                        */
-                      }
-                    }
-                  }
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-  return true;
-}
-/**
- * Given a model, make sure all its vertices have been soft assigned.  If not
- * hard assign to the last joint we saw.
- */
-bool SoftToEggConverter::
-cleanup_soft_skin()
-{
-  int num_nodes = _tree.get_num_nodes();
-  SoftNodeDesc *node_desc;
-
-  softegg_cat.spam() << endl << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl;
-
-  for (int i = 0; i < num_nodes; i++) {
-    node_desc = _tree.get_node(i);
-    if (node_desc->is_partial(search_prefix))
-      continue;
-
-    SAA_Elem *model = node_desc->get_model();
-    EggGroup *joint = nullptr;
-    EggVertexPool *vpool = nullptr;
-    SAA_ModelType type;
-
-    // find out what type of node we're dealing with
-
-    SAA_modelGetType( &scene, model, &type );
-
-    softegg_cat.debug() << "Cleaning up model------- " << node_desc->get_name() << endl;
-
-    // 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
-    // fulrndpubvrmlchipchips_adventurecharzone1roomswarehouse_final need to
-    // do the "if (skel)" bit.
-
-    // find the vpool for this model
-    string vpool_name = node_desc->get_name() + ".verts";
-    EggNode *t = _tree.get_egg_root()->find_child(vpool_name);
-    if (t)
-      DCAST_INTO_R(vpool, t, nullptr);
-
-    if (!vpool) {
-      // softegg_cat.spam() << "couldn't find vpool " << vpool_name << endl;
-      continue;
-    }
-
-    int numVerts = (int)vpool->size();
-    softegg_cat.spam() << "found vpool " << vpool_name << " w/ " << numVerts << " verts\n";
-
-    // if this node is a joint, then these vertices belong to this joint
-    if (node_desc->is_joint())
-      joint = node_desc->get_egg_group();
-    else {
-      // find the closest _parentJoint
-      SoftNodeDesc *parentJ = node_desc;
-      while( parentJ && !parentJ->_parentJoint) {
-        if ( parentJ->_parent) {
-          SAA_Boolean isSkeleton;
-          // softegg_cat.spam() << " checking parent " <<
-          // parentJ->_parent->get_name() << endl;
-          if (parentJ->_parent->has_model())
-            SAA_modelIsSkeleton( &scene, parentJ->_parent->get_model(), &isSkeleton );
-
-          if (isSkeleton) {
-            joint = parentJ->_parent->get_egg_group();
-            softegg_cat.spam() << "parent to " << parentJ->_parent->get_name() << endl;
-            break;
-          }
-
-          parentJ = parentJ->_parent;
-        }
-        else
-          break;
-      }
-      if (!joint && (!parentJ || !parentJ->_parentJoint)) {
-        softegg_cat.spam() << node_desc->get_name() << " has no _parentJoint?!" << endl;
-        continue;
-      }
-
-      if (!joint) {
-        softegg_cat.spam() << "parent joint to " << parentJ->_parentJoint->get_name() << endl;
-        joint = parentJ->_parentJoint->get_egg_group();
-      }
-    }
-    EggVertexPool::iterator vi;
-    double membership = 1.0f;
-    for ( vi = vpool->begin(); vi != vpool->end(); ++vi) {
-      EggVertex *vert = (*vi);
-
-      // if this vertex has not been soft assigned, then hard assign it to the
-      // parentJoint
-      if ( vert->gref_size() == 0 ) {
-
-        softegg_cat.spam() << "vert " << vert->get_external_index() << " not assigned!\n";
-
-        // hard skin this vertex
-        joint->ref_vertex( vert, 1.0f );
-      }
-    }
-  }
-  return true;
-}
-
-/**
- * Applies the known shader attributes to the indicated egg primitive.
- */
-void SoftToEggConverter::
-set_shader_attributes(SoftNodeDesc *node_desc, EggPrimitive &primitive, int idx) {
-  char *texName = node_desc->texNameArray[idx];
-  EggTexture tex(texName, "");
-
-  Filename filename = Filename::from_os_specific(texName);
-  Filename fullpath = _path_replace->match_path(filename, get_model_path());
-  tex.set_filename(_path_replace->store_path(fullpath));
-  tex.set_fullpath(fullpath);
-  // tex.set_format(EggTexture::F_rgb);
-  apply_texture_properties(tex, node_desc->uRepeat[idx], node_desc->vRepeat[idx]);
-
-  EggTexture *new_tex = _textures.create_unique_texture(tex, ~EggTexture::E_tref_name);
-  primitive.set_texture(new_tex);
-}
-
-/**
- * Applies all the appropriate texture properties to the EggTexture object,
- * including wrap modes and texture matrix.
- */
-void SoftToEggConverter::
-apply_texture_properties(EggTexture &tex, int uRepeat, int vRepeat) {
-  // Let's mipmap all textures by default.
-  tex.set_minfilter(EggTexture::FT_linear_mipmap_linear);
-  tex.set_magfilter(EggTexture::FT_linear);
-
-  EggTexture::WrapMode wrap_u = uRepeat > 0 ? EggTexture::WM_repeat : EggTexture::WM_clamp;
-  EggTexture::WrapMode wrap_v = vRepeat > 0 ? EggTexture::WM_repeat : EggTexture::WM_clamp;
-
-  tex.set_wrap_u(wrap_u);
-  tex.set_wrap_v(wrap_v);
-  /*
-  LMatrix3d mat = color_def.compute_texture_matrix();
-  if (!mat.almost_equal(LMatrix3d::ident_mat())) {
-    tex.set_transform(mat);
-  }
-  */
-}
-#if 0
-/**
- * Compares the texture properties already on the texture (presumably set by a
- * previous call to apply_texture_properties()) and returns false if they
- * differ from that specified by the indicated color_def object, or true if
- * they match.
- */
-bool SoftToEggConverter::
-compare_texture_properties(EggTexture &tex,
-                           const SoftShaderColorDef &color_def) {
-  bool okflag = true;
-
-  EggTexture::WrapMode wrap_u = color_def._wrap_u ? EggTexture::WM_repeat : EggTexture::WM_clamp;
-  EggTexture::WrapMode wrap_v = color_def._wrap_v ? EggTexture::WM_repeat : EggTexture::WM_clamp;
-
-  if (wrap_u != tex.determine_wrap_u()) {
-    // Choose the more general of the two.
-    if (wrap_u == EggTexture::WM_repeat) {
-      tex.set_wrap_u(wrap_u);
-    }
-    okflag = false;
-  }
-  if (wrap_v != tex.determine_wrap_v()) {
-    if (wrap_v == EggTexture::WM_repeat) {
-      tex.set_wrap_v(wrap_v);
-    }
-    okflag = false;
-  }
-
-  LMatrix3d mat = color_def.compute_texture_matrix();
-  if (!mat.almost_equal(tex.get_transform())) {
-    okflag = false;
-  }
-
-  return okflag;
-}
-#endif
-/**
- * Recursively walks the egg hierarchy, reparenting "decal" type nodes below
- * their corresponding "decalbase" type nodes, and setting the flags.
- *
- * Returns true on success, false if some nodes were incorrect.
- */
-bool SoftToEggConverter::
-reparent_decals(EggGroupNode *egg_parent) {
-  bool okflag = true;
-
-  // First, walk through all children of this node, looking for the one decal
-  // base, if any.
-  EggGroup *decal_base = nullptr;
-  pvector<EggGroup *> decal_children;
-
-  EggGroupNode::iterator ci;
-  for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
-    EggNode *child =  (*ci);
-    if (child->is_of_type(EggGroup::get_class_type())) {
-      EggGroup *child_group = DCAST(EggGroup, child);
-      if (child_group->has_object_type("decalbase")) {
-        if (decal_base != nullptr) {
-          softegg_cat.error()
-            << "Two children of " << egg_parent->get_name()
-            << " both have decalbase set: " << decal_base->get_name()
-            << " and " << child_group->get_name() << "\n";
-          okflag = false;
-        }
-        child_group->remove_object_type("decalbase");
-        decal_base = child_group;
-
-      } else if (child_group->has_object_type("decal")) {
-        child_group->remove_object_type("decal");
-        decal_children.push_back(child_group);
-      }
-    }
-  }
-
-  if (decal_base == nullptr) {
-    if (!decal_children.empty()) {
-      softegg_cat.warning()
-        << decal_children.front()->get_name()
-        << " has decal, but no sibling node has decalbase.\n";
-    }
-
-  } else {
-    if (decal_children.empty()) {
-      softegg_cat.warning()
-        << decal_base->get_name()
-        << " has decalbase, but no sibling nodes have decal.\n";
-
-    } else {
-      // All the decal children get moved to be a child of decal base.  This
-      // usually will not affect the vertex positions, but it could if the
-      // decal base has a transform and the decal child is an instance node.
-      // So don't do that.
-      pvector<EggGroup *>::iterator di;
-      for (di = decal_children.begin(); di != decal_children.end(); ++di) {
-        EggGroup *child_group = (*di);
-        decal_base->add_child(child_group);
-      }
-
-      // Also set the decal state on the base.
-      decal_base->set_decal_flag(true);
-    }
-  }
-
-  // Now recurse on each of the child nodes.
-  for (ci = egg_parent->begin(); ci != egg_parent->end(); ++ci) {
-    EggNode *child =  (*ci);
-    if (child->is_of_type(EggGroupNode::get_class_type())) {
-      EggGroupNode *child_group = DCAST(EggGroupNode, child);
-      if (!reparent_decals(child_group)) {
-        okflag = false;
-      }
-    }
-  }
-
-  return okflag;
-}
-
-/**
- * Returns the TransformType value corresponding to the indicated string, or
- * TT_invalid.
- */
-SoftToEggConverter::TransformType SoftToEggConverter::
-string_transform_type(const string &arg) {
-  if (cmp_nocase(arg, "all") == 0) {
-    return TT_all;
-  } else if (cmp_nocase(arg, "model") == 0) {
-    return TT_model;
-  } else if (cmp_nocase(arg, "dcs") == 0) {
-    return TT_dcs;
-  } else if (cmp_nocase(arg, "none") == 0) {
-    return TT_none;
-  } else {
-    return TT_invalid;
-  }
-}
-
-/**
- * Invokes the softToEggConverter class
- */
-extern "C" int init_soft2egg(int argc, char **argv) {
-  stec._commandName = argv[0];
-  stec.rsrc_path = "c:\\Softimage\\SOFT3D_3.9.2\\3D\\rsrc";
-
-  if (stec.DoGetopts(argc, argv)) {
-    // Create a Filename object and convert the file
-    Filename softFile(argv[1]);
-    stec.convert_file(softFile);
-  }
-
-  return 0;
-}

+ 0 - 179
pandatool/src/softegg/softToEggConverter.h

@@ -1,179 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softToEggConverter.h
- * @author masad
- * @date 2003-09-25
- */
-
-#ifndef SOFTTOEGGCONVERTER_H
-#define SOFTTOEGGCONVERTER_H
-
-#include "pandatoolbase.h"
-#include "somethingToEggConverter.h"
-#include "softNodeTree.h"
-
-#include "eggTextureCollection.h"
-#include "distanceUnit.h"
-#include "coordinateSystem.h"
-
-#ifdef _MIN
-#undef _MIN
-#endif
-#ifdef _MAX
-#undef _MAX
-#endif
-
-#include <SAA.h>
-#include <SI_macros.h>
-
-class EggData;
-class EggGroup;
-class EggTable;
-class EggVertexPool;
-class EggNurbsCurve;
-class EggPrimitive;
-class EggXfmSAnim;
-class EggSAnimData;
-
-
-/**
- * This class supervises the construction of an EggData structure from a
- * single Softimage file, or from the data already in th    cout << "egg name
- * = " << eggFilename << endl;e global Softimage model space.
- *
- */
-class SoftToEggConverter : public SomethingToEggConverter {
-public:
-  SoftToEggConverter(const std::string &program_name = "");
-  SoftToEggConverter(const SoftToEggConverter &copy);
-  virtual ~SoftToEggConverter();
-
-  void Help();
-  void Usage();
-  void ShowOpts();
-
-  bool HandleGetopts(int &idx, int argc, char **argv);
-  bool DoGetopts(int &argc, char **&argv);
-
-  SoftNodeDesc *find_node(std::string name);
-  int *FindClosestTriVert( EggVertexPool *vpool, SAA_DVector *vertices, int numVert );
-
-  virtual SomethingToEggConverter *make_copy();
-  virtual std::string get_name() const;
-  virtual std::string get_extension() const;
-
-  virtual bool convert_file(const Filename &filename);
-  bool convert_soft(bool from_selection);
-  bool open_api();
-  void close_api();
-
-private:
-  bool convert_flip(double start_frame, double end_frame,
-                    double frame_inc, double output_frame_rate);
-
-  bool make_soft_skin();
-  bool cleanup_soft_skin();
-  bool convert_char_chan();
-  bool convert_char_model();
-  bool convert_hierarchy(EggGroupNode *egg_root);
-  bool process_model_node(SoftNodeDesc *node_desc);
-
-  void make_polyset(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type);
-  void make_nurb_surface(SoftNodeDesc *node_desc, EggGroup *egg_group, SAA_ModelType type);
-  void add_knots( vector <double> &eggKnots, double *knots, int numKnots, SAA_Boolean closed, int degree );
-
-  void set_shader_attributes(SoftNodeDesc *node_desc, EggPrimitive &primitive, int idx);
-  void apply_texture_properties(EggTexture &tex, int uRepeat, int vRepeat);
-
-  bool reparent_decals(EggGroupNode *egg_parent);
-
-  std::string _program_name;
-  bool _from_selection;
-
-  SI_Error            result;
-  SAA_Elem            model;
-  SAA_Database        database;
-
-public:
-
-  SoftNodeTree _tree;
-
-  SAA_Scene           scene;
-
-  char *_getopts;
-
-  // This is argv[0].
-  const char *_commandName;
-
-  // This is the entire command line.
-  char _commandLine[4096];
-
-  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;
-
-  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;
-
-
-  char *GetTextureName( SAA_Scene *scene, SAA_Elem *texture );
-
-  EggTextureCollection _textures;
-
-  bool _polygon_output;
-  double _polygon_tolerance;
-
-  enum TransformType {
-    TT_invalid,
-    TT_all,
-    TT_model,
-    TT_dcs,
-    TT_none,
-  };
-  TransformType _transform_type;
-
-  static TransformType string_transform_type(const std::string &arg);
-
-  typedef pvector<EggSAnimData *> MorphTable;
-  MorphTable _morph_table;
-
-  EggTable *morph_node;
-  EggSAnimData *find_morph_table(char *name);
-};
-
-extern const int TEX_PER_MAT;
-
-#endif

+ 0 - 588
pandatool/src/softprogs/softCVS.cxx

@@ -1,588 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softCVS.cxx
- * @author drose
- * @date 2000-11-10
- */
-
-#include "softCVS.h"
-
-#include "pnotify.h"
-#include "multifile.h"
-
-#include <algorithm>
-
-using std::string;
-
-/**
- *
- */
-SoftCVS::
-SoftCVS() {
-  _cvs_binary = "cvs";
-
-  set_program_brief("prepare a SoftImage database directory for adding to CVS");
-  set_program_description
-    ("softcvs is designed to prepare a directory hierarchy "
-     "representing a SoftImage database for adding to CVS.  "
-     "First, it eliminates SoftImage's silly filename-based "
-     "versioning system by renaming versioned filenames higher "
-     "than 1-0 back to version 1-0.  Then, it rolls up all the "
-     "files for each scene except the texture images into a Panda "
-     "multifile, which is added to CVS; the texture images are "
-     "directly added to CVS where they are.\n\n"
-
-     "The reduction of hundreds of SoftImage files per scene down to one "
-     "multifile and a handle of texture images should greatly improve "
-     "the update and commit times of CVS.\n\n"
-
-     "You must run this from within the root of a SoftImage database "
-     "directory; e.g. the directory that contains SCENES, PICTURES, MODELS, "
-     "and so on.");
-
-  clear_runlines();
-  add_runline("[opts]");
-
-  add_option
-    ("nc", "", 80,
-     "Do not attempt to add newly-created files to CVS.  The default "
-     "is to add them.",
-     &SoftCVS::dispatch_none, &_no_cvs);
-
-  add_option
-    ("cvs", "cvs_binary", 80,
-     "Specify how to run the cvs program for adding newly-created files.  "
-     "The default is simply \"cvs\".",
-     &SoftCVS::dispatch_string, nullptr, &_cvs_binary);
-}
-
-
-/**
- *
- */
-void SoftCVS::
-run() {
-  // First, check for the scenes directory.  If it doesn't exist, we must not
-  // be in the root of a soft database.
-  Filename scenes = "SCENES/.";
-  if (!scenes.exists()) {
-    nout << "No SCENES directory found; you are not in the root of a "
-      "SoftImage database.\n";
-    exit(1);
-  }
-
-  // Also, if we're expecting to use CVS, make sure the CVS directory exists.
-  Filename cvs_entries = "CVS/Entries";
-  if (!_no_cvs && !cvs_entries.exists()) {
-    nout << "You do not appear to be within a CVS-controlled source "
-      "directory.\n";
-    exit(1);
-  }
-
-  // Scan all the files in the database.
-  traverse_root();
-
-  // Collapse out the higher-versioned scene files.
-  collapse_scene_files();
-
-  // Now determine which element files are actually referenced by at least one
-  // of the scene files.
-  if (!get_scenes()) {
-    exit(1);
-  }
-
-  // Finally, remove all the element files that are no longer referenced by
-  // any scenes.
-  remove_unused_elements();
-
-  // Now do all the cvs adding and removing we need.
-  if (!_no_cvs) {
-    cvs_add_or_remove("remove", _cvs_remove);
-    cvs_add_or_remove("add -kb", _cvs_add);
-  }
-}
-
-/**
- * Reads all of the toplevel directory names, e.g.  SCENES, MATERIALS, etc.,
- * and traverses them.
- */
-void SoftCVS::
-traverse_root() {
-  Filename root(".");
-
-  // Get the list of subdirectories.
-  vector_string subdirs;
-  if (!root.scan_directory(subdirs)) {
-    nout << "Unable to scan directory.\n";
-    return;
-  }
-
-  vector_string::const_iterator di;
-  for (di = subdirs.begin(); di != subdirs.end(); ++di) {
-    Filename subdir = (*di);
-    if (subdir.is_directory() && subdir != "CVS") {
-      traverse_subdir(subdir);
-    }
-  }
-}
-
-/**
- * Reads the directory indicated by prefix and identifies all of the SoftImage
- * files stored there.
- */
-void SoftCVS::
-traverse_subdir(const Filename &directory) {
-  // Get the list of files in the directory.
-  vector_string files;
-  if (!directory.scan_directory(files)) {
-    nout << "Unable to scan directory " << directory << "\n";
-    return;
-  }
-
-  // We need to know the set of files in this directory that are CVS elements.
-  pset<string> cvs_elements;
-  bool in_cvs = false;
-  if (!_no_cvs) {
-    in_cvs = scan_cvs(directory, cvs_elements);
-  }
-
-  bool is_scenes = false;
-  bool keep_all = false;
-  bool wants_cvs = false;
-
-  // Now make some special-case behavior based on the particular SoftImage
-  // subdirectory we're in.
-  string dirname = directory.get_basename();
-  if (dirname == "SCENES") {
-    is_scenes = true;
-
-  } else if (dirname == "CAMERAS") {
-    // We don't want anything in the cameras directory.  These may change
-    // arbitrarily and have no bearing on the model or animation that we will
-    // extract, so avoid them altogether.
-    return;
-
-  } else if (dirname == "PICTURES") {
-    // In the pictures directory, we must keep everything, since the scene
-    // files don't explicitly reference these but they're still important.
-    // Textures that are no longer used will pile up; we leave this as the
-    // user's problem.
-
-    // We not only keep the textures, but we also move them into CVS, since
-    // (again) they're not part of the scene files and thus won't get added to
-    // the multifiles.  Also, some textures are shared between different
-    // scenes, and it would be wasteful to add them to each scene multifile;
-    // furthermore, some scenes are used for animation only, and we don't want
-    // to modify these multifiles when the textures change.
-
-    keep_all = true;
-    wants_cvs = !_no_cvs;
-  }
-
-  vector_string::const_iterator fi;
-  for (fi = files.begin(); fi != files.end(); ++fi) {
-    const string &filename = (*fi);
-    if (filename == "CVS") {
-      // This special filename is not to be considered.
-
-    } else if (filename == "Chapter.rsrc") {
-      // This special filename should not be considered, except to add it to
-      // the multifiles.
-      _global_files.push_back(Filename(directory, filename));
-
-    } else {
-      SoftFilename soft(directory, filename);
-
-      if (cvs_elements.count(filename) != 0) {
-        // This file is known to be in CVS.
-        soft.set_in_cvs(true);
-      }
-
-      if (keep_all) {
-        soft.increment_use_count();
-      }
-      if (wants_cvs && !in_cvs) {
-        // Try to CVSify the directory.
-        cvs_add(directory);
-        in_cvs = true;
-      }
-      soft.set_wants_cvs(wants_cvs);
-
-      if (is_scenes && soft.has_version() && soft.get_extension() == ".dsc") {
-        _scene_files.push_back(soft);
-      } else {
-        _element_files.insert(soft);
-      }
-    }
-  }
-}
-
-/**
- * Walks through the list of scene files found, and renames the higher-
- * versioned ones to version 1-0, removing the intervening versions.
- */
-void SoftCVS::
-collapse_scene_files() {
-  // Get a copy of the scene files vector so we can modify it.  Also empty out
-  // the _scene_files at the same time so we can fill it up again.
-  SceneFiles versions;
-  versions.swap(_scene_files);
-
-  // And sort them into order so we can easily compare higher and lower
-  // versions.
-  sort(versions.begin(), versions.end());
-
-  SceneFiles::iterator vi;
-  vi = versions.begin();
-  while (vi != versions.end()) {
-    SoftFilename &file = (*vi);
-
-    if (!file.is_1_0()) {
-      // Here's a file that needs to be renamed.  But first, identify all the
-      // other versions of the same file.
-      SceneFiles::iterator start_vi;
-      start_vi = vi;
-      while (vi != versions.end() && (*vi).is_same_file(file)) {
-        ++vi;
-      }
-
-      rename_file(start_vi, vi);
-
-    } else {
-      ++vi;
-    }
-
-    file.make_1_0();
-    _scene_files.push_back(file);
-  }
-}
-
-/**
- * Walks through the list of scene files and looks for the set of element
- * files referenced by each one, updating multifile accordingly.
- */
-bool SoftCVS::
-get_scenes() {
-  bool okflag = true;
-
-  // We will be added the multifiles to CVS if they're not already added, so
-  // we have to know which files are in CVS already.
-  pset<string> cvs_elements;
-  if (!_no_cvs) {
-    scan_cvs(".", cvs_elements);
-  }
-
-  SceneFiles::const_iterator vi;
-  for (vi = _scene_files.begin(); vi != _scene_files.end(); ++vi) {
-    const SoftFilename &sf = (*vi);
-    Filename file(sf.get_dirname(), sf.get_filename());
-
-    file.set_text();
-    std::ifstream in;
-    if (!file.open_read(in)) {
-      nout << "Unable to read " << file << "\n";
-    } else {
-      nout << "Scanning " << file << "\n";
-
-      Multifile multifile;
-      Filename multifile_name = sf.get_base() + "mf";
-
-      if (!multifile.open_read_write(multifile_name)) {
-        nout << "Unable to open " << multifile_name << " for updating.\n";
-        okflag = false;
-
-      } else {
-        if (!scan_scene_file(in, multifile)) {
-          okflag = false;
-        }
-
-        // Add all the global files to the multifile too.  These probably
-        // can't take compression (since in SoftImage they're just the
-        // Chapter.rsrc files, each very tiny).
-        vector_string::const_iterator gi;
-        for (gi = _global_files.begin(); gi != _global_files.end(); ++gi) {
-          if (multifile.update_subfile((*gi), (*gi), 0).empty()) {
-            nout << "Unable to add " << (*gi) << "\n";
-            okflag = false;
-          }
-        }
-
-        // Also add the scene file itself.
-        if (multifile.update_subfile(file, file, 6).empty()) {
-          nout << "Unable to add " << file << "\n";
-          okflag = false;
-        }
-
-        bool flushed = false;
-        if (multifile.needs_repack()) {
-          flushed = multifile.repack();
-        } else {
-          flushed = multifile.flush();
-        }
-        if (!flushed) {
-          nout << "Failed to write " << multifile_name << ".\n";
-          okflag = false;
-        } else {
-          nout << "Wrote " << multifile_name << ".\n";
-
-          if (!_no_cvs && cvs_elements.count(multifile_name) == 0) {
-            // Add the multifile to CVS.
-            _cvs_add.push_back(multifile_name);
-          }
-        }
-      }
-    }
-  }
-
-  return okflag;
-}
-
-
-/**
- * Remove all the element files that weren't referenced by any scene file.
- * Also plan to cvs add all those that were referenced.
- */
-void SoftCVS::
-remove_unused_elements() {
-  ElementFiles::const_iterator fi;
-  for (fi = _element_files.begin(); fi != _element_files.end(); ++fi) {
-    const SoftFilename &sf = (*fi);
-    Filename file(sf.get_dirname(), sf.get_filename());
-
-    if (sf.get_use_count() == 0) {
-      nout << file << " is unused.\n";
-
-      if (!file.unlink()) {
-        nout << "Unable to remove " << file << ".\n";
-
-      } else if (sf.get_in_cvs()) {
-        _cvs_remove.push_back(file);
-      }
-
-    } else if (sf.get_wants_cvs() && !sf.get_in_cvs()) {
-      _cvs_add.push_back(file);
-    }
-  }
-}
-
-
-/**
- * Renames the first file in the indicated list to a version 1-0 filename,
- * superceding all the other files in the list.  Returns true if the file is
- * renamed, false otherwise.
- */
-bool SoftCVS::
-rename_file(SoftCVS::SceneFiles::iterator begin,
-            SoftCVS::SceneFiles::iterator end) {
-  int length = end - begin;
-  nassertr(length > 0, false);
-
-  SoftFilename &orig = (*begin);
-
-  string dirname = orig.get_dirname();
-  string source_filename = orig.get_filename();
-  string dest_filename = orig.get_1_0_filename();
-
-  if (length > 2) {
-    nout << source_filename << " supercedes:\n";
-    SceneFiles::const_iterator p;
-    for (p = begin + 1; p != end; ++p) {
-      nout << "  " << (*p).get_filename() << "\n";
-    }
-
-  } else if (length == 2) {
-    nout << source_filename << " supercedes "
-         << (*(begin + 1)).get_filename() << ".\n";
-
-  } else {
-    nout << source_filename << " renamed.\n";
-  }
-
-  // Now remove all of the "wrong" files.
-
-  SceneFiles::const_iterator p;
-  for (p = begin + 1; p != end; ++p) {
-    Filename file((*p).get_dirname(), (*p).get_filename());
-    if (!file.unlink()) {
-      nout << "Unable to remove " << file << ".\n";
-    }
-  }
-
-  // And rename the good one.
-  Filename source(dirname, source_filename);
-  Filename dest(dirname, dest_filename);
-
-  if (!source.rename_to(dest)) {
-    nout << "Unable to rename " << source << " to " << dest_filename << ".\n";
-    exit(1);
-  }
-
-  return true;
-}
-
-/**
- * Scans the CVS repository in the indicated directory to determine which
- * files are already versioned elements.  Returns true if the directory is
- * CVS-controlled, false otherwise.
- */
-bool SoftCVS::
-scan_cvs(const string &dirname, pset<string> &cvs_elements) {
-  Filename cvs_entries = dirname + "/CVS/Entries";
-  if (!cvs_entries.exists()) {
-    return false;
-  }
-
-  std::ifstream in;
-  cvs_entries.set_text();
-  if (!cvs_entries.open_read(in)) {
-    nout << "Unable to read CVS directory.\n";
-    return true;
-  }
-
-  string line;
-  std::getline(in, line);
-  while (!in.fail() && !in.eof()) {
-    if (!line.empty() && line[0] == '/') {
-      size_t slash = line.find('/', 1);
-      if (slash != string::npos) {
-        string filename = line.substr(1, slash - 1);
-
-        if (line.substr(slash + 1, 2) == "-1") {
-          // If the first number after the slash is -1, the file used to be
-          // here but was recently cvs removed.  It counts as no longer being
-          // an element.
-        } else {
-          cvs_elements.insert(filename);
-        }
-      }
-    }
-
-    std::getline(in, line);
-  }
-
-  return true;
-}
-
-/**
- * Reads a scene file, looking for references to element files.  For each
- * reference found, increments the appropriate element file's reference count.
- */
-bool SoftCVS::
-scan_scene_file(std::istream &in, Multifile &multifile) {
-  bool okflag = true;
-
-  int c = in.get();
-  while (!in.eof() && !in.fail()) {
-    // Skip whitespace.
-    while (isspace(c) && !in.eof() && !in.fail()) {
-      c = in.get();
-    }
-
-    // Now begin a word.
-    string word;
-    while (!isspace(c) && !in.eof() && !in.fail()) {
-      word += c;
-      c = in.get();
-    }
-
-    if (!word.empty()) {
-      SoftFilename v("", word);
-
-      // Increment the use count on all matching elements of the multiset.
-      std::pair<ElementFiles::iterator, ElementFiles::iterator> range;
-      range = _element_files.equal_range(v);
-
-      ElementFiles::iterator ei;
-      for (ei = range.first; ei != range.second; ++ei) {
-        // We cheat and get a non-const reference to the filename out of the
-        // set.  We can safely do this because incrementing the use count
-        // won't change its position in the set.
-        SoftFilename &sf = (SoftFilename &)(*ei);
-        sf.increment_use_count();
-
-        Filename file(sf.get_dirname(), sf.get_filename());
-        if (multifile.update_subfile(file, file, 6).empty()) {
-          nout << "Unable to add " << file << "\n";
-          okflag = false;
-        }
-      }
-    }
-  }
-
-  return okflag;
-}
-
-/**
- * Invokes CVS to add just the named file to the repository.  Returns true on
- * success, false on failure.
- */
-bool SoftCVS::
-cvs_add(const string &path) {
-  string command = _cvs_binary + " add -kb " + path;
-  nout << command << "\n";
-  int result = system(command.c_str());
-
-  if (result != 0) {
-    nout << "Failure invoking cvs.\n";
-    return false;
-  }
-  return true;
-}
-
-/**
- * Invokes CVS to add (or remove) all of the files in the indicated vector.
- * Returns true on success, false on failure.
- */
-bool SoftCVS::
-cvs_add_or_remove(const string &cvs_command, const vector_string &paths) {
-  static const int max_command = 4096;
-
-  if (!paths.empty()) {
-    string command = _cvs_binary + " " + cvs_command;
-    vector_string::const_iterator pi;
-    pi = paths.begin();
-    while (pi != paths.end()) {
-      const string &path = (*pi);
-
-      if ((int)command.length() + 1 + (int)path.length() >= max_command) {
-        // Fire off the command now.
-        nout << command << "\n";
-        int result = system(command.c_str());
-
-        if (result != 0) {
-          nout << "Failure invoking cvs.\n";
-          return false;
-        }
-
-        command = _cvs_binary + " " + cvs_command;
-      }
-
-      command += ' ';
-      command += path;
-
-      ++pi;
-    }
-    nout << command << "\n";
-    int result = system(command.c_str());
-
-    if (result != 0) {
-      nout << "Failure invoking cvs.\n";
-      return false;
-    }
-  }
-  return true;
-}
-
-
-int main(int argc, char *argv[]) {
-  SoftCVS prog;
-  prog.parse_command_line(argc, argv);
-  prog.run();
-  return 0;
-}

+ 0 - 70
pandatool/src/softprogs/softCVS.h

@@ -1,70 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softCVS.h
- * @author drose
- * @date 2000-11-10
- */
-
-#ifndef SOFTCVS_H
-#define SOFTCVS_H
-
-#include "pandatoolbase.h"
-
-#include "softFilename.h"
-
-#include "programBase.h"
-#include "vector_string.h"
-#include "filename.h"
-
-#include "pvector.h"
-#include "pset.h"
-
-class Multifile;
-
-/**
- * This program prepares a SoftImage database for CVS by renaming everything
- * to version 1-0, and adding new files to CVS.
- */
-class SoftCVS : public ProgramBase {
-public:
-  SoftCVS();
-
-  void run();
-
-private:
-  typedef pvector<SoftFilename> SceneFiles;
-  typedef pmultiset<SoftFilename> ElementFiles;
-
-  void traverse_root();
-  void traverse_subdir(const Filename &directory);
-
-  void collapse_scene_files();
-  bool get_scenes();
-  void remove_unused_elements();
-
-  bool rename_file(SceneFiles::iterator begin, SceneFiles::iterator end);
-  bool scan_cvs(const std::string &dirname, pset<std::string> &cvs_elements);
-  bool scan_scene_file(std::istream &in, Multifile &multifile);
-
-  bool cvs_add(const std::string &path);
-  bool cvs_add_or_remove(const std::string &cvs_command,
-                         const vector_string &paths);
-
-  SceneFiles _scene_files;
-  ElementFiles _element_files;
-  vector_string _global_files;
-
-  vector_string _cvs_add;
-  vector_string _cvs_remove;
-
-  bool _no_cvs;
-  std::string _cvs_binary;
-};
-
-#endif

+ 0 - 291
pandatool/src/softprogs/softFilename.cxx

@@ -1,291 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softFilename.cxx
- * @author drose
- * @date 2000-11-10
- */
-
-#include "softFilename.h"
-
-#include "pnotify.h"
-
-using std::string;
-
-/**
- *
- */
-SoftFilename::
-SoftFilename(const string &dirname, const string &filename) :
-  _dirname(dirname),
-  _filename(filename)
-{
-  _has_version = false;
-  _major = 0;
-  _minor = 0;
-  _in_cvs = false;
-  _wants_cvs = false;
-  _use_count = 0;
-
-  _base = _filename;
-
-  // Scan for a version number and an optional extension after each dot in the
-  // filename.
-  size_t dot = _filename.find('.');
-  while (dot != string::npos) {
-    size_t m = dot + 1;
-    const char *fstr = _filename.c_str();
-    char *endptr;
-    // Check for a numeric version number.
-    int major = strtol(fstr + m , &endptr, 10);
-    if (endptr != fstr + m && *endptr == '-') {
-      // We got a major number, is there a minor number?
-      m = (endptr - fstr) + 1;
-      int minor = strtol(fstr + m, &endptr, 10);
-      if (endptr != fstr + m && (*endptr == '.' || *endptr == '\0')) {
-        // We got a minor number too!
-        _has_version = true;
-        _base = _filename.substr(0, dot + 1);
-        _major = major;
-        _minor = minor;
-        _ext = endptr;
-        return;
-      }
-    }
-
-    // That wasn't a version number.  Is there more?
-    dot = _filename.find('.', dot + 1);
-  }
-}
-
-/**
- *
- */
-SoftFilename::
-SoftFilename(const SoftFilename &copy) :
-  _dirname(copy._dirname),
-  _filename(copy._filename),
-  _has_version(copy._has_version),
-  _base(copy._base),
-  _major(copy._major),
-  _minor(copy._minor),
-  _ext(copy._ext),
-  _in_cvs(copy._in_cvs),
-  _wants_cvs(copy._wants_cvs),
-  _use_count(copy._use_count)
-{
-}
-
-/**
- *
- */
-void SoftFilename::
-operator = (const SoftFilename &copy) {
-  _dirname = copy._dirname;
-  _filename = copy._filename;
-  _has_version = copy._has_version;
-  _base = copy._base;
-  _major = copy._major;
-  _minor = copy._minor;
-  _ext = copy._ext;
-  _in_cvs = copy._in_cvs;
-  _wants_cvs = copy._wants_cvs;
-  _use_count = copy._use_count;
-}
-
-/**
- * Returns the name of the directory this file was found in.
- */
-const string &SoftFilename::
-get_dirname() const {
-  return _dirname;
-}
-
-/**
- * Returns the actual filename as found in the directory.
- */
-const string &SoftFilename::
-get_filename() const {
-  return _filename;
-}
-
-/**
- * Returns true if the filename had a version number, false otherwise.
- */
-bool SoftFilename::
-has_version() const {
-  return _has_version;
-}
-
-/**
- * Returns what the filename would be if it were version 1-0.
- */
-string SoftFilename::
-get_1_0_filename() const {
-  nassertr(_has_version, string());
-  return _base + "1-0" + _ext;
-}
-
-/**
- * Returns the base part of the filename.  This is everything before the
- * version number.
- */
-const string &SoftFilename::
-get_base() const {
-  nassertr(_has_version, _filename);
-  return _base;
-}
-
-/**
- * Returns the major version number.
- */
-int SoftFilename::
-get_major() const {
-  nassertr(_has_version, 0);
-  return _major;
-}
-
-/**
- * Returns the minor version number.
- */
-int SoftFilename::
-get_minor() const {
-  nassertr(_has_version, 0);
-  return _minor;
-}
-
-/**
- * Returns the extension part of the filename.  This is everything after the
- * version number.
- */
-const string &SoftFilename::
-get_extension() const {
-  nassertr(_has_version, _ext);
-  return _ext;
-}
-
-/**
- * Returns the filename part, without the extension.
- */
-string SoftFilename::
-get_non_extension() const {
-  nassertr(_has_version, _filename);
-  nassertr(_ext.length() < _filename.length(), _filename);
-  return _filename.substr(0, _filename.length() - _ext.length());
-}
-
-/**
- * Returns true if this is a version 1_0 filename, false otherwise.
- */
-bool SoftFilename::
-is_1_0() const {
-  nassertr(_has_version, false);
-  return (_major == 1 && _minor == 0);
-}
-
-/**
- * Makes this a 1_0 filename.
- */
-void SoftFilename::
-make_1_0() {
-  _has_version = true;
-  _major = 1;
-  _minor = 0;
-  _filename = get_1_0_filename();
-}
-
-/**
- * Returns true if this file has the same base and extension as the other,
- * disregarding the version number; false otherwise.
- */
-bool SoftFilename::
-is_same_file(const SoftFilename &other) const {
-  return _base == other._base && _ext == other._ext;
-}
-
-/**
- * Puts filenames in order such that the files with the same base are sorted
- * together, ignoring extension; and within files with the same base, files
- * are sorted in decreasing version number order so that the most recent
- * version appears first.
- */
-bool SoftFilename::
-operator < (const SoftFilename &other) const {
-  if (_base != other._base) {
-    return _base < other._base;
-  }
-
-  if (_has_version != other._has_version) {
-    // If one has a version and the other one doesn't, the one without a
-    // version comes first.
-    return _has_version < other._has_version;
-  }
-
-  if (_has_version) {
-    if (_major != other._major) {
-      return _major > other._major;
-    }
-    if (_minor != other._minor) {
-      return _minor > other._minor;
-    }
-  }
-
-  return false;
-}
-
-/**
- * Sets the flag that indicates whether this file is known to be entered into
- * the CVS database.
- */
-void SoftFilename::
-set_in_cvs(bool in_cvs) {
-  _in_cvs = in_cvs;
-}
-
-/**
- * Returns true if this file is known to be entered in the CVS database, false
- * if it is not.
- */
-bool SoftFilename::
-get_in_cvs() const {
-  return _in_cvs;
-}
-
-/**
- * Sets the flag that indicates whether this file should be entered into the
- * CVS database.
- */
-void SoftFilename::
-set_wants_cvs(bool wants_cvs) {
-  _wants_cvs = wants_cvs;
-}
-
-/**
- * Returns true if this file should be entered into the CVS database, false
- * otherwise.
- */
-bool SoftFilename::
-get_wants_cvs() const {
-  return _wants_cvs;
-}
-
-/**
- * Indicates that this filename is referenced by one more scene file.
- */
-void SoftFilename::
-increment_use_count() {
-  _use_count++;
-}
-
-/**
- * Returns the number of scene files that referenced this filename.
- */
-int SoftFilename::
-get_use_count() const {
-  return _use_count;
-}

+ 0 - 73
pandatool/src/softprogs/softFilename.h

@@ -1,73 +0,0 @@
-/**
- * PANDA 3D SOFTWARE
- * Copyright (c) Carnegie Mellon University.  All rights reserved.
- *
- * All use of this software is subject to the terms of the revised BSD
- * license.  You should have received a copy of this license along
- * with this source code in a file named "LICENSE."
- *
- * @file softFilename.h
- * @author drose
- * @date 2000-11-10
- */
-
-#ifndef SOFTFILENAME_H
-#define SOFTFILENAME_H
-
-#include "pandatoolbase.h"
-
-/**
- * This encapsulates a SoftImage versioned filename, of the form base.v-v.ext:
- * it consists of a directory name, a base, a major and minor version number,
- * and an optional extension.
- *
- * It also keeps track of whether the named file has been added to CVS, and
- * how many scene files it is referenced by,
- */
-class SoftFilename {
-public:
-  SoftFilename(const std::string &dirname, const std::string &filename);
-  SoftFilename(const SoftFilename &copy);
-  void operator = (const SoftFilename &copy);
-
-  const std::string &get_dirname() const;
-  const std::string &get_filename() const;
-  bool has_version() const;
-
-  std::string get_1_0_filename() const;
-
-  const std::string &get_base() const;
-  int get_major() const;
-  int get_minor() const;
-  const std::string &get_extension() const;
-  std::string get_non_extension() const;
-
-  bool is_1_0() const;
-  void make_1_0();
-
-  bool is_same_file(const SoftFilename &other) const;
-  bool operator < (const SoftFilename &other) const;
-
-  void set_in_cvs(bool in_cvs);
-  bool get_in_cvs() const;
-
-  void set_wants_cvs(bool wants_cvs);
-  bool get_wants_cvs() const;
-
-  void increment_use_count();
-  int get_use_count() const;
-
-private:
-  std::string _dirname;
-  std::string _filename;
-  bool _has_version;
-  std::string _base;
-  int _major;
-  int _minor;
-  std::string _ext;
-  bool _in_cvs;
-  bool _wants_cvs;
-  int _use_count;
-};
-
-#endif

+ 1 - 0
pandatool/src/xfileegg/xFileMaterial.cxx

@@ -18,6 +18,7 @@
 #include "eggTexture.h"
 #include "eggTexture.h"
 #include "eggPrimitive.h"
 #include "eggPrimitive.h"
 #include "datagram.h"
 #include "datagram.h"
+#include "config_xfile.h"
 
 
 #include <string.h>  // for strcmp, strdup
 #include <string.h>  // for strcmp, strdup
 
 

+ 2 - 0
pandatool/src/xfileegg/xFileMesh.cxx

@@ -12,6 +12,7 @@
  */
  */
 
 
 #include "xFileMesh.h"
 #include "xFileMesh.h"
+#include "xFileToEggConverter.h"
 #include "xFileFace.h"
 #include "xFileFace.h"
 #include "xFileVertex.h"
 #include "xFileVertex.h"
 #include "xFileNormal.h"
 #include "xFileNormal.h"
@@ -22,6 +23,7 @@
 #include "eggVertexPool.h"
 #include "eggVertexPool.h"
 #include "eggVertex.h"
 #include "eggVertex.h"
 #include "eggPolygon.h"
 #include "eggPolygon.h"
+#include "eggGroup.h"
 #include "eggGroupNode.h"
 #include "eggGroupNode.h"
 
 
 using std::min;
 using std::min;

+ 2 - 0
pandatool/src/xfileegg/xFileMesh.h

@@ -22,6 +22,8 @@
 #include "namable.h"
 #include "namable.h"
 #include "coordinateSystem.h"
 #include "coordinateSystem.h"
 
 
+#include "luse.h"
+
 class XFileNode;
 class XFileNode;
 class XFileDataNode;
 class XFileDataNode;
 class XFileMesh;
 class XFileMesh;

+ 1 - 0
pandatool/src/xfileegg/xFileToEggConverter.cxx

@@ -19,6 +19,7 @@
 
 
 #include "eggData.h"
 #include "eggData.h"
 #include "eggGroup.h"
 #include "eggGroup.h"
+#include "eggTable.h"
 #include "eggXfmSAnim.h"
 #include "eggXfmSAnim.h"
 #include "eggGroupUniquifier.h"
 #include "eggGroupUniquifier.h"
 #include "datagram.h"
 #include "datagram.h"

+ 25 - 12
tests/display/test_glsl_shader.py

@@ -10,6 +10,7 @@ from _pytest.outcomes import Failed
 # The reset() function serves to prevent the _triggered variable from being
 # The reset() function serves to prevent the _triggered variable from being
 # optimized out in the case that the assertions are being optimized out.
 # optimized out in the case that the assertions are being optimized out.
 GLSL_COMPUTE_TEMPLATE = """#version {version}
 GLSL_COMPUTE_TEMPLATE = """#version {version}
+{extensions}
 
 
 layout(local_size_x = 1, local_size_y = 1) in;
 layout(local_size_x = 1, local_size_y = 1) in;
 
 
@@ -37,7 +38,7 @@ void main() {{
 """
 """
 
 
 
 
-def run_glsl_test(gsg, body, preamble="", inputs={}, version=430):
+def run_glsl_test(gsg, body, preamble="", inputs={}, version=130, exts=set()):
     """ Runs a GLSL test on the given GSG.  The given body is executed in the
     """ Runs a GLSL test on the given GSG.  The given body is executed in the
     main function and should call assert().  The preamble should contain all
     main function and should call assert().  The preamble should contain all
     of the shader inputs. """
     of the shader inputs. """
@@ -48,11 +49,20 @@ def run_glsl_test(gsg, body, preamble="", inputs={}, version=430):
     if not gsg.supports_buffer_texture:
     if not gsg.supports_buffer_texture:
         pytest.skip("buffer textures not supported")
         pytest.skip("buffer textures not supported")
 
 
+    exts = exts | {'GL_ARB_compute_shader', 'GL_ARB_shader_image_load_store'}
+    missing_exts = sorted(ext for ext in exts if not gsg.has_extension(ext))
+    if missing_exts:
+        pytest.skip("missing extensions: " + ' '.join(missing_exts))
+
+    extensions = ''
+    for ext in exts:
+        extensions += '#extension {ext} : require\n'.format(ext=ext)
+
     __tracebackhide__ = True
     __tracebackhide__ = True
 
 
     preamble = preamble.strip()
     preamble = preamble.strip()
     body = body.rstrip().lstrip('\n')
     body = body.rstrip().lstrip('\n')
-    code = GLSL_COMPUTE_TEMPLATE.format(version=version, preamble=preamble, body=body)
+    code = GLSL_COMPUTE_TEMPLATE.format(version=version, extensions=extensions, preamble=preamble, body=body)
     line_offset = code[:code.find(body)].count('\n') + 1
     line_offset = code[:code.find(body)].count('\n') + 1
     shader = core.Shader.make_compute(core.Shader.SL_GLSL, code)
     shader = core.Shader.make_compute(core.Shader.SL_GLSL, code)
     assert shader, code
     assert shader, code
@@ -122,7 +132,7 @@ def test_glsl_sampler(gsg):
     assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1));
     assert(texelFetch(tex1, 0, 0) == vec4(0, 2 / 255.0, 1, 1));
     assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0));
     assert(texelFetch(tex2, ivec2(0, 0), 0) == vec4(1.0, 2.0, -3.14, 0.0));
     """
     """
-    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}), code
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
 
 
 
 
 def test_glsl_image(gsg):
 def test_glsl_image(gsg):
@@ -142,7 +152,7 @@ def test_glsl_image(gsg):
     assert(imageLoad(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
     assert(imageLoad(tex1, 0) == vec4(0, 2 / 255.0, 1, 1));
     assert(imageLoad(tex2, ivec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
     assert(imageLoad(tex2, ivec2(0, 0)) == vec4(1.0, 2.0, -3.14, 0.0));
     """
     """
-    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2}), code
+    run_glsl_test(gsg, code, preamble, {'tex1': tex1, 'tex2': tex2})
 
 
 
 
 def test_glsl_ssbo(gsg):
 def test_glsl_ssbo(gsg):
@@ -164,7 +174,10 @@ def test_glsl_ssbo(gsg):
     assert(value1 == 1234567);
     assert(value1 == 1234567);
     assert(value2 == -1234567);
     assert(value2 == -1234567);
     """
     """
-    run_glsl_test(gsg, code, preamble, {'buffer1': buffer1, 'buffer2': buffer2}), code
+    run_glsl_test(gsg, code, preamble, {'buffer1': buffer1, 'buffer2': buffer2},
+                  exts={'GL_ARB_shader_storage_buffer_object',
+                        'GL_ARB_uniform_buffer_object',
+                        'GL_ARB_shading_language_420pack'})
 
 
 
 
 def test_glsl_int(gsg):
 def test_glsl_int(gsg):
@@ -197,8 +210,8 @@ def test_glsl_uint(gsg):
     uniform uint intmax;
     uniform uint intmax;
     """
     """
     code = """
     code = """
-    assert(zero == 0);
-    assert(intmax == 0x7fffffff);
+    assert(zero == 0u);
+    assert(intmax == 0x7fffffffu);
     """
     """
     run_glsl_test(gsg, code, preamble, inputs)
     run_glsl_test(gsg, code, preamble, inputs)
 
 
@@ -243,7 +256,7 @@ def test_glsl_pta_int(gsg):
     assert(pta[2] == 2);
     assert(pta[2] == 2);
     assert(pta[3] == 3);
     assert(pta[3] == 3);
     """
     """
-    run_glsl_test(gsg, code, preamble, {'pta': pta}), code
+    run_glsl_test(gsg, code, preamble, {'pta': pta})
 
 
 
 
 def test_glsl_pta_ivec4(gsg):
 def test_glsl_pta_ivec4(gsg):
@@ -256,7 +269,7 @@ def test_glsl_pta_ivec4(gsg):
     assert(pta[0] == ivec4(0, 1, 2, 3));
     assert(pta[0] == ivec4(0, 1, 2, 3));
     assert(pta[1] == ivec4(4, 5, 6, 7));
     assert(pta[1] == ivec4(4, 5, 6, 7));
     """
     """
-    run_glsl_test(gsg, code, preamble, {'pta': pta}), code
+    run_glsl_test(gsg, code, preamble, {'pta': pta})
 
 
 
 
 def test_glsl_pta_mat4(gsg):
 def test_glsl_pta_mat4(gsg):
@@ -278,7 +291,7 @@ def test_glsl_pta_mat4(gsg):
     assert(pta[1][2] == vec4(24, 25, 26, 27));
     assert(pta[1][2] == vec4(24, 25, 26, 27));
     assert(pta[1][3] == vec4(28, 29, 30, 31));
     assert(pta[1][3] == vec4(28, 29, 30, 31));
     """
     """
-    run_glsl_test(gsg, code, preamble, {'pta': pta}), code
+    run_glsl_test(gsg, code, preamble, {'pta': pta})
 
 
 
 
 def test_glsl_write_extract_image_buffer(gsg):
 def test_glsl_write_extract_image_buffer(gsg):
@@ -299,12 +312,12 @@ def test_glsl_write_extract_image_buffer(gsg):
     layout(r32i) uniform iimageBuffer tex2;
     layout(r32i) uniform iimageBuffer tex2;
     """
     """
     code = """
     code = """
-    assert(imageLoad(tex1, 0).r == 0);
+    assert(imageLoad(tex1, 0).r == 0u);
     assert(imageLoad(tex2, 0).r == 0);
     assert(imageLoad(tex2, 0).r == 0);
     imageStore(tex1, 0, uvec4(123));
     imageStore(tex1, 0, uvec4(123));
     imageStore(tex2, 0, ivec4(-456));
     imageStore(tex2, 0, ivec4(-456));
     memoryBarrier();
     memoryBarrier();
-    assert(imageLoad(tex1, 0).r == 123);
+    assert(imageLoad(tex1, 0).r == 123u);
     assert(imageLoad(tex2, 0).r == -456);
     assert(imageLoad(tex2, 0).r == -456);
     """
     """
 
 

+ 8 - 1
tests/event/test_futures.py

@@ -1,6 +1,5 @@
 from panda3d import core
 from panda3d import core
 import pytest
 import pytest
-import threading
 import time
 import time
 import sys
 import sys
 
 
@@ -39,7 +38,11 @@ def test_future_timeout():
         fut.result(0.001)
         fut.result(0.001)
 
 
 
 
[email protected](not core.Thread.is_threading_supported(),
+                    reason="Threading support disabled")
 def test_future_wait():
 def test_future_wait():
+    threading = pytest.importorskip("direct.stdpy.threading")
+
     fut = core.AsyncFuture()
     fut = core.AsyncFuture()
 
 
     # Launch a thread to set the result value.
     # Launch a thread to set the result value.
@@ -59,7 +62,11 @@ def test_future_wait():
     assert fut.result() is None
     assert fut.result() is None
 
 
 
 
[email protected](not core.Thread.is_threading_supported(),
+                    reason="Threading support disabled")
 def test_future_wait_cancel():
 def test_future_wait_cancel():
+    threading = pytest.importorskip("direct.stdpy.threading")
+
     fut = core.AsyncFuture()
     fut = core.AsyncFuture()
 
 
     # Launch a thread to cancel the future.
     # Launch a thread to cancel the future.

+ 7 - 0
tests/text/test_textnode.py

@@ -1,6 +1,13 @@
 from panda3d import core
 from panda3d import core
 
 
 
 
+def test_textnode_write():
+    out = core.StringStream()
+    text = core.TextNode("test")
+    text.write(out, 0)
+    assert out.data.startswith(b"TextNode test")
+
+
 def test_textnode_card_as_margin():
 def test_textnode_card_as_margin():
     text = core.TextNode("test")
     text = core.TextNode("test")
     text.text = "Test"
     text.text = "Test"