Prechádzať zdrojové kódy

add 3-d texture coordinates to egg syntax

David Rose 20 rokov pred
rodič
commit
ae4051cef8
45 zmenil súbory, kde vykonal 4685 pridanie a 4220 odobranie
  1. 74 53
      panda/src/doc/eggSyntax.txt
  2. 3 3
      panda/src/egg/Sources.pp
  3. 4 4
      panda/src/egg/eggAttributes.cxx
  4. 13 2
      panda/src/egg/eggGroup.cxx
  5. 5 2
      panda/src/egg/eggGroup.h
  6. 22 0
      panda/src/egg/eggMiscFuncs.cxx
  7. 8 0
      panda/src/egg/eggMiscFuncs.h
  8. 11 34
      panda/src/egg/eggMorph.I
  9. 4 11
      panda/src/egg/eggMorph.h
  10. 5 2
      panda/src/egg/eggMorphList.I
  11. 2 1
      panda/src/egg/eggMorphList.h
  12. 12 0
      panda/src/egg/eggObject.cxx
  13. 5 0
      panda/src/egg/eggObject.h
  14. 7 2
      panda/src/egg/eggPrimitive.cxx
  15. 6 61
      panda/src/egg/eggTexture.I
  16. 5 6
      panda/src/egg/eggTexture.cxx
  17. 2 9
      panda/src/egg/eggTexture.h
  18. 369 0
      panda/src/egg/eggTransform.I
  19. 155 62
      panda/src/egg/eggTransform.cxx
  20. 48 27
      panda/src/egg/eggTransform.h
  21. 0 240
      panda/src/egg/eggTransform3d.I
  22. 1 1
      panda/src/egg/eggVertex.I
  23. 62 4
      panda/src/egg/eggVertex.cxx
  24. 5 2
      panda/src/egg/eggVertex.h
  25. 15 6
      panda/src/egg/eggVertexPool.cxx
  26. 2 1
      panda/src/egg/eggVertexPool.h
  27. 73 5
      panda/src/egg/eggVertexUV.I
  28. 37 9
      panda/src/egg/eggVertexUV.cxx
  29. 10 2
      panda/src/egg/eggVertexUV.h
  30. 1 1
      panda/src/egg/egg_composite2.cxx
  31. 2944 2965
      panda/src/egg/lexer.cxx.prebuilt
  32. 440 435
      panda/src/egg/parser.cxx.prebuilt
  33. 2 2
      panda/src/egg/parser.h.prebuilt
  34. 104 99
      panda/src/egg/parser.yxx
  35. 144 112
      panda/src/egg2pg/eggLoader.cxx
  36. 3 3
      panda/src/egg2pg/eggLoader.h
  37. 1 18
      panda/src/egg2pg/eggRenderState.cxx
  38. 1 1
      panda/src/egg2pg/eggRenderState.h
  39. 2 0
      panda/src/linmath/aa_luse.h
  40. 3 3
      pandatool/src/bam/bamToEgg.cxx
  41. 13 13
      pandatool/src/fltegg/fltToEggLevelState.cxx
  42. 56 13
      pandatool/src/fltprogs/eggToFlt.cxx
  43. 2 2
      pandatool/src/fltprogs/eggToFlt.h
  44. 2 2
      pandatool/src/palettizer/textureReference.cxx
  45. 2 2
      pandatool/src/xfileegg/xFileVertex.cxx

+ 74 - 53
panda/src/doc/eggSyntax.txt

@@ -372,36 +372,49 @@ appear before they are referenced.
 
 
   <Transform> { transform-definition }
   <Transform> { transform-definition }
 
 
-    This specifies a 2-d transformation that is applied to the UV's of
-    a surface to generate the texture coordinates.
-
-    The transform syntax is similar to that for groups, except it
-    defines a 2-d 3x3 matrix.  The definition may be any sequence of
-    zero or more of the following.  Transformations are post
-    multiplied in the order they are encountered to produce a net
-    transformation matrix.  Rotations are counterclockwise about the
-    origin in degrees.  Matrices, when specified explicitly, are
-    row-major.
-
-    <Translate> { x y }
-    <Rotate> { degrees }
-    <Scale> { x y }
-    <Scale> { s }
-
-    <Matrix3> {
-      00 01 02
-      10 11 12
-      20 21 22
-    }
+    This specifies a 2-d or 3-d transformation that is applied to the
+    UV's of a surface to generate the texture coordinates.
 
 
-    The transform definition might also include the following scalar:
+    The transform syntax is similar to that for groups, except it may
+    define either a 2-d 3x3 matrix or a 3-d 4x4 matrix.  (You should
+    use the two-dimensional forms if the UV's are two-dimensional, and
+    the three-dimensional forms if the UV's are three-dimensional.)
 
 
-    <Scalar> animated { 1 }
+    A two-dimensional transform may be any sequence of zero or more of
+    the following.  Transformations are post multiplied in the order
+    they are encountered to produce a net transformation matrix.
+    Rotations are counterclockwise about the origin in degrees.
+    Matrices, when specified explicitly, are row-major.
+
+      <Translate> { x y }
+      <Rotate> { degrees }
+      <Scale> { x y }
+      <Scale> { s }
+
+      <Matrix3> {
+        00 01 02
+        10 11 12
+        20 21 22
+      }
 
 
-    If this is set, it indicates the matrix may be animated by a
-    matrix channel, like a joint.  At present, this flag is not used;
-    eventually, it may be used to define an arbitrary texture
-    coordinate animation.
+    A three-dimensional transform may be any sequence of zero or more
+    of the following.  See the description under <Group>, below, for
+    more information.
+
+      <Translate> { x y z }
+      <RotX> { degrees }
+      <RotY> { degrees }
+      <RotZ> { degrees }
+      <Rotate> { degrees x y z }
+      <Scale> { x y z }
+      <Scale> { s }
+
+      <Matrix4> {
+        00 01 02 03
+        10 11 12 13
+        20 21 22 23
+        30 31 32 33
+      }
 
 
 
 
 <Material> name { [scalars] }
 <Material> name { [scalars] }
@@ -525,11 +538,18 @@ appear before they are referenced.
     (1 1 1 1).  The morph-list is an optional list of <DRGBA> entries.
     (1 1 1 1).  The morph-list is an optional list of <DRGBA> entries.
 
 
 
 
-    <UV> [name] { u v [tangent] [binormal] [morph-list] }
+    <UV> [name] { u v [w] [tangent] [binormal] [morph-list] }
 
 
     This gives the texture coordinates of the vertex.  This must be
     This gives the texture coordinates of the vertex.  This must be
-    specified if a texture is to be mapped onto this geometry.  As
-    before, morph-list is an optional list of <DUV> entries.
+    specified if a texture is to be mapped onto this geometry.  
+
+    The texture coordinates are usually two-dimensional, with two
+    component values (u v), but they may also be three-dimensional,
+    with three component values (u v w).  (Arguably, it should be
+    called <UVW> instead of <UV> in the three-dimensional case, but
+    it's not.)
+
+    As before, morph-list is an optional list of <DUV> entries.
 
 
     Unlike the other kinds of attributes, there may be multiple sets
     Unlike the other kinds of attributes, there may be multiple sets
     of UV's on each vertex, each with a unique name; this provides
     of UV's on each vertex, each with a unique name; this provides
@@ -544,7 +564,7 @@ appear before they are referenced.
     different UV coordinate set.  If present, they have the expected
     different UV coordinate set.  If present, they have the expected
     syntax:
     syntax:
 
 
-    <UV> [name] { u v <Tangent> { x y z } <Binormal> { x y z } }
+    <UV> [name] { u v [w] <Tangent> { x y z } <Binormal> { x y z } }
 
 
 
 
 <DynamicVertexPool> name { vertices }
 <DynamicVertexPool> name { vertices }
@@ -1000,12 +1020,13 @@ corresponding attribute entries:
   normalized to unit length.
   normalized to unit length.
 
 
 
 
-<DUV> target { u v }
+<DUV> target { u v [w] }
 
 
   A texture-coordinate delta, valid within a <UV> entry (within a
   A texture-coordinate delta, valid within a <UV> entry (within a
-  <Vertex> entry).  The given 2-valued offset vector, scaled by the
-  morph target's value, is added to the vertex's texture coordinates
-  each frame.
+  <Vertex> entry).  The offset vector should be 2-valued if the
+  enclosing UV is 2-valued, or 3-valued if the enclosing UV is
+  3-valued.  The given offset vector, scaled by the morph target's
+  value, is added to the vertex's texture coordinates each frame.
 
 
 
 
 <DRGBA> target { r g b a }
 <DRGBA> target { r g b a }
@@ -1366,25 +1387,25 @@ GROUPING ENTRIES
     a particular axis, either implicit (about the x, y, or z axis), or
     a particular axis, either implicit (about the x, y, or z axis), or
     arbitrary.  Matrices, when specified explicitly, are row-major.
     arbitrary.  Matrices, when specified explicitly, are row-major.
 
 
-    <Translate> { x y z }
-    <RotX> { degrees }
-    <RotY> { degrees }
-    <RotZ> { degrees }
-    <Rotate> { degrees x y z }
-    <Scale> { x y z }
-    <Scale> { s }
-
-    <Matrix4> {
-      00 01 02 03
-      10 11 12 13
-      20 21 22 23
-      30 31 32 33
-    }
+      <Translate> { x y z }
+      <RotX> { degrees }
+      <RotY> { degrees }
+      <RotZ> { degrees }
+      <Rotate> { degrees x y z }
+      <Scale> { x y z }
+      <Scale> { s }
+
+      <Matrix4> {
+        00 01 02 03
+        10 11 12 13
+        20 21 22 23
+        30 31 32 33
+      }
 
 
-    Note that the <Transform> block defines a 3-d transform when it
-    appears within the context of a node, while it defines a 2-d
-    transform (and has correspondingly different entries) when it
-    appears within the context of a texture.
+    Note that the <Transform> block should always define a 3-d
+    transform when it appears within the body of a <Group>, while it
+    may define either a 2-d or a 3-d transform when it appears within
+    the body of a <Texture>.  See <Texture>, above.
 
 
 
 
   <VertexRef> { indices <Ref> { pool-name } }
   <VertexRef> { indices <Ref> { pool-name } }

+ 3 - 3
panda/src/egg/Sources.pp

@@ -41,7 +41,7 @@
      eggTexture.h eggTextureCollection.I eggTextureCollection.h  \
      eggTexture.h eggTextureCollection.I eggTextureCollection.h  \
      eggTriangleFan.I eggTriangleFan.h \
      eggTriangleFan.I eggTriangleFan.h \
      eggTriangleStrip.I eggTriangleStrip.h \
      eggTriangleStrip.I eggTriangleStrip.h \
-     eggTransform3d.I eggTransform3d.h \
+     eggTransform.I eggTransform.h \
      eggUserData.I eggUserData.h \
      eggUserData.I eggUserData.h \
      eggUtilities.I eggUtilities.h \
      eggUtilities.I eggUtilities.h \
      eggVertex.I eggVertex.h eggVertexPool.I eggVertexPool.h \
      eggVertex.I eggVertex.h eggVertexPool.I eggVertexPool.h \
@@ -72,7 +72,7 @@
      eggPoolUniquifier.cxx eggPrimitive.cxx eggRenderMode.cxx  \
      eggPoolUniquifier.cxx eggPrimitive.cxx eggRenderMode.cxx  \
      eggSAnimData.cxx eggSurface.cxx eggSwitchCondition.cxx  \
      eggSAnimData.cxx eggSurface.cxx eggSwitchCondition.cxx  \
      eggTable.cxx eggTexture.cxx eggTextureCollection.cxx  \
      eggTable.cxx eggTexture.cxx eggTextureCollection.cxx  \
-     eggTransform3d.cxx \
+     eggTransform.cxx \
      eggTriangleFan.cxx \
      eggTriangleFan.cxx \
      eggTriangleStrip.cxx \
      eggTriangleStrip.cxx \
      eggUserData.cxx \
      eggUserData.cxx \
@@ -104,7 +104,7 @@
     eggSAnimData.I eggSAnimData.h eggSurface.I eggSurface.h \
     eggSAnimData.I eggSAnimData.h eggSurface.I eggSurface.h \
     eggSwitchCondition.h eggTable.I eggTable.h eggTexture.I \
     eggSwitchCondition.h eggTable.I eggTable.h eggTexture.I \
     eggTexture.h eggTextureCollection.I eggTextureCollection.h \
     eggTexture.h eggTextureCollection.I eggTextureCollection.h \
-    eggTransform3d.I eggTransform3d.h \
+    eggTransform.I eggTransform.h \
     eggTriangleFan.I eggTriangleFan.h \
     eggTriangleFan.I eggTriangleFan.h \
     eggTriangleStrip.I eggTriangleStrip.h \
     eggTriangleStrip.I eggTriangleStrip.h \
     eggUserData.I eggUserData.h \
     eggUserData.I eggUserData.h \

+ 4 - 4
panda/src/egg/eggAttributes.cxx

@@ -85,8 +85,8 @@ write(ostream &out, int indent_level) const {
         << "<Normal> { " << get_normal() << " }\n";
         << "<Normal> { " << get_normal() << " }\n";
     } else {
     } else {
       indent(out, indent_level) << "<Normal> {\n";
       indent(out, indent_level) << "<Normal> {\n";
-      indent(out, indent_level+2) << get_normal() << "\n";
-      _dnormals.write(out, indent_level+2);
+      indent(out, indent_level + 2) << get_normal() << "\n";
+      _dnormals.write(out, indent_level + 2, "<DNormal>", 3);
       indent(out, indent_level) << "}\n";
       indent(out, indent_level) << "}\n";
     }
     }
   }
   }
@@ -96,8 +96,8 @@ write(ostream &out, int indent_level) const {
         << "<RGBA> { " << get_color() << " }\n";
         << "<RGBA> { " << get_color() << " }\n";
     } else {
     } else {
       indent(out, indent_level) << "<RGBA> {\n";
       indent(out, indent_level) << "<RGBA> {\n";
-      indent(out, indent_level+2) << get_color() << "\n";
-      _drgbas.write(out, indent_level+2);
+      indent(out, indent_level + 2) << get_color() << "\n";
+      _drgbas.write(out, indent_level + 2, "<DRBGA>", 4);
       indent(out, indent_level) << "}\n";
       indent(out, indent_level) << "}\n";
     }
     }
   }
   }

+ 13 - 2
panda/src/egg/eggGroup.cxx

@@ -63,7 +63,7 @@ EggGroup(const EggGroup &copy) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 EggGroup &EggGroup::
 EggGroup &EggGroup::
 operator = (const EggGroup &copy) {
 operator = (const EggGroup &copy) {
-  EggTransform3d::operator = (copy);
+  EggTransform::operator = (copy);
   _flags = copy._flags;
   _flags = copy._flags;
   _flags2 = copy._flags2;
   _flags2 = copy._flags2;
   _collide_mask = copy._collide_mask;
   _collide_mask = copy._collide_mask;
@@ -215,7 +215,7 @@ write(ostream &out, int indent_level) const {
   write_switch_flags(out, indent_level + 2);
   write_switch_flags(out, indent_level + 2);
 
 
   if (has_transform()) {
   if (has_transform()) {
-    EggTransform3d::write(out, indent_level + 2);
+    EggTransform::write(out, indent_level + 2);
   }
   }
 
 
   write_object_types(out, indent_level + 2);
   write_object_types(out, indent_level + 2);
@@ -995,6 +995,17 @@ string_blend_operand(const string &strval) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::as_transform
+//       Access: Public, Virtual
+//  Description: Returns this object cross-cast to an EggTransform
+//               pointer, if it inherits from EggTransform, or NULL if
+//               it does not.
+////////////////////////////////////////////////////////////////////
+EggTransform *EggGroup::
+as_transform() {
+  return this;
+}
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 5 - 2
panda/src/egg/eggGroup.h

@@ -23,7 +23,7 @@
 
 
 #include "eggGroupNode.h"
 #include "eggGroupNode.h"
 #include "eggRenderMode.h"
 #include "eggRenderMode.h"
-#include "eggTransform3d.h"
+#include "eggTransform.h"
 #include "eggVertex.h"
 #include "eggVertex.h"
 #include "eggSwitchCondition.h"
 #include "eggSwitchCondition.h"
 #include "pt_EggVertex.h"
 #include "pt_EggVertex.h"
@@ -37,7 +37,7 @@
 // Description : The main glue of the egg hierarchy, this corresponds
 // Description : The main glue of the egg hierarchy, this corresponds
 //               to the <Group>, <Instance>, and <Joint> type nodes.
 //               to the <Group>, <Instance>, and <Joint> type nodes.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDAEGG EggGroup : public EggGroupNode, public EggRenderMode, public EggTransform3d {
+class EXPCL_PANDAEGG EggGroup : public EggGroupNode, public EggRenderMode, public EggTransform {
 PUBLISHED:
 PUBLISHED:
   typedef pmap<PT_EggVertex, double> VertexRef;
   typedef pmap<PT_EggVertex, double> VertexRef;
   typedef pmap<string, string> TagData;
   typedef pmap<string, string> TagData;
@@ -297,6 +297,9 @@ PUBLISHED:
   static BlendMode string_blend_mode(const string &strval);
   static BlendMode string_blend_mode(const string &strval);
   static BlendOperand string_blend_operand(const string &strval);
   static BlendOperand string_blend_operand(const string &strval);
 
 
+public:
+  virtual EggTransform *as_transform();
+
 protected:
 protected:
   void write_vertex_ref(ostream &out, int indent_level) const;
   void write_vertex_ref(ostream &out, int indent_level) const;
   virtual bool egg_start_parse_body();
   virtual bool egg_start_parse_body();

+ 22 - 0
panda/src/egg/eggMiscFuncs.cxx

@@ -94,3 +94,25 @@ write_transform(ostream &out, const LMatrix3d &mat, int indent_level) {
   indent(out, indent_level+2) << "}\n";
   indent(out, indent_level+2) << "}\n";
   indent(out, indent_level) << "}\n";
   indent(out, indent_level) << "}\n";
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: write_transform
+//  Description: A helper function to write out a 4x4 transform
+//               matrix.
+////////////////////////////////////////////////////////////////////
+void
+write_transform(ostream &out, const LMatrix4d &mat, int indent_level) {
+  indent(out, indent_level) << "<Transform> {\n";
+
+  indent(out, indent_level+2) << "<Matrix4> {\n";
+
+  for (int r = 0; r < 4; r++) {
+    indent(out, indent_level+3);
+    for (int c = 0; c < 4; c++) {
+      out << " " << mat(r, c);
+    }
+    out << "\n";
+  }
+  indent(out, indent_level+2) << "}\n";
+  indent(out, indent_level) << "}\n";
+}

+ 8 - 0
panda/src/egg/eggMiscFuncs.h

@@ -55,6 +55,14 @@ enquote_string(ostream &out, const string &str,
 void
 void
 write_transform(ostream &out, const LMatrix3d &mat, int indent_level);
 write_transform(ostream &out, const LMatrix3d &mat, int indent_level);
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: write_transform
+//  Description: A helper function to write out a 4x4 transform
+//               matrix.
+////////////////////////////////////////////////////////////////////
+void
+write_transform(ostream &out, const LMatrix4d &mat, int indent_level);
+
 
 
 #include "eggMiscFuncs.I"
 #include "eggMiscFuncs.I"
 
 

+ 11 - 34
panda/src/egg/eggMorph.I

@@ -105,40 +105,17 @@ compare_to(const EggMorph<Parameter> &other) const {
   return _offset.compare_to(other._offset);
   return _offset.compare_to(other._offset);
 }
 }
 
 
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggMorphVertex output operator
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE ostream &operator << (ostream &out, const EggMorphVertex &m) {
-  return out << "<Dxyz> " << m.get_name() << " { " << m.get_offset() << " }";
-}
-
-
-/*
-////////////////////////////////////////////////////////////////////
-//     Function: EggMorphNormal output operator
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE ostream &operator << (ostream &out, const EggMorphNormal &m) {
-  return out << "<DNormal> " << m.get_name() << " { " << m.get_offset() << " }";
-}
-*/
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggMorphTexCoord output operator
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE ostream &operator << (ostream &out, const EggMorphTexCoord &m) {
-  return out << "<Duv> " << m.get_name() << " { " << m.get_offset() << " }";
-}
-
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggMorphColor output operator
-//  Description:
+//     Function: EggMorph::output
+//       Access: Public
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE ostream &operator << (ostream &out, const EggMorphColor &m) {
-  return out << "<Drgba> " << m.get_name() << " { " << m.get_offset() << " }";
+template<class Parameter>
+INLINE void EggMorph<Parameter>::
+output(ostream &out, const string &tag, int num_dimensions) const {
+  out << tag << " " << get_name() << " {";
+  for (int i = 0; i < num_dimensions; ++i) {
+    out << " " << MAYBE_ZERO(_offset[i]);
+  }
+  out << " }";
 }
 }

+ 4 - 11
panda/src/egg/eggMorph.h

@@ -46,28 +46,21 @@ public:
 
 
   INLINE int compare_to(const EggMorph<Parameter> &other) const;
   INLINE int compare_to(const EggMorph<Parameter> &other) const;
 
 
+  INLINE void output(ostream &out, const string &tag,
+                     int num_dimensions) const;
+
 private:
 private:
   Parameter _offset;
   Parameter _offset;
 };
 };
 
 
 EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, EggMorph<LVector3d>);
 EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, EggMorph<LVector3d>);
-EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, EggMorph<LVector2d>);
 EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, EggMorph<LVector4f>);
 EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEGG, EXPTP_PANDAEGG, EggMorph<LVector4f>);
 
 
 typedef EggMorph<LVector3d> EggMorphVertex;
 typedef EggMorph<LVector3d> EggMorphVertex;
 typedef EggMorph<LVector3d> EggMorphNormal;
 typedef EggMorph<LVector3d> EggMorphNormal;
-typedef EggMorph<LVector2d> EggMorphTexCoord;
+typedef EggMorph<LVector3d> EggMorphTexCoord;
 typedef EggMorph<LVector4f> EggMorphColor;
 typedef EggMorph<LVector4f> EggMorphColor;
 
 
-INLINE ostream &operator << (ostream &out, const EggMorphVertex &m);
-INLINE ostream &operator << (ostream &out, const EggMorphTexCoord &m);
-INLINE ostream &operator << (ostream &out, const EggMorphColor &m);
-
-// EggMorphNormal is, by virtue of equivalent typedefs, another name
-// for EggMorphVertex.  Therefore we shouldn't define its output
-// operator again.
-//INLINE ostream &operator << (ostream &out, const EggMorphNormal &m);
-
 #include "eggMorph.I"
 #include "eggMorph.I"
 
 
 #endif
 #endif

+ 5 - 2
panda/src/egg/eggMorphList.I

@@ -231,11 +231,14 @@ clear() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class MorphType>
 template<class MorphType>
 void EggMorphList<MorphType>::
 void EggMorphList<MorphType>::
-write(ostream &out, int indent_level) const {
+write(ostream &out, int indent_level, const string &tag, 
+      int num_dimensions) const {
   const_iterator i;
   const_iterator i;
 
 
   for (i = begin(); i != end(); ++i) {
   for (i = begin(); i != end(); ++i) {
-    indent(out, indent_level) << *i << "\n";
+    indent(out, indent_level);
+    i->output(out, tag, num_dimensions);
+    out << "\n";
   }
   }
 }
 }
 
 

+ 2 - 1
panda/src/egg/eggMorphList.h

@@ -62,7 +62,8 @@ public:
   pair<iterator, bool> insert(const MorphType &value);
   pair<iterator, bool> insert(const MorphType &value);
   INLINE void clear();
   INLINE void clear();
 
 
-  void write(ostream &out, int indent_level) const;
+  void write(ostream &out, int indent_level,
+             const string &tag, int num_dimensions) const;
 
 
 private:
 private:
   Morphs _morphs;
   Morphs _morphs;

+ 12 - 0
panda/src/egg/eggObject.cxx

@@ -175,3 +175,15 @@ clear_user_data(TypeHandle type) {
     _user_data.erase(ui);
     _user_data.erase(ui);
   }
   }
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggObject::as_transform
+//       Access: Public, Virtual
+//  Description: Returns this object cross-cast to an EggTransform
+//               pointer, if it inherits from EggTransform, or NULL if
+//               it does not.
+////////////////////////////////////////////////////////////////////
+EggTransform *EggObject::
+as_transform() {
+  return NULL;
+}

+ 5 - 0
panda/src/egg/eggObject.h

@@ -25,6 +25,8 @@
 #include "pointerTo.h"
 #include "pointerTo.h"
 #include "pmap.h"
 #include "pmap.h"
 
 
+class EggTransform;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : EggObject
 //       Class : EggObject
 // Description : The highest-level base class in the egg directory.
 // Description : The highest-level base class in the egg directory.
@@ -46,6 +48,9 @@ PUBLISHED:
   void clear_user_data();
   void clear_user_data();
   void clear_user_data(TypeHandle type);
   void clear_user_data(TypeHandle type);
 
 
+public:
+  virtual EggTransform *as_transform();
+
 private:
 private:
   typedef pmap<TypeHandle, PT(EggUserData) > UserData;
   typedef pmap<TypeHandle, PT(EggUserData) > UserData;
   UserData _user_data;
   UserData _user_data;

+ 7 - 2
panda/src/egg/eggPrimitive.cxx

@@ -1037,7 +1037,7 @@ r_apply_texmats(EggTextureCollection &textures) {
 
 
       // We've got a texture with a matrix applied.  Save the matrix,
       // We've got a texture with a matrix applied.  Save the matrix,
       // and get a new texture without the matrix.
       // and get a new texture without the matrix.
-      LMatrix3d mat = texture->get_transform();
+      LMatrix4d mat = texture->get_transform();
       EggTexture new_texture(*texture);
       EggTexture new_texture(*texture);
       new_texture.clear_transform();
       new_texture.clear_transform();
       EggTexture *unique = textures.create_unique_texture(new_texture, ~0);
       EggTexture *unique = textures.create_unique_texture(new_texture, ~0);
@@ -1055,7 +1055,12 @@ r_apply_texmats(EggTextureCollection &textures) {
         if (uv_obj != (EggVertexUV *)NULL) {
         if (uv_obj != (EggVertexUV *)NULL) {
           EggVertex new_vertex(*vertex);
           EggVertex new_vertex(*vertex);
           PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj);
           PT(EggVertexUV) new_uv_obj = new EggVertexUV(*uv_obj);
-          new_uv_obj->set_uv(uv_obj->get_uv() * mat);
+          TexCoord3d uvw = uv_obj->get_uvw() * mat;
+          if (uv_obj->has_w() || !texture->is_transform_2d()) {
+            new_uv_obj->set_uvw(uvw);
+          } else {
+            new_uv_obj->set_uv(TexCoordd(uvw[0], uvw[1]));
+          }
           new_vertex.set_uv_obj(new_uv_obj);
           new_vertex.set_uv_obj(new_uv_obj);
           
           
           EggVertexPool *pool = vertex->get_pool();
           EggVertexPool *pool = vertex->get_pool();

+ 6 - 61
panda/src/egg/eggTexture.I

@@ -522,8 +522,12 @@ get_color() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void EggTexture::
 INLINE void EggTexture::
 set_uv_name(const string &uv_name) {
 set_uv_name(const string &uv_name) {
-  _uv_name = uv_name;
-  _flags |= F_has_uv_name;
+  if (uv_name == "default" || uv_name.empty()) {
+    clear_uv_name();
+  } else {
+    _uv_name = uv_name;
+    _flags |= F_has_uv_name;
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -663,65 +667,6 @@ get_alpha_scale() const {
   return _alpha_scale;
   return _alpha_scale;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: EggTexture::set_transform
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void EggTexture::
-set_transform(const LMatrix3d &transform) {
-  _transform = transform;
-  _flags |= F_has_transform;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTexture::clear_transform
-//       Access: Published
-//  Description:
-////////////////////////////////////////////////////////////////////
-INLINE void EggTexture::
-clear_transform() {
-  _transform = LMatrix3d::ident_mat();
-  _flags &= ~F_has_transform;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTexture::has_transform
-//       Access: Published
-//  Description: Returns true if a texture matrix transform has been
-//               specified for the texture (even if the transform is
-//               identity).
-////////////////////////////////////////////////////////////////////
-INLINE bool EggTexture::
-has_transform() const {
-  return (_flags & F_has_transform) != 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTexture::get_transform
-//       Access: Published
-//  Description: Returns the texture matrix transform if one has been
-//               specified, or identity matrix otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE const LMatrix3d &EggTexture::
-get_transform() const {
-  return _transform;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTexture::transform_is_identity()
-//       Access: Published
-//  Description: Returns true if no texture matrix transform has been
-//               specified, or if the one specified is the identity
-//               transform.  Returns false only if a nonidentity
-//               transform has been applied.
-////////////////////////////////////////////////////////////////////
-INLINE bool EggTexture::
-transform_is_identity() const {
-  return (!has_transform() ||
-          _transform.almost_equal(LMatrix3d::ident_mat(), 0.0001));
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggTexture::set_alpha_filename
 //     Function: EggTexture::set_alpha_filename
 //       Access: Published
 //       Access: Published

+ 5 - 6
panda/src/egg/eggTexture.cxx

@@ -48,7 +48,6 @@ EggTexture(const string &tref_name, const string &filename)
   _priority = 0;
   _priority = 0;
   _color.set(0.0f, 0.0f, 0.0f, 1.0f);
   _color.set(0.0f, 0.0f, 0.0f, 1.0f);
   _flags = 0;
   _flags = 0;
-  _transform = LMatrix3d::ident_mat();
   _alpha_file_channel = 0;
   _alpha_file_channel = 0;
   _multitexture_sort = 0;
   _multitexture_sort = 0;
 }
 }
@@ -74,6 +73,7 @@ operator = (const EggTexture &copy) {
 
 
   EggFilenameNode::operator = (copy);
   EggFilenameNode::operator = (copy);
   EggRenderMode::operator = (copy);
   EggRenderMode::operator = (copy);
+  EggTransform::operator = (copy);
 
 
   _format = copy._format;
   _format = copy._format;
   _wrap_mode = copy._wrap_mode;
   _wrap_mode = copy._wrap_mode;
@@ -92,7 +92,6 @@ operator = (const EggTexture &copy) {
   _rgb_scale = 1;
   _rgb_scale = 1;
   _alpha_scale = 1;
   _alpha_scale = 1;
   _flags = copy._flags;
   _flags = copy._flags;
-  _transform = copy._transform;
   _alpha_filename = copy._alpha_filename;
   _alpha_filename = copy._alpha_filename;
   _alpha_fullpath = copy._alpha_fullpath;
   _alpha_fullpath = copy._alpha_fullpath;
   _alpha_file_channel = copy._alpha_file_channel;
   _alpha_file_channel = copy._alpha_file_channel;
@@ -247,7 +246,7 @@ write(ostream &out, int indent_level) const {
   EggRenderMode::write(out, indent_level + 2);
   EggRenderMode::write(out, indent_level + 2);
 
 
   if (has_transform()) {
   if (has_transform()) {
-    write_transform(out, _transform, indent_level + 2);
+    EggTransform::write(out, indent_level + 2);
   }
   }
 
 
   indent(out, indent_level) << "}\n";
   indent(out, indent_level) << "}\n";
@@ -324,7 +323,7 @@ is_equivalent_to(const EggTexture &other, int eq) const {
     }
     }
 
 
     if (has_transform() && other.has_transform()) {
     if (has_transform() && other.has_transform()) {
-      if (!_transform.almost_equal(other._transform, 0.0001)) {
+      if (!get_transform().almost_equal(other.get_transform(), 0.0001)) {
         return false;
         return false;
       }
       }
     }
     }
@@ -400,9 +399,9 @@ sorts_less_than(const EggTexture &other, int eq) const {
     }
     }
 
 
     if (has_transform() && other.has_transform()) {
     if (has_transform() && other.has_transform()) {
-      int compare = _transform.compare_to(other._transform);
+      int compare = get_transform().compare_to(other.get_transform());
       if (compare != 0) {
       if (compare != 0) {
-    return compare < 0;
+        return compare < 0;
       }
       }
     }
     }
   }
   }

+ 2 - 9
panda/src/egg/eggTexture.h

@@ -23,6 +23,7 @@
 
 
 #include "eggRenderMode.h"
 #include "eggRenderMode.h"
 #include "eggFilenameNode.h"
 #include "eggFilenameNode.h"
+#include "eggTransform.h"
 
 
 #include "pset.h"
 #include "pset.h"
 #include "luse.h"
 #include "luse.h"
@@ -33,7 +34,7 @@
 // Description : Defines a texture map that may be applied to
 // Description : Defines a texture map that may be applied to
 //               geometry.
 //               geometry.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDAEGG EggTexture : public EggFilenameNode, public EggRenderMode {
+class EXPCL_PANDAEGG EggTexture : public EggFilenameNode, public EggRenderMode, public EggTransform {
 PUBLISHED:
 PUBLISHED:
   EggTexture(const string &tref_name, const string &filename);
   EggTexture(const string &tref_name, const string &filename);
   EggTexture(const EggTexture &copy);
   EggTexture(const EggTexture &copy);
@@ -216,12 +217,6 @@ PUBLISHED:
   INLINE bool has_alpha_scale() const;
   INLINE bool has_alpha_scale() const;
   INLINE int get_alpha_scale() const;
   INLINE int get_alpha_scale() const;
 
 
-  INLINE void set_transform(const LMatrix3d &transform);
-  INLINE void clear_transform();
-  INLINE bool has_transform() const;
-  INLINE const LMatrix3d &get_transform() const;
-  INLINE bool transform_is_identity() const;
-
   INLINE void set_alpha_filename(const Filename &filename);
   INLINE void set_alpha_filename(const Filename &filename);
   INLINE void clear_alpha_filename();
   INLINE void clear_alpha_filename();
   INLINE bool has_alpha_filename() const;
   INLINE bool has_alpha_filename() const;
@@ -256,7 +251,6 @@ private:
   bool r_min_multitexture_sort(int sort, MultiTextures &cycle_detector);
   bool r_min_multitexture_sort(int sort, MultiTextures &cycle_detector);
 
 
   enum Flags {
   enum Flags {
-    F_has_transform          = 0x0001,
     F_has_alpha_filename     = 0x0002,
     F_has_alpha_filename     = 0x0002,
     F_has_anisotropic_degree = 0x0004,
     F_has_anisotropic_degree = 0x0004,
     F_has_alpha_file_channel = 0x0008,
     F_has_alpha_file_channel = 0x0008,
@@ -282,7 +276,6 @@ private:
   int _rgb_scale;
   int _rgb_scale;
   int _alpha_scale;
   int _alpha_scale;
   int _flags;
   int _flags;
-  LMatrix3d _transform;
   Filename _alpha_filename;
   Filename _alpha_filename;
   Filename _alpha_fullpath;
   Filename _alpha_fullpath;
   int _alpha_file_channel;
   int _alpha_file_channel;

+ 369 - 0
panda/src/egg/eggTransform.I

@@ -0,0 +1,369 @@
+// Filename: eggTransform.I
+// Created by:  drose (21Jun02)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::Component::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE EggTransform::Component::
+Component(EggTransform::ComponentType type, double number) :
+  _type(type),
+  _number(number)
+{
+  _vec2 = (LVecBase2d *)NULL;
+  _vec3 = (LVecBase3d *)NULL;
+  _mat3 = (LMatrix3d *)NULL;
+  _mat4 = (LMatrix4d *)NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::Component::Copy Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE EggTransform::Component::
+Component(const EggTransform::Component &copy) :
+  _type(copy._type),
+  _number(copy._number)
+{
+  _vec2 = (LVecBase2d *)NULL;
+  _vec3 = (LVecBase3d *)NULL;
+  _mat3 = (LMatrix3d *)NULL;
+  _mat4 = (LMatrix4d *)NULL;
+  if (copy._vec2 != (LVecBase2d *)NULL) {
+    _vec2 = new LVector2d(*copy._vec2);
+  }
+  if (copy._vec3 != (LVecBase3d *)NULL) {
+    _vec3 = new LVector3d(*copy._vec3);
+  }
+  if (copy._mat3 != (LMatrix3d *)NULL) {
+    _mat3 = new LMatrix3d(*copy._mat3);
+  }
+  if (copy._mat4 != (LMatrix4d *)NULL) {
+    _mat4 = new LMatrix4d(*copy._mat4);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::Component::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::Component::
+operator = (const EggTransform::Component &copy) {
+  _type = copy._type;
+  _number = copy._number;
+  if (_vec2 != (LVecBase2d *)NULL) {
+    delete _vec2;
+    _vec2 = (LVecBase2d *)NULL;
+  }
+  if (_vec3 != (LVecBase3d *)NULL) {
+    delete _vec3;
+    _vec3 = (LVecBase3d *)NULL;
+  }
+  if (_mat3 != (LMatrix3d *)NULL) {
+    delete _mat3;
+    _mat3 = (LMatrix3d *)NULL;
+  }
+  if (_mat4 != (LMatrix4d *)NULL) {
+    delete _mat4;
+    _mat4 = (LMatrix4d *)NULL;
+  }
+  if (copy._vec2 != (LVecBase2d *)NULL) {
+    _vec2 = new LVecBase2d(*copy._vec2);
+  }
+  if (copy._vec3 != (LVecBase3d *)NULL) {
+    _vec3 = new LVecBase3d(*copy._vec3);
+  }
+  if (copy._mat3 != (LMatrix3d *)NULL) {
+    _mat3 = new LMatrix3d(*copy._mat3);
+  }
+  if (copy._mat4 != (LMatrix4d *)NULL) {
+    _mat4 = new LMatrix4d(*copy._mat4);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::Component::Destructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE EggTransform::Component::
+~Component() {
+  if (_vec2 != (LVecBase2d *)NULL) {
+    delete _vec2;
+  }
+  if (_vec3 != (LVecBase3d *)NULL) {
+    delete _vec3;
+  }
+  if (_mat3 != (LMatrix3d *)NULL) {
+    delete _mat3;
+  }
+  if (_mat4 != (LMatrix4d *)NULL) {
+    delete _mat4;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::clear_transform
+//       Access: Public
+//  Description: Resets the transform to empty, identity.
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+clear_transform() {
+  internal_clear_transform();
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::add_matrix3
+//       Access: Public
+//  Description: Appends an arbitrary 3x3 matrix to the current
+//               transform.
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+add_matrix3(const LMatrix3d &mat) {
+  internal_add_matrix(mat);
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::add_matrix4
+//       Access: Public
+//  Description: Appends an arbitrary 4x4 matrix to the current
+//               transform.
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+add_matrix4(const LMatrix4d &mat) {
+  internal_add_matrix(mat);
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::has_transform
+//       Access: Public
+//  Description: Returns true if the transform is nonempty, false if
+//               it is empty (no transform components have been
+//               added).
+////////////////////////////////////////////////////////////////////
+INLINE bool EggTransform::
+has_transform() const {
+  return !_components.empty();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::is_transform_2d
+//       Access: Public
+//  Description: Returns true if the transform is specified as a 2-d
+//               transform, e.g. with a 3x3 matrix, or false if it is
+//               specified as a 3-d transform, with a 4x4 matrix.
+//
+//               Normally, EggTextures have a 2-d matrix (but
+//               occasionally they use a 3-d matrix), and EggGroups
+//               always have a 3-d matrix.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggTransform::
+is_transform_2d() const {
+  return _is_transform_2d;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::set_transform_2d
+//       Access: Public
+//  Description: Sets the overall transform as a 3x3 matrix.  This
+//               completely replaces whatever componentwise transform
+//               may have been defined.
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+set_transform_2d(const LMatrix3d &mat) {
+  internal_set_transform(mat);
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::set_transform
+//       Access: Public
+//  Description: Sets the overall transform as a 4x4 matrix.  This
+//               completely replaces whatever componentwise transform
+//               may have been defined.
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+set_transform(const LMatrix4d &mat) {
+  internal_set_transform(mat);
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_transform_2d
+//       Access: Public
+//  Description: Returns the overall transform as a 3x3 matrix.  It is
+//               only valid to call this if is_transform_2d() has
+//               returned true.
+////////////////////////////////////////////////////////////////////
+INLINE LMatrix3d EggTransform::
+get_transform_2d() const {
+  nassertr(is_transform_2d(), LMatrix3d::ident_mat());
+  const LMatrix4d &t = _transform;
+  return LMatrix3d(t(0, 0), t(0, 1), t(0, 3),
+                   t(1, 0), t(1, 1), t(1, 3),
+                   t(3, 0), t(3, 1), t(3, 3));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_transform
+//       Access: Public
+//  Description: Returns the overall transform as a 4x4 matrix.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4d &EggTransform::
+get_transform() const {
+  return _transform;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::transform_is_identity
+//       Access: Public
+//  Description: Returns true if the described transform is identity,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggTransform::
+transform_is_identity() const {
+  return _components.empty() ||
+    _transform.almost_equal(LMatrix4d::ident_mat(), 0.0001);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_num_components
+//       Access: Public
+//  Description: Returns the number of components that make up the
+//               transform.
+////////////////////////////////////////////////////////////////////
+INLINE int EggTransform::
+get_num_components() const {
+  return _components.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_type
+//       Access: Public
+//  Description: Returns the type of the nth component.
+////////////////////////////////////////////////////////////////////
+INLINE EggTransform::ComponentType EggTransform::
+get_component_type(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), CT_invalid);
+  return _components[n]._type;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_number
+//       Access: Public
+//  Description: Returns the solitary number associated with the nth
+//               component.  In the case of a rotation, this is the
+//               angle in degrees to rotate; in the case of uniform
+//               scale, this is the amount of the scale.  Other types
+//               do not use this property.
+////////////////////////////////////////////////////////////////////
+INLINE double EggTransform::
+get_component_number(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), 0.0);
+  return _components[n]._number;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_vec2
+//       Access: Public
+//  Description: Returns the 2-component vector associated with the
+//               nth component.  This may be the translate vector,
+//               rotate axis, or non-uniform scale.  It is an error to
+//               call this if the component type does not use a 2-d
+//               vector property.
+////////////////////////////////////////////////////////////////////
+INLINE const LVecBase2d &EggTransform::
+get_component_vec2(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), LVector2d::zero());
+  nassertr(_components[n]._vec2 != (LVecBase2d *)NULL, LVector2d::zero());
+  return *_components[n]._vec2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_vec3
+//       Access: Public
+//  Description: Returns the 3-component vector associated with the
+//               nth component.  This may be the translate vector,
+//               rotate axis, or non-uniform scale.  It is an error to
+//               call this if the component type does not use a 3-d
+//               vector property.
+////////////////////////////////////////////////////////////////////
+INLINE const LVecBase3d &EggTransform::
+get_component_vec3(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), LVector3d::zero());
+  nassertr(_components[n]._vec3 != (LVecBase3d *)NULL, LVector3d::zero());
+  return *_components[n]._vec3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_mat3
+//       Access: Public
+//  Description: Returns the 3x3 matrix associated with the nth
+//               component.  It is an error to call this if the
+//               component type is not CT_matrix3.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix3d &EggTransform::
+get_component_mat3(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), LMatrix3d::ident_mat());
+  nassertr(_components[n]._mat3 != (LMatrix3d *)NULL, LMatrix3d::ident_mat());
+  return *_components[n]._mat3;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::get_component_mat4
+//       Access: Public
+//  Description: Returns the 4x4 matrix associated with the nth
+//               component.  It is an error to call this if the
+//               component type is not CT_matrix4.
+////////////////////////////////////////////////////////////////////
+INLINE const LMatrix4d &EggTransform::
+get_component_mat4(int n) const {
+  nassertr(n >= 0 && n < (int)_components.size(), LMatrix4d::ident_mat());
+  nassertr(_components[n]._mat4 != (LMatrix4d *)NULL, LMatrix4d::ident_mat());
+  return *_components[n]._mat4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::internal_set_transform
+//       Access: Protected
+//  Description: Sets the overall transform without calling
+//               transform_changed().
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+internal_set_transform(const LMatrix3d &mat) {
+  internal_clear_transform();
+  internal_add_matrix(mat);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::internal_set_transform
+//       Access: Protected
+//  Description: Sets the overall transform without calling
+//               transform_changed().
+////////////////////////////////////////////////////////////////////
+INLINE void EggTransform::
+internal_set_transform(const LMatrix4d &mat) {
+  internal_clear_transform();
+  internal_add_matrix(mat);
+}

+ 155 - 62
panda/src/egg/eggTransform3d.cxx → panda/src/egg/eggTransform.cxx

@@ -1,4 +1,4 @@
-// Filename: eggTransform3d.cxx
+// Filename: eggTransform.cxx
 // Created by:  drose (21Jun02)
 // Created by:  drose (21Jun02)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -16,158 +16,211 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-#include "eggTransform3d.h"
+#include "eggTransform.h"
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Constructor
+//     Function: EggTransform::Constructor
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggTransform3d::
-EggTransform3d() :
+EggTransform::
+EggTransform() :
+  _is_transform_2d(true),
   _transform(LMatrix4d::ident_mat())
   _transform(LMatrix4d::ident_mat())
 {
 {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Copy Constructor
+//     Function: EggTransform::Copy Constructor
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggTransform3d::
-EggTransform3d(const EggTransform3d &copy) :
+EggTransform::
+EggTransform(const EggTransform &copy) :
+  _is_transform_2d(copy._is_transform_2d),
   _components(copy._components),
   _components(copy._components),
   _transform(copy._transform)
   _transform(copy._transform)
 {
 {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Copy assignment operator
+//     Function: EggTransform::Copy assignment operator
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggTransform3d &EggTransform3d::
-operator = (const EggTransform3d &copy) {
+EggTransform &EggTransform::
+operator = (const EggTransform &copy) {
+  _is_transform_2d = copy._is_transform_2d;
   _components = copy._components;
   _components = copy._components;
   _transform = copy._transform;
   _transform = copy._transform;
   return *this;
   return *this;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Destructor
+//     Function: EggTransform::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggTransform3d::
-~EggTransform3d() {
+EggTransform::
+~EggTransform() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_translate
+//     Function: EggTransform::add_translate2d
 //       Access: Public
 //       Access: Public
-//  Description: Appends a translation operation to the current
+//  Description: Appends a 2-d translation operation to the current
 //               transform.
 //               transform.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
-add_translate(const LVector3d &translate) {
-  _components.push_back(Component(CT_translate));
-  _components.back()._vector = new LVector3d(translate);
+void EggTransform::
+add_translate2d(const LVector2d &translate) {
+  _components.push_back(Component(CT_translate2d));
+  _components.back()._vec2 = new LVecBase2d(translate);
+  _transform *= LMatrix4d::translate_mat(LVector3d(translate[0], translate[1], 0.0));
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::add_translate3d
+//       Access: Public
+//  Description: Appends a 3-d translation operation to the current
+//               transform.
+////////////////////////////////////////////////////////////////////
+void EggTransform::
+add_translate3d(const LVector3d &translate) {
+  _is_transform_2d = false;
+  _components.push_back(Component(CT_translate3d));
+  _components.back()._vec3 = new LVecBase3d(translate);
   _transform *= LMatrix4d::translate_mat(translate);
   _transform *= LMatrix4d::translate_mat(translate);
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_rotx
+//     Function: EggTransform::add_rotate2d
+//       Access: Public
+//  Description: Appends a 2-d rotation to the current transform.  The
+//               rotation angle is specified in degrees
+//               counterclockwise about the origin.
+////////////////////////////////////////////////////////////////////
+void EggTransform::
+add_rotate2d(double angle) {
+  _components.push_back(Component(CT_rotate2d, angle));
+  _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0));
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::add_rotx
 //       Access: Public
 //       Access: Public
 //  Description: Appends a rotation about the X axis to the current
 //  Description: Appends a rotation about the X axis to the current
 //               transform.  The rotation angle is specified in
 //               transform.  The rotation angle is specified in
 //               degrees counterclockwise about the axis.
 //               degrees counterclockwise about the axis.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 add_rotx(double angle) {
 add_rotx(double angle) {
+  _is_transform_2d = false;
   _components.push_back(Component(CT_rotx, angle));
   _components.push_back(Component(CT_rotx, angle));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(1.0, 0.0, 0.0));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(1.0, 0.0, 0.0));
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_roty
+//     Function: EggTransform::add_roty
 //       Access: Public
 //       Access: Public
 //  Description: Appends a rotation about the Y axis to the current
 //  Description: Appends a rotation about the Y axis to the current
 //               transform.  The rotation angle is specified in
 //               transform.  The rotation angle is specified in
 //               degrees counterclockwise about the axis.
 //               degrees counterclockwise about the axis.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 add_roty(double angle) {
 add_roty(double angle) {
+  _is_transform_2d = false;
   _components.push_back(Component(CT_roty, angle));
   _components.push_back(Component(CT_roty, angle));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 1.0, 0.0));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 1.0, 0.0));
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_rotz
+//     Function: EggTransform::add_rotz
 //       Access: Public
 //       Access: Public
 //  Description: Appends a rotation about the Z axis to the current
 //  Description: Appends a rotation about the Z axis to the current
 //               transform.  The rotation angle is specified in
 //               transform.  The rotation angle is specified in
 //               degrees counterclockwise about the axis.
 //               degrees counterclockwise about the axis.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 add_rotz(double angle) {
 add_rotz(double angle) {
+  _is_transform_2d = false;
   _components.push_back(Component(CT_rotz, angle));
   _components.push_back(Component(CT_rotz, angle));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0));
   _transform *= LMatrix4d::rotate_mat_normaxis(angle, LVector3d(0.0, 0.0, 1.0));
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_rotate
+//     Function: EggTransform::add_rotate3d
 //       Access: Public
 //       Access: Public
-//  Description: Appends a rotation about an arbitrary axis to the
+//  Description: Appends a 3-d rotation about an arbitrary axis to the
 //               current transform.  The rotation angle is specified
 //               current transform.  The rotation angle is specified
 //               in degrees counterclockwise about the axis.
 //               in degrees counterclockwise about the axis.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
-add_rotate(double angle, const LVector3d &axis) {
+void EggTransform::
+add_rotate3d(double angle, const LVector3d &axis) {
+  _is_transform_2d = false;
   LVector3d normaxis = normalize(axis);
   LVector3d normaxis = normalize(axis);
-  _components.push_back(Component(CT_rotate, angle));
-  _components.back()._vector = new LVector3d(normaxis);
+  _components.push_back(Component(CT_rotate3d, angle));
+  _components.back()._vec3 = new LVecBase3d(normaxis);
   _transform *= LMatrix4d::rotate_mat(angle, normaxis);
   _transform *= LMatrix4d::rotate_mat(angle, normaxis);
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_rotate
+//     Function: EggTransform::add_rotate3d
 //       Access: Public
 //       Access: Public
-//  Description: Appends an arbitrary rotation to the current
+//  Description: Appends an arbitrary 3-d rotation to the current
 //               transform, expressed as a quaternion.  This is
 //               transform, expressed as a quaternion.  This is
 //               converted to axis-angle notation for the egg file.
 //               converted to axis-angle notation for the egg file.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
-add_rotate(const LQuaterniond &quat) {
-  add_rotate(quat.get_angle(), quat.get_axis());
+void EggTransform::
+add_rotate3d(const LQuaterniond &quat) {
+  _is_transform_2d = false;
+  add_rotate3d(quat.get_angle(), quat.get_axis());
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_scale
+//     Function: EggTransform::add_scale2d
 //       Access: Public
 //       Access: Public
 //  Description: Appends a possibly non-uniform scale to the current
 //  Description: Appends a possibly non-uniform scale to the current
 //               transform.
 //               transform.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
-add_scale(const LVecBase3d &scale) {
-  _components.push_back(Component(CT_scale));
-  _components.back()._vector = new LVector3d(scale);
+void EggTransform::
+add_scale2d(const LVecBase2d &scale) {
+  _is_transform_2d = false;
+  _components.push_back(Component(CT_scale2d));
+  _components.back()._vec2 = new LVecBase2d(scale);
+  _transform *= LMatrix4d::scale_mat(LVecBase3d(scale[0], scale[1], 1.0));
+  transform_changed();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::add_scale3d
+//       Access: Public
+//  Description: Appends a possibly non-uniform scale to the current
+//               transform.
+////////////////////////////////////////////////////////////////////
+void EggTransform::
+add_scale3d(const LVecBase3d &scale) {
+  _is_transform_2d = false;
+  _components.push_back(Component(CT_scale3d));
+  _components.back()._vec3 = new LVecBase3d(scale);
   _transform *= LMatrix4d::scale_mat(scale);
   _transform *= LMatrix4d::scale_mat(scale);
   transform_changed();
   transform_changed();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_uniform_scale
+//     Function: EggTransform::add_uniform_scale
 //       Access: Public
 //       Access: Public
 //  Description: Appends a uniform scale to the current transform.
 //  Description: Appends a uniform scale to the current transform.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 add_uniform_scale(double scale) {
 add_uniform_scale(double scale) {
   _components.push_back(Component(CT_uniform_scale, scale));
   _components.push_back(Component(CT_uniform_scale, scale));
   _transform *= LMatrix4d::scale_mat(scale);
   _transform *= LMatrix4d::scale_mat(scale);
@@ -175,21 +228,31 @@ add_uniform_scale(double scale) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::write
+//     Function: EggTransform::write
 //       Access: Public
 //       Access: Public
 //  Description: Writes the transform to the indicated stream in Egg
 //  Description: Writes the transform to the indicated stream in Egg
 //               format.
 //               format.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
   indent(out, indent_level) << "<Transform> {\n";
   indent(out, indent_level) << "<Transform> {\n";
 
 
   int num_components = get_num_components();
   int num_components = get_num_components();
   for (int i = 0; i < num_components; i++) {
   for (int i = 0; i < num_components; i++) {
     switch (get_component_type(i)) {
     switch (get_component_type(i)) {
-    case CT_translate:
+    case CT_translate2d:
+      indent(out, indent_level + 2)
+        << "<Translate> { " << get_component_vec2(i) << " }\n";
+      break;
+
+    case CT_translate3d:
+      indent(out, indent_level + 2)
+        << "<Translate> { " << get_component_vec3(i) << " }\n";
+      break;
+
+    case CT_rotate2d:
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
-        << "<Translate> { " << get_component_vector(i) << " }\n";
+        << "<Rotate> { " << get_component_number(i) << " }\n";
       break;
       break;
 
 
     case CT_rotx:
     case CT_rotx:
@@ -207,15 +270,20 @@ write(ostream &out, int indent_level) const {
         << "<RotZ> { " << get_component_number(i) << " }\n";
         << "<RotZ> { " << get_component_number(i) << " }\n";
       break;
       break;
 
 
-    case CT_rotate:
+    case CT_rotate3d:
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
         << "<Rotate> { " << get_component_number(i) << " " 
         << "<Rotate> { " << get_component_number(i) << " " 
-        << get_component_vector(i) << " }\n";
+        << get_component_vec3(i) << " }\n";
+      break;
+
+    case CT_scale2d:
+      indent(out, indent_level + 2)
+        << "<Scale> { " << get_component_vec2(i) << " }\n";
       break;
       break;
 
 
-    case CT_scale:
+    case CT_scale3d:
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
-        << "<Scale> { " << get_component_vector(i) << " }\n";
+        << "<Scale> { " << get_component_vec3(i) << " }\n";
       break;
       break;
 
 
     case CT_uniform_scale:
     case CT_uniform_scale:
@@ -223,9 +291,15 @@ write(ostream &out, int indent_level) const {
         << "<Scale> { " << get_component_number(i) << " }\n";
         << "<Scale> { " << get_component_number(i) << " }\n";
       break;
       break;
 
 
-    case CT_matrix:
+    case CT_matrix3:
+      indent(out, indent_level + 2) << "<Matrix3> {\n";
+      get_component_mat3(i).write(out, indent_level + 4);
+      indent(out, indent_level + 2) << "}\n";
+      break;
+
+    case CT_matrix4:
       indent(out, indent_level + 2) << "<Matrix4> {\n";
       indent(out, indent_level + 2) << "<Matrix4> {\n";
-      get_component_matrix(i).write(out, indent_level + 4);
+      get_component_mat4(i).write(out, indent_level + 4);
       indent(out, indent_level + 2) << "}\n";
       indent(out, indent_level + 2) << "}\n";
       break;
       break;
 
 
@@ -239,39 +313,58 @@ write(ostream &out, int indent_level) const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::internal_clear_transform
+//     Function: EggTransform::internal_clear_transform
 //       Access: Public
 //       Access: Public
 //  Description: Resets the transform to empty without calling
 //  Description: Resets the transform to empty without calling
 //               transform_changed().
 //               transform_changed().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 internal_clear_transform() {
 internal_clear_transform() {
+  _is_transform_2d = true;
   _components.clear();
   _components.clear();
   _transform = LMatrix4d::ident_mat();
   _transform = LMatrix4d::ident_mat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::internal_add_matrix
+//     Function: EggTransform::internal_add_matrix
+//       Access: Public
+//  Description: Appends an arbitrary 4x4 matrix to the current
+//               transform, without calling transform_changed().
+////////////////////////////////////////////////////////////////////
+void EggTransform::
+internal_add_matrix(const LMatrix3d &mat) {
+  _components.push_back(Component(CT_matrix3));
+  _components.back()._mat3 = new LMatrix3d(mat);
+  LMatrix4d mat4(mat(0, 0), mat(0, 1), 0.0, mat(0, 2),
+                 mat(1, 0), mat(1, 1), 0.0, mat(1, 2),
+                 0.0, 0.0, 1.0, 0.0,
+                 mat(2, 0), mat(2, 1), 0.0, mat(2, 2));
+  _transform *= mat4;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggTransform::internal_add_matrix
 //       Access: Public
 //       Access: Public
 //  Description: Appends an arbitrary 4x4 matrix to the current
 //  Description: Appends an arbitrary 4x4 matrix to the current
 //               transform, without calling transform_changed().
 //               transform, without calling transform_changed().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 internal_add_matrix(const LMatrix4d &mat) {
 internal_add_matrix(const LMatrix4d &mat) {
-  _components.push_back(Component(CT_matrix));
-  _components.back()._matrix = new LMatrix4d(mat);
+  _is_transform_2d = false;
+  _components.push_back(Component(CT_matrix4));
+  _components.back()._mat4 = new LMatrix4d(mat);
   _transform *= mat;
   _transform *= mat;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::transform_changed
+//     Function: EggTransform::transform_changed
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
 //  Description: This virtual method is called whenever the transform
 //  Description: This virtual method is called whenever the transform
 //               is changed; it is intended to provide a hook for
 //               is changed; it is intended to provide a hook for
 //               derived classes (e.g. EggGroup) to update their
 //               derived classes (e.g. EggGroup) to update their
 //               internal cache appropriately.
 //               internal cache appropriately.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggTransform3d::
+void EggTransform::
 transform_changed() {
 transform_changed() {
 }
 }
 
 

+ 48 - 27
panda/src/egg/eggTransform3d.h → panda/src/egg/eggTransform.h

@@ -1,4 +1,4 @@
-// Filename: eggTransform3d.h
+// Filename: eggTransform.h
 // Created by:  drose (21Jun02)
 // Created by:  drose (21Jun02)
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -16,67 +16,85 @@
 //
 //
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
-#ifndef EGGTRANSFORM3D_H
-#define EGGTRANSFORM3D_H
+#ifndef EGGTRANSFORM_H
+#define EGGTRANSFORM_H
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 #include "luse.h"
 #include "luse.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//       Class : EggTransform3d
+//       Class : EggTransform
 // Description : This represents the <Transform> entry of a group
 // Description : This represents the <Transform> entry of a group
-//               node: a list of component transform operations,
-//               applied in order, that describe a net transform
-//               matrix.  This is a 3-d transform, and therefore
-//               computes a 4x4 matrix.
+//               or texture node: a list of component transform
+//               operations, applied in order, that describe a net
+//               transform matrix.  
+//
+//               This may be either a 3-d transform, and therefore
+//               described by a 4x4 matrix, or a 2-d transform,
+//               described by a 3x3 matrix.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDAEGG EggTransform3d {
+class EXPCL_PANDAEGG EggTransform {
 PUBLISHED:
 PUBLISHED:
-  EggTransform3d();
-  EggTransform3d(const EggTransform3d &copy);
-  EggTransform3d &operator = (const EggTransform3d &copy);
-  virtual ~EggTransform3d();
+  EggTransform();
+  EggTransform(const EggTransform &copy);
+  EggTransform &operator = (const EggTransform &copy);
+  virtual ~EggTransform();
 
 
   INLINE void clear_transform();
   INLINE void clear_transform();
 
 
-  void add_translate(const LVector3d &translate);
+  void add_translate2d(const LVector2d &translate);
+  void add_translate3d(const LVector3d &translate);
+  void add_rotate2d(double angle);
   void add_rotx(double angle); 
   void add_rotx(double angle); 
   void add_roty(double angle); 
   void add_roty(double angle); 
   void add_rotz(double angle); 
   void add_rotz(double angle); 
-  void add_rotate(double angle, const LVector3d &axis);
-  void add_rotate(const LQuaterniond &quat);
-  void add_scale(const LVecBase3d &scale);
+  void add_rotate3d(double angle, const LVector3d &axis);
+  void add_rotate3d(const LQuaterniond &quat);
+  void add_scale2d(const LVecBase2d &scale);
+  void add_scale3d(const LVecBase3d &scale);
   void add_uniform_scale(double scale);
   void add_uniform_scale(double scale);
-  INLINE void add_matrix(const LMatrix4d &mat);
+  INLINE void add_matrix3(const LMatrix3d &mat);
+  INLINE void add_matrix4(const LMatrix4d &mat);
 
 
   INLINE bool has_transform() const;
   INLINE bool has_transform() const;
+  INLINE bool is_transform_2d() const;
+  INLINE void set_transform_2d(const LMatrix3d &mat);
   INLINE void set_transform(const LMatrix4d &mat);
   INLINE void set_transform(const LMatrix4d &mat);
+  INLINE LMatrix3d get_transform_2d() const;
   INLINE const LMatrix4d &get_transform() const;
   INLINE const LMatrix4d &get_transform() const;
   INLINE bool transform_is_identity() const;
   INLINE bool transform_is_identity() const;
 
 
   enum ComponentType {
   enum ComponentType {
     CT_invalid,
     CT_invalid,
-    CT_translate,
+    CT_translate2d,
+    CT_translate3d,
+    CT_rotate2d,
     CT_rotx,
     CT_rotx,
     CT_roty,
     CT_roty,
     CT_rotz,
     CT_rotz,
-    CT_rotate,
-    CT_scale,
+    CT_rotate3d,
+    CT_scale2d,
+    CT_scale3d,
     CT_uniform_scale,
     CT_uniform_scale,
-    CT_matrix
+    CT_matrix3,
+    CT_matrix4
   };
   };
 
 
   INLINE int get_num_components() const;
   INLINE int get_num_components() const;
   INLINE ComponentType get_component_type(int n) const;
   INLINE ComponentType get_component_type(int n) const;
   INLINE double get_component_number(int n) const;
   INLINE double get_component_number(int n) const;
-  INLINE const LVector3d &get_component_vector(int n) const;
-  INLINE const LMatrix4d &get_component_matrix(int n) const;
+  INLINE const LVecBase2d &get_component_vec2(int n) const;
+  INLINE const LVecBase3d &get_component_vec3(int n) const;
+  INLINE const LMatrix3d &get_component_mat3(int n) const;
+  INLINE const LMatrix4d &get_component_mat4(int n) const;
 
 
   void write(ostream &out, int indent_level) const;
   void write(ostream &out, int indent_level) const;
 
 
 protected:
 protected:
   void internal_clear_transform();
   void internal_clear_transform();
+  void internal_add_matrix(const LMatrix3d &mat);
   void internal_add_matrix(const LMatrix4d &mat);
   void internal_add_matrix(const LMatrix4d &mat);
+  INLINE void internal_set_transform(const LMatrix3d &mat);
   INLINE void internal_set_transform(const LMatrix4d &mat);
   INLINE void internal_set_transform(const LMatrix4d &mat);
 
 
   virtual void transform_changed();
   virtual void transform_changed();
@@ -91,15 +109,18 @@ private:
 
 
     ComponentType _type;
     ComponentType _type;
     double _number;
     double _number;
-    LVector3d *_vector;
-    LMatrix4d *_matrix;
+    LVecBase2d *_vec2;
+    LVecBase3d *_vec3;
+    LMatrix3d *_mat3;
+    LMatrix4d *_mat4;
   };
   };
 
 
+  bool _is_transform_2d;
   typedef pvector<Component> Components;
   typedef pvector<Component> Components;
   Components _components;
   Components _components;
   LMatrix4d _transform;
   LMatrix4d _transform;
 };
 };
 
 
-#include "eggTransform3d.I"
+#include "eggTransform.I"
 
 
 #endif
 #endif

+ 0 - 240
panda/src/egg/eggTransform3d.I

@@ -1,240 +0,0 @@
-// Filename: eggTransform3d.I
-// Created by:  drose (21Jun02)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://etc.cmu.edu/panda3d/docs/license/ .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Component::Constructor
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE EggTransform3d::Component::
-Component(EggTransform3d::ComponentType type, double number) :
-  _type(type),
-  _number(number)
-{
-  _vector = (LVector3d *)NULL;
-  _matrix = (LMatrix4d *)NULL;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Component::Copy Constructor
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE EggTransform3d::Component::
-Component(const EggTransform3d::Component &copy) :
-  _type(copy._type),
-  _number(copy._number)
-{
-  _vector = (LVector3d *)NULL;
-  _matrix = (LMatrix4d *)NULL;
-  if (copy._vector != (LVector3d *)NULL) {
-    _vector = new LVector3d(*copy._vector);
-  }
-  if (copy._matrix != (LMatrix4d *)NULL) {
-    _matrix = new LMatrix4d(*copy._matrix);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Component::Copy Assignment Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE void EggTransform3d::Component::
-operator = (const EggTransform3d::Component &copy) {
-  _type = copy._type;
-  _number = copy._number;
-  if (_vector != (LVector3d *)NULL) {
-    delete _vector;
-    _vector = (LVector3d *)NULL;
-  }
-  if (_matrix != (LMatrix4d *)NULL) {
-    delete _matrix;
-    _matrix = (LMatrix4d *)NULL;
-  }
-  if (copy._vector != (LVector3d *)NULL) {
-    _vector = new LVector3d(*copy._vector);
-  }
-  if (copy._matrix != (LMatrix4d *)NULL) {
-    _matrix = new LMatrix4d(*copy._matrix);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::Component::Destructor
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE EggTransform3d::Component::
-~Component() {
-  if (_vector != (LVector3d *)NULL) {
-    delete _vector;
-  }
-  if (_matrix != (LMatrix4d *)NULL) {
-    delete _matrix;
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::clear_transform
-//       Access: Public
-//  Description: Resets the transform to empty, identity.
-////////////////////////////////////////////////////////////////////
-INLINE void EggTransform3d::
-clear_transform() {
-  internal_clear_transform();
-  transform_changed();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::add_matrix
-//       Access: Public
-//  Description: Appends an arbitrary 4x4 matrix to the current
-//               transform.
-////////////////////////////////////////////////////////////////////
-INLINE void EggTransform3d::
-add_matrix(const LMatrix4d &mat) {
-  internal_add_matrix(mat);
-  transform_changed();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::has_transform
-//       Access: Public
-//  Description: Returns true if the transform is nonempty, false if
-//               it is empty (no transform components have been
-//               added).
-////////////////////////////////////////////////////////////////////
-INLINE bool EggTransform3d::
-has_transform() const {
-  return !_components.empty();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::set_transform
-//       Access: Public
-//  Description: Sets the overall transform as a 4x4 matrix.  This
-//               completely replaces whatever componentwise transform
-//               may have been defined.
-////////////////////////////////////////////////////////////////////
-INLINE void EggTransform3d::
-set_transform(const LMatrix4d &mat) {
-  internal_set_transform(mat);
-  transform_changed();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_transform
-//       Access: Public
-//  Description: Returns the overall transform as a 4x4 matrix.
-////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4d &EggTransform3d::
-get_transform() const {
-  return _transform;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::transform_is_identity
-//       Access: Public
-//  Description: Returns true if the described transform is identity,
-//               false otherwise.
-////////////////////////////////////////////////////////////////////
-INLINE bool EggTransform3d::
-transform_is_identity() const {
-  return _components.empty() ||
-    _transform.almost_equal(LMatrix4d::ident_mat(), 0.0001);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_num_components
-//       Access: Public
-//  Description: Returns the number of components that make up the
-//               transform.
-////////////////////////////////////////////////////////////////////
-INLINE int EggTransform3d::
-get_num_components() const {
-  return _components.size();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_component_type
-//       Access: Public
-//  Description: Returns the type of the nth component.
-////////////////////////////////////////////////////////////////////
-INLINE EggTransform3d::ComponentType EggTransform3d::
-get_component_type(int n) const {
-  nassertr(n >= 0 && n < (int)_components.size(), CT_invalid);
-  return _components[n]._type;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_component_number
-//       Access: Public
-//  Description: Returns the solitary number associated with the nth
-//               component.  In the case of a rotation, this is the
-//               angle in degrees to rotate; in the case of uniform
-//               scale, this is the amount of the scale.  Other types
-//               do not use this property.
-////////////////////////////////////////////////////////////////////
-INLINE double EggTransform3d::
-get_component_number(int n) const {
-  nassertr(n >= 0 && n < (int)_components.size(), 0.0);
-  return _components[n]._number;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_component_vector
-//       Access: Public
-//  Description: Returns the 3-component vector associated with the
-//               nth component.  This may be the translate vector,
-//               rotate axis, or non-uniform scale.  It is an error to
-//               call this if the component type does not use a vector
-//               property.
-////////////////////////////////////////////////////////////////////
-INLINE const LVector3d &EggTransform3d::
-get_component_vector(int n) const {
-  nassertr(n >= 0 && n < (int)_components.size(), LVector3d::zero());
-  nassertr(_components[n]._vector != (LVector3d *)NULL, LVector3d::zero());
-  return *_components[n]._vector;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::get_component_matrix
-//       Access: Public
-//  Description: Returns the 4x4 matrix associated with the nth
-//               component.  It is an error to call this if the
-//               component type is not CT_matrix.
-////////////////////////////////////////////////////////////////////
-INLINE const LMatrix4d &EggTransform3d::
-get_component_matrix(int n) const {
-  nassertr(n >= 0 && n < (int)_components.size(), LMatrix4d::ident_mat());
-  nassertr(_components[n]._matrix != (LMatrix4d *)NULL, LMatrix4d::ident_mat());
-  return *_components[n]._matrix;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggTransform3d::internal_set_transform
-//       Access: Protected
-//  Description: Sets the overall transform without calling
-//               transform_changed().
-////////////////////////////////////////////////////////////////////
-INLINE void EggTransform3d::
-internal_set_transform(const LMatrix4d &mat) {
-  internal_clear_transform();
-  internal_add_matrix(mat);
-}

+ 1 - 1
panda/src/egg/eggVertex.I

@@ -211,7 +211,7 @@ has_uv() const {
 //               multitexturing; see get_uv(name) for the interface
 //               multitexturing; see get_uv(name) for the interface
 //               that supports multitexturing.
 //               that supports multitexturing.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const TexCoordd &EggVertex::
+INLINE TexCoordd EggVertex::
 get_uv() const {
 get_uv() const {
   nassertr(has_uv(), TexCoordd::zero());
   nassertr(has_uv(), TexCoordd::zero());
   return get_uv("");
   return get_uv("");

+ 62 - 4
panda/src/egg/eggVertex.cxx

@@ -117,12 +117,34 @@ EggVertex::
 //     Function: EggVertex::has_uv
 //     Function: EggVertex::has_uv
 //       Access: Published
 //       Access: Published
 //  Description: Returns true if the vertex has the named UV
 //  Description: Returns true if the vertex has the named UV
-//               coordinate pair, false otherwise.
+//               coordinate pair, and the named UV coordinate pair is
+//               2-d, false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool EggVertex::
 bool EggVertex::
 has_uv(const string &name) const {
 has_uv(const string &name) const {
   UVMap::const_iterator ui = _uv_map.find(name);
   UVMap::const_iterator ui = _uv_map.find(name);
-  return (ui != _uv_map.end());
+  if (ui != _uv_map.end()) {
+    EggVertexUV *uv_obj = (*ui).second;
+    return !uv_obj->has_w();
+  }
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::has_uvw
+//       Access: Published
+//  Description: Returns true if the vertex has the named UV
+//               coordinate triple, and the named UV coordinate triple is
+//               3-d, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool EggVertex::
+has_uvw(const string &name) const {
+  UVMap::const_iterator ui = _uv_map.find(name);
+  if (ui != _uv_map.end()) {
+    EggVertexUV *uv_obj = (*ui).second;
+    return uv_obj->has_w();
+  }
+  return false;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -132,13 +154,27 @@ has_uv(const string &name) const {
 //               vertex.  It is an error to call this if has_uv(name)
 //               vertex.  It is an error to call this if has_uv(name)
 //               returned false.
 //               returned false.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-const TexCoordd &EggVertex::
+TexCoordd EggVertex::
 get_uv(const string &name) const {
 get_uv(const string &name) const {
   UVMap::const_iterator ui = _uv_map.find(name);
   UVMap::const_iterator ui = _uv_map.find(name);
   nassertr(ui != _uv_map.end(), TexCoordd::zero());
   nassertr(ui != _uv_map.end(), TexCoordd::zero());
   return (*ui).second->get_uv();
   return (*ui).second->get_uv();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::get_uvw
+//       Access: Published
+//  Description: Returns the named UV coordinate triple on the vertex.
+//               vertex.  It is an error to call this if has_uvw(name)
+//               returned false.
+////////////////////////////////////////////////////////////////////
+const TexCoord3d &EggVertex::
+get_uvw(const string &name) const {
+  UVMap::const_iterator ui = _uv_map.find(name);
+  nassertr(ui != _uv_map.end(), TexCoord3d::zero());
+  return (*ui).second->get_uvw();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::set_uv
 //     Function: EggVertex::set_uv
 //       Access: Published
 //       Access: Published
@@ -160,6 +196,28 @@ set_uv(const string &name, const TexCoordd &uv) {
   nassertv(get_uv(name) == uv);
   nassertv(get_uv(name) == uv);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::set_uvw
+//       Access: Published
+//  Description: Sets the indicated UV coordinate triple on the vertex.
+//               This replaces any UV coordinate pair or triple with
+//               the same name already on the vertex, but preserves UV
+//               morphs.
+////////////////////////////////////////////////////////////////////
+void EggVertex::
+set_uvw(const string &name, const TexCoord3d &uvw) {
+  PT(EggVertexUV) &uv_obj = _uv_map[name];
+
+  if (uv_obj.is_null()) {
+    uv_obj = new EggVertexUV(name, uvw);
+  } else {
+    uv_obj = new EggVertexUV(*uv_obj);
+    uv_obj->set_uvw(uvw);
+  }
+
+  nassertv(get_uvw(name) == uvw);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::get_uv_obj
 //     Function: EggVertex::get_uv_obj
 //       Access: Published
 //       Access: Published
@@ -257,7 +315,7 @@ write(ostream &out, int indent_level) const {
 
 
   EggAttributes::write(out, indent_level+2);
   EggAttributes::write(out, indent_level+2);
 
 
-  _dxyzs.write(out, indent_level+2);
+  _dxyzs.write(out, indent_level + 2, "<Dxyz>", 3);
 
 
   // If the vertex is referenced by one or more groups, write that as
   // If the vertex is referenced by one or more groups, write that as
   // a helpful comment.
   // a helpful comment.

+ 5 - 2
panda/src/egg/eggVertex.h

@@ -82,12 +82,15 @@ PUBLISHED:
   INLINE LPoint4d get_pos4() const;
   INLINE LPoint4d get_pos4() const;
 
 
   INLINE bool has_uv() const;
   INLINE bool has_uv() const;
-  INLINE const TexCoordd &get_uv() const;
+  INLINE TexCoordd get_uv() const;
   INLINE void set_uv(const TexCoordd &texCoord);
   INLINE void set_uv(const TexCoordd &texCoord);
   INLINE void clear_uv();
   INLINE void clear_uv();
   bool has_uv(const string &name) const;
   bool has_uv(const string &name) const;
-  const TexCoordd &get_uv(const string &name) const;
+  bool has_uvw(const string &name) const;
+  TexCoordd get_uv(const string &name) const;
+  const TexCoord3d &get_uvw(const string &name) const;
   void set_uv(const string &name, const TexCoordd &texCoord);
   void set_uv(const string &name, const TexCoordd &texCoord);
+  void set_uvw(const string &name, const TexCoord3d &texCoord);
   EggVertexUV *get_uv_obj(const string &name) const;
   EggVertexUV *get_uv_obj(const string &name) const;
   void set_uv_obj(EggVertexUV *vertex_uv);
   void set_uv_obj(EggVertexUV *vertex_uv);
   void clear_uv(const string &name);
   void clear_uv(const string &name);

+ 15 - 6
panda/src/egg/eggVertexPool.cxx

@@ -295,14 +295,17 @@ has_uvs() const {
 //     Function: EggVertexPool::get_uv_names
 //     Function: EggVertexPool::get_uv_names
 //       Access: Public
 //       Access: Public
 //  Description: Returns the list of UV names that are defined by any
 //  Description: Returns the list of UV names that are defined by any
-//               vertices in the pool.  Also returns the subset of UV
-//               names that define the tangent and binormal.  It is
-//               the user's responsibility to clear both vectors
-//               before calling this method.
+//               vertices in the pool, as well as the subset of UV
+//               names that actually define 3-d texture coordinates
+//               ("uvw_names").  Also returns the subset of UV/UVW
+//               names that define a tangent and binormal.  It is the
+//               user's responsibility to clear both vectors before
+//               calling this method.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void EggVertexPool::
 void EggVertexPool::
-get_uv_names(vector_string &uv_names, vector_string &tbn_names) const {
-  pset<string> uv_names_set, tbn_names_set;
+get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
+             vector_string &tbn_names) const {
+  pset<string> uv_names_set, uvw_names_set, tbn_names_set;
   IndexVertices::const_iterator ivi;
   IndexVertices::const_iterator ivi;
   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
   for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
     EggVertex *vertex = (*ivi).second;
     EggVertex *vertex = (*ivi).second;
@@ -310,6 +313,9 @@ get_uv_names(vector_string &uv_names, vector_string &tbn_names) const {
     for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
     for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
       EggVertexUV *uv_obj = (*uvi);
       EggVertexUV *uv_obj = (*uvi);
       uv_names_set.insert(uv_obj->get_name());
       uv_names_set.insert(uv_obj->get_name());
+      if (uv_obj->has_w()) {
+        uvw_names_set.insert(uv_obj->get_name());
+      }
       if (uv_obj->has_tangent() && uv_obj->has_binormal()) {
       if (uv_obj->has_tangent() && uv_obj->has_binormal()) {
         tbn_names_set.insert(uv_obj->get_name());
         tbn_names_set.insert(uv_obj->get_name());
       }
       }
@@ -320,6 +326,9 @@ get_uv_names(vector_string &uv_names, vector_string &tbn_names) const {
   for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) {
   for (si = uv_names_set.begin(); si != uv_names_set.end(); ++si) {
     uv_names.push_back(*si);
     uv_names.push_back(*si);
   }
   }
+  for (si = uvw_names_set.begin(); si != uvw_names_set.end(); ++si) {
+    uvw_names.push_back(*si);
+  }
   for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) {
   for (si = tbn_names_set.begin(); si != tbn_names_set.end(); ++si) {
     tbn_names.push_back(*si);
     tbn_names.push_back(*si);
   }
   }

+ 2 - 1
panda/src/egg/eggVertexPool.h

@@ -98,7 +98,8 @@ PUBLISHED:
   bool has_colors() const;
   bool has_colors() const;
   bool has_nonwhite_colors() const;
   bool has_nonwhite_colors() const;
   bool has_uvs() const;
   bool has_uvs() const;
-  void get_uv_names(vector_string &uv_names, vector_string &tbn_names) const;
+  void get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
+                    vector_string &tbn_names) const;
 
 
 public:
 public:
   // Can be used to traverse all the vertices in index number order.
   // Can be used to traverse all the vertices in index number order.

+ 73 - 5
panda/src/egg/eggVertexUV.I

@@ -17,24 +17,92 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::set_name
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void EggVertexUV::
+set_name(const string &name) {
+  if (name == "default") {
+    clear_name();
+  } else {
+    Namable::set_name(name);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::get_num_dimensions
+//       Access: Published
+//  Description: Returns the number of components of the texture
+//               coordinate set.  This is either 2 (the normal case)
+//               or 3 (for a 3-d texture coordinate).
+////////////////////////////////////////////////////////////////////
+INLINE int EggVertexUV::
+get_num_dimensions() const {
+  return has_w() ? 3 : 2;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::has_w
+//       Access: Published
+//  Description: Returns true if the texture coordinate has a third, w
+//               component, false if it is just a normal 2-d texture
+//               coordinate.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggVertexUV::
+has_w() const {
+  return (_flags & F_has_w) != 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::get_uv
 //     Function: EggVertexUV::get_uv
 //       Access: Published
 //       Access: Published
-//  Description: Returns the texture coordinate pair.
+//  Description: Returns the texture coordinate pair, if
+//               get_num_dimensions() is 2.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const TexCoordd &EggVertexUV::
+INLINE TexCoordd EggVertexUV::
 get_uv() const {
 get_uv() const {
-  return _uv;
+  nassertr(!has_w(), TexCoordd::zero());
+  return TexCoordd(_uvw[0], _uvw[1]);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::get_uvw
+//       Access: Published
+//  Description: Returns the texture coordinate triple, if
+//               get_num_dimensions() is 3.  This is also legal to
+//               call if get_num_dimensions() is 2 (but the last
+//               dimension will be zero).
+////////////////////////////////////////////////////////////////////
+INLINE const TexCoord3d &EggVertexUV::
+get_uvw() const {
+  return _uvw;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexUV::set_uv
 //     Function: EggVertexUV::set_uv
 //       Access: Published
 //       Access: Published
-//  Description: Sets the texture coordinate pair.
+//  Description: Sets the texture coordinate pair.  This makes the
+//               texture coordinate a 2-d texture coordinate, which is
+//               the usual case.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void EggVertexUV::
 INLINE void EggVertexUV::
 set_uv(const TexCoordd &uv) {
 set_uv(const TexCoordd &uv) {
-  _uv = uv;
+  _uvw.set(uv[0], uv[1], 0.0);
+  _flags &= ~F_has_w;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::set_uvw
+//       Access: Published
+//  Description: Sets the texture coordinate triple.  This makes the
+//               texture coordinate a 3-d texture coordinate.
+////////////////////////////////////////////////////////////////////
+INLINE void EggVertexUV::
+set_uvw(const TexCoord3d &uvw) {
+  _uvw = uvw;
+  _flags |= F_has_w;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 37 - 9
panda/src/egg/eggVertexUV.cxx

@@ -32,8 +32,27 @@ EggVertexUV::
 EggVertexUV(const string &name, const TexCoordd &uv) :
 EggVertexUV(const string &name, const TexCoordd &uv) :
   EggNamedObject(name),
   EggNamedObject(name),
   _flags(0),
   _flags(0),
-  _uv(uv)
+  _uvw(uv[0], uv[1], 0.0)
 {
 {
+  if (get_name() == "default") {
+    clear_name();
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexUV::Constructor
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggVertexUV::
+EggVertexUV(const string &name, const TexCoord3d &uvw) :
+  EggNamedObject(name),
+  _flags(F_has_w),
+  _uvw(uvw)
+{
+  if (get_name() == "default") {
+    clear_name();
+  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -48,7 +67,7 @@ EggVertexUV(const EggVertexUV &copy) :
   _flags(copy._flags),
   _flags(copy._flags),
   _tangent(copy._tangent),
   _tangent(copy._tangent),
   _binormal(copy._binormal),
   _binormal(copy._binormal),
-  _uv(copy._uv)
+  _uvw(copy._uvw)
 {
 {
 }
 }
 
 
@@ -64,7 +83,7 @@ operator = (const EggVertexUV &copy) {
   _flags = copy._flags;
   _flags = copy._flags;
   _tangent = copy._tangent;
   _tangent = copy._tangent;
   _binormal = copy._binormal;
   _binormal = copy._binormal;
-  _uv = copy._uv;
+  _uvw = copy._uvw;
 
 
   return (*this);
   return (*this);
 }
 }
@@ -109,12 +128,21 @@ write(ostream &out, int indent_level) const {
     inline_name += ' ';
     inline_name += ' ';
   }
   }
 
 
-  if (_duvs.empty() && _flags == 0) {
-    indent(out, indent_level)
-      << "<UV> " << inline_name << "{ " << get_uv() << " }\n";
+  if (_duvs.empty() && (_flags & ~F_has_w) == 0) {
+    if (has_w()) {
+      indent(out, indent_level)
+        << "<UV> " << inline_name << "{ " << get_uvw() << " }\n";
+    } else {
+      indent(out, indent_level)
+        << "<UV> " << inline_name << "{ " << get_uv() << " }\n";
+    }
   } else {
   } else {
     indent(out, indent_level) << "<UV> " << inline_name << "{\n";
     indent(out, indent_level) << "<UV> " << inline_name << "{\n";
-    indent(out, indent_level+2) << get_uv() << "\n";
+    if (has_w()) {
+      indent(out, indent_level+2) << get_uvw() << "\n";
+    } else {
+      indent(out, indent_level+2) << get_uv() << "\n";
+    }
     if (has_tangent()) {
     if (has_tangent()) {
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
         << "<Tangent> { " << get_tangent() << " }\n";
         << "<Tangent> { " << get_tangent() << " }\n";
@@ -123,7 +151,7 @@ write(ostream &out, int indent_level) const {
       indent(out, indent_level + 2)
       indent(out, indent_level + 2)
         << "<Binormal> { " << get_binormal() << " }\n";
         << "<Binormal> { " << get_binormal() << " }\n";
     }
     }
-    _duvs.write(out, indent_level+2);
+    _duvs.write(out, indent_level + 2, "<Duv>", get_num_dimensions());
     indent(out, indent_level) << "}\n";
     indent(out, indent_level) << "}\n";
   }
   }
 }
 }
@@ -141,7 +169,7 @@ compare_to(const EggVertexUV &other) const {
     return _flags - other._flags;
     return _flags - other._flags;
   }
   }
   int compare;
   int compare;
-  compare = _uv.compare_to(other._uv, egg_parameters->_uv_threshold);
+  compare = _uvw.compare_to(other._uvw, egg_parameters->_uv_threshold);
   if (compare != 0) {
   if (compare != 0) {
     return compare;
     return compare;
   }
   }

+ 10 - 2
panda/src/egg/eggVertexUV.h

@@ -36,12 +36,19 @@
 class EXPCL_PANDAEGG EggVertexUV : public EggNamedObject {
 class EXPCL_PANDAEGG EggVertexUV : public EggNamedObject {
 PUBLISHED:
 PUBLISHED:
   EggVertexUV(const string &name, const TexCoordd &uv);
   EggVertexUV(const string &name, const TexCoordd &uv);
+  EggVertexUV(const string &name, const TexCoord3d &uvw);
   EggVertexUV(const EggVertexUV &copy);
   EggVertexUV(const EggVertexUV &copy);
   EggVertexUV &operator = (const EggVertexUV &copy);
   EggVertexUV &operator = (const EggVertexUV &copy);
   virtual ~EggVertexUV();
   virtual ~EggVertexUV();
 
 
-  INLINE const TexCoordd &get_uv() const;
+  INLINE void set_name(const string &name);
+
+  INLINE int get_num_dimensions() const;
+  INLINE bool has_w() const;
+  INLINE TexCoordd get_uv() const;
+  INLINE const TexCoord3d &get_uvw() const;
   INLINE void set_uv(const TexCoordd &texCoord);
   INLINE void set_uv(const TexCoordd &texCoord);
+  INLINE void set_uvw(const TexCoord3d &texCoord);
 
 
   INLINE bool has_tangent() const;
   INLINE bool has_tangent() const;
   INLINE const Normald &get_tangent() const;
   INLINE const Normald &get_tangent() const;
@@ -64,12 +71,13 @@ private:
   enum Flags {
   enum Flags {
     F_has_tangent   = 0x001,
     F_has_tangent   = 0x001,
     F_has_binormal  = 0x002,
     F_has_binormal  = 0x002,
+    F_has_w         = 0x004,
   };
   };
 
 
   int _flags;
   int _flags;
   Normald _tangent;
   Normald _tangent;
   Normald _binormal;
   Normald _binormal;
-  TexCoordd _uv;
+  TexCoord3d _uvw;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 1 - 1
panda/src/egg/egg_composite2.cxx

@@ -12,7 +12,7 @@
 #include "eggTable.cxx"
 #include "eggTable.cxx"
 #include "eggTexture.cxx"
 #include "eggTexture.cxx"
 #include "eggTextureCollection.cxx"
 #include "eggTextureCollection.cxx"
-#include "eggTransform3d.cxx"
+#include "eggTransform.cxx"
 #include "eggTriangleFan.cxx"
 #include "eggTriangleFan.cxx"
 #include "eggTriangleStrip.cxx"
 #include "eggTriangleStrip.cxx"
 #include "eggUserData.cxx"
 #include "eggUserData.cxx"

+ 2944 - 2965
panda/src/egg/lexer.cxx.prebuilt

@@ -1,2965 +1,2944 @@
-#define yy_create_buffer eggyy_create_buffer
-#define yy_delete_buffer eggyy_delete_buffer
-#define yy_scan_buffer eggyy_scan_buffer
-#define yy_scan_string eggyy_scan_string
-#define yy_scan_bytes eggyy_scan_bytes
-#define yy_flex_debug eggyy_flex_debug
-#define yy_init_buffer eggyy_init_buffer
-#define yy_flush_buffer eggyy_flush_buffer
-#define yy_load_buffer_state eggyy_load_buffer_state
-#define yy_switch_to_buffer eggyy_switch_to_buffer
-#define yyin eggyyin
-#define yyleng eggyyleng
-#define yylex eggyylex
-#define yyout eggyyout
-#define yyrestart eggyyrestart
-#define yytext eggyytext
-#define yywrap eggyywrap
-
-#line 20 "lex.yy.c"
-/* A lexical scanner generated by flex */
-
-/* Scanner skeleton version:
- * $Header$
- */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-
-#include <stdio.h>
-#include <errno.h>
-
-/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
-#ifdef c_plusplus
-#ifndef __cplusplus
-#define __cplusplus
-#endif
-#endif
-
-
-#ifdef __cplusplus
-
-#include <stdlib.h>
-#ifndef _WIN32
-#endif
-
-/* Use prototypes in function declarations. */
-#define YY_USE_PROTOS
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else	/* ! __cplusplus */
-
-#if __STDC__
-
-#define YY_USE_PROTOS
-#define YY_USE_CONST
-
-#endif	/* __STDC__ */
-#endif	/* ! __cplusplus */
-
-#ifdef __TURBOC__
- #pragma warn -rch
- #pragma warn -use
-#include <io.h>
-#include <stdlib.h>
-#define YY_USE_CONST
-#define YY_USE_PROTOS
-#endif
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-
-#ifdef YY_USE_PROTOS
-#define YY_PROTO(proto) proto
-#else
-#define YY_PROTO(proto) ()
-#endif
-
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index.  If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition.  This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN yy_start = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state.  The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START ((yy_start - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart( yyin )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#define YY_BUF_SIZE 16384
-
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-
-extern int yyleng;
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
-/* The funky do-while in the following #define is used to turn the definition
- * int a single C statement (which needs a semi-colon terminator).  This
- * avoids problems with code like:
- *
- * 	if ( condition_holds )
- *		yyless( 5 );
- *	else
- *		do_something_else();
- *
- * Prior to using the do-while the compiler would get upset at the
- * "else" because it interpreted the "if" statement as being all
- * done when it reached the ';' after the yyless() call.
- */
-
-/* Return all but the first 'n' matched characters back to the input stream. */
-
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-		*yy_cp = yy_hold_char; \
-		YY_RESTORE_YY_MORE_OFFSET \
-		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
-		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
-		} \
-	while ( 0 )
-
-#define unput(c) yyunput( c, yytext_ptr )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- */
-typedef unsigned int yy_size_t;
-
-
-struct yy_buffer_state
-	{
-	FILE *yy_input_file;
-
-	char *yy_ch_buf;		/* input buffer */
-	char *yy_buf_pos;		/* current position in input buffer */
-
-	/* Size of input buffer in bytes, not including room for EOB
-	 * characters.
-	 */
-	yy_size_t yy_buf_size;
-
-	/* Number of characters read into yy_ch_buf, not including EOB
-	 * characters.
-	 */
-	int yy_n_chars;
-
-	/* Whether we "own" the buffer - i.e., we know we created it,
-	 * and can realloc() it to grow it, and should free() it to
-	 * delete it.
-	 */
-	int yy_is_our_buffer;
-
-	/* Whether this is an "interactive" input source; if so, and
-	 * if we're using stdio for input, then we want to use getc()
-	 * instead of fread(), to make sure we stop fetching input after
-	 * each newline.
-	 */
-	int yy_is_interactive;
-
-	/* Whether we're considered to be at the beginning of a line.
-	 * If so, '^' rules will be active on the next match, otherwise
-	 * not.
-	 */
-	int yy_at_bol;
-
-	/* Whether to try to fill the input buffer when we reach the
-	 * end of it.
-	 */
-	int yy_fill_buffer;
-
-	int yy_buffer_status;
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
-	/* When an EOF's been seen but there's still some text to process
-	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
-	 * shouldn't try reading from the input source any more.  We might
-	 * still have a bunch of tokens to match, though, because of
-	 * possible backing-up.
-	 *
-	 * When we actually see the EOF, we change the status to "new"
-	 * (via yyrestart()), so that the user can continue scanning by
-	 * just pointing yyin at a new input file.
-	 */
-#define YY_BUFFER_EOF_PENDING 2
-	};
-
-static YY_BUFFER_STATE yy_current_buffer = 0;
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- */
-#define YY_CURRENT_BUFFER yy_current_buffer
-
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-
-
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 1;		/* whether we need to initialize */
-static int yy_start = 0;	/* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin.  A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart YY_PROTO(( FILE *input_file ));
-
-void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
-void yy_load_buffer_state YY_PROTO(( void ));
-YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
-void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
-void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
-#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
-
-YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
-YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
-YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
-
-static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
-static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
-static void yy_flex_free YY_PROTO(( void * ));
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
-	{ \
-	if ( ! yy_current_buffer ) \
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
-	yy_current_buffer->yy_is_interactive = is_interactive; \
-	}
-
-#define yy_set_bol(at_bol) \
-	{ \
-	if ( ! yy_current_buffer ) \
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
-	yy_current_buffer->yy_at_bol = at_bol; \
-	}
-
-#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
-
-typedef unsigned char YY_CHAR;
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-typedef int yy_state_type;
-extern char *yytext;
-#define yytext_ptr yytext
-
-static yy_state_type yy_get_previous_state YY_PROTO(( void ));
-static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
-static int yy_get_next_buffer YY_PROTO(( void ));
-static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
-	yytext_ptr = yy_bp; \
-	yyleng = (int) (yy_cp - yy_bp); \
-	yy_hold_char = *yy_cp; \
-	*yy_cp = '\0'; \
-	yy_c_buf_p = yy_cp;
-
-#define YY_NUM_RULES 98
-#define YY_END_OF_BUFFER 99
-static yyconst short int yy_accept[557] =
-    {   0,
-        0,    0,   99,   97,    2,    1,   96,   97,   97,   97,
-       97,   90,   90,   97,   97,   97,    5,   97,    1,   97,
-       90,   97,   90,    4,    3,   90,   92,   97,   91,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,    3,    3,   92,   97,   90,   91,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       66,   97,   97,   97,   94,   97,   95,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   18,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   32,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   81,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   24,   97,   97,   97,   97,
-
-       22,   97,   97,   97,   97,   97,   31,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   52,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   67,   97,   97,   97,
-       97,   97,   97,   97,   97,   78,   97,   97,   97,   97,
-       97,   97,   93,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   19,   97,   97,   97,   97,   23,
-       97,   28,   97,   97,   97,   97,   97,   97,   37,   38,
-       97,   97,   97,   43,   97,   97,   97,   97,   97,   97,
-       97,   53,   97,   55,   56,   57,   97,   97,   97,   97,
-
-       97,   97,   97,   97,   97,   97,   97,   97,   74,   97,
-       77,   97,   97,   97,   97,   97,   97,   93,   97,    7,
-       97,   97,   97,   12,   97,   97,   97,   97,   97,   97,
-       97,   21,   26,   97,   97,   30,   97,   97,   33,   34,
-       97,   97,   42,   97,   97,   97,   97,   48,   97,   97,
-       97,   97,   97,   97,   60,   97,   97,   97,   65,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   11,   13,   97,   97,   97,
-       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-       44,   97,   97,   97,   97,   97,   97,   54,   58,   59,
-
-       97,   97,   63,   97,   97,   97,   97,   97,   97,   97,
-       97,   97,   97,   97,   97,   84,   97,   97,   97,   97,
-       97,   97,   97,   14,   15,   97,   97,   97,   20,   97,
-       97,   35,   97,   97,   40,   41,   97,   97,   97,   97,
-       97,   51,   97,   62,   97,   68,   69,   70,   97,   97,
-       97,   97,   79,   80,   82,   83,   97,   97,   97,   97,
-       97,   97,   10,   97,   97,   25,   97,   97,   36,   39,
-       97,   97,   97,   97,   97,   61,   97,   71,   97,   97,
-       97,   97,   97,   97,   97,   88,   97,   97,    8,   97,
-       16,   97,   97,   97,   97,   97,   97,   97,   97,   97,
-
-       72,   73,   97,   97,   97,   97,   87,   97,   97,   97,
-       97,   97,   29,   45,   97,   47,   49,   50,   97,   97,
-       97,   85,   86,   97,    6,   97,   97,   97,   97,   97,
-       75,   97,   89,   97,   97,   97,   46,   97,   97,   97,
-       97,   97,   97,   76,   97,   97,   97,   97,    9,   97,
-       97,   64,   17,   97,   27,    0
-    } ;
-
-static yyconst int yy_ec[256] =
-    {   0,
-        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
-        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    2,    1,    4,    1,    5,    1,    1,    1,    1,
-        1,    6,    7,    1,    8,    9,   10,   11,   12,   13,
-       14,   15,   13,   13,   13,   13,   13,    1,    1,   16,
-        1,   17,    1,    1,   19,   20,   21,   22,   23,   24,
-       25,   26,   27,   28,   29,   30,   31,   32,   33,   34,
-       35,   36,   37,   38,   39,   40,   41,   42,   43,   44,
-        1,    1,    1,    1,   18,    1,   19,   20,   21,   22,
-
-       23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
-       33,   34,   35,   36,   37,   38,   39,   40,   41,   42,
-       43,   44,   45,    1,   45,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1
-    } ;
-
-static yyconst int yy_meta[46] =
-    {   0,
-        1,    2,    3,    2,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,    1,    2
-    } ;
-
-static yyconst short int yy_base[562] =
-    {   0,
-        0,   44,  663,    0,  664,    0,  664,    8,   81,   22,
-       18,  100,   19,  123,  630,  642,  664,    0,    0,   29,
-       30,  628,   51,    0,   65,   68,   14,  159,  164,   61,
-       91,  170,   43,  623,  631,  625,  623,  623,   70,   68,
-       66,   86,  621,   93,  175,  181,  128,  111,  629,  628,
-      619,  626,  136,    0,   18,  207,  213,    0,  605,  629,
-       45,  615,  627,  612,  102,  627,  607,  605,  604,  607,
-      614,  602,  597,  593,  603,  604,  595,  599,  597,  173,
-      603,  596,  596,  594,  588,  603,  601,  587,  586,  593,
-      598,  581,  100,  594,  597,  578,  596,  595,  578,  593,
-
-      584,  209,  568,  586,  176,  570,  578,  577,  588,  575,
-        0,  574,  566,  570,    0,  589,    0,  572,  577,  567,
-      563,  573,  558,  556,  562,  199,  555,    0,  552,  572,
-      550,  551,  566,  562,  567,  539,  563,  558,  562,  540,
-      561,    0,  547,  538,  543,  536,  550,  538,  146,  548,
-      546,  538,  548,  544,  543,  527,  532,  520,  545,  542,
-      195,  528,  529,  519,  535,  518,  525,  537,  528,   48,
-      520,  519,  526,  174,  532,  516,  515,    0,  514,  513,
-      506,  538,  500,  518,  517,  519,  502,  507,  530,  512,
-      507,  510,  499,  509,  513,    0,  510,  497,  508,  502,
-
-        0,  508,  493,  506,  496,  487,    0,  481,  500,  480,
-      480,  499,  498,  478,  486,  482,  494,  491,  472,  487,
-      471,  487,  467,  479,    0,  486,  464,  484,  483,  482,
-      471,   79,  474,  469,  474,  471,    0,  470,  465,  452,
-      465,  452,  471,  455,  469,    0,  452,  451,  450,  449,
-      458,  461,  231,  443,  461,  444,  445,  452,  457,  451,
-      450,  439,  438,  442,    0,  436,  448,  449,  448,    0,
-      437,    0,  440,  445,  439,  428,  442,  441,    0,    0,
-      430,  414,  438,    0,  424,  194,  415,  435,  419,  420,
-      416,    0,  425,    0,    0,    0,  416,  410,  428,  412,
-
-      411,  416,  424,  408,  402,  402,  399,  134,    0,  411,
-        0,  397,  396,  395,  394,  389,  398,    0,  408,    0,
-      409,  408,  409,    0,  408,  401,  385,  399,  389,  399,
-      389,    0,    0,  397,  398,    0,  393,  394,    0,    0,
-      395,  221,    0,  396,  373,  372,  372,    0,  384,  381,
-      375,  389,  388,  387,    0,  382,  377,  120,    0,  363,
-      362,  376,  372,  364,  377,  365,  357,  356,  355,  354,
-      230,  363,  350,  352,  357,    0,    0,  369,  368,  352,
-      364,  359,  364,  340,  357,  361,  354,  346,  358,  357,
-        0,  337,  336,  328,  347,  344,  351,    0,    0,    0,
-
-      344,  349,    0,  332,  347,  346,  345,  324,  324,  321,
-      335,  340,  339,  338,  337,    0,  321,  319,  328,  319,
-      313,  326,  330,    0,    0,  308,  307,  327,    0,  320,
-      319,    0,  324,  323,    0,    0,  299,  314,  303,  304,
-      309,    0,  317,    0,  301,    0,    0,    0,  315,  300,
-      307,  224,    0,    0,    0,    0,  302,  295,  303,  239,
-      286,  241,    0,  308,  301,    0,  287,  286,    0,    0,
-      298,  301,  296,  280,  279,    0,  294,    0,  298,  297,
-      294,  274,  280,  280,  292,    0,  271,  284,    0,  283,
-        0,  268,  266,  286,  285,  280,  283,  282,  281,  270,
-
-        0,    0,  264,  259,  277,  276,    0,  287,  274,  258,
-      246,  265,    0,    0,  264,    0,    0,    0,  248,  268,
-      257,    0,    0,  266,    0,  244,  244,  238,  262,  251,
-        0,  243,    0,  253,  227,  229,    0,  227,  242,  204,
-      209,  174,  160,    0,  122,   76,   35,   32,    0,   21,
-        1,    0,    0,    1,    0,  664,  266,    0,  269,  271,
-      273
-    } ;
-
-static yyconst short int yy_def[562] =
-    {   0,
-      557,  557,  556,  558,  556,  559,  556,  558,  558,  558,
-      558,  558,   12,  558,  558,  558,  556,  558,  559,  558,
-       12,  558,  558,  558,  560,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  560,  561,  558,  558,  558,   29,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  253,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
-      558,  558,  558,  558,  558,    0,  556,  556,  556,  556,
-      556
-    } ;
-
-static yyconst short int yy_nxt[710] =
-    {   0,
-       18,    5,    6,    7,  556,  556,    8,    9,   10,   11,
-       12,   13,   13,   13,   13,   14,   20,  555,   21,   21,
-       21,   21,   21,   24,   55,   55,   15,   25,   55,   55,
-      554,   16,   23,   23,   23,   23,   23,  553,   18,   23,
-       23,   23,   23,   23,   17,    5,    6,    7,  552,   18,
-        8,    9,   10,   11,   12,   13,   13,   13,   13,   14,
-       18,   23,   23,   23,   23,   23,   54,  551,   54,   76,
-       15,   18,   77,   28,  120,   16,  121,  239,   23,   23,
-       23,   23,   23,   59,   60,  240,   85,   61,   17,   20,
-       28,   21,   21,   21,   21,   21,   83,  298,   88,   62,
-
-       86,  299,   84,   87,   89,   90,  550,   22,   26,   54,
-       21,   21,   21,   21,   21,   94,   63,   95,  110,   27,
-       64,   91,   28,   65,   92,   96,  157,  111,  112,  158,
-       66,  125,  126,  113,  127,  107,  403,   54,  549,   54,
-      404,   29,   30,   31,   32,  108,   33,   34,   35,   36,
-       37,   38,   39,   40,   41,   42,   43,  364,   44,   45,
-       46,   47,   48,  365,   49,   56,   56,  109,  214,   57,
-       57,   57,   57,   57,   58,   58,   58,   58,   58,   97,
-       54,  215,   58,   58,   58,   58,   58,   58,   67,  142,
-       68,  548,  244,  143,  172,   98,   69,   99,  173,  102,
-
-      100,   70,  174,  103,  245,   71,  547,   72,   73,  144,
-      104,   74,   75,  227,  345,  101,  105,   57,   57,   57,
-       57,   57,  106,   57,   57,   57,   57,   57,  167,  192,
-      346,  546,  193,  168,  389,  390,  228,  229,  230,  545,
-      169,  318,  318,  318,  318,  318,  416,  481,  417,  318,
-      318,  318,  318,  318,  318,  486,  487,  489,  544,  543,
-      482,  490,  542,  418,  541,  419,    4,    4,    4,   19,
-       19,   53,   53,   54,   54,  540,  539,  538,  537,  536,
-      535,  534,  533,  532,  531,  530,  529,  528,  527,  526,
-      525,  524,  523,  522,  521,  520,  519,  518,  517,  516,
-
-      515,  514,  513,  512,  511,  510,  509,  508,  507,  506,
-      505,  504,  503,  502,  501,  500,  499,  498,  497,  496,
-      495,  494,  493,  492,  491,  488,  485,  484,  483,  480,
-      479,  478,  477,  476,  475,  474,  473,  472,  471,  470,
-      469,  468,  467,  466,  465,  464,  463,  462,  461,  460,
-      459,  458,  457,  456,  455,  454,  453,  452,  451,  450,
-      449,  448,  447,  446,  445,  444,  443,  442,  441,  440,
-      439,  438,  437,  436,  435,  434,  433,  432,  431,  430,
-      429,  428,  427,  426,  425,  424,  423,  422,  421,  420,
-      415,  414,  413,  412,  411,  410,  409,  408,  407,  406,
-
-      405,  402,  401,  400,  399,  398,  397,  396,  395,  394,
-      393,  392,  391,  388,  387,  386,  385,  384,  383,  382,
-      381,  380,  379,  378,  377,  376,  375,  374,  373,  372,
-      371,  370,  369,  368,  367,  366,  363,  362,  361,  360,
-      359,  358,  357,  356,  355,  354,  353,  352,  351,  350,
-      349,  348,  347,  344,  343,  342,  341,  340,  339,  338,
-      337,  336,  335,  334,  333,  332,  331,  330,  329,  328,
-      327,  326,  325,  324,  323,  322,  321,  320,  319,  317,
-      316,  315,  314,  313,  312,  311,  310,  309,  308,  307,
-      306,  305,  304,  303,  302,  301,  300,  297,  296,  295,
-
-      294,  293,  292,  291,  290,  289,  288,  287,  286,  285,
-      284,  283,  282,  281,  280,  279,  278,  277,  276,  275,
-      274,  273,  272,  271,  270,  269,  268,  267,  266,  265,
-      264,  263,  262,  261,  260,  259,  258,  257,  256,  255,
-      254,  253,  252,  251,  250,  249,  248,  247,  246,  243,
-      242,  241,  238,  237,  236,  235,  234,  233,  232,  231,
-      226,  225,  224,  223,  222,  221,  220,  219,  218,  217,
-      216,  213,  212,  211,  210,  209,  208,  207,  206,  205,
-      204,  203,  202,  201,  200,  199,  198,  197,  196,  195,
-      194,  191,  190,  189,  188,  187,  186,  185,  184,  183,
-
-      182,  181,  180,  179,  178,  177,  176,  175,  171,  170,
-      166,  165,  164,  163,  162,  161,  160,  159,  156,  155,
-      154,  153,  152,  151,  150,  149,  148,  147,  146,  145,
-      141,  140,  139,  138,  137,  136,  135,  134,  133,  132,
-      131,  130,  129,  128,  124,  123,  122,  119,  118,  117,
-      116,  115,  114,   93,   82,   81,   80,   79,   78,   52,
-       51,   50,  556,    3,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-
-      556,  556,  556,  556,  556,  556,  556,  556,  556
-    } ;
-
-static yyconst short int yy_chk[710] =
-    {   0,
-      558,    1,    1,    1,    0,    0,    1,    1,    1,    1,
-        1,    1,    1,    1,    1,    1,    8,  554,    8,    8,
-        8,    8,    8,   11,   27,   27,    1,   11,   55,   55,
-      551,    1,   10,   10,   10,   10,   10,  550,   13,   20,
-       20,   20,   20,   20,    1,    2,    2,    2,  548,   21,
-        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
-       13,   23,   23,   23,   23,   23,   25,  547,   25,   33,
-        2,   21,   33,   23,   61,    2,   61,  170,   26,   26,
-       26,   26,   26,   30,   30,  170,   40,   30,    2,    9,
-       26,    9,    9,    9,    9,    9,   39,  232,   41,   30,
-
-       40,  232,   39,   40,   41,   42,  546,    9,   12,   25,
-       12,   12,   12,   12,   12,   44,   31,   44,   48,   12,
-       31,   42,   12,   31,   42,   44,   93,   48,   48,   93,
-       31,   65,   65,   48,   65,   47,  358,   53,  545,   53,
-      358,   12,   14,   14,   14,   47,   14,   14,   14,   14,
-       14,   14,   14,   14,   14,   14,   14,  308,   14,   14,
-       14,   14,   14,  308,   14,   28,   28,   47,  149,   28,
-       28,   28,   28,   28,   29,   29,   29,   29,   29,   45,
-       53,  149,   29,   29,   29,   29,   29,   29,   32,   80,
-       32,  543,  174,   80,  105,   45,   32,   45,  105,   46,
-
-       45,   32,  105,   46,  174,   32,  542,   32,   32,   80,
-       46,   32,   32,  161,  286,   45,   46,   56,   56,   56,
-       56,   56,   46,   57,   57,   57,   57,   57,  102,  126,
-      286,  541,  126,  102,  342,  342,  161,  161,  161,  540,
-      102,  253,  253,  253,  253,  253,  371,  452,  371,  253,
-      253,  253,  253,  253,  253,  460,  460,  462,  539,  538,
-      452,  462,  536,  371,  535,  371,  557,  557,  557,  559,
-      559,  560,  560,  561,  561,  534,  532,  530,  529,  528,
-      527,  526,  524,  521,  520,  519,  515,  512,  511,  510,
-      509,  508,  506,  505,  504,  503,  500,  499,  498,  497,
-
-      496,  495,  494,  493,  492,  490,  488,  487,  485,  484,
-      483,  482,  481,  480,  479,  477,  475,  474,  473,  472,
-      471,  468,  467,  465,  464,  461,  459,  458,  457,  451,
-      450,  449,  445,  443,  441,  440,  439,  438,  437,  434,
-      433,  431,  430,  428,  427,  426,  423,  422,  421,  420,
-      419,  418,  417,  415,  414,  413,  412,  411,  410,  409,
-      408,  407,  406,  405,  404,  402,  401,  397,  396,  395,
-      394,  393,  392,  390,  389,  388,  387,  386,  385,  384,
-      383,  382,  381,  380,  379,  378,  375,  374,  373,  372,
-      370,  369,  368,  367,  366,  365,  364,  363,  362,  361,
-
-      360,  357,  356,  354,  353,  352,  351,  350,  349,  347,
-      346,  345,  344,  341,  338,  337,  335,  334,  331,  330,
-      329,  328,  327,  326,  325,  323,  322,  321,  319,  317,
-      316,  315,  314,  313,  312,  310,  307,  306,  305,  304,
-      303,  302,  301,  300,  299,  298,  297,  293,  291,  290,
-      289,  288,  287,  285,  283,  282,  281,  278,  277,  276,
-      275,  274,  273,  271,  269,  268,  267,  266,  264,  263,
-      262,  261,  260,  259,  258,  257,  256,  255,  254,  252,
-      251,  250,  249,  248,  247,  245,  244,  243,  242,  241,
-      240,  239,  238,  236,  235,  234,  233,  231,  230,  229,
-
-      228,  227,  226,  224,  223,  222,  221,  220,  219,  218,
-      217,  216,  215,  214,  213,  212,  211,  210,  209,  208,
-      206,  205,  204,  203,  202,  200,  199,  198,  197,  195,
-      194,  193,  192,  191,  190,  189,  188,  187,  186,  185,
-      184,  183,  182,  181,  180,  179,  177,  176,  175,  173,
-      172,  171,  169,  168,  167,  166,  165,  164,  163,  162,
-      160,  159,  158,  157,  156,  155,  154,  153,  152,  151,
-      150,  148,  147,  146,  145,  144,  143,  141,  140,  139,
-      138,  137,  136,  135,  134,  133,  132,  131,  130,  129,
-      127,  125,  124,  123,  122,  121,  120,  119,  118,  116,
-
-      114,  113,  112,  110,  109,  108,  107,  106,  104,  103,
-      101,  100,   99,   98,   97,   96,   95,   94,   92,   91,
-       90,   89,   88,   87,   86,   85,   84,   83,   82,   81,
-       79,   78,   77,   76,   75,   74,   73,   72,   71,   70,
-       69,   68,   67,   66,   64,   63,   62,   60,   59,   52,
-       51,   50,   49,   43,   38,   37,   36,   35,   34,   22,
-       16,   15,    3,  556,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
-
-      556,  556,  556,  556,  556,  556,  556,  556,  556
-    } ;
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "lexer.lxx"
-#define INITIAL 0
-/*
-// Filename: lexer.l
-// Created by:  drose (16Jan99)
-// 
-////////////////////////////////////////////////////////////////////
-*/
-#line 9 "lexer.lxx"
-#include "lexerDefs.h"
-#include "parserDefs.h"
-#include "config_egg.h"
-#include "parser.h"
-
-#include <indent.h>
-#include <notify.h>
-
-#include <math.h>
-#include <pandabase.h>
-
-extern "C" int eggyywrap(void);  // declared below.
-
-static int yyinput(void);        // declared by flex.
-
-
-////////////////////////////////////////////////////////////////////
-// Static variables
-////////////////////////////////////////////////////////////////////
-
-// We'll increment line_number and col_number as we parse the file, so
-// that we can report the position of an error.
-static int line_number = 0;
-static int col_number = 0;
-
-// current_line holds as much of the current line as will fit.  Its
-// only purpose is for printing it out to report an error to the user.
-static const int max_error_width = 1024;
-static char current_line[max_error_width + 1];
-
-static int error_count = 0;
-static int warning_count = 0;
-
-// This is the pointer to the current input stream.
-static istream *inp = NULL;
-
-// This is the name of the egg file we're parsing.  We keep it so we
-// can print it out for error messages.
-static string egg_filename;
-
-// This is the initial token state returned by the lexer.  It allows
-// the yacc grammar to start from initial points.
-static int initial_token;
-
-
-////////////////////////////////////////////////////////////////////
-// Defining the interface to the lexer.
-////////////////////////////////////////////////////////////////////
-
-void
-egg_init_lexer(istream &in, const string &filename) {
-  inp = &in;
-  egg_filename = filename;
-  line_number = 0;
-  col_number = 0;
-  error_count = 0;
-  warning_count = 0;
-  initial_token = START_EGG;
-}
-
-void
-egg_start_group_body() {
-  /* Set the initial state to begin within a group_body context,
-     instead of at the beginning of the egg file. */
-  initial_token = START_GROUP_BODY;
-}
-
-void
-egg_start_texture_body() {
-  initial_token = START_TEXTURE_BODY;
-}
-
-void
-egg_start_primitive_body() {
-  initial_token = START_PRIMITIVE_BODY;
-}
-
-int
-egg_error_count() {
-  return error_count;
-}
-
-int
-egg_warning_count() {
-  return warning_count;
-}
-
-
-////////////////////////////////////////////////////////////////////
-// Internal support functions.
-////////////////////////////////////////////////////////////////////
-
-int
-eggyywrap(void) {
-  return 1;
-}
-
-void
-eggyyerror(const string &msg) {
-  if (egg_cat.is_error()) {
-    ostream &out = egg_cat.error(false);
-
-    out << "\nError";
-    if (!egg_filename.empty()) {
-      out << " in " << egg_filename;
-    }
-    out 
-      << " at line " << line_number << ", column " << col_number << ":\n"
-      << setiosflags(Notify::get_literal_flag())
-      << current_line << "\n";
-    indent(out, col_number-1) 
-      << "^\n" << msg << "\n\n" 
-      << resetiosflags(Notify::get_literal_flag()) << flush;
-  }
-  error_count++;
-}
-
-void
-eggyyerror(ostringstream &strm) {
-  string s = strm.str();
-  eggyyerror(s);
-}
-
-void
-eggyywarning(const string &msg) {
-  if (egg_cat.is_warning()) {
-    ostream &out = egg_cat.warning(false);
-
-    out << "\nWarning";
-    if (!egg_filename.empty()) {
-      out << " in " << egg_filename;
-    }
-    out 
-      << " at line " << line_number << ", column " << col_number << ":\n"
-      << setiosflags(Notify::get_literal_flag())
-      << current_line << "\n";
-    indent(out, col_number-1) 
-      << "^\n" << msg << "\n\n" 
-      << resetiosflags(Notify::get_literal_flag()) << flush;
-  }
-  warning_count++;
-}
-
-void
-eggyywarning(ostringstream &strm) {
-  string s = strm.str();
-  eggyywarning(s);
-}
-
-// Now define a function to take input from an istream instead of a
-// stdio FILE pointer.  This is flex-specific.
-static void
-input_chars(char *buffer, int &result, int max_size) {
-  nassertv(inp != NULL);
-  if (*inp) {
-    inp->read(buffer, max_size);
-    result = inp->gcount();
-
-    if (line_number == 0) {
-      // This is a special case.  If we are reading the very first bit
-      // from the stream, copy it into the current_line array.  This
-      // is because the \n.* rule below, which fills current_line
-      // normally, doesn't catch the first line.
-      int length = min(max_error_width, result);
-      strncpy(current_line, buffer, length);
-      current_line[length] = '\0';
-      line_number++;
-      col_number = 0;
-
-      // Truncate it at the newline.
-      char *end = strchr(current_line, '\n');
-      if (end != NULL) {
-        *end = '\0';
-      }
-    }
-
-  } else {
-    // End of file or I/O error.
-    result = 0;
-  }
-}
-#undef YY_INPUT
-#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
-
-// read_char reads and returns a single character, incrementing the
-// supplied line and column numbers as appropriate.  A convenience
-// function for the scanning functions below.
-static int
-read_char(int &line, int &col) {
-  int c = yyinput();
-  if (c == '\n') {
-    line++;
-    col = 0;
-  } else {
-    col++;
-  }
-  return c;
-}
-
-// scan_quoted_string reads a string delimited by quotation marks and
-// returns it.
-static string
-scan_quoted_string() {
-  string result;
-
-  // We don't touch the current line number and column number during
-  // scanning, so that if we detect an error while scanning the string
-  // (e.g. an unterminated string), we'll report the error as
-  // occurring at the start of the string, not at the end--somewhat
-  // more convenient for the user.
-
-  // Instead of adjusting the global line_number and col_number
-  // variables, we'll operate on our own local variables for the
-  // interim.
-  int line = line_number;
-  int col = col_number;
-
-  int c;
-  c = read_char(line, col);
-  while (c != '"' && c != EOF) {
-    result += c;
-    c = read_char(line, col);
-  }
-
-  if (c == EOF) {
-    eggyyerror("This quotation mark is unterminated.");
-  }
-
-  line_number = line;
-  col_number = col;
-
-  return result;
-}
-
-// eat_c_comment scans past all characters up until the first */
-// encountered.
-static void
-eat_c_comment() {
-  // As above, we'll operate on our own local copies of line_number
-  // and col_number within this function.
-
-  int line = line_number;
-  int col = col_number;
-
-  int c, last_c;
-  
-  last_c = '\0';
-  c = read_char(line, col);
-  while (c != EOF && !(last_c == '*' && c == '/')) {
-    if (last_c == '/' && c == '*') {
-      ostringstream errmsg;
-      errmsg << "This comment contains a nested /* symbol at line "
-             << line << ", column " << col-1 << "--possibly unclosed?"
-             << ends;
-      eggyywarning(errmsg);
-    }
-    last_c = c;
-    c = read_char(line, col);
-  }
-
-  if (c == EOF) {
-    eggyyerror("This comment marker is unclosed.");
-  }
-
-  line_number = line;
-  col_number = col;
-}
-
-
-// accept() is called below as each piece is pulled off and
-// accepted by the lexer; it increments the current column number.
-INLINE void accept() {
-  col_number += yyleng;
-}
-
-#line 1007 "lex.yy.c"
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap YY_PROTO(( void ));
-#else
-extern int yywrap YY_PROTO(( void ));
-#endif
-#endif
-
-#ifndef YY_NO_UNPUT
-static void yyunput YY_PROTO(( int c, char *buf_ptr ));
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen YY_PROTO(( yyconst char * ));
-#endif
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
-static int yyinput YY_PROTO(( void ));
-#else
-static int input YY_PROTO(( void ));
-#endif
-#endif
-
-#if YY_STACK_USED
-static int yy_start_stack_ptr = 0;
-static int yy_start_stack_depth = 0;
-static int *yy_start_stack = 0;
-#ifndef YY_NO_PUSH_STATE
-static void yy_push_state YY_PROTO(( int new_state ));
-#endif
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state YY_PROTO(( void ));
-#endif
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state YY_PROTO(( void ));
-#endif
-
-#else
-#define YY_NO_PUSH_STATE 1
-#define YY_NO_POP_STATE 1
-#define YY_NO_TOP_STATE 1
-#endif
-
-#ifdef YY_MALLOC_DECL
-YY_MALLOC_DECL
-#else
-#if __STDC__
-#ifndef __cplusplus
-#include <stdlib.h>
-#endif
-#else
-/* Just try to get by without declaring the routines.  This will fail
- * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
- * or sizeof(void*) != sizeof(int).
- */
-#endif
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
-	if ( yy_current_buffer->yy_is_interactive ) \
-		{ \
-		int c = '*', n; \
-		for ( n = 0; n < max_size && \
-			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
-			buf[n] = (char) c; \
-		if ( c == '\n' ) \
-			buf[n++] = (char) c; \
-		if ( c == EOF && ferror( yyin ) ) \
-			YY_FATAL_ERROR( "input in flex scanner failed" ); \
-		result = n; \
-		} \
-	else \
-		{ \
-		errno=0; \
-		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
-			{ \
-			if( errno != EINTR) \
-				{ \
-				YY_FATAL_ERROR( "input in flex scanner failed" ); \
-				break; \
-				} \
-			errno=0; \
-			clearerr(yyin); \
-			} \
-		}
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL int yylex YY_PROTO(( void ))
-#endif
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
-	YY_USER_ACTION
-
-YY_DECL
-	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp, *yy_bp;
-	register int yy_act;
-
-#line 290 "lexer.lxx"
-
-
-
-  if (initial_token != 0) {
-    int t = initial_token;
-    initial_token = 0;
-    return t;
-  }
-
-
-#line 1180 "lex.yy.c"
-
-	if ( yy_init )
-		{
-		yy_init = 0;
-
-#ifdef YY_USER_INIT
-		YY_USER_INIT;
-#endif
-
-		if ( ! yy_start )
-			yy_start = 1;	/* first start state */
-
-		if ( ! yyin )
-			yyin = stdin;
-
-		if ( ! yyout )
-			yyout = stdout;
-
-		if ( ! yy_current_buffer )
-			yy_current_buffer =
-				yy_create_buffer( yyin, YY_BUF_SIZE );
-
-		yy_load_buffer_state();
-		}
-
-	while ( 1 )		/* loops until end-of-file is reached */
-		{
-		yy_cp = yy_c_buf_p;
-
-		/* Support of yytext. */
-		*yy_cp = yy_hold_char;
-
-		/* yy_bp points to the position in yy_ch_buf of the start of
-		 * the current run.
-		 */
-		yy_bp = yy_cp;
-
-		yy_current_state = yy_start;
-yy_match:
-		do
-			{
-			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
-			if ( yy_accept[yy_current_state] )
-				{
-				yy_last_accepting_state = yy_current_state;
-				yy_last_accepting_cpos = yy_cp;
-				}
-			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-				{
-				yy_current_state = (int) yy_def[yy_current_state];
-				if ( yy_current_state >= 557 )
-					yy_c = yy_meta[(unsigned int) yy_c];
-				}
-			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-			++yy_cp;
-			}
-		while ( yy_base[yy_current_state] != 664 );
-
-yy_find_action:
-		yy_act = yy_accept[yy_current_state];
-		if ( yy_act == 0 )
-			{ /* have to back up */
-			yy_cp = yy_last_accepting_cpos;
-			yy_current_state = yy_last_accepting_state;
-			yy_act = yy_accept[yy_current_state];
-			}
-
-		YY_DO_BEFORE_ACTION;
-
-
-do_action:	/* This label is used only to access EOF actions. */
-
-
-		switch ( yy_act )
-	{ /* beginning of action switch */
-			case 0: /* must back up */
-			/* undo the effects of YY_DO_BEFORE_ACTION */
-			*yy_cp = yy_hold_char;
-			yy_cp = yy_last_accepting_cpos;
-			yy_current_state = yy_last_accepting_state;
-			goto yy_find_action;
-
-case 1:
-YY_RULE_SETUP
-#line 300 "lexer.lxx"
-{
-  // New line.  Save a copy of the line so we can print it out for the
-  // benefit of the user in case we get an error.
-
-  strncpy(current_line, yytext+1, max_error_width);
-  current_line[max_error_width] = '\0';
-  line_number++;
-  col_number=0;
-
-  // Return the whole line to the lexer, except the newline character,
-  // which we eat.
-  yyless(1);
-}
-	YY_BREAK
-case 2:
-YY_RULE_SETUP
-#line 314 "lexer.lxx"
-{ 
-  // Eat whitespace.
-  accept();
-}
-	YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 319 "lexer.lxx"
-{ 
-  // Eat C++-style comments.
-  accept();
-}
-	YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 324 "lexer.lxx"
-{
-  // Eat C-style comments.
-  accept();
-  eat_c_comment(); 
-}
-	YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 330 "lexer.lxx"
-{
-  // Send curly braces as themselves.
-  accept(); 
-  return eggyytext[0];
-}
-	YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 338 "lexer.lxx"
-{
-  accept();
-  return BEZIERCURVE;
-}
-	YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 342 "lexer.lxx"
-{
-  accept();
-  return BFACE;
-}
-	YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 346 "lexer.lxx"
-{
-  accept();
-  return BILLBOARD;
-}
-	YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 350 "lexer.lxx"
-{
-  accept();
-  return BILLBOARDCENTER;
-}
-	YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 354 "lexer.lxx"
-{
-  accept();
-  return BINORMAL;
-}
-	YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 358 "lexer.lxx"
-{
-  accept();
-  return BUNDLE;
-}
-	YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 362 "lexer.lxx"
-{
-  accept();
-  return SCALAR;
-}
-	YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 366 "lexer.lxx"
-{
-  accept();
-  return CLOSED;
-}
-	YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 370 "lexer.lxx"
-{
-  accept();
-  return COLLIDE;
-}
-	YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 374 "lexer.lxx"
-{
-  accept();
-  return COMMENT;
-}
-	YY_BREAK
-case 16:
-YY_RULE_SETUP
-#line 378 "lexer.lxx"
-{
-  accept();
-  return COMPONENT;
-}
-	YY_BREAK
-case 17:
-YY_RULE_SETUP
-#line 382 "lexer.lxx"
-{
-  accept();
-  return COORDSYSTEM;
-}
-	YY_BREAK
-case 18:
-YY_RULE_SETUP
-#line 386 "lexer.lxx"
-{
-  accept();
-  return CV;
-}
-	YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 390 "lexer.lxx"
-{
-  accept();
-  return DART;
-}
-	YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 394 "lexer.lxx"
-{
-  accept();
-  return DNORMAL;
-}
-	YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 398 "lexer.lxx"
-{
-  accept();
-  return DRGBA;
-}
-	YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 402 "lexer.lxx"
-{
-  accept();
-  return DUV;
-}
-	YY_BREAK
-case 23:
-YY_RULE_SETUP
-#line 406 "lexer.lxx"
-{
-  accept();
-  return DXYZ;
-}
-	YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 410 "lexer.lxx"
-{
-  accept();
-  return DCS;
-}
-	YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 414 "lexer.lxx"
-{
-  accept();
-  return DISTANCE;
-}
-	YY_BREAK
-case 26:
-YY_RULE_SETUP
-#line 418 "lexer.lxx"
-{
-  accept();
-  return DTREF;
-}
-	YY_BREAK
-case 27:
-YY_RULE_SETUP
-#line 422 "lexer.lxx"
-{
-  accept();
-  return DYNAMICVERTEXPOOL;
-}
-	YY_BREAK
-case 28:
-YY_RULE_SETUP
-#line 426 "lexer.lxx"
-{
-  accept();
-  return EXTERNAL_FILE;
-}
-	YY_BREAK
-case 29:
-YY_RULE_SETUP
-#line 430 "lexer.lxx"
-{
-  accept();
-  return FLIGHT;
-}
-	YY_BREAK
-case 30:
-YY_RULE_SETUP
-#line 434 "lexer.lxx"
-{
-  accept();
-  return GROUP;
-}
-	YY_BREAK
-case 31:
-YY_RULE_SETUP
-#line 438 "lexer.lxx"
-{
-  accept();
-  return HIP;
-}
-	YY_BREAK
-case 32:
-YY_RULE_SETUP
-#line 442 "lexer.lxx"
-{
-  accept();
-  return INTANGENT;
-}
-	YY_BREAK
-case 33:
-YY_RULE_SETUP
-#line 446 "lexer.lxx"
-{
-  accept();
-  return JOINT;
-}
-	YY_BREAK
-case 34:
-YY_RULE_SETUP
-#line 450 "lexer.lxx"
-{
-  accept();
-  return KNOTS;
-}
-	YY_BREAK
-case 35:
-YY_RULE_SETUP
-#line 454 "lexer.lxx"
-{
-  accept();
-  return INCLUDE;
-}
-	YY_BREAK
-case 36:
-YY_RULE_SETUP
-#line 458 "lexer.lxx"
-{
-  accept();
-  return INSTANCE;
-}
-	YY_BREAK
-case 37:
-YY_RULE_SETUP
-#line 462 "lexer.lxx"
-{
-  accept();
-  return LINE;
-}
-	YY_BREAK
-case 38:
-YY_RULE_SETUP
-#line 466 "lexer.lxx"
-{
-  accept();
-  return LOOP;
-}
-	YY_BREAK
-case 39:
-YY_RULE_SETUP
-#line 470 "lexer.lxx"
-{
-  accept();
-  return MATERIAL;
-}
-	YY_BREAK
-case 40:
-YY_RULE_SETUP
-#line 474 "lexer.lxx"
-{
-  accept();
-  return MATRIX3;
-}
-	YY_BREAK
-case 41:
-YY_RULE_SETUP
-#line 478 "lexer.lxx"
-{
-  accept();
-  return MATRIX4;
-}
-	YY_BREAK
-case 42:
-YY_RULE_SETUP
-#line 482 "lexer.lxx"
-{
-  accept();
-  return MODEL;
-}
-	YY_BREAK
-case 43:
-YY_RULE_SETUP
-#line 486 "lexer.lxx"
-{
-  accept();
-  return MREF;
-}
-	YY_BREAK
-case 44:
-YY_RULE_SETUP
-#line 490 "lexer.lxx"
-{
-  accept();
-  return NORMAL;
-}
-	YY_BREAK
-case 45:
-YY_RULE_SETUP
-#line 494 "lexer.lxx"
-{
-  accept();
-  return NURBSCURVE;
-}
-	YY_BREAK
-case 46:
-YY_RULE_SETUP
-#line 498 "lexer.lxx"
-{
-  accept();
-  return NURBSSURFACE;
-}
-	YY_BREAK
-case 47:
-YY_RULE_SETUP
-#line 502 "lexer.lxx"
-{
-  accept();
-  return OBJECTTYPE;
-}
-	YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 506 "lexer.lxx"
-{
-  accept();
-  return ORDER;
-}
-	YY_BREAK
-case 49:
-YY_RULE_SETUP
-#line 510 "lexer.lxx"
-{
-  accept();
-  return OUTTANGENT;
-}
-	YY_BREAK
-case 50:
-YY_RULE_SETUP
-#line 514 "lexer.lxx"
-{
-  accept();
-  return POINTLIGHT;
-}
-	YY_BREAK
-case 51:
-YY_RULE_SETUP
-#line 518 "lexer.lxx"
-{
-  accept();
-  return POLYGON;
-}
-	YY_BREAK
-case 52:
-YY_RULE_SETUP
-#line 522 "lexer.lxx"
-{
-  accept();
-  return REF;
-}
-	YY_BREAK
-case 53:
-YY_RULE_SETUP
-#line 526 "lexer.lxx"
-{
-  accept();
-  return RGBA;
-}
-	YY_BREAK
-case 54:
-YY_RULE_SETUP
-#line 530 "lexer.lxx"
-{
-  accept();
-  return ROTATE;
-}
-	YY_BREAK
-case 55:
-YY_RULE_SETUP
-#line 534 "lexer.lxx"
-{
-  accept();
-  return ROTX;
-}
-	YY_BREAK
-case 56:
-YY_RULE_SETUP
-#line 538 "lexer.lxx"
-{
-  accept();
-  return ROTY;
-}
-	YY_BREAK
-case 57:
-YY_RULE_SETUP
-#line 542 "lexer.lxx"
-{
-  accept();
-  return ROTZ;
-}
-	YY_BREAK
-case 58:
-YY_RULE_SETUP
-#line 546 "lexer.lxx"
-{
-  accept();
-  return SANIM;
-}
-	YY_BREAK
-case 59:
-YY_RULE_SETUP
-#line 550 "lexer.lxx"
-{
-  accept();
-  return SCALAR;
-}
-	YY_BREAK
-case 60:
-YY_RULE_SETUP
-#line 554 "lexer.lxx"
-{
-  accept();
-  return SCALE;
-}
-	YY_BREAK
-case 61:
-YY_RULE_SETUP
-#line 558 "lexer.lxx"
-{
-  accept();
-  return SEQUENCE;
-}
-	YY_BREAK
-case 62:
-YY_RULE_SETUP
-#line 562 "lexer.lxx"
-{
-  accept();
-  return SHADING;
-}
-	YY_BREAK
-case 63:
-YY_RULE_SETUP
-#line 566 "lexer.lxx"
-{
-  accept();
-  return SWITCH;
-}
-	YY_BREAK
-case 64:
-YY_RULE_SETUP
-#line 570 "lexer.lxx"
-{
-  accept();
-  return SWITCHCONDITION;
-}
-	YY_BREAK
-case 65:
-YY_RULE_SETUP
-#line 574 "lexer.lxx"
-{
-  accept();
-  return TABLE;
-}
-	YY_BREAK
-case 66:
-YY_RULE_SETUP
-#line 578 "lexer.lxx"
-{
-  accept();
-  return TABLE_V;
-}
-	YY_BREAK
-case 67:
-YY_RULE_SETUP
-#line 582 "lexer.lxx"
-{
-  accept();
-  return TAG;
-}
-	YY_BREAK
-case 68:
-YY_RULE_SETUP
-#line 586 "lexer.lxx"
-{
-  accept();
-  return TANGENT;
-}
-	YY_BREAK
-case 69:
-YY_RULE_SETUP
-#line 590 "lexer.lxx"
-{
-  accept();
-  return TEXLIST;
-}
-	YY_BREAK
-case 70:
-YY_RULE_SETUP
-#line 594 "lexer.lxx"
-{
-  accept();
-  return TEXTURE;
-}
-	YY_BREAK
-case 71:
-YY_RULE_SETUP
-#line 598 "lexer.lxx"
-{
-  accept();
-  return TLENGTHS;
-}
-	YY_BREAK
-case 72:
-YY_RULE_SETUP
-#line 602 "lexer.lxx"
-{
-  accept();
-  return TRANSFORM;
-}
-	YY_BREAK
-case 73:
-YY_RULE_SETUP
-#line 606 "lexer.lxx"
-{
-  accept();
-  return TRANSLATE;
-}
-	YY_BREAK
-case 74:
-YY_RULE_SETUP
-#line 610 "lexer.lxx"
-{
-  accept();
-  return TREF;
-}
-	YY_BREAK
-case 75:
-YY_RULE_SETUP
-#line 614 "lexer.lxx"
-{
-  accept();
-  return TRIANGLEFAN;
-}
-	YY_BREAK
-case 76:
-YY_RULE_SETUP
-#line 618 "lexer.lxx"
-{
-  accept();
-  return TRIANGLESTRIP;
-}
-	YY_BREAK
-case 77:
-YY_RULE_SETUP
-#line 622 "lexer.lxx"
-{
-  accept();
-  return TRIM;
-}
-	YY_BREAK
-case 78:
-YY_RULE_SETUP
-#line 626 "lexer.lxx"
-{
-  accept();
-  return TXT;
-}
-	YY_BREAK
-case 79:
-YY_RULE_SETUP
-#line 630 "lexer.lxx"
-{
-  accept();
-  return UKNOTS;
-}
-	YY_BREAK
-case 80:
-YY_RULE_SETUP
-#line 634 "lexer.lxx"
-{
-  accept();
-  return UKNOTS;
-}
-	YY_BREAK
-case 81:
-YY_RULE_SETUP
-#line 638 "lexer.lxx"
-{
-  accept();
-  return UV;
-}
-	YY_BREAK
-case 82:
-YY_RULE_SETUP
-#line 642 "lexer.lxx"
-{
-  accept();
-  return VKNOTS;
-}
-	YY_BREAK
-case 83:
-YY_RULE_SETUP
-#line 646 "lexer.lxx"
-{
-  accept();
-  return VKNOTS;
-}
-	YY_BREAK
-case 84:
-YY_RULE_SETUP
-#line 650 "lexer.lxx"
-{
-  accept();
-  return VERTEX;
-}
-	YY_BREAK
-case 85:
-YY_RULE_SETUP
-#line 654 "lexer.lxx"
-{
-  accept();
-  return VERTEXANIM;
-}
-	YY_BREAK
-case 86:
-YY_RULE_SETUP
-#line 658 "lexer.lxx"
-{
-  accept();
-  return VERTEXPOOL;
-}
-	YY_BREAK
-case 87:
-YY_RULE_SETUP
-#line 662 "lexer.lxx"
-{
-  accept();
-  return VERTEXREF;
-}
-	YY_BREAK
-case 88:
-YY_RULE_SETUP
-#line 666 "lexer.lxx"
-{
-  accept();
-  return XFMANIM;
-}
-	YY_BREAK
-case 89:
-YY_RULE_SETUP
-#line 670 "lexer.lxx"
-{
-  accept();
-  return XFMSANIM;
-}
-	YY_BREAK
-case 90:
-YY_RULE_SETUP
-#line 677 "lexer.lxx"
-{ 
-  // An integer or floating-point number.
-  accept(); 
-  eggyylval._number = atof(eggyytext); 
-  eggyylval._string = yytext;
-  return NUMBER; 
-}
-	YY_BREAK
-case 91:
-YY_RULE_SETUP
-#line 685 "lexer.lxx"
-{
-  // A hexadecimal integer number.
-  accept(); 
-  eggyylval._ulong = strtoul(yytext+2, NULL, 16);
-  eggyylval._string = yytext;
-  return ULONG; 
-}
-	YY_BREAK
-case 92:
-YY_RULE_SETUP
-#line 693 "lexer.lxx"
-{
-  // A binary integer number.
-  accept(); 
-  eggyylval._ulong = strtoul(yytext+2, NULL, 2);
-  eggyylval._string = yytext;
-  return ULONG; 
-}
-	YY_BREAK
-case 93:
-YY_RULE_SETUP
-#line 701 "lexer.lxx"
-{
-  // not-a-number.  These sometimes show up in egg files accidentally.
-  accept(); 
-  memset(&eggyylval._number, 0, sizeof(eggyylval._number));
-  *(unsigned long *)&eggyylval._number = strtoul(yytext+3, NULL, 0);
-  eggyylval._string = yytext;
-  return NUMBER;
-}
-	YY_BREAK
-case 94:
-YY_RULE_SETUP
-#line 710 "lexer.lxx"
-{ 
-  // infinity.  As above.
-  accept(); 
-  eggyylval._number = HUGE_VAL;
-  eggyylval._string = yytext;
-  return NUMBER; 
-}
-	YY_BREAK
-case 95:
-YY_RULE_SETUP
-#line 718 "lexer.lxx"
-{
-  // minus infinity.  As above.
-  accept(); 
-  eggyylval._number = -HUGE_VAL;
-  eggyylval._string = yytext;
-  return NUMBER; 
-}
-	YY_BREAK
-case 96:
-YY_RULE_SETUP
-#line 727 "lexer.lxx"
-{
-  // Quoted string.
-  accept();
-  eggyylval._string = scan_quoted_string();
-  return STRING;
-}
-	YY_BREAK
-case 97:
-YY_RULE_SETUP
-#line 734 "lexer.lxx"
-{ 
-  // Unquoted string.
-  accept();
-  eggyylval._string = yytext;
-  return STRING;
-}
-	YY_BREAK
-case 98:
-YY_RULE_SETUP
-#line 740 "lexer.lxx"
-ECHO;
-	YY_BREAK
-#line 2078 "lex.yy.c"
-case YY_STATE_EOF(INITIAL):
-	yyterminate();
-
-	case YY_END_OF_BUFFER:
-		{
-		/* Amount of text matched not including the EOB char. */
-		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
-
-		/* Undo the effects of YY_DO_BEFORE_ACTION. */
-		*yy_cp = yy_hold_char;
-		YY_RESTORE_YY_MORE_OFFSET
-
-		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
-			{
-			/* We're scanning a new file or input source.  It's
-			 * possible that this happened because the user
-			 * just pointed yyin at a new source and called
-			 * yylex().  If so, then we have to assure
-			 * consistency between yy_current_buffer and our
-			 * globals.  Here is the right place to do so, because
-			 * this is the first action (other than possibly a
-			 * back-up) that will match for the new input source.
-			 */
-			yy_n_chars = yy_current_buffer->yy_n_chars;
-			yy_current_buffer->yy_input_file = yyin;
-			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
-			}
-
-		/* Note that here we test for yy_c_buf_p "<=" to the position
-		 * of the first EOB in the buffer, since yy_c_buf_p will
-		 * already have been incremented past the NUL character
-		 * (since all states make transitions on EOB to the
-		 * end-of-buffer state).  Contrast this with the test
-		 * in input().
-		 */
-		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
-			{ /* This was really a NUL. */
-			yy_state_type yy_next_state;
-
-			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
-
-			yy_current_state = yy_get_previous_state();
-
-			/* Okay, we're now positioned to make the NUL
-			 * transition.  We couldn't have
-			 * yy_get_previous_state() go ahead and do it
-			 * for us because it doesn't know how to deal
-			 * with the possibility of jamming (and we don't
-			 * want to build jamming into it because then it
-			 * will run more slowly).
-			 */
-
-			yy_next_state = yy_try_NUL_trans( yy_current_state );
-
-			yy_bp = yytext_ptr + YY_MORE_ADJ;
-
-			if ( yy_next_state )
-				{
-				/* Consume the NUL. */
-				yy_cp = ++yy_c_buf_p;
-				yy_current_state = yy_next_state;
-				goto yy_match;
-				}
-
-			else
-				{
-				yy_cp = yy_c_buf_p;
-				goto yy_find_action;
-				}
-			}
-
-		else switch ( yy_get_next_buffer() )
-			{
-			case EOB_ACT_END_OF_FILE:
-				{
-				yy_did_buffer_switch_on_eof = 0;
-
-				if ( yywrap() )
-					{
-					/* Note: because we've taken care in
-					 * yy_get_next_buffer() to have set up
-					 * yytext, we can now set up
-					 * yy_c_buf_p so that if some total
-					 * hoser (like flex itself) wants to
-					 * call the scanner after we return the
-					 * YY_NULL, it'll still work - another
-					 * YY_NULL will get returned.
-					 */
-					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
-
-					yy_act = YY_STATE_EOF(YY_START);
-					goto do_action;
-					}
-
-				else
-					{
-					if ( ! yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-					}
-				break;
-				}
-
-			case EOB_ACT_CONTINUE_SCAN:
-				yy_c_buf_p =
-					yytext_ptr + yy_amount_of_matched_text;
-
-				yy_current_state = yy_get_previous_state();
-
-				yy_cp = yy_c_buf_p;
-				yy_bp = yytext_ptr + YY_MORE_ADJ;
-				goto yy_match;
-
-			case EOB_ACT_LAST_MATCH:
-				yy_c_buf_p =
-				&yy_current_buffer->yy_ch_buf[yy_n_chars];
-
-				yy_current_state = yy_get_previous_state();
-
-				yy_cp = yy_c_buf_p;
-				yy_bp = yytext_ptr + YY_MORE_ADJ;
-				goto yy_find_action;
-			}
-		break;
-		}
-
-	default:
-		YY_FATAL_ERROR(
-			"fatal flex scanner internal error--no action found" );
-	} /* end of action switch */
-		} /* end of scanning one token */
-	} /* end of yylex */
-
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- *	EOB_ACT_LAST_MATCH -
- *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- *	EOB_ACT_END_OF_FILE - end of file
- */
-
-static int yy_get_next_buffer()
-	{
-	register char *dest = yy_current_buffer->yy_ch_buf;
-	register char *source = yytext_ptr;
-	register int number_to_move, i;
-	int ret_val;
-
-	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
-		YY_FATAL_ERROR(
-		"fatal flex scanner internal error--end of buffer missed" );
-
-	if ( yy_current_buffer->yy_fill_buffer == 0 )
-		{ /* Don't try to fill the buffer, so this is an EOF. */
-		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
-			{
-			/* We matched a single character, the EOB, so
-			 * treat this as a final EOF.
-			 */
-			return EOB_ACT_END_OF_FILE;
-			}
-
-		else
-			{
-			/* We matched some text prior to the EOB, first
-			 * process it.
-			 */
-			return EOB_ACT_LAST_MATCH;
-			}
-		}
-
-	/* Try to read more data. */
-
-	/* First move last chars to start of buffer. */
-	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
-
-	for ( i = 0; i < number_to_move; ++i )
-		*(dest++) = *(source++);
-
-	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
-		/* don't do the read, it's not guaranteed to return an EOF,
-		 * just force an EOF
-		 */
-		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
-
-	else
-		{
-		int num_to_read =
-			yy_current_buffer->yy_buf_size - number_to_move - 1;
-
-		while ( num_to_read <= 0 )
-			{ /* Not enough room in the buffer - grow it. */
-#ifdef YY_USES_REJECT
-			YY_FATAL_ERROR(
-"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
-#else
-
-			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = yy_current_buffer;
-
-			int yy_c_buf_p_offset =
-				(int) (yy_c_buf_p - b->yy_ch_buf);
-
-			if ( b->yy_is_our_buffer )
-				{
-				int new_size = b->yy_buf_size * 2;
-
-				if ( new_size <= 0 )
-					b->yy_buf_size += b->yy_buf_size / 8;
-				else
-					b->yy_buf_size *= 2;
-
-				b->yy_ch_buf = (char *)
-					/* Include room in for 2 EOB chars. */
-					yy_flex_realloc( (void *) b->yy_ch_buf,
-							 b->yy_buf_size + 2 );
-				}
-			else
-				/* Can't grow it, we don't own it. */
-				b->yy_ch_buf = 0;
-
-			if ( ! b->yy_ch_buf )
-				YY_FATAL_ERROR(
-				"fatal error - scanner input buffer overflow" );
-
-			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
-
-			num_to_read = yy_current_buffer->yy_buf_size -
-						number_to_move - 1;
-#endif
-			}
-
-		if ( num_to_read > YY_READ_BUF_SIZE )
-			num_to_read = YY_READ_BUF_SIZE;
-
-		/* Read in more data. */
-		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
-			yy_n_chars, num_to_read );
-
-		yy_current_buffer->yy_n_chars = yy_n_chars;
-		}
-
-	if ( yy_n_chars == 0 )
-		{
-		if ( number_to_move == YY_MORE_ADJ )
-			{
-			ret_val = EOB_ACT_END_OF_FILE;
-			yyrestart( yyin );
-			}
-
-		else
-			{
-			ret_val = EOB_ACT_LAST_MATCH;
-			yy_current_buffer->yy_buffer_status =
-				YY_BUFFER_EOF_PENDING;
-			}
-		}
-
-	else
-		ret_val = EOB_ACT_CONTINUE_SCAN;
-
-	yy_n_chars += number_to_move;
-	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
-	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
-
-	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
-
-	return ret_val;
-	}
-
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
-static yy_state_type yy_get_previous_state()
-	{
-	register yy_state_type yy_current_state;
-	register char *yy_cp;
-
-	yy_current_state = yy_start;
-
-	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
-		{
-		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
-		if ( yy_accept[yy_current_state] )
-			{
-			yy_last_accepting_state = yy_current_state;
-			yy_last_accepting_cpos = yy_cp;
-			}
-		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-			{
-			yy_current_state = (int) yy_def[yy_current_state];
-			if ( yy_current_state >= 557 )
-				yy_c = yy_meta[(unsigned int) yy_c];
-			}
-		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-		}
-
-	return yy_current_state;
-	}
-
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- *	next_state = yy_try_NUL_trans( current_state );
- */
-
-#ifdef YY_USE_PROTOS
-static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
-#else
-static yy_state_type yy_try_NUL_trans( yy_current_state )
-yy_state_type yy_current_state;
-#endif
-	{
-	register int yy_is_jam;
-	register char *yy_cp = yy_c_buf_p;
-
-	register YY_CHAR yy_c = 1;
-	if ( yy_accept[yy_current_state] )
-		{
-		yy_last_accepting_state = yy_current_state;
-		yy_last_accepting_cpos = yy_cp;
-		}
-	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
-		{
-		yy_current_state = (int) yy_def[yy_current_state];
-		if ( yy_current_state >= 557 )
-			yy_c = yy_meta[(unsigned int) yy_c];
-		}
-	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-	yy_is_jam = (yy_current_state == 556);
-
-	return yy_is_jam ? 0 : yy_current_state;
-	}
-
-
-#ifndef YY_NO_UNPUT
-#ifdef YY_USE_PROTOS
-static void yyunput( int c, register char *yy_bp )
-#else
-static void yyunput( c, yy_bp )
-int c;
-register char *yy_bp;
-#endif
-	{
-	register char *yy_cp = yy_c_buf_p;
-
-	/* undo effects of setting up yytext */
-	*yy_cp = yy_hold_char;
-
-	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
-		{ /* need to shift things up to make room */
-		/* +2 for EOB chars. */
-		register int number_to_move = yy_n_chars + 2;
-		register char *dest = &yy_current_buffer->yy_ch_buf[
-					yy_current_buffer->yy_buf_size + 2];
-		register char *source =
-				&yy_current_buffer->yy_ch_buf[number_to_move];
-
-		while ( source > yy_current_buffer->yy_ch_buf )
-			*--dest = *--source;
-
-		yy_cp += (int) (dest - source);
-		yy_bp += (int) (dest - source);
-		yy_current_buffer->yy_n_chars =
-			yy_n_chars = yy_current_buffer->yy_buf_size;
-
-		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
-			YY_FATAL_ERROR( "flex scanner push-back overflow" );
-		}
-
-	*--yy_cp = (char) c;
-
-
-	yytext_ptr = yy_bp;
-	yy_hold_char = *yy_cp;
-	yy_c_buf_p = yy_cp;
-	}
-#endif	/* ifndef YY_NO_UNPUT */
-
-
-#ifdef __cplusplus
-static int yyinput()
-#else
-static int input()
-#endif
-	{
-	int c;
-
-	*yy_c_buf_p = yy_hold_char;
-
-	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
-		{
-		/* yy_c_buf_p now points to the character we want to return.
-		 * If this occurs *before* the EOB characters, then it's a
-		 * valid NUL; if not, then we've hit the end of the buffer.
-		 */
-		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
-			/* This was really a NUL. */
-			*yy_c_buf_p = '\0';
-
-		else
-			{ /* need more input */
-			int offset = yy_c_buf_p - yytext_ptr;
-			++yy_c_buf_p;
-
-			switch ( yy_get_next_buffer() )
-				{
-				case EOB_ACT_LAST_MATCH:
-					/* This happens because yy_g_n_b()
-					 * sees that we've accumulated a
-					 * token and flags that we need to
-					 * try matching the token before
-					 * proceeding.  But for input(),
-					 * there's no matching to consider.
-					 * So convert the EOB_ACT_LAST_MATCH
-					 * to EOB_ACT_END_OF_FILE.
-					 */
-
-					/* Reset buffer status. */
-					yyrestart( yyin );
-
-					/* fall through */
-
-				case EOB_ACT_END_OF_FILE:
-					{
-					if ( yywrap() )
-						return EOF;
-
-					if ( ! yy_did_buffer_switch_on_eof )
-						YY_NEW_FILE;
-#ifdef __cplusplus
-					return yyinput();
-#else
-					return input();
-#endif
-					}
-
-				case EOB_ACT_CONTINUE_SCAN:
-					yy_c_buf_p = yytext_ptr + offset;
-					break;
-				}
-			}
-		}
-
-	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
-	*yy_c_buf_p = '\0';	/* preserve yytext */
-	yy_hold_char = *++yy_c_buf_p;
-
-
-	return c;
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yyrestart( FILE *input_file )
-#else
-void yyrestart( input_file )
-FILE *input_file;
-#endif
-	{
-	if ( ! yy_current_buffer )
-		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
-
-	yy_init_buffer( yy_current_buffer, input_file );
-	yy_load_buffer_state();
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
-#else
-void yy_switch_to_buffer( new_buffer )
-YY_BUFFER_STATE new_buffer;
-#endif
-	{
-	if ( yy_current_buffer == new_buffer )
-		return;
-
-	if ( yy_current_buffer )
-		{
-		/* Flush out information for old buffer. */
-		*yy_c_buf_p = yy_hold_char;
-		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
-		yy_current_buffer->yy_n_chars = yy_n_chars;
-		}
-
-	yy_current_buffer = new_buffer;
-	yy_load_buffer_state();
-
-	/* We don't actually know whether we did this switch during
-	 * EOF (yywrap()) processing, but the only time this flag
-	 * is looked at is after yywrap() is called, so it's safe
-	 * to go ahead and always set it.
-	 */
-	yy_did_buffer_switch_on_eof = 1;
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_load_buffer_state( void )
-#else
-void yy_load_buffer_state()
-#endif
-	{
-	yy_n_chars = yy_current_buffer->yy_n_chars;
-	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
-	yyin = yy_current_buffer->yy_input_file;
-	yy_hold_char = *yy_c_buf_p;
-	}
-
-
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
-#else
-YY_BUFFER_STATE yy_create_buffer( file, size )
-FILE *file;
-int size;
-#endif
-	{
-	YY_BUFFER_STATE b;
-
-	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_buf_size = size;
-
-	/* yy_ch_buf has to be 2 characters longer than the size given because
-	 * we need to put in 2 end-of-buffer characters.
-	 */
-	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
-	if ( ! b->yy_ch_buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
-	b->yy_is_our_buffer = 1;
-
-	yy_init_buffer( b, file );
-
-	return b;
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_delete_buffer( YY_BUFFER_STATE b )
-#else
-void yy_delete_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-	{
-	if ( ! b )
-		return;
-
-	if ( b == yy_current_buffer )
-		yy_current_buffer = (YY_BUFFER_STATE) 0;
-
-	if ( b->yy_is_our_buffer )
-		yy_flex_free( (void *) b->yy_ch_buf );
-
-	yy_flex_free( (void *) b );
-	}
-
-
-#ifndef _WIN32
-#else
-#ifndef YY_ALWAYS_INTERACTIVE
-#ifndef YY_NEVER_INTERACTIVE
-extern int isatty YY_PROTO(( int ));
-#endif
-#endif
-#endif
-
-#ifdef YY_USE_PROTOS
-void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
-#else
-void yy_init_buffer( b, file )
-YY_BUFFER_STATE b;
-FILE *file;
-#endif
-
-
-	{
-	yy_flush_buffer( b );
-
-	b->yy_input_file = file;
-	b->yy_fill_buffer = 1;
-
-#if YY_ALWAYS_INTERACTIVE
-	b->yy_is_interactive = 1;
-#else
-#if YY_NEVER_INTERACTIVE
-	b->yy_is_interactive = 0;
-#else
-	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-#endif
-#endif
-	}
-
-
-#ifdef YY_USE_PROTOS
-void yy_flush_buffer( YY_BUFFER_STATE b )
-#else
-void yy_flush_buffer( b )
-YY_BUFFER_STATE b;
-#endif
-
-	{
-	if ( ! b )
-		return;
-
-	b->yy_n_chars = 0;
-
-	/* We always need two end-of-buffer characters.  The first causes
-	 * a transition to the end-of-buffer state.  The second causes
-	 * a jam in that state.
-	 */
-	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
-	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
-	b->yy_buf_pos = &b->yy_ch_buf[0];
-
-	b->yy_at_bol = 1;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	if ( b == yy_current_buffer )
-		yy_load_buffer_state();
-	}
-
-
-#ifndef YY_NO_SCAN_BUFFER
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
-#else
-YY_BUFFER_STATE yy_scan_buffer( base, size )
-char *base;
-yy_size_t size;
-#endif
-	{
-	YY_BUFFER_STATE b;
-
-	if ( size < 2 ||
-	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
-	     base[size-1] != YY_END_OF_BUFFER_CHAR )
-		/* They forgot to leave room for the EOB's. */
-		return 0;
-
-	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
-	if ( ! b )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
-	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
-	b->yy_buf_pos = b->yy_ch_buf = base;
-	b->yy_is_our_buffer = 0;
-	b->yy_input_file = 0;
-	b->yy_n_chars = b->yy_buf_size;
-	b->yy_is_interactive = 0;
-	b->yy_at_bol = 1;
-	b->yy_fill_buffer = 0;
-	b->yy_buffer_status = YY_BUFFER_NEW;
-
-	yy_switch_to_buffer( b );
-
-	return b;
-	}
-#endif
-
-
-#ifndef YY_NO_SCAN_STRING
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
-#else
-YY_BUFFER_STATE yy_scan_string( yy_str )
-yyconst char *yy_str;
-#endif
-	{
-	int len;
-	for ( len = 0; yy_str[len]; ++len )
-		;
-
-	return yy_scan_bytes( yy_str, len );
-	}
-#endif
-
-
-#ifndef YY_NO_SCAN_BYTES
-#ifdef YY_USE_PROTOS
-YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
-#else
-YY_BUFFER_STATE yy_scan_bytes( bytes, len )
-yyconst char *bytes;
-int len;
-#endif
-	{
-	YY_BUFFER_STATE b;
-	char *buf;
-	yy_size_t n;
-	int i;
-
-	/* Get memory for full buffer, including space for trailing EOB's. */
-	n = len + 2;
-	buf = (char *) yy_flex_alloc( n );
-	if ( ! buf )
-		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
-	for ( i = 0; i < len; ++i )
-		buf[i] = bytes[i];
-
-	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
-
-	b = yy_scan_buffer( buf, n );
-	if ( ! b )
-		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
-	/* It's okay to grow etc. this buffer, and we should throw it
-	 * away when we're done.
-	 */
-	b->yy_is_our_buffer = 1;
-
-	return b;
-	}
-#endif
-
-
-#ifndef YY_NO_PUSH_STATE
-#ifdef YY_USE_PROTOS
-static void yy_push_state( int new_state )
-#else
-static void yy_push_state( new_state )
-int new_state;
-#endif
-	{
-	if ( yy_start_stack_ptr >= yy_start_stack_depth )
-		{
-		yy_size_t new_size;
-
-		yy_start_stack_depth += YY_START_STACK_INCR;
-		new_size = yy_start_stack_depth * sizeof( int );
-
-		if ( ! yy_start_stack )
-			yy_start_stack = (int *) yy_flex_alloc( new_size );
-
-		else
-			yy_start_stack = (int *) yy_flex_realloc(
-					(void *) yy_start_stack, new_size );
-
-		if ( ! yy_start_stack )
-			YY_FATAL_ERROR(
-			"out of memory expanding start-condition stack" );
-		}
-
-	yy_start_stack[yy_start_stack_ptr++] = YY_START;
-
-	BEGIN(new_state);
-	}
-#endif
-
-
-#ifndef YY_NO_POP_STATE
-static void yy_pop_state()
-	{
-	if ( --yy_start_stack_ptr < 0 )
-		YY_FATAL_ERROR( "start-condition stack underflow" );
-
-	BEGIN(yy_start_stack[yy_start_stack_ptr]);
-	}
-#endif
-
-
-#ifndef YY_NO_TOP_STATE
-static int yy_top_state()
-	{
-	return yy_start_stack[yy_start_stack_ptr - 1];
-	}
-#endif
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-#ifdef YY_USE_PROTOS
-static void yy_fatal_error( yyconst char msg[] )
-#else
-static void yy_fatal_error( msg )
-char msg[];
-#endif
-	{
-	(void) fprintf( stderr, "%s\n", msg );
-	exit( YY_EXIT_FAILURE );
-	}
-
-
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
-	do \
-		{ \
-		/* Undo effects of setting up yytext. */ \
-		yytext[yyleng] = yy_hold_char; \
-		yy_c_buf_p = yytext + n; \
-		yy_hold_char = *yy_c_buf_p; \
-		*yy_c_buf_p = '\0'; \
-		yyleng = n; \
-		} \
-	while ( 0 )
-
-
-/* Internal utility routines. */
-
-#ifndef yytext_ptr
-#ifdef YY_USE_PROTOS
-static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
-#else
-static void yy_flex_strncpy( s1, s2, n )
-char *s1;
-yyconst char *s2;
-int n;
-#endif
-	{
-	register int i;
-	for ( i = 0; i < n; ++i )
-		s1[i] = s2[i];
-	}
-#endif
-
-#ifdef YY_NEED_STRLEN
-#ifdef YY_USE_PROTOS
-static int yy_flex_strlen( yyconst char *s )
-#else
-static int yy_flex_strlen( s )
-yyconst char *s;
-#endif
-	{
-	register int n;
-	for ( n = 0; s[n]; ++n )
-		;
-
-	return n;
-	}
-#endif
-
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_alloc( yy_size_t size )
-#else
-static void *yy_flex_alloc( size )
-yy_size_t size;
-#endif
-	{
-	return (void *) malloc( size );
-	}
-
-#ifdef YY_USE_PROTOS
-static void *yy_flex_realloc( void *ptr, yy_size_t size )
-#else
-static void *yy_flex_realloc( ptr, size )
-void *ptr;
-yy_size_t size;
-#endif
-	{
-	/* The cast to (char *) in the following accommodates both
-	 * implementations that use char* generic pointers, and those
-	 * that use void* generic pointers.  It works with the latter
-	 * because both ANSI C and C++ allow castless assignment from
-	 * any pointer type to void*, and deal with argument conversions
-	 * as though doing an assignment.
-	 */
-	return (void *) realloc( (char *) ptr, size );
-	}
-
-#ifdef YY_USE_PROTOS
-static void yy_flex_free( void *ptr )
-#else
-static void yy_flex_free( ptr )
-void *ptr;
-#endif
-	{
-	free( ptr );
-	}
-
-#if YY_MAIN
-int main()
-	{
-	yylex();
-	return 0;
-	}
-#endif
-#line 740 "lexer.lxx"
+#define yy_create_buffer eggyy_create_buffer
+#define yy_delete_buffer eggyy_delete_buffer
+#define yy_scan_buffer eggyy_scan_buffer
+#define yy_scan_string eggyy_scan_string
+#define yy_scan_bytes eggyy_scan_bytes
+#define yy_flex_debug eggyy_flex_debug
+#define yy_init_buffer eggyy_init_buffer
+#define yy_flush_buffer eggyy_flush_buffer
+#define yy_load_buffer_state eggyy_load_buffer_state
+#define yy_switch_to_buffer eggyy_switch_to_buffer
+#define yyin eggyyin
+#define yyleng eggyyleng
+#define yylex eggyylex
+#define yyout eggyyout
+#define yyrestart eggyyrestart
+#define yytext eggyytext
+#define yywrap eggyywrap
+
+#line 20 "lex.yy.c"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header$
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 98
+#define YY_END_OF_BUFFER 99
+static yyconst short int yy_accept[557] =
+    {   0,
+        0,    0,   99,   97,    2,    1,   96,   97,   97,   97,
+       97,   90,   90,   97,   97,   97,    5,   97,    1,   97,
+       90,   97,   90,    4,    3,   90,   92,   97,   91,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,    3,    3,   92,   97,   90,   91,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       66,   97,   97,   97,   94,   97,   95,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   18,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   32,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   81,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   24,   97,   97,   97,   97,
+
+       22,   97,   97,   97,   97,   97,   31,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   52,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   67,   97,   97,   97,
+       97,   97,   97,   97,   97,   78,   97,   97,   97,   97,
+       97,   97,   93,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   19,   97,   97,   97,   97,   23,
+       97,   28,   97,   97,   97,   97,   97,   97,   37,   38,
+       97,   97,   97,   43,   97,   97,   97,   97,   97,   97,
+       97,   53,   97,   55,   56,   57,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   74,   97,
+       77,   97,   97,   97,   97,   97,   97,   93,   97,    7,
+       97,   97,   97,   12,   97,   97,   97,   97,   97,   97,
+       97,   21,   26,   97,   97,   30,   97,   97,   33,   34,
+       97,   97,   42,   97,   97,   97,   97,   48,   97,   97,
+       97,   97,   97,   97,   60,   97,   97,   97,   65,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   11,   13,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       44,   97,   97,   97,   97,   97,   97,   54,   58,   59,
+
+       97,   97,   63,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   84,   97,   97,   97,   97,
+       97,   97,   97,   14,   15,   97,   97,   97,   20,   97,
+       97,   35,   97,   97,   40,   41,   97,   97,   97,   97,
+       97,   51,   97,   62,   97,   68,   69,   70,   97,   97,
+       97,   97,   79,   80,   82,   83,   97,   97,   97,   97,
+       97,   97,   10,   97,   97,   25,   97,   97,   36,   39,
+       97,   97,   97,   97,   97,   61,   97,   71,   97,   97,
+       97,   97,   97,   97,   97,   88,   97,   97,    8,   97,
+       16,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+
+       72,   73,   97,   97,   97,   97,   87,   97,   97,   97,
+       97,   97,   29,   45,   97,   47,   49,   50,   97,   97,
+       97,   85,   86,   97,    6,   97,   97,   97,   97,   97,
+       75,   97,   89,   97,   97,   97,   46,   97,   97,   97,
+       97,   97,   97,   76,   97,   97,   97,   97,    9,   97,
+       97,   64,   17,   97,   27,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    2,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    4,    1,    5,    1,    1,    1,    1,
+        1,    6,    7,    1,    8,    9,   10,   11,   12,   13,
+       14,   15,   13,   13,   13,   13,   13,    1,    1,   16,
+        1,   17,    1,    1,   19,   20,   21,   22,   23,   24,
+       25,   26,   27,   28,   29,   30,   31,   32,   33,   34,
+       35,   36,   37,   38,   39,   40,   41,   42,   43,   44,
+        1,    1,    1,    1,   18,    1,   19,   20,   21,   22,
+
+       23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+       33,   34,   35,   36,   37,   38,   39,   40,   41,   42,
+       43,   44,   45,    1,   45,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[46] =
+    {   0,
+        1,    2,    3,    2,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    2
+    } ;
+
+static yyconst short int yy_base[562] =
+    {   0,
+        0,   44,  663,    0,  664,    0,  664,    8,   81,   22,
+       18,  100,   19,  123,  630,  642,  664,    0,    0,   29,
+       30,  628,   51,    0,   65,   68,   14,  159,  164,   61,
+       91,  170,   43,  623,  631,  625,  623,  623,   70,   68,
+       66,   86,  621,   93,  175,  181,  128,  111,  629,  628,
+      619,  626,  136,    0,   18,  207,  213,    0,  605,  629,
+       45,  615,  627,  612,  102,  627,  607,  605,  604,  607,
+      614,  602,  597,  593,  603,  604,  595,  599,  597,  173,
+      603,  596,  596,  594,  588,  603,  601,  587,  586,  593,
+      598,  581,  100,  594,  597,  578,  596,  595,  578,  593,
+
+      584,  209,  568,  586,  176,  570,  578,  577,  588,  575,
+        0,  574,  566,  570,    0,  589,    0,  572,  577,  567,
+      563,  573,  558,  556,  562,  199,  555,    0,  552,  572,
+      550,  551,  566,  562,  567,  539,  563,  558,  562,  540,
+      561,    0,  547,  538,  543,  536,  550,  538,  146,  548,
+      546,  538,  548,  544,  543,  527,  532,  520,  545,  542,
+      195,  528,  529,  519,  535,  518,  525,  537,  528,   48,
+      520,  519,  526,  174,  532,  516,  515,    0,  514,  513,
+      506,  538,  500,  518,  517,  519,  502,  507,  530,  512,
+      507,  510,  499,  509,  513,    0,  510,  497,  508,  502,
+
+        0,  508,  493,  506,  496,  487,    0,  481,  500,  480,
+      480,  499,  498,  478,  486,  482,  494,  491,  472,  487,
+      471,  487,  467,  479,    0,  486,  464,  484,  483,  482,
+      471,   79,  474,  469,  474,  471,    0,  470,  465,  452,
+      465,  452,  471,  455,  469,    0,  452,  451,  450,  449,
+      458,  461,  231,  443,  461,  444,  445,  452,  457,  451,
+      450,  439,  438,  442,    0,  436,  448,  449,  448,    0,
+      437,    0,  440,  445,  439,  428,  442,  441,    0,    0,
+      430,  414,  438,    0,  424,  194,  415,  435,  419,  420,
+      416,    0,  425,    0,    0,    0,  416,  410,  428,  412,
+
+      411,  416,  424,  408,  402,  402,  399,  134,    0,  411,
+        0,  397,  396,  395,  394,  389,  398,    0,  408,    0,
+      409,  408,  409,    0,  408,  401,  385,  399,  389,  399,
+      389,    0,    0,  397,  398,    0,  393,  394,    0,    0,
+      395,  221,    0,  396,  373,  372,  372,    0,  384,  381,
+      375,  389,  388,  387,    0,  382,  377,  120,    0,  363,
+      362,  376,  372,  364,  377,  365,  357,  356,  355,  354,
+      230,  363,  350,  352,  357,    0,    0,  369,  368,  352,
+      364,  359,  364,  340,  357,  361,  354,  346,  358,  357,
+        0,  337,  336,  328,  347,  344,  351,    0,    0,    0,
+
+      344,  349,    0,  332,  347,  346,  345,  324,  324,  321,
+      335,  340,  339,  338,  337,    0,  321,  319,  328,  319,
+      313,  326,  330,    0,    0,  308,  307,  327,    0,  320,
+      319,    0,  324,  323,    0,    0,  299,  314,  303,  304,
+      309,    0,  317,    0,  301,    0,    0,    0,  315,  300,
+      307,  224,    0,    0,    0,    0,  302,  295,  303,  239,
+      286,  241,    0,  308,  301,    0,  287,  286,    0,    0,
+      298,  301,  296,  280,  279,    0,  294,    0,  298,  297,
+      294,  274,  280,  280,  292,    0,  271,  284,    0,  283,
+        0,  268,  266,  286,  285,  280,  283,  282,  281,  270,
+
+        0,    0,  264,  259,  277,  276,    0,  287,  274,  258,
+      246,  265,    0,    0,  264,    0,    0,    0,  248,  268,
+      257,    0,    0,  266,    0,  244,  244,  238,  262,  251,
+        0,  243,    0,  253,  227,  229,    0,  227,  242,  204,
+      209,  174,  160,    0,  122,   76,   35,   32,    0,   21,
+        1,    0,    0,    1,    0,  664,  266,    0,  269,  271,
+      273
+    } ;
+
+static yyconst short int yy_def[562] =
+    {   0,
+      557,  557,  556,  558,  556,  559,  556,  558,  558,  558,
+      558,  558,   12,  558,  558,  558,  556,  558,  559,  558,
+       12,  558,  558,  558,  560,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  560,  561,  558,  558,  558,   29,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  253,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,  558,  558,  558,  558,  558,
+      558,  558,  558,  558,  558,    0,  556,  556,  556,  556,
+      556
+    } ;
+
+static yyconst short int yy_nxt[710] =
+    {   0,
+       18,    5,    6,    7,  556,  556,    8,    9,   10,   11,
+       12,   13,   13,   13,   13,   14,   20,  555,   21,   21,
+       21,   21,   21,   24,   55,   55,   15,   25,   55,   55,
+      554,   16,   23,   23,   23,   23,   23,  553,   18,   23,
+       23,   23,   23,   23,   17,    5,    6,    7,  552,   18,
+        8,    9,   10,   11,   12,   13,   13,   13,   13,   14,
+       18,   23,   23,   23,   23,   23,   54,  551,   54,   76,
+       15,   18,   77,   28,  120,   16,  121,  239,   23,   23,
+       23,   23,   23,   59,   60,  240,   85,   61,   17,   20,
+       28,   21,   21,   21,   21,   21,   83,  298,   88,   62,
+
+       86,  299,   84,   87,   89,   90,  550,   22,   26,   54,
+       21,   21,   21,   21,   21,   94,   63,   95,  110,   27,
+       64,   91,   28,   65,   92,   96,  157,  111,  112,  158,
+       66,  125,  126,  113,  127,  107,  403,   54,  549,   54,
+      404,   29,   30,   31,   32,  108,   33,   34,   35,   36,
+       37,   38,   39,   40,   41,   42,   43,  364,   44,   45,
+       46,   47,   48,  365,   49,   56,   56,  109,  214,   57,
+       57,   57,   57,   57,   58,   58,   58,   58,   58,   97,
+       54,  215,   58,   58,   58,   58,   58,   58,   67,  142,
+       68,  548,  244,  143,  172,   98,   69,   99,  173,  102,
+
+      100,   70,  174,  103,  245,   71,  547,   72,   73,  144,
+      104,   74,   75,  227,  345,  101,  105,   57,   57,   57,
+       57,   57,  106,   57,   57,   57,   57,   57,  167,  192,
+      346,  546,  193,  168,  389,  390,  228,  229,  230,  545,
+      169,  318,  318,  318,  318,  318,  416,  481,  417,  318,
+      318,  318,  318,  318,  318,  486,  487,  489,  544,  543,
+      482,  490,  542,  418,  541,  419,    4,    4,    4,   19,
+       19,   53,   53,   54,   54,  540,  539,  538,  537,  536,
+      535,  534,  533,  532,  531,  530,  529,  528,  527,  526,
+      525,  524,  523,  522,  521,  520,  519,  518,  517,  516,
+
+      515,  514,  513,  512,  511,  510,  509,  508,  507,  506,
+      505,  504,  503,  502,  501,  500,  499,  498,  497,  496,
+      495,  494,  493,  492,  491,  488,  485,  484,  483,  480,
+      479,  478,  477,  476,  475,  474,  473,  472,  471,  470,
+      469,  468,  467,  466,  465,  464,  463,  462,  461,  460,
+      459,  458,  457,  456,  455,  454,  453,  452,  451,  450,
+      449,  448,  447,  446,  445,  444,  443,  442,  441,  440,
+      439,  438,  437,  436,  435,  434,  433,  432,  431,  430,
+      429,  428,  427,  426,  425,  424,  423,  422,  421,  420,
+      415,  414,  413,  412,  411,  410,  409,  408,  407,  406,
+
+      405,  402,  401,  400,  399,  398,  397,  396,  395,  394,
+      393,  392,  391,  388,  387,  386,  385,  384,  383,  382,
+      381,  380,  379,  378,  377,  376,  375,  374,  373,  372,
+      371,  370,  369,  368,  367,  366,  363,  362,  361,  360,
+      359,  358,  357,  356,  355,  354,  353,  352,  351,  350,
+      349,  348,  347,  344,  343,  342,  341,  340,  339,  338,
+      337,  336,  335,  334,  333,  332,  331,  330,  329,  328,
+      327,  326,  325,  324,  323,  322,  321,  320,  319,  317,
+      316,  315,  314,  313,  312,  311,  310,  309,  308,  307,
+      306,  305,  304,  303,  302,  301,  300,  297,  296,  295,
+
+      294,  293,  292,  291,  290,  289,  288,  287,  286,  285,
+      284,  283,  282,  281,  280,  279,  278,  277,  276,  275,
+      274,  273,  272,  271,  270,  269,  268,  267,  266,  265,
+      264,  263,  262,  261,  260,  259,  258,  257,  256,  255,
+      254,  253,  252,  251,  250,  249,  248,  247,  246,  243,
+      242,  241,  238,  237,  236,  235,  234,  233,  232,  231,
+      226,  225,  224,  223,  222,  221,  220,  219,  218,  217,
+      216,  213,  212,  211,  210,  209,  208,  207,  206,  205,
+      204,  203,  202,  201,  200,  199,  198,  197,  196,  195,
+      194,  191,  190,  189,  188,  187,  186,  185,  184,  183,
+
+      182,  181,  180,  179,  178,  177,  176,  175,  171,  170,
+      166,  165,  164,  163,  162,  161,  160,  159,  156,  155,
+      154,  153,  152,  151,  150,  149,  148,  147,  146,  145,
+      141,  140,  139,  138,  137,  136,  135,  134,  133,  132,
+      131,  130,  129,  128,  124,  123,  122,  119,  118,  117,
+      116,  115,  114,   93,   82,   81,   80,   79,   78,   52,
+       51,   50,  556,    3,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+
+      556,  556,  556,  556,  556,  556,  556,  556,  556
+    } ;
+
+static yyconst short int yy_chk[710] =
+    {   0,
+      558,    1,    1,    1,    0,    0,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    8,  554,    8,    8,
+        8,    8,    8,   11,   27,   27,    1,   11,   55,   55,
+      551,    1,   10,   10,   10,   10,   10,  550,   13,   20,
+       20,   20,   20,   20,    1,    2,    2,    2,  548,   21,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+       13,   23,   23,   23,   23,   23,   25,  547,   25,   33,
+        2,   21,   33,   23,   61,    2,   61,  170,   26,   26,
+       26,   26,   26,   30,   30,  170,   40,   30,    2,    9,
+       26,    9,    9,    9,    9,    9,   39,  232,   41,   30,
+
+       40,  232,   39,   40,   41,   42,  546,    9,   12,   25,
+       12,   12,   12,   12,   12,   44,   31,   44,   48,   12,
+       31,   42,   12,   31,   42,   44,   93,   48,   48,   93,
+       31,   65,   65,   48,   65,   47,  358,   53,  545,   53,
+      358,   12,   14,   14,   14,   47,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,  308,   14,   14,
+       14,   14,   14,  308,   14,   28,   28,   47,  149,   28,
+       28,   28,   28,   28,   29,   29,   29,   29,   29,   45,
+       53,  149,   29,   29,   29,   29,   29,   29,   32,   80,
+       32,  543,  174,   80,  105,   45,   32,   45,  105,   46,
+
+       45,   32,  105,   46,  174,   32,  542,   32,   32,   80,
+       46,   32,   32,  161,  286,   45,   46,   56,   56,   56,
+       56,   56,   46,   57,   57,   57,   57,   57,  102,  126,
+      286,  541,  126,  102,  342,  342,  161,  161,  161,  540,
+      102,  253,  253,  253,  253,  253,  371,  452,  371,  253,
+      253,  253,  253,  253,  253,  460,  460,  462,  539,  538,
+      452,  462,  536,  371,  535,  371,  557,  557,  557,  559,
+      559,  560,  560,  561,  561,  534,  532,  530,  529,  528,
+      527,  526,  524,  521,  520,  519,  515,  512,  511,  510,
+      509,  508,  506,  505,  504,  503,  500,  499,  498,  497,
+
+      496,  495,  494,  493,  492,  490,  488,  487,  485,  484,
+      483,  482,  481,  480,  479,  477,  475,  474,  473,  472,
+      471,  468,  467,  465,  464,  461,  459,  458,  457,  451,
+      450,  449,  445,  443,  441,  440,  439,  438,  437,  434,
+      433,  431,  430,  428,  427,  426,  423,  422,  421,  420,
+      419,  418,  417,  415,  414,  413,  412,  411,  410,  409,
+      408,  407,  406,  405,  404,  402,  401,  397,  396,  395,
+      394,  393,  392,  390,  389,  388,  387,  386,  385,  384,
+      383,  382,  381,  380,  379,  378,  375,  374,  373,  372,
+      370,  369,  368,  367,  366,  365,  364,  363,  362,  361,
+
+      360,  357,  356,  354,  353,  352,  351,  350,  349,  347,
+      346,  345,  344,  341,  338,  337,  335,  334,  331,  330,
+      329,  328,  327,  326,  325,  323,  322,  321,  319,  317,
+      316,  315,  314,  313,  312,  310,  307,  306,  305,  304,
+      303,  302,  301,  300,  299,  298,  297,  293,  291,  290,
+      289,  288,  287,  285,  283,  282,  281,  278,  277,  276,
+      275,  274,  273,  271,  269,  268,  267,  266,  264,  263,
+      262,  261,  260,  259,  258,  257,  256,  255,  254,  252,
+      251,  250,  249,  248,  247,  245,  244,  243,  242,  241,
+      240,  239,  238,  236,  235,  234,  233,  231,  230,  229,
+
+      228,  227,  226,  224,  223,  222,  221,  220,  219,  218,
+      217,  216,  215,  214,  213,  212,  211,  210,  209,  208,
+      206,  205,  204,  203,  202,  200,  199,  198,  197,  195,
+      194,  193,  192,  191,  190,  189,  188,  187,  186,  185,
+      184,  183,  182,  181,  180,  179,  177,  176,  175,  173,
+      172,  171,  169,  168,  167,  166,  165,  164,  163,  162,
+      160,  159,  158,  157,  156,  155,  154,  153,  152,  151,
+      150,  148,  147,  146,  145,  144,  143,  141,  140,  139,
+      138,  137,  136,  135,  134,  133,  132,  131,  130,  129,
+      127,  125,  124,  123,  122,  121,  120,  119,  118,  116,
+
+      114,  113,  112,  110,  109,  108,  107,  106,  104,  103,
+      101,  100,   99,   98,   97,   96,   95,   94,   92,   91,
+       90,   89,   88,   87,   86,   85,   84,   83,   82,   81,
+       79,   78,   77,   76,   75,   74,   73,   72,   71,   70,
+       69,   68,   67,   66,   64,   63,   62,   60,   59,   52,
+       51,   50,   49,   43,   38,   37,   36,   35,   34,   22,
+       16,   15,    3,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+      556,  556,  556,  556,  556,  556,  556,  556,  556,  556,
+
+      556,  556,  556,  556,  556,  556,  556,  556,  556
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "lexer.lxx"
+#define INITIAL 0
+/*
+// Filename: lexer.l
+// Created by:  drose (16Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+*/
+#line 9 "lexer.lxx"
+#include "lexerDefs.h"
+#include "parserDefs.h"
+#include "config_egg.h"
+#include "parser.h"
+
+#include <indent.h>
+#include <notify.h>
+
+#include <math.h>
+#include <pandabase.h>
+
+extern "C" int eggyywrap(void);  // declared below.
+
+static int yyinput(void);        // declared by flex.
+
+
+////////////////////////////////////////////////////////////////////
+// Static variables
+////////////////////////////////////////////////////////////////////
+
+// We'll increment line_number and col_number as we parse the file, so
+// that we can report the position of an error.
+static int line_number = 0;
+static int col_number = 0;
+
+// current_line holds as much of the current line as will fit.  Its
+// only purpose is for printing it out to report an error to the user.
+static const int max_error_width = 1024;
+static char current_line[max_error_width + 1];
+
+static int error_count = 0;
+static int warning_count = 0;
+
+// This is the pointer to the current input stream.
+static istream *inp = NULL;
+
+// This is the name of the egg file we're parsing.  We keep it so we
+// can print it out for error messages.
+static string egg_filename;
+
+// This is the initial token state returned by the lexer.  It allows
+// the yacc grammar to start from initial points.
+static int initial_token;
+
+
+////////////////////////////////////////////////////////////////////
+// Defining the interface to the lexer.
+////////////////////////////////////////////////////////////////////
+
+void
+egg_init_lexer(istream &in, const string &filename) {
+  inp = &in;
+  egg_filename = filename;
+  line_number = 0;
+  col_number = 0;
+  error_count = 0;
+  warning_count = 0;
+  initial_token = START_EGG;
+}
+
+void
+egg_start_group_body() {
+  /* Set the initial state to begin within a group_body context,
+     instead of at the beginning of the egg file. */
+  initial_token = START_GROUP_BODY;
+}
+
+void
+egg_start_texture_body() {
+  initial_token = START_TEXTURE_BODY;
+}
+
+void
+egg_start_primitive_body() {
+  initial_token = START_PRIMITIVE_BODY;
+}
+
+int
+egg_error_count() {
+  return error_count;
+}
+
+int
+egg_warning_count() {
+  return warning_count;
+}
+
+
+////////////////////////////////////////////////////////////////////
+// Internal support functions.
+////////////////////////////////////////////////////////////////////
+
+int
+eggyywrap(void) {
+  return 1;
+}
+
+void
+eggyyerror(const string &msg) {
+  if (egg_cat.is_error()) {
+    ostream &out = egg_cat.error(false);
+
+    out << "\nError";
+    if (!egg_filename.empty()) {
+      out << " in " << egg_filename;
+    }
+    out 
+      << " at line " << line_number << ", column " << col_number << ":\n"
+      << setiosflags(Notify::get_literal_flag())
+      << current_line << "\n";
+    indent(out, col_number-1) 
+      << "^\n" << msg << "\n\n" 
+      << resetiosflags(Notify::get_literal_flag()) << flush;
+  }
+  error_count++;
+}
+
+void
+eggyyerror(ostringstream &strm) {
+  string s = strm.str();
+  eggyyerror(s);
+}
+
+void
+eggyywarning(const string &msg) {
+  if (egg_cat.is_warning()) {
+    ostream &out = egg_cat.warning(false);
+
+    out << "\nWarning";
+    if (!egg_filename.empty()) {
+      out << " in " << egg_filename;
+    }
+    out 
+      << " at line " << line_number << ", column " << col_number << ":\n"
+      << setiosflags(Notify::get_literal_flag())
+      << current_line << "\n";
+    indent(out, col_number-1) 
+      << "^\n" << msg << "\n\n" 
+      << resetiosflags(Notify::get_literal_flag()) << flush;
+  }
+  warning_count++;
+}
+
+void
+eggyywarning(ostringstream &strm) {
+  string s = strm.str();
+  eggyywarning(s);
+}
+
+// Now define a function to take input from an istream instead of a
+// stdio FILE pointer.  This is flex-specific.
+static void
+input_chars(char *buffer, int &result, int max_size) {
+  nassertv(inp != NULL);
+  if (*inp) {
+    inp->read(buffer, max_size);
+    result = inp->gcount();
+
+    if (line_number == 0) {
+      // This is a special case.  If we are reading the very first bit
+      // from the stream, copy it into the current_line array.  This
+      // is because the \n.* rule below, which fills current_line
+      // normally, doesn't catch the first line.
+      int length = min(max_error_width, result);
+      strncpy(current_line, buffer, length);
+      current_line[length] = '\0';
+      line_number++;
+      col_number = 0;
+
+      // Truncate it at the newline.
+      char *end = strchr(current_line, '\n');
+      if (end != NULL) {
+        *end = '\0';
+      }
+    }
+
+  } else {
+    // End of file or I/O error.
+    result = 0;
+  }
+}
+#undef YY_INPUT
+#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
+
+// read_char reads and returns a single character, incrementing the
+// supplied line and column numbers as appropriate.  A convenience
+// function for the scanning functions below.
+static int
+read_char(int &line, int &col) {
+  int c = yyinput();
+  if (c == '\n') {
+    line++;
+    col = 0;
+  } else {
+    col++;
+  }
+  return c;
+}
+
+// scan_quoted_string reads a string delimited by quotation marks and
+// returns it.
+static string
+scan_quoted_string() {
+  string result;
+
+  // We don't touch the current line number and column number during
+  // scanning, so that if we detect an error while scanning the string
+  // (e.g. an unterminated string), we'll report the error as
+  // occurring at the start of the string, not at the end--somewhat
+  // more convenient for the user.
+
+  // Instead of adjusting the global line_number and col_number
+  // variables, we'll operate on our own local variables for the
+  // interim.
+  int line = line_number;
+  int col = col_number;
+
+  int c;
+  c = read_char(line, col);
+  while (c != '"' && c != EOF) {
+    result += c;
+    c = read_char(line, col);
+  }
+
+  if (c == EOF) {
+    eggyyerror("This quotation mark is unterminated.");
+  }
+
+  line_number = line;
+  col_number = col;
+
+  return result;
+}
+
+// eat_c_comment scans past all characters up until the first */
+// encountered.
+static void
+eat_c_comment() {
+  // As above, we'll operate on our own local copies of line_number
+  // and col_number within this function.
+
+  int line = line_number;
+  int col = col_number;
+
+  int c, last_c;
+  
+  last_c = '\0';
+  c = read_char(line, col);
+  while (c != EOF && !(last_c == '*' && c == '/')) {
+    if (last_c == '/' && c == '*') {
+      ostringstream errmsg;
+      errmsg << "This comment contains a nested /* symbol at line "
+             << line << ", column " << col-1 << "--possibly unclosed?"
+             << ends;
+      eggyywarning(errmsg);
+    }
+    last_c = c;
+    c = read_char(line, col);
+  }
+
+  if (c == EOF) {
+    eggyyerror("This comment marker is unclosed.");
+  }
+
+  line_number = line;
+  col_number = col;
+}
+
+
+// accept() is called below as each piece is pulled off and
+// accepted by the lexer; it increments the current column number.
+INLINE void accept() {
+  col_number += yyleng;
+}
+
+#line 1004 "lex.yy.c"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( yy_current_buffer->yy_is_interactive ) \
+		{ \
+		int c = '*', n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+		  && ferror( yyin ) ) \
+		YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp = NULL, *yy_bp = NULL;
+	register int yy_act;
+
+#line 290 "lexer.lxx"
+
+
+
+  if (initial_token != 0) {
+    int t = initial_token;
+    initial_token = 0;
+    return t;
+  }
+
+
+#line 1166 "lex.yy.c"
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yy_last_accepting_state = yy_current_state;
+				yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 557 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 664 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yy_hold_char;
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 300 "lexer.lxx"
+{
+  // New line.  Save a copy of the line so we can print it out for the
+  // benefit of the user in case we get an error.
+
+  strncpy(current_line, yytext+1, max_error_width);
+  current_line[max_error_width] = '\0';
+  line_number++;
+  col_number=0;
+
+  // Return the whole line to the lexer, except the newline character,
+  // which we eat.
+  yyless(1);
+}
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 314 "lexer.lxx"
+{ 
+  // Eat whitespace.
+  accept();
+}
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 319 "lexer.lxx"
+{ 
+  // Eat C++-style comments.
+  accept();
+}
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 324 "lexer.lxx"
+{
+  // Eat C-style comments.
+  accept();
+  eat_c_comment(); 
+}
+	YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 330 "lexer.lxx"
+{
+  // Send curly braces as themselves.
+  accept(); 
+  return eggyytext[0];
+}
+	YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 338 "lexer.lxx"
+{
+  accept();
+  return BEZIERCURVE;
+}
+	YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 342 "lexer.lxx"
+{
+  accept();
+  return BFACE;
+}
+	YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 346 "lexer.lxx"
+{
+  accept();
+  return BILLBOARD;
+}
+	YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 350 "lexer.lxx"
+{
+  accept();
+  return BILLBOARDCENTER;
+}
+	YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 354 "lexer.lxx"
+{
+  accept();
+  return BINORMAL;
+}
+	YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 358 "lexer.lxx"
+{
+  accept();
+  return BUNDLE;
+}
+	YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 362 "lexer.lxx"
+{
+  accept();
+  return SCALAR;
+}
+	YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 366 "lexer.lxx"
+{
+  accept();
+  return CLOSED;
+}
+	YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 370 "lexer.lxx"
+{
+  accept();
+  return COLLIDE;
+}
+	YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 374 "lexer.lxx"
+{
+  accept();
+  return COMMENT;
+}
+	YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 378 "lexer.lxx"
+{
+  accept();
+  return COMPONENT;
+}
+	YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 382 "lexer.lxx"
+{
+  accept();
+  return COORDSYSTEM;
+}
+	YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 386 "lexer.lxx"
+{
+  accept();
+  return CV;
+}
+	YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 390 "lexer.lxx"
+{
+  accept();
+  return DART;
+}
+	YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 394 "lexer.lxx"
+{
+  accept();
+  return DNORMAL;
+}
+	YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 398 "lexer.lxx"
+{
+  accept();
+  return DRGBA;
+}
+	YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 402 "lexer.lxx"
+{
+  accept();
+  return DUV;
+}
+	YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 406 "lexer.lxx"
+{
+  accept();
+  return DXYZ;
+}
+	YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 410 "lexer.lxx"
+{
+  accept();
+  return DCS;
+}
+	YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 414 "lexer.lxx"
+{
+  accept();
+  return DISTANCE;
+}
+	YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 418 "lexer.lxx"
+{
+  accept();
+  return DTREF;
+}
+	YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 422 "lexer.lxx"
+{
+  accept();
+  return DYNAMICVERTEXPOOL;
+}
+	YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 426 "lexer.lxx"
+{
+  accept();
+  return EXTERNAL_FILE;
+}
+	YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 430 "lexer.lxx"
+{
+  accept();
+  return FLIGHT;
+}
+	YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 434 "lexer.lxx"
+{
+  accept();
+  return GROUP;
+}
+	YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 438 "lexer.lxx"
+{
+  accept();
+  return HIP;
+}
+	YY_BREAK
+case 32:
+YY_RULE_SETUP
+#line 442 "lexer.lxx"
+{
+  accept();
+  return INTANGENT;
+}
+	YY_BREAK
+case 33:
+YY_RULE_SETUP
+#line 446 "lexer.lxx"
+{
+  accept();
+  return JOINT;
+}
+	YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 450 "lexer.lxx"
+{
+  accept();
+  return KNOTS;
+}
+	YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 454 "lexer.lxx"
+{
+  accept();
+  return INCLUDE;
+}
+	YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 458 "lexer.lxx"
+{
+  accept();
+  return INSTANCE;
+}
+	YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 462 "lexer.lxx"
+{
+  accept();
+  return LINE;
+}
+	YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 466 "lexer.lxx"
+{
+  accept();
+  return LOOP;
+}
+	YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 470 "lexer.lxx"
+{
+  accept();
+  return MATERIAL;
+}
+	YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 474 "lexer.lxx"
+{
+  accept();
+  return MATRIX3;
+}
+	YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 478 "lexer.lxx"
+{
+  accept();
+  return MATRIX4;
+}
+	YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 482 "lexer.lxx"
+{
+  accept();
+  return MODEL;
+}
+	YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 486 "lexer.lxx"
+{
+  accept();
+  return MREF;
+}
+	YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 490 "lexer.lxx"
+{
+  accept();
+  return NORMAL;
+}
+	YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 494 "lexer.lxx"
+{
+  accept();
+  return NURBSCURVE;
+}
+	YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 498 "lexer.lxx"
+{
+  accept();
+  return NURBSSURFACE;
+}
+	YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 502 "lexer.lxx"
+{
+  accept();
+  return OBJECTTYPE;
+}
+	YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 506 "lexer.lxx"
+{
+  accept();
+  return ORDER;
+}
+	YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 510 "lexer.lxx"
+{
+  accept();
+  return OUTTANGENT;
+}
+	YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 514 "lexer.lxx"
+{
+  accept();
+  return POINTLIGHT;
+}
+	YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 518 "lexer.lxx"
+{
+  accept();
+  return POLYGON;
+}
+	YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 522 "lexer.lxx"
+{
+  accept();
+  return REF;
+}
+	YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 526 "lexer.lxx"
+{
+  accept();
+  return RGBA;
+}
+	YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 530 "lexer.lxx"
+{
+  accept();
+  return ROTATE;
+}
+	YY_BREAK
+case 55:
+YY_RULE_SETUP
+#line 534 "lexer.lxx"
+{
+  accept();
+  return ROTX;
+}
+	YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 538 "lexer.lxx"
+{
+  accept();
+  return ROTY;
+}
+	YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 542 "lexer.lxx"
+{
+  accept();
+  return ROTZ;
+}
+	YY_BREAK
+case 58:
+YY_RULE_SETUP
+#line 546 "lexer.lxx"
+{
+  accept();
+  return SANIM;
+}
+	YY_BREAK
+case 59:
+YY_RULE_SETUP
+#line 550 "lexer.lxx"
+{
+  accept();
+  return SCALAR;
+}
+	YY_BREAK
+case 60:
+YY_RULE_SETUP
+#line 554 "lexer.lxx"
+{
+  accept();
+  return SCALE;
+}
+	YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 558 "lexer.lxx"
+{
+  accept();
+  return SEQUENCE;
+}
+	YY_BREAK
+case 62:
+YY_RULE_SETUP
+#line 562 "lexer.lxx"
+{
+  accept();
+  return SHADING;
+}
+	YY_BREAK
+case 63:
+YY_RULE_SETUP
+#line 566 "lexer.lxx"
+{
+  accept();
+  return SWITCH;
+}
+	YY_BREAK
+case 64:
+YY_RULE_SETUP
+#line 570 "lexer.lxx"
+{
+  accept();
+  return SWITCHCONDITION;
+}
+	YY_BREAK
+case 65:
+YY_RULE_SETUP
+#line 574 "lexer.lxx"
+{
+  accept();
+  return TABLE;
+}
+	YY_BREAK
+case 66:
+YY_RULE_SETUP
+#line 578 "lexer.lxx"
+{
+  accept();
+  return TABLE_V;
+}
+	YY_BREAK
+case 67:
+YY_RULE_SETUP
+#line 582 "lexer.lxx"
+{
+  accept();
+  return TAG;
+}
+	YY_BREAK
+case 68:
+YY_RULE_SETUP
+#line 586 "lexer.lxx"
+{
+  accept();
+  return TANGENT;
+}
+	YY_BREAK
+case 69:
+YY_RULE_SETUP
+#line 590 "lexer.lxx"
+{
+  accept();
+  return TEXLIST;
+}
+	YY_BREAK
+case 70:
+YY_RULE_SETUP
+#line 594 "lexer.lxx"
+{
+  accept();
+  return TEXTURE;
+}
+	YY_BREAK
+case 71:
+YY_RULE_SETUP
+#line 598 "lexer.lxx"
+{
+  accept();
+  return TLENGTHS;
+}
+	YY_BREAK
+case 72:
+YY_RULE_SETUP
+#line 602 "lexer.lxx"
+{
+  accept();
+  return TRANSFORM;
+}
+	YY_BREAK
+case 73:
+YY_RULE_SETUP
+#line 606 "lexer.lxx"
+{
+  accept();
+  return TRANSLATE;
+}
+	YY_BREAK
+case 74:
+YY_RULE_SETUP
+#line 610 "lexer.lxx"
+{
+  accept();
+  return TREF;
+}
+	YY_BREAK
+case 75:
+YY_RULE_SETUP
+#line 614 "lexer.lxx"
+{
+  accept();
+  return TRIANGLEFAN;
+}
+	YY_BREAK
+case 76:
+YY_RULE_SETUP
+#line 618 "lexer.lxx"
+{
+  accept();
+  return TRIANGLESTRIP;
+}
+	YY_BREAK
+case 77:
+YY_RULE_SETUP
+#line 622 "lexer.lxx"
+{
+  accept();
+  return TRIM;
+}
+	YY_BREAK
+case 78:
+YY_RULE_SETUP
+#line 626 "lexer.lxx"
+{
+  accept();
+  return TXT;
+}
+	YY_BREAK
+case 79:
+YY_RULE_SETUP
+#line 630 "lexer.lxx"
+{
+  accept();
+  return UKNOTS;
+}
+	YY_BREAK
+case 80:
+YY_RULE_SETUP
+#line 634 "lexer.lxx"
+{
+  accept();
+  return UKNOTS;
+}
+	YY_BREAK
+case 81:
+YY_RULE_SETUP
+#line 638 "lexer.lxx"
+{
+  accept();
+  return UV;
+}
+	YY_BREAK
+case 82:
+YY_RULE_SETUP
+#line 642 "lexer.lxx"
+{
+  accept();
+  return VKNOTS;
+}
+	YY_BREAK
+case 83:
+YY_RULE_SETUP
+#line 646 "lexer.lxx"
+{
+  accept();
+  return VKNOTS;
+}
+	YY_BREAK
+case 84:
+YY_RULE_SETUP
+#line 650 "lexer.lxx"
+{
+  accept();
+  return VERTEX;
+}
+	YY_BREAK
+case 85:
+YY_RULE_SETUP
+#line 654 "lexer.lxx"
+{
+  accept();
+  return VERTEXANIM;
+}
+	YY_BREAK
+case 86:
+YY_RULE_SETUP
+#line 658 "lexer.lxx"
+{
+  accept();
+  return VERTEXPOOL;
+}
+	YY_BREAK
+case 87:
+YY_RULE_SETUP
+#line 662 "lexer.lxx"
+{
+  accept();
+  return VERTEXREF;
+}
+	YY_BREAK
+case 88:
+YY_RULE_SETUP
+#line 666 "lexer.lxx"
+{
+  accept();
+  return XFMANIM;
+}
+	YY_BREAK
+case 89:
+YY_RULE_SETUP
+#line 670 "lexer.lxx"
+{
+  accept();
+  return XFMSANIM;
+}
+	YY_BREAK
+case 90:
+YY_RULE_SETUP
+#line 677 "lexer.lxx"
+{ 
+  // An integer or floating-point number.
+  accept(); 
+  eggyylval._number = atof(eggyytext); 
+  eggyylval._string = yytext;
+  return NUMBER; 
+}
+	YY_BREAK
+case 91:
+YY_RULE_SETUP
+#line 685 "lexer.lxx"
+{
+  // A hexadecimal integer number.
+  accept(); 
+  eggyylval._ulong = strtoul(yytext+2, NULL, 16);
+  eggyylval._string = yytext;
+  return ULONG; 
+}
+	YY_BREAK
+case 92:
+YY_RULE_SETUP
+#line 693 "lexer.lxx"
+{
+  // A binary integer number.
+  accept(); 
+  eggyylval._ulong = strtoul(yytext+2, NULL, 2);
+  eggyylval._string = yytext;
+  return ULONG; 
+}
+	YY_BREAK
+case 93:
+YY_RULE_SETUP
+#line 701 "lexer.lxx"
+{
+  // not-a-number.  These sometimes show up in egg files accidentally.
+  accept(); 
+  memset(&eggyylval._number, 0, sizeof(eggyylval._number));
+  *(unsigned long *)&eggyylval._number = strtoul(yytext+3, NULL, 0);
+  eggyylval._string = yytext;
+  return NUMBER;
+}
+	YY_BREAK
+case 94:
+YY_RULE_SETUP
+#line 710 "lexer.lxx"
+{ 
+  // infinity.  As above.
+  accept(); 
+  eggyylval._number = HUGE_VAL;
+  eggyylval._string = yytext;
+  return NUMBER; 
+}
+	YY_BREAK
+case 95:
+YY_RULE_SETUP
+#line 718 "lexer.lxx"
+{
+  // minus infinity.  As above.
+  accept(); 
+  eggyylval._number = -HUGE_VAL;
+  eggyylval._string = yytext;
+  return NUMBER; 
+}
+	YY_BREAK
+case 96:
+YY_RULE_SETUP
+#line 727 "lexer.lxx"
+{
+  // Quoted string.
+  accept();
+  eggyylval._string = scan_quoted_string();
+  return STRING;
+}
+	YY_BREAK
+case 97:
+YY_RULE_SETUP
+#line 734 "lexer.lxx"
+{ 
+  // Unquoted string.
+  accept();
+  eggyylval._string = yytext;
+  return STRING;
+}
+	YY_BREAK
+case 98:
+YY_RULE_SETUP
+#line 740 "lexer.lxx"
+ECHO;
+	YY_BREAK
+#line 2064 "lex.yy.c"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 557 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+	register char *yy_cp = yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yy_last_accepting_state = yy_current_state;
+		yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 557 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 556);
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+
+	return c;
+	}
+#endif /* YY_NO_INPUT */
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 740 "lexer.lxx"

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 440 - 435
panda/src/egg/parser.cxx.prebuilt


+ 2 - 2
panda/src/egg/parser.h.prebuilt

@@ -1,7 +1,7 @@
-/* A Bison parser, made by GNU Bison 1.875b.  */
+/* A Bison parser, made by GNU Bison 2.0.  */
 
 
 /* Skeleton parser for Yacc-like parsing with Bison,
 /* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by

+ 104 - 99
panda/src/egg/parser.yxx

@@ -622,7 +622,7 @@ texture_body:
     eggyywarning("Unsupported texture scalar: " + name);
     eggyywarning("Unsupported texture scalar: " + name);
   }
   }
 }
 }
-        | texture_body transform_2d
+        | texture_body transform
         ;
         ;
 
 
 /*
 /*
@@ -955,6 +955,10 @@ vertex_uv_body:
         real real
         real real
 {
 {
   DCAST(EggVertexUV, egg_stack.back())->set_uv(TexCoordd($1, $2));
   DCAST(EggVertexUV, egg_stack.back())->set_uv(TexCoordd($1, $2));
+}
+        | real real real
+{
+  DCAST(EggVertexUV, egg_stack.back())->set_uvw(LVecBase3d($1, $2, $3));
 }
 }
         | vertex_uv_body TANGENT '{' real real real '}'
         | vertex_uv_body TANGENT '{' real real real '}'
 {
 {
@@ -975,15 +979,31 @@ vertex_uv_body:
         | vertex_uv_body DUV string '{' real real '}'
         | vertex_uv_body DUV string '{' real real '}'
 {
 {
   bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
   bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
-    insert(EggMorphTexCoord($3, LVector2d($5, $6))).second;
+    insert(EggMorphTexCoord($3, LVector3d($5, $6, 0.0))).second;
+  if (!inserted) {
+    eggyywarning("Ignoring repeated morph name " + $3);
+  }
+}
+        | vertex_uv_body DUV string '{' real real real '}'
+{
+  bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
+    insert(EggMorphTexCoord($3, LVector3d($5, $6, $7))).second;
   if (!inserted) {
   if (!inserted) {
     eggyywarning("Ignoring repeated morph name " + $3);
     eggyywarning("Ignoring repeated morph name " + $3);
   }
   }
 }
 }
-       | vertex_uv_body DUV '{' string real real '}'
+        | vertex_uv_body DUV '{' string real real '}'
+{
+  bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
+    insert(EggMorphTexCoord($4, LVector3d($5, $6, 0.0))).second;
+  if (!inserted) {
+    eggyywarning("Ignoring repeated morph name " + $4);
+  }
+}
+        | vertex_uv_body DUV '{' string real real real '}'
 {
 {
   bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
   bool inserted = DCAST(EggVertexUV, egg_stack.back())->_duvs.
-    insert(EggMorphTexCoord($4, LVector2d($5, $6))).second;
+    insert(EggMorphTexCoord($4, LVector3d($5, $6, $7))).second;
   if (!inserted) {
   if (!inserted) {
     eggyywarning("Ignoring repeated morph name " + $4);
     eggyywarning("Ignoring repeated morph name " + $4);
   }
   }
@@ -1343,7 +1363,7 @@ group_body:
   int value = (int)$4;
   int value = (int)$4;
   group->set_texlist_flag(value!=0);
   group->set_texlist_flag(value!=0);
 }
 }
-        | group_body transform_3d
+        | group_body transform
         | group_body group_vertex_ref
         | group_body group_vertex_ref
         | group_body switchcondition
         | group_body switchcondition
         | group_body node
         | group_body node
@@ -1406,163 +1426,148 @@ collide_flags:
         ;
         ;
 
 
 /*
 /*
- * transform_3d
+ * transform
  *
  *
- * enter: TOS is EggGroup.
- * exit: group's transform matrix has been set.
+ * enter: TOS is some kind of EggTransform.
+ * exit: transform matrix has been set.
  *
  *
  */
  */
-transform_3d:
+transform:
         TRANSFORM
         TRANSFORM
 {
 {
-  DCAST(EggGroup, egg_stack.back())->clear_transform();
+  egg_stack.back()->as_transform()->clear_transform();
 }
 }
-        '{' transform_3d_body '}'
+        '{' transform_body '}'
         ;
         ;
 
 
 
 
 /*
 /*
- * transform_3d_body
+ * transform_body
  *
  *
- * enter: matrix_3d contains some sensible value.
- * exit: matrix_3d has been transformed by the parsed transformation.
+ * enter: TOS is some kind of EggTransform.
+ * exit: transform has been filled in.
  *
  *
  */
  */
-transform_3d_body:
+transform_body:
           empty
           empty
-        | transform_3d_body translate_3d
-        | transform_3d_body rotx_3d
-        | transform_3d_body roty_3d
-        | transform_3d_body rotz_3d
-        | transform_3d_body rotate_3d
-        | transform_3d_body scale_3d
-        | transform_3d_body matrix4_3d
+        | transform_body translate2d
+        | transform_body translate3d
+        | transform_body rotate2d
+        | transform_body rotx
+        | transform_body roty
+        | transform_body rotz
+        | transform_body rotate3d
+        | transform_body scale2d
+        | transform_body scale3d
+        | transform_body uniform_scale
+        | transform_body matrix3
+        | transform_body matrix4
         ;
         ;
 
 
-translate_3d: TRANSLATE '{' real real real '}'
+translate2d:
+        TRANSLATE '{' real real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_translate(LVector3d($3, $4, $5));
+  egg_stack.back()->as_transform()->add_translate2d(LVector2d($3, $4));
 }
 }
         ;
         ;
 
 
-rotx_3d: ROTX '{' real '}'
+translate3d:
+        TRANSLATE '{' real real real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_rotx($3);
+  egg_stack.back()->as_transform()->add_translate3d(LVector3d($3, $4, $5));
 }
 }
         ;
         ;
 
 
-roty_3d: ROTY '{' real '}'
+rotate2d:
+        ROTATE '{' real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_roty($3);
+  egg_stack.back()->as_transform()->add_rotate2d($3);
 }
 }
         ;
         ;
 
 
-rotz_3d: ROTZ '{' real '}'
+rotx:
+        ROTX '{' real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_rotz($3);
+  egg_stack.back()->as_transform()->add_rotx($3);
 }
 }
         ;
         ;
 
 
-rotate_3d: ROTATE '{' real real real real '}'
+roty:
+        ROTY '{' real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_rotate($3, LVector3d($4, $5, $6));
+  egg_stack.back()->as_transform()->add_roty($3);
 }
 }
         ;
         ;
 
 
-scale_3d: SCALE '{' real real real '}'
+rotz:
+        ROTZ '{' real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_scale(LVecBase3d($3, $4, $5));
+  egg_stack.back()->as_transform()->add_rotz($3);
 }
 }
-	| SCALE '{' real '}'
-{
-  DCAST(EggGroup, egg_stack.back())->add_uniform_scale($3);
-}
-        ;
-
-matrix4_3d:
-        MATRIX4 '{' matrix4_3d_body '}'
         ;
         ;
 
 
-matrix4_3d_body: 
-          empty
-        | real real real real
-          real real real real 
-          real real real real 
-          real real real real 
+rotate3d:
+	ROTATE '{' real real real real '}'
 {
 {
-  DCAST(EggGroup, egg_stack.back())->add_matrix
-    (LMatrix4d($1, $2, $3, $4,
-               $5, $6, $7, $8,
-               $9, $10, $11, $12,
-               $13, $14, $15, $16));
+  egg_stack.back()->as_transform()->add_rotate3d($3, LVector3d($4, $5, $6));
 }
 }
         ;
         ;
 
 
-
-/*
- * transform_2d
- *
- * enter: TOS is EggTexture.
- * exit: texture's transform matrix has been set.
- *
- */
-transform_2d:
-        TRANSFORM
+scale2d:
+        SCALE '{' real real '}'
 {
 {
-  matrix_2d = LMatrix3d::ident_mat();
+  egg_stack.back()->as_transform()->add_scale2d(LVecBase2d($3, $4));
 }
 }
-        '{' transform_2d_body '}'
-{
-  DCAST(EggTexture, egg_stack.back())->set_transform(matrix_2d);
-}
-        ;
-
-
-/*
- * transform_2d_body
- *
- * enter: matrix contains some sensible value.
- * exit: matrix has been transformed by the parsed transformation.
- *
- */
-transform_2d_body:
-          empty
-        | transform_2d_body matrix3_2d
-        | transform_2d_body translate_2d
-        | transform_2d_body rotate_2d
-        | transform_2d_body scale_2d
         ;
         ;
 
 
-translate_2d: TRANSLATE '{' real real '}'
+scale3d:
+	SCALE '{' real real real '}'
 {
 {
-  matrix_2d *= LMatrix3d::translate_mat($3, $4);
+  egg_stack.back()->as_transform()->add_scale3d(LVecBase3d($3, $4, $5));
 }
 }
-        ;
+	;
 
 
-rotate_2d: ROTATE '{' real '}'
+uniform_scale:
+	SCALE '{' real '}'
 {
 {
-  matrix_2d *= LMatrix3d::rotate_mat($3);
+  egg_stack.back()->as_transform()->add_uniform_scale($3);
 }
 }
         ;
         ;
 
 
-scale_2d: SCALE '{' real real '}'
+matrix3:
+        MATRIX3 '{' matrix3_body '}'
+        ;
+
+matrix3_body: 
+          empty
+        | real real real real
+          real real real real 
+          real real real real 
+          real real real real 
 {
 {
-  matrix_2d *= LMatrix3d::scale_mat($3, $4);
+  egg_stack.back()->as_transform()->add_matrix3
+    (LMatrix3d($1, $2, $3,
+               $4, $5, $6,
+               $7, $8, $9));
 }
 }
         ;
         ;
 
 
-matrix3_2d: MATRIX3 '{' matrix3_2d_body '}'
+matrix4:
+        MATRIX4 '{' matrix4_body '}'
         ;
         ;
 
 
-matrix3_2d_body: 
+matrix4_body: 
           empty
           empty
-        | real real real
-          real real real
-          real real real
+        | real real real real
+          real real real real 
+          real real real real 
+          real real real real 
 {
 {
-  matrix_2d *= LMatrix3d($1, $2, $3,
-                         $4, $5, $6,
-                         $7, $8, $9);
+  egg_stack.back()->as_transform()->add_matrix4
+    (LMatrix4d($1, $2, $3, $4,
+               $5, $6, $7, $8,
+               $9, $10, $11, $12,
+               $13, $14, $15, $16));
 }
 }
         ;
         ;
 
 

+ 144 - 112
panda/src/egg2pg/eggLoader.cxx

@@ -391,6 +391,126 @@ make_polyset(EggBin *egg_bin, PandaNode *parent, const LMatrix4d *transform,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggLoader::make_transform
+//       Access: Public, Static
+//  Description: Creates a TransformState object corresponding to the
+//               indicated EggTransform.
+////////////////////////////////////////////////////////////////////
+CPT(TransformState) EggLoader::
+make_transform(const EggTransform *egg_transform) {
+  // We'll build up the transform componentwise, so we preserve any
+  // componentwise properties of the egg transform.
+
+  CPT(TransformState) ts = TransformState::make_identity();
+  int num_components = egg_transform->get_num_components();
+  for (int i = 0; i < num_components; i++) {
+    switch (egg_transform->get_component_type(i)) {
+    case EggTransform::CT_translate2d:
+      {
+        LVecBase2f trans2d(LCAST(float, egg_transform->get_component_vec2(i)));
+        LVecBase3f trans3d(trans2d[0], trans2d[1], 0.0f);
+        ts = TransformState::make_pos(trans3d)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_translate3d:
+      {
+        LVecBase3f trans3d(LCAST(float, egg_transform->get_component_vec3(i)));
+        ts = TransformState::make_pos(trans3d)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_rotate2d:
+      {
+        LRotationf rot(LVector3f(0.0f, 0.0f, 1.0f),
+                       (float)egg_transform->get_component_number(i));
+        ts = TransformState::make_quat(rot)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_rotx:
+      {
+        LRotationf rot(LVector3f(1.0f, 0.0f, 0.0f),
+                       (float)egg_transform->get_component_number(i));
+        ts = TransformState::make_quat(rot)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_roty:
+      {
+        LRotationf rot(LVector3f(0.0f, 1.0f, 0.0f),
+                       (float)egg_transform->get_component_number(i));
+        ts = TransformState::make_quat(rot)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_rotz:
+      {
+        LRotationf rot(LVector3f(0.0f, 0.0f, 1.0f),
+                       (float)egg_transform->get_component_number(i));
+        ts = TransformState::make_quat(rot)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_rotate3d:
+      {
+        LRotationf rot(LCAST(float, egg_transform->get_component_vec3(i)),
+                       (float)egg_transform->get_component_number(i));
+        ts = TransformState::make_quat(rot)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_scale2d:
+      {
+        LVecBase2f scale2d(LCAST(float, egg_transform->get_component_vec2(i)));
+        LVecBase3f scale3d(scale2d[0], scale2d[1], 1.0f);
+        ts = TransformState::make_scale(scale3d)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_scale3d:
+      {
+        LVecBase3f scale3d(LCAST(float, egg_transform->get_component_vec3(i)));
+        ts = TransformState::make_scale(scale3d)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_uniform_scale:
+      {
+        float scale = (float)egg_transform->get_component_number(i);
+        ts = TransformState::make_scale(scale)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_matrix3:
+      {
+        LMatrix3f m(LCAST(float, egg_transform->get_component_mat3(i)));
+        LMatrix4f mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
+                       m(1, 0), m(1, 1), 0.0, m(1, 2),
+                       0.0, 0.0, 1.0, 0.0,
+                       m(2, 0), m(2, 1), 0.0, m(2, 2));
+
+        ts = TransformState::make_mat(mat4)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_matrix4:
+      {
+        LMatrix4f mat4(LCAST(float, egg_transform->get_component_mat4(i)));
+        ts = TransformState::make_mat(mat4)->compose(ts);
+      }
+      break;
+
+    case EggTransform::CT_invalid:
+      nassertr(false, ts);
+      break;
+    }
+  }
+
+  return ts;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggLoader::show_normals
 //     Function: EggLoader::show_normals
 //       Access: Private
 //       Access: Private
@@ -1183,8 +1303,7 @@ make_texture_stage(const EggTexture *egg_tex) {
   }
   }
 
 
 
 
-  if (egg_tex->has_uv_name() && !egg_tex->get_uv_name().empty() &&
-      egg_tex->get_uv_name() != string("default")) {
+  if (egg_tex->has_uv_name()) {
     CPT(InternalName) name = 
     CPT(InternalName) name = 
       InternalName::get_texcoord_name(egg_tex->get_uv_name());
       InternalName::get_texcoord_name(egg_tex->get_uv_name());
     stage->set_texcoord_name(name);
     stage->set_texcoord_name(name);
@@ -1725,23 +1844,26 @@ make_vertex_data(const EggRenderState *render_state,
        Geom::NT_packed_dabc, Geom::C_color);
        Geom::NT_packed_dabc, Geom::C_color);
   }
   }
 
 
-  vector_string uv_names, tbn_names;
-  vertex_pool->get_uv_names(uv_names, tbn_names);
+  vector_string uv_names, uvw_names, tbn_names;
+  vertex_pool->get_uv_names(uv_names, uvw_names, tbn_names);
   vector_string::const_iterator ni;
   vector_string::const_iterator ni;
   for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
   for (ni = uv_names.begin(); ni != uv_names.end(); ++ni) {
     string name = (*ni);
     string name = (*ni);
-    if (name == "default") {
-      name = string();
-    }
+
     PT(InternalName) iname = InternalName::get_texcoord_name(name);
     PT(InternalName) iname = InternalName::get_texcoord_name(name);
-    array_format->add_column
-      (iname, 2, Geom::NT_float32, Geom::C_texcoord);
+
+    if (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end()) {
+      // This one actually represents 3-d texture coordinates.
+      array_format->add_column
+        (iname, 3, Geom::NT_float32, Geom::C_texcoord);
+    } else {
+      array_format->add_column
+        (iname, 2, Geom::NT_float32, Geom::C_texcoord);
+    }
   }
   }
   for (ni = tbn_names.begin(); ni != tbn_names.end(); ++ni) {
   for (ni = tbn_names.begin(); ni != tbn_names.end(); ++ni) {
     string name = (*ni);
     string name = (*ni);
-    if (name == "default") {
-      name = string();
-    }
+
     PT(InternalName) iname = InternalName::get_tangent_name(name);
     PT(InternalName) iname = InternalName::get_tangent_name(name);
     array_format->add_column
     array_format->add_column
       (iname, 3, Geom::NT_float32, Geom::C_vector);
       (iname, 3, Geom::NT_float32, Geom::C_vector);
@@ -1807,16 +1929,14 @@ make_vertex_data(const EggRenderState *render_state,
       for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
       for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
         EggVertexUV *egg_uv = (*uvi);
         EggVertexUV *egg_uv = (*uvi);
         string name = egg_uv->get_name();
         string name = egg_uv->get_name();
-        if (name == "default") {
-          name = string();
-        }
+        bool has_w = (find(uvw_names.begin(), uvw_names.end(), name) != uvw_names.end());
         PT(InternalName) iname = InternalName::get_texcoord_name(name);
         PT(InternalName) iname = InternalName::get_texcoord_name(name);
 
 
         EggMorphTexCoordList::const_iterator mti;
         EggMorphTexCoordList::const_iterator mti;
         for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
         for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
           slider_names.insert((*mti).get_name());
           slider_names.insert((*mti).get_name());
           record_morph(anim_array_format, character_maker, (*mti).get_name(),
           record_morph(anim_array_format, character_maker, (*mti).get_name(),
-                       iname, 2);
+                       iname, has_w ? 3 : 2);
         }
         }
       }
       }
     }
     }
@@ -1910,23 +2030,20 @@ make_vertex_data(const EggRenderState *render_state,
     EggVertex::const_uv_iterator uvi;
     EggVertex::const_uv_iterator uvi;
     for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
     for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
       EggVertexUV *egg_uv = (*uvi);
       EggVertexUV *egg_uv = (*uvi);
-      TexCoordd orig_uv = egg_uv->get_uv();
-      TexCoordd uv = egg_uv->get_uv();
+      TexCoord3d orig_uvw = egg_uv->get_uvw();
+      TexCoord3d uvw = egg_uv->get_uvw();
 
 
       string name = egg_uv->get_name();
       string name = egg_uv->get_name();
-      if (name == "default") {
-        name = string();
-      }
       PT(InternalName) iname = InternalName::get_texcoord_name(name);
       PT(InternalName) iname = InternalName::get_texcoord_name(name);
       gvw.set_column(iname);
       gvw.set_column(iname);
 
 
       BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname);
       BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname);
       if (buv != render_state->_bake_in_uvs.end()) {
       if (buv != render_state->_bake_in_uvs.end()) {
         // If we are to bake in a texture matrix, do so now.
         // If we are to bake in a texture matrix, do so now.
-        uv = uv * (*buv).second->get_transform();
+        uvw = uvw * (*buv).second->get_transform();
       }
       }
 
 
-      gvw.set_data2f(LCAST(float, uv));
+      gvw.set_data3f(LCAST(float, uvw));
 
 
       if (is_dynamic) {
       if (is_dynamic) {
         EggMorphTexCoordList::const_iterator mti;
         EggMorphTexCoordList::const_iterator mti;
@@ -1935,13 +2052,13 @@ make_vertex_data(const EggRenderState *render_state,
           CPT(InternalName) delta_name = 
           CPT(InternalName) delta_name = 
             InternalName::get_morph(iname, morph.get_name());
             InternalName::get_morph(iname, morph.get_name());
           gvw.set_column(delta_name);
           gvw.set_column(delta_name);
-          TexCoordd duv = morph.get_offset();
+          TexCoord3d duvw = morph.get_offset();
           if (buv != render_state->_bake_in_uvs.end()) {
           if (buv != render_state->_bake_in_uvs.end()) {
-            TexCoordd new_uv = orig_uv + duv;
-            duv = (new_uv * (*buv).second->get_transform()) - uv;
+            TexCoord3d new_uvw = orig_uvw + duvw;
+            duvw = (new_uvw * (*buv).second->get_transform()) - uvw;
           }
           }
           
           
-          gvw.add_data2f(LCAST(float, duv));
+          gvw.add_data3f(LCAST(float, duvw));
         }
         }
       }
       }
 
 
@@ -2994,91 +3111,6 @@ do_expand_object_type(EggGroup *egg_group, const pset<string> &expanded,
   return true;
   return true;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: EggLoader::make_transform
-//       Access: Private
-//  Description: Walks back over the tree and applies the
-//               DeferredNodeProperties that were saved up along the
-//               way.
-////////////////////////////////////////////////////////////////////
-CPT(TransformState) EggLoader::
-make_transform(const EggTransform3d *egg_transform) {
-  // We'll build up the transform componentwise, so we preserve any
-  // componentwise properties of the egg transform.
-
-  CPT(TransformState) ts = TransformState::make_identity();
-  int num_components = egg_transform->get_num_components();
-  for (int i = 0; i < num_components; i++) {
-    switch (egg_transform->get_component_type(i)) {
-    case EggTransform3d::CT_translate:
-      {
-        LVector3f trans(LCAST(float, egg_transform->get_component_vector(i)));
-        ts = TransformState::make_pos(trans)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_rotx:
-      {
-        LRotationf rot(LVector3f(1.0f, 0.0f, 0.0f),
-                       (float)egg_transform->get_component_number(i));
-        ts = TransformState::make_quat(rot)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_roty:
-      {
-        LRotationf rot(LVector3f(0.0f, 1.0f, 0.0f),
-                       (float)egg_transform->get_component_number(i));
-        ts = TransformState::make_quat(rot)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_rotz:
-      {
-        LRotationf rot(LVector3f(0.0f, 0.0f, 1.0f),
-                       (float)egg_transform->get_component_number(i));
-        ts = TransformState::make_quat(rot)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_rotate:
-      {
-        LRotationf rot(LCAST(float, egg_transform->get_component_vector(i)),
-                       (float)egg_transform->get_component_number(i));
-        ts = TransformState::make_quat(rot)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_scale:
-      {
-        LVecBase3f scale(LCAST(float, egg_transform->get_component_vector(i)));
-        ts = TransformState::make_scale(scale)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_uniform_scale:
-      {
-        float scale = (float)egg_transform->get_component_number(i);
-        ts = TransformState::make_scale(scale)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_matrix:
-      {
-        LMatrix4f mat(LCAST(float, egg_transform->get_component_matrix(i)));
-        ts = TransformState::make_mat(mat)->compose(ts);
-      }
-      break;
-
-    case EggTransform3d::CT_invalid:
-      nassertr(false, ts);
-      break;
-    }
-  }
-
-  return ts;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggLoader::get_combine_mode
 //     Function: EggLoader::get_combine_mode
 //       Access: Private, Static
 //       Access: Private, Static

+ 3 - 3
panda/src/egg2pg/eggLoader.h

@@ -38,7 +38,7 @@
 #include "textureStage.h"
 #include "textureStage.h"
 #include "texGenAttrib.h"
 #include "texGenAttrib.h"
 #include "colorBlendAttrib.h"
 #include "colorBlendAttrib.h"
-#include "eggTransform3d.h"
+#include "eggTransform.h"
 #include "geomVertexData.h"
 #include "geomVertexData.h"
 #include "geomPrimitive.h"
 #include "geomPrimitive.h"
 
 
@@ -80,6 +80,8 @@ public:
                     const LMatrix4d *transform, bool is_dynamic,
                     const LMatrix4d *transform, bool is_dynamic,
                     CharacterMaker *character_maker);
                     CharacterMaker *character_maker);
 
 
+  static CPT(TransformState) make_transform(const EggTransform *egg_transform);
+
 private:
 private:
   class TextureDef {
   class TextureDef {
   public:
   public:
@@ -185,8 +187,6 @@ private:
                              const pvector<string> &expanded_history,
                              const pvector<string> &expanded_history,
                              const string &object_type);
                              const string &object_type);
 
 
-  CPT(TransformState) make_transform(const EggTransform3d *egg_transform);
-
   static TextureStage::CombineMode 
   static TextureStage::CombineMode 
   get_combine_mode(const EggTexture *egg_tex, 
   get_combine_mode(const EggTexture *egg_tex, 
                    EggTexture::CombineChannel channel);
                    EggTexture::CombineChannel channel);

+ 1 - 18
panda/src/egg2pg/eggRenderState.cxx

@@ -536,24 +536,7 @@ CPT(RenderAttrib) EggRenderState::
 apply_tex_mat(CPT(RenderAttrib) tex_mat_attrib, 
 apply_tex_mat(CPT(RenderAttrib) tex_mat_attrib, 
               TextureStage *stage, const EggTexture *egg_tex) {
               TextureStage *stage, const EggTexture *egg_tex) {
   if (egg_tex->has_transform()) {
   if (egg_tex->has_transform()) {
-    const LMatrix3d &tex_mat = egg_tex->get_transform();
-    LMatrix4f mat4(tex_mat(0, 0), tex_mat(0, 1), 0.0f, tex_mat(0, 2),
-                   tex_mat(1, 0), tex_mat(1, 1), 0.0f, tex_mat(1, 2),
-                   0.0f, 0.0f, 1.0f, 0.0f,
-                   tex_mat(2, 0), tex_mat(2, 1), 0.0f, tex_mat(2, 2));
-    CPT(TransformState) transform;
-
-    LVecBase3f scale, shear, hpr, translate;
-    if (decompose_matrix(mat4, scale, shear, hpr, translate)) {
-      // If the texture matrix can be represented componentwise, do
-      // so.
-      transform = TransformState::make_pos_hpr_scale_shear
-        (translate, hpr, scale, shear);
-
-    } else {
-      // Otherwise, make a matrix transform.
-      transform = TransformState::make_mat(mat4);
-    }
+    CPT(TransformState) transform = EggLoader::make_transform(egg_tex);
   
   
     if (tex_mat_attrib == (const RenderAttrib *)NULL) {
     if (tex_mat_attrib == (const RenderAttrib *)NULL) {
       tex_mat_attrib = TexMatrixAttrib::make();
       tex_mat_attrib = TexMatrixAttrib::make();

+ 1 - 1
panda/src/egg2pg/eggRenderState.h

@@ -77,7 +77,7 @@ private:
   EggLoader &_loader;
   EggLoader &_loader;
 
 
   typedef pvector<const TextureDef *> TexMatTextures;
   typedef pvector<const TextureDef *> TexMatTextures;
-  typedef pmap<LMatrix3d, TexMatTextures> TexMatTransforms;
+  typedef pmap<LMatrix4d, TexMatTextures> TexMatTransforms;
   typedef pmap<CPT(InternalName), TexMatTransforms> TexMats;
   typedef pmap<CPT(InternalName), TexMatTransforms> TexMats;
 };
 };
 
 

+ 2 - 0
panda/src/linmath/aa_luse.h

@@ -53,12 +53,14 @@
 typedef LPoint3f Vertexf;
 typedef LPoint3f Vertexf;
 typedef LVector3f Normalf;
 typedef LVector3f Normalf;
 typedef LPoint2f TexCoordf;
 typedef LPoint2f TexCoordf;
+typedef LPoint3f TexCoord3f;
 typedef LVecBase4f Colorf;
 typedef LVecBase4f Colorf;
 typedef LVecBase3f RGBColorf;
 typedef LVecBase3f RGBColorf;
 
 
 typedef LPoint3d Vertexd;
 typedef LPoint3d Vertexd;
 typedef LVector3d Normald;
 typedef LVector3d Normald;
 typedef LPoint2d TexCoordd;
 typedef LPoint2d TexCoordd;
+typedef LPoint3d TexCoord3d;
 typedef LVecBase4d Colord;
 typedef LVecBase4d Colord;
 typedef LVecBase3d RGBColord;
 typedef LVecBase3d RGBColord;
 
 

+ 3 - 3
pandatool/src/bam/bamToEgg.cxx

@@ -429,13 +429,13 @@ apply_node_properties(EggGroup *egg_group, PandaNode *node) {
       const LQuaternionf &quat = transform->get_quat();
       const LQuaternionf &quat = transform->get_quat();
       const LVecBase3f &pos = transform->get_pos();
       const LVecBase3f &pos = transform->get_pos();
       if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
       if (!scale.almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
-        egg_group->add_scale(LCAST(double, scale));
+        egg_group->add_scale3d(LCAST(double, scale));
       }
       }
       if (!quat.is_identity()) {
       if (!quat.is_identity()) {
-        egg_group->add_rotate(LCAST(double, quat));
+        egg_group->add_rotate3d(LCAST(double, quat));
       }
       }
       if (!pos.almost_equal(LVecBase3f::zero())) {
       if (!pos.almost_equal(LVecBase3f::zero())) {
-        egg_group->add_translate(LCAST(double, pos));
+        egg_group->add_translate3d(LCAST(double, pos));
       }
       }
 
 
     } else if (transform->has_mat()) {
     } else if (transform->has_mat()) {

+ 13 - 13
pandatool/src/fltegg/fltToEggLevelState.cxx

@@ -161,7 +161,7 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           const FltTransformTranslate *trans;
           const FltTransformTranslate *trans;
           DCAST_INTO_V(trans, step);
           DCAST_INTO_V(trans, step);
           if (!trans->get_delta().almost_equal(LVector3d::zero())) {
           if (!trans->get_delta().almost_equal(LVector3d::zero())) {
-            egg_group->add_translate(trans->get_delta());
+            egg_group->add_translate3d(trans->get_delta());
           }
           }
 
 
         } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) {
         } else if (step->is_exact_type(FltTransformRotateAboutPoint::get_class_type())) {
@@ -169,12 +169,12 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           DCAST_INTO_V(rap, step); 
           DCAST_INTO_V(rap, step); 
           if (!IS_NEARLY_ZERO(rap->get_angle())) {
           if (!IS_NEARLY_ZERO(rap->get_angle())) {
             if (!rap->get_center().almost_equal(LVector3d::zero())) {
             if (!rap->get_center().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(-rap->get_center());
+              egg_group->add_translate3d(-rap->get_center());
             }
             }
             LVector3d axis = LCAST(double, rap->get_axis());
             LVector3d axis = LCAST(double, rap->get_axis());
-            egg_group->add_rotate(rap->get_angle(), axis);
+            egg_group->add_rotate3d(rap->get_angle(), axis);
             if (!rap->get_center().almost_equal(LVector3d::zero())) {
             if (!rap->get_center().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(rap->get_center());
+              egg_group->add_translate3d(rap->get_center());
             }
             }
           }
           }
 
 
@@ -183,12 +183,12 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           DCAST_INTO_V(rae, step);
           DCAST_INTO_V(rae, step);
           if (!IS_NEARLY_ZERO(rae->get_angle())) {
           if (!IS_NEARLY_ZERO(rae->get_angle())) {
             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(-rae->get_point_a());
+              egg_group->add_translate3d(-rae->get_point_a());
             }
             }
             LVector3d axis = rae->get_point_b() - rae->get_point_a();
             LVector3d axis = rae->get_point_b() - rae->get_point_a();
-            egg_group->add_rotate(rae->get_angle(), axis);
+            egg_group->add_rotate3d(rae->get_angle(), axis);
             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
             if (!rae->get_point_a().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(rae->get_point_a());
+              egg_group->add_translate3d(rae->get_point_a());
             }
             }
           }
           }
 
 
@@ -198,12 +198,12 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           if (!scale->get_scale().almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
           if (!scale->get_scale().almost_equal(LVecBase3f(1.0f, 1.0f, 1.0f))) {
             if (scale->has_center() && 
             if (scale->has_center() && 
                 !scale->get_center().almost_equal(LVector3d::zero())) {
                 !scale->get_center().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(-scale->get_center());
+              egg_group->add_translate3d(-scale->get_center());
             }
             }
-            egg_group->add_scale(LCAST(double, scale->get_scale()));
+            egg_group->add_scale3d(LCAST(double, scale->get_scale()));
             if (scale->has_center() && 
             if (scale->has_center() && 
                 !scale->get_center().almost_equal(LVector3d::zero())) {
                 !scale->get_center().almost_equal(LVector3d::zero())) {
-              egg_group->add_translate(scale->get_center());
+              egg_group->add_translate3d(scale->get_center());
             }
             }
           }
           }
 
 
@@ -212,7 +212,7 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           DCAST_INTO_V(put, step);
           DCAST_INTO_V(put, step);
 
 
           if (!put->get_from_origin().almost_equal(LVector3d::zero())) {
           if (!put->get_from_origin().almost_equal(LVector3d::zero())) {
-            egg_group->add_translate(-put->get_from_origin());
+            egg_group->add_translate3d(-put->get_from_origin());
           }
           }
           LQuaterniond q1, q2;
           LQuaterniond q1, q2;
           look_at(q1, put->get_from_align() - put->get_from_origin(),
           look_at(q1, put->get_from_align() - put->get_from_origin(),
@@ -225,10 +225,10 @@ set_transform(const FltBead *flt_bead, EggGroup *egg_group) {
           LQuaterniond q = invert(q1) * q2;
           LQuaterniond q = invert(q1) * q2;
 
 
           if (!q.is_identity()) {
           if (!q.is_identity()) {
-            egg_group->add_rotate(q);
+            egg_group->add_rotate3d(q);
           }
           }
           if (!put->get_to_origin().almost_equal(LVector3d::zero())) {
           if (!put->get_to_origin().almost_equal(LVector3d::zero())) {
-            egg_group->add_translate(put->get_to_origin());
+            egg_group->add_translate3d(put->get_to_origin());
           }
           }
 
 
         } else {
         } else {

+ 56 - 13
pandatool/src/fltprogs/eggToFlt.cxx

@@ -317,23 +317,43 @@ convert_group(EggGroup *egg_group, FltBead *flt_node,
 //               flt bead.
 //               flt bead.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void EggToFlt::
 void EggToFlt::
-apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) {
+apply_transform(EggTransform *egg_transform, FltBead *flt_node) {
   flt_node->clear_transform();
   flt_node->clear_transform();
 
 
   bool components_ok = true;
   bool components_ok = true;
   int num_components = egg_transform->get_num_components();
   int num_components = egg_transform->get_num_components();
   for (int i = num_components - 1; i >= 0 && components_ok; i--) {
   for (int i = num_components - 1; i >= 0 && components_ok; i--) {
     switch (egg_transform->get_component_type(i)) {
     switch (egg_transform->get_component_type(i)) {
-    case EggTransform3d::CT_translate:
+    case EggTransform::CT_translate2d:
       {
       {
         FltTransformTranslate *translate = 
         FltTransformTranslate *translate = 
           new FltTransformTranslate(_flt_header);
           new FltTransformTranslate(_flt_header);
-        translate->set(LPoint3d::zero(), egg_transform->get_component_vector(i));
+        LVector2d v2 = egg_transform->get_component_vec2(i);
+        translate->set(LPoint3d::zero(), LVector3d(v2[0], v2[1], 0.0));
         flt_node->add_transform_step(translate);
         flt_node->add_transform_step(translate);
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_rotx:
+    case EggTransform::CT_translate3d:
+      {
+        FltTransformTranslate *translate = 
+          new FltTransformTranslate(_flt_header);
+        translate->set(LPoint3d::zero(), egg_transform->get_component_vec3(i));
+        flt_node->add_transform_step(translate);
+      }
+      break;
+
+    case EggTransform::CT_rotate2d:
+      {
+        FltTransformRotateAboutEdge *rotate = 
+          new FltTransformRotateAboutEdge(_flt_header);
+        rotate->set(LPoint3d::zero(), LPoint3d(0.0, 0.0, 1.0),
+                    egg_transform->get_component_number(i));
+        flt_node->add_transform_step(rotate);
+      }
+      break;
+
+    case EggTransform::CT_rotx:
       {
       {
         FltTransformRotateAboutEdge *rotate = 
         FltTransformRotateAboutEdge *rotate = 
           new FltTransformRotateAboutEdge(_flt_header);
           new FltTransformRotateAboutEdge(_flt_header);
@@ -343,7 +363,7 @@ apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) {
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_roty:
+    case EggTransform::CT_roty:
       {
       {
         FltTransformRotateAboutEdge *rotate = 
         FltTransformRotateAboutEdge *rotate = 
           new FltTransformRotateAboutEdge(_flt_header);
           new FltTransformRotateAboutEdge(_flt_header);
@@ -353,7 +373,7 @@ apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) {
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_rotz:
+    case EggTransform::CT_rotz:
       {
       {
         FltTransformRotateAboutEdge *rotate = 
         FltTransformRotateAboutEdge *rotate = 
           new FltTransformRotateAboutEdge(_flt_header);
           new FltTransformRotateAboutEdge(_flt_header);
@@ -363,25 +383,34 @@ apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) {
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_rotate:
+    case EggTransform::CT_rotate3d:
       {
       {
         FltTransformRotateAboutEdge *rotate = 
         FltTransformRotateAboutEdge *rotate = 
           new FltTransformRotateAboutEdge(_flt_header);
           new FltTransformRotateAboutEdge(_flt_header);
-        rotate->set(LPoint3d::zero(), egg_transform->get_component_vector(i),
+        rotate->set(LPoint3d::zero(), egg_transform->get_component_vec3(i),
                     egg_transform->get_component_number(i));
                     egg_transform->get_component_number(i));
         flt_node->add_transform_step(rotate);
         flt_node->add_transform_step(rotate);
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_scale:
+    case EggTransform::CT_scale2d:
+      {
+        FltTransformScale *scale = new FltTransformScale(_flt_header);
+        LVector2d v2 = egg_transform->get_component_vec2(i);
+        scale->set(LPoint3d::zero(), LVector3f(v2[0], v2[1], 1.0f));
+        flt_node->add_transform_step(scale);
+      }
+      break;
+
+    case EggTransform::CT_scale3d:
       {
       {
         FltTransformScale *scale = new FltTransformScale(_flt_header);
         FltTransformScale *scale = new FltTransformScale(_flt_header);
-        scale->set(LPoint3d::zero(), LCAST(float, egg_transform->get_component_vector(i)));
+        scale->set(LPoint3d::zero(), LCAST(float, egg_transform->get_component_vec3(i)));
         flt_node->add_transform_step(scale);
         flt_node->add_transform_step(scale);
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_uniform_scale:
+    case EggTransform::CT_uniform_scale:
       {
       {
         FltTransformScale *scale = new FltTransformScale(_flt_header);
         FltTransformScale *scale = new FltTransformScale(_flt_header);
         float factor = (float)egg_transform->get_component_number(i);
         float factor = (float)egg_transform->get_component_number(i);
@@ -390,11 +419,25 @@ apply_transform(EggTransform3d *egg_transform, FltBead *flt_node) {
       }
       }
       break;
       break;
 
 
-    case EggTransform3d::CT_matrix:
+    case EggTransform::CT_matrix3:
+      {
+        FltTransformGeneralMatrix *matrix = 
+          new FltTransformGeneralMatrix(_flt_header);
+        const LMatrix3d &m = egg_transform->get_component_mat3(i);
+        LMatrix4d mat4(m(0, 0), m(0, 1), 0.0, m(0, 2),
+                       m(1, 0), m(1, 1), 0.0, m(1, 2),
+                       0.0, 0.0, 1.0, 0.0,
+                       m(2, 0), m(2, 1), 0.0, m(2, 2));
+        matrix->set_matrix(mat4);
+        flt_node->add_transform_step(matrix);
+      }
+      break;
+
+    case EggTransform::CT_matrix4:
       {
       {
         FltTransformGeneralMatrix *matrix = 
         FltTransformGeneralMatrix *matrix = 
           new FltTransformGeneralMatrix(_flt_header);
           new FltTransformGeneralMatrix(_flt_header);
-        matrix->set_matrix(egg_transform->get_component_matrix(i));
+        matrix->set_matrix(egg_transform->get_component_mat4(i));
         flt_node->add_transform_step(matrix);
         flt_node->add_transform_step(matrix);
       }
       }
       break;
       break;

+ 2 - 2
pandatool/src/fltprogs/eggToFlt.h

@@ -32,7 +32,7 @@ class EggGroup;
 class EggVertex;
 class EggVertex;
 class EggPrimitive;
 class EggPrimitive;
 class EggTexture;
 class EggTexture;
-class EggTransform3d;
+class EggTransform;
 class FltVertex;
 class FltVertex;
 class FltBead;
 class FltBead;
 class FltTexture;
 class FltTexture;
@@ -56,7 +56,7 @@ private:
                          FltGeometry::BillboardType billboard);
                          FltGeometry::BillboardType billboard);
   void convert_group(EggGroup *egg_group, FltBead *flt_node,
   void convert_group(EggGroup *egg_group, FltBead *flt_node,
                      FltGeometry::BillboardType billboard);
                      FltGeometry::BillboardType billboard);
-  void apply_transform(EggTransform3d *egg_transform, FltBead *flt_node);
+  void apply_transform(EggTransform *egg_transform, FltBead *flt_node);
   void apply_egg_syntax(const string &egg_syntax, FltRecord *flt_record);
   void apply_egg_syntax(const string &egg_syntax, FltRecord *flt_record);
   FltVertex *get_flt_vertex(EggVertex *egg_vertex, EggNode *context);
   FltVertex *get_flt_vertex(EggVertex *egg_vertex, EggNode *context);
   FltTexture *get_flt_texture(EggTexture *egg_texture);
   FltTexture *get_flt_texture(EggTexture *egg_texture);

+ 2 - 2
pandatool/src/palettizer/textureReference.cxx

@@ -86,8 +86,8 @@ from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex) {
   _egg_data = data;
   _egg_data = data;
   _tref_name = egg_tex->get_name();
   _tref_name = egg_tex->get_name();
 
 
-  if (_egg_tex->has_transform()) {
-    _tex_mat = _egg_tex->get_transform();
+  if (_egg_tex->has_transform() && egg_tex->is_transform_2d()) {
+    _tex_mat = _egg_tex->get_transform_2d();
     if (!_inv_tex_mat.invert_from(_tex_mat)) {
     if (!_inv_tex_mat.invert_from(_tex_mat)) {
       _inv_tex_mat = LMatrix3d::ident_mat();
       _inv_tex_mat = LMatrix3d::ident_mat();
     }
     }

+ 2 - 2
pandatool/src/xfileegg/xFileVertex.cxx

@@ -60,8 +60,8 @@ set_from_egg(EggVertex *egg_vertex, EggPrimitive *egg_prim) {
     if (egg_prim->has_texture()) {
     if (egg_prim->has_texture()) {
       // Check if there's a texture matrix on the texture.
       // Check if there's a texture matrix on the texture.
       EggTexture *egg_tex = egg_prim->get_texture();
       EggTexture *egg_tex = egg_prim->get_texture();
-      if (egg_tex->has_transform()) {
-        uv = uv * egg_tex->get_transform();
+      if (egg_tex->has_transform() && egg_tex->is_transform_2d()) {
+        uv = uv * egg_tex->get_transform_2d();
       }
       }
     }
     }
 
 

Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov