Browse Source

Add patch from community member teedee for egg <Aux> syntax

David Rose 14 years ago
parent
commit
be7f483478

+ 12 - 0
panda/src/doc/eggSyntax.txt

@@ -720,6 +720,18 @@ appear before they are referenced.
     <UV> [name] { u v [w] <Tangent> { x y z } <Binormal> { x y z } }
     <UV> [name] { u v [w] <Tangent> { x y z } <Binormal> { x y z } }
 
 
 
 
+    <AUX> name { x y z w }
+
+    This specifies some named per-vertex auxiliary data which is
+    imported from the egg file without further interpretation by
+    Panda.  The auxiliary data is copied to the vertex data under a
+    column with the specified name.  Presumably the data will have
+    meaning to custom code or a custom shader.  Like named UV's, there
+    may be multiple Aux entries for a given vertex, each with a
+    different name.
+    
+
+
 <DynamicVertexPool> name { vertices }
 <DynamicVertexPool> name { vertices }
 
 
   A dynamic vertex pool is similar to a vertex pool in most respects,
   A dynamic vertex pool is similar to a vertex pool in most respects,

+ 2 - 0
panda/src/egg/config_egg.cxx

@@ -52,6 +52,7 @@
 #include "eggVertex.h"
 #include "eggVertex.h"
 #include "eggVertexPool.h"
 #include "eggVertexPool.h"
 #include "eggVertexUV.h"
 #include "eggVertexUV.h"
+#include "eggVertexAux.h"
 #include "eggXfmAnimData.h"
 #include "eggXfmAnimData.h"
 #include "eggXfmSAnim.h"
 #include "eggXfmSAnim.h"
 
 
@@ -207,6 +208,7 @@ init_libegg() {
   EggVertex::init_type();
   EggVertex::init_type();
   EggVertexPool::init_type();
   EggVertexPool::init_type();
   EggVertexUV::init_type();
   EggVertexUV::init_type();
+  EggVertexAux::init_type();
   EggXfmAnimData::init_type();
   EggXfmAnimData::init_type();
   EggXfmSAnim::init_type();
   EggXfmSAnim::init_type();
 }
 }

+ 59 - 0
panda/src/egg/eggVertex.I

@@ -195,6 +195,17 @@ has_uv() const {
   return has_uv("");
   return has_uv("");
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::has_aux
+//       Access: Published
+//  Description: Returns true if the vertex has any auxiliary
+//               data, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggVertex::
+has_aux() const {
+  return (_aux_map.size() != 0);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::get_uv
 //     Function: EggVertex::get_uv
 //       Access: Published
 //       Access: Published
@@ -239,6 +250,16 @@ clear_uv() {
   _uv_map.clear();
   _uv_map.clear();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::clear_aux
+//       Access: Published
+//  Description: Removes all auxiliary data from the vertex.
+////////////////////////////////////////////////////////////////////
+INLINE void EggVertex::
+clear_aux() {
+  _aux_map.clear();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::uv_begin
 //     Function: EggVertex::uv_begin
 //       Access: Public
 //       Access: Public
@@ -253,6 +274,20 @@ uv_begin() const {
   return _uv_map.begin();
   return _uv_map.begin();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::aux_begin
+//       Access: Public
+//  Description: Returns an iterator that allows walking through the
+//               complete set of auxiliary data on the vertex.
+//
+//               This interface is not safe to use outside of
+//               PANDAEGG.DLL.
+////////////////////////////////////////////////////////////////////
+INLINE EggVertex::const_aux_iterator EggVertex::
+aux_begin() const {
+  return _aux_map.begin();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::uv_end
 //     Function: EggVertex::uv_end
 //       Access: Public
 //       Access: Public
@@ -267,6 +302,20 @@ uv_end() const {
   return _uv_map.end();
   return _uv_map.end();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::aux_end
+//       Access: Public
+//  Description: Returns an iterator that allows walking through the
+//               complete set of auxiliary data on the vertex.
+//
+//               This interface is not safe to use outside of
+//               PANDAEGG.DLL.
+////////////////////////////////////////////////////////////////////
+INLINE EggVertex::const_aux_iterator EggVertex::
+aux_end() const {
+  return _aux_map.end();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::uv_size
 //     Function: EggVertex::uv_size
 //       Access: Public
 //       Access: Public
@@ -277,6 +326,16 @@ uv_size() const {
   return _uv_map.size();
   return _uv_map.size();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::aux_size
+//       Access: Public
+//  Description: Returns the number of auxiliary datas on the vertex.
+////////////////////////////////////////////////////////////////////
+INLINE EggVertex::aux_size_type EggVertex::
+aux_size() const {
+  return _aux_map.size();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::get_index
 //     Function: EggVertex::get_index
 //       Access: Published
 //       Access: Published

+ 150 - 3
panda/src/egg/eggVertex.cxx

@@ -59,7 +59,8 @@ EggVertex(const EggVertex &copy)
     _external_index(copy._external_index),
     _external_index(copy._external_index),
     _pos(copy._pos),
     _pos(copy._pos),
     _num_dimensions(copy._num_dimensions),
     _num_dimensions(copy._num_dimensions),
-    _uv_map(copy._uv_map)
+    _uv_map(copy._uv_map),
+    _aux_map(copy._aux_map)
 {
 {
   _pool = NULL;
   _pool = NULL;
   _forward_reference = false;
   _forward_reference = false;
@@ -84,6 +85,7 @@ operator = (const EggVertex &copy) {
   _pos = copy._pos;
   _pos = copy._pos;
   _num_dimensions = copy._num_dimensions;
   _num_dimensions = copy._num_dimensions;
   _uv_map = copy._uv_map;
   _uv_map = copy._uv_map;
+  _aux_map = copy._aux_map;
 
 
   test_pref_integrity();
   test_pref_integrity();
   test_gref_integrity();
   test_gref_integrity();
@@ -143,11 +145,27 @@ has_uvw(const string &name) const {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::has_aux
+//       Access: Published
+//  Description: Returns true if the vertex has the named
+//               auxiliary data quadruple.
+////////////////////////////////////////////////////////////////////
+bool EggVertex::
+has_aux(const string &name) const {
+  AuxMap::const_iterator xi = _aux_map.find(name);
+  if (xi != _aux_map.end()) {
+    EggVertexAux *aux_obj = (*xi).second;
+    return true;
+  }
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::get_uv
 //     Function: EggVertex::get_uv
 //       Access: Published
 //       Access: Published
 //  Description: Returns the named UV coordinate pair on the vertex.
 //  Description: Returns the named UV coordinate pair on the vertex.
-//               vertex.  It is an error to call this if has_uv(name)
+//               It is an error to call this if has_uv(name)
 //               returned false.
 //               returned false.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 LTexCoordd EggVertex::
 LTexCoordd EggVertex::
@@ -161,7 +179,7 @@ get_uv(const string &name) const {
 //     Function: EggVertex::get_uvw
 //     Function: EggVertex::get_uvw
 //       Access: Published
 //       Access: Published
 //  Description: Returns the named UV coordinate triple on the vertex.
 //  Description: Returns the named UV coordinate triple on the vertex.
-//               vertex.  It is an error to call this if has_uvw(name)
+//               It is an error to call this if has_uvw(name)
 //               returned false.
 //               returned false.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 const LTexCoord3d &EggVertex::
 const LTexCoord3d &EggVertex::
@@ -171,6 +189,20 @@ get_uvw(const string &name) const {
   return (*ui).second->get_uvw();
   return (*ui).second->get_uvw();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::get_aux
+//       Access: Published
+//  Description: Returns the named auxiliary data quadruple on the
+//               vertex. It is an error to call this if has_aux(name)
+//               returned false.
+////////////////////////////////////////////////////////////////////
+const LVecBase4d &EggVertex::
+get_aux(const string &name) const {
+  AuxMap::const_iterator xi = _aux_map.find(name);
+  nassertr(xi != _aux_map.end(), LVecBase4d::zero());
+  return (*xi).second->get_aux();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::set_uv
 //     Function: EggVertex::set_uv
 //       Access: Published
 //       Access: Published
@@ -216,6 +248,27 @@ set_uvw(const string &name, const LTexCoord3d &uvw) {
   nassertv(get_uvw(fname) == uvw);
   nassertv(get_uvw(fname) == uvw);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::set_aux
+//       Access: Published
+//  Description: Sets the indicated auxiliary data quadruple on the
+//               vertex. This replaces any auxiliary data with the
+//               same name already on the vertex.
+////////////////////////////////////////////////////////////////////
+void EggVertex::
+set_aux(const string &name, const LVecBase4d &aux) {
+  PT(EggVertexAux) &aux_obj = _aux_map[name];
+
+  if (aux_obj.is_null()) {
+    aux_obj = new EggVertexAux(name, aux);
+  } else {
+    aux_obj = new EggVertexAux(*aux_obj);
+    aux_obj->set_aux(aux);
+  }
+
+  nassertv(get_aux(name) == aux);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::get_uv_obj
 //     Function: EggVertex::get_uv_obj
 //       Access: Published
 //       Access: Published
@@ -235,6 +288,24 @@ get_uv_obj(const string &name) const {
   return NULL;
   return NULL;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::get_aux_obj
+//       Access: Published
+//  Description: Returns the named EggVertexAux object, which defines
+//               the auxiliary data for this name. This object might
+//               be shared between multiple vertices.  You should not
+//               attempt to modify this object; instead, call
+//               modify_aux_object to return a modifiable pointer.
+////////////////////////////////////////////////////////////////////
+const EggVertexAux *EggVertex::
+get_aux_obj(const string &name) const {
+  AuxMap::const_iterator xi = _aux_map.find(name);
+  if (xi != _aux_map.end()) {
+    return (*xi).second;
+  }
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::modify_uv_obj
 //     Function: EggVertex::modify_uv_obj
 //       Access: Published
 //       Access: Published
@@ -257,6 +328,28 @@ modify_uv_obj(const string &name) {
   return NULL;
   return NULL;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::modify_aux_obj
+//       Access: Published
+//  Description: Returns a modifiable pointer to the named EggVertexAux
+//               object, which defines the auxiliary data for
+//               this name.  Returns NULL if there is no such
+//               named UV object.
+////////////////////////////////////////////////////////////////////
+EggVertexAux *EggVertex::
+modify_aux_obj(const string &name) {
+  AuxMap::iterator xi = _aux_map.find(name);
+  if (xi != _aux_map.end()) {
+    if ((*xi).second->get_ref_count() != 1) {
+      // Copy on write.
+      (*xi).second = new EggVertexAux(*(*xi).second);
+    }
+    return (*xi).second;
+  }
+
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::set_uv_obj
 //     Function: EggVertex::set_uv_obj
 //       Access: Published
 //       Access: Published
@@ -269,6 +362,18 @@ set_uv_obj(EggVertexUV *uv) {
   _uv_map[uv->get_name()] = uv;
   _uv_map[uv->get_name()] = uv;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::set_aux_obj
+//       Access: Published
+//  Description: Sets the indicated EggVertexAux on the vertex.
+//               This replaces any auxiliary data with the same
+//               name already on the vertex.
+////////////////////////////////////////////////////////////////////
+void EggVertex::
+set_aux_obj(EggVertexAux *aux) {
+  _aux_map[aux->get_name()] = aux;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertex::clear_uv
 //     Function: EggVertex::clear_uv
 //       Access: Published
 //       Access: Published
@@ -280,6 +385,16 @@ clear_uv(const string &name) {
   _uv_map.erase(EggVertexUV::filter_name(name));
   _uv_map.erase(EggVertexUV::filter_name(name));
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertex::clear_aux
+//       Access: Published
+//  Description: Removes the named auxiliary data from the vertex.
+///////////////////////////////////////////////////////////////////
+void EggVertex::
+clear_aux(const string &name) {
+  _aux_map.erase(name);
+}
+
 
 
 ///////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////
 //       Class : GroupRefEntry
 //       Class : GroupRefEntry
@@ -335,6 +450,11 @@ write(ostream &out, int indent_level) const {
     (*ui).second->write(out, indent_level + 2);
     (*ui).second->write(out, indent_level + 2);
   }
   }
 
 
+  AuxMap::const_iterator xi;
+  for (xi = _aux_map.begin(); xi != _aux_map.end(); ++xi) {
+    (*xi).second->write(out, indent_level + 2);
+  }
+
   EggAttributes::write(out, indent_level+2);
   EggAttributes::write(out, indent_level+2);
 
 
   _dxyzs.write(out, indent_level + 2, "<Dxyz>", 3);
   _dxyzs.write(out, indent_level + 2, "<Dxyz>", 3);
@@ -427,6 +547,33 @@ compare_to(const EggVertex &other) const {
     return 1;
     return 1;
   }
   }
 
 
+  // Merge-compare the aux maps.
+  AuxMap::const_iterator ci, di;
+  ci = _aux_map.begin();
+  di = other._aux_map.begin();
+  while (ci != _aux_map.end() && di != other._aux_map.end()) {
+    if ((*ci).first < (*di).first) {
+      return -1;
+
+    } else if ((*di).first < (*ci).first) {
+      return 1;
+
+    } else {
+      int compare = (*ci).second->compare_to(*(*di).second);
+      if (compare != 0) {
+        return compare;
+      }
+    }
+    ++ci;
+    ++di;
+  }
+  if (di != other._aux_map.end()) {
+    return -1;
+  }
+  if (ci != _aux_map.end()) {
+    return 1;
+  }
+
   return EggAttributes::compare_to(other);
   return EggAttributes::compare_to(other);
 }
 }
 
 

+ 22 - 0
panda/src/egg/eggVertex.h

@@ -21,6 +21,7 @@
 #include "eggAttributes.h"
 #include "eggAttributes.h"
 #include "eggMorphList.h"
 #include "eggMorphList.h"
 #include "eggVertexUV.h"
 #include "eggVertexUV.h"
+#include "eggVertexAux.h"
 
 
 #include "referenceCount.h"
 #include "referenceCount.h"
 #include "luse.h"
 #include "luse.h"
@@ -42,11 +43,17 @@ public:
   typedef pset<EggGroup *> GroupRef;
   typedef pset<EggGroup *> GroupRef;
   typedef pmultiset<EggPrimitive *> PrimitiveRef;
   typedef pmultiset<EggPrimitive *> PrimitiveRef;
   typedef pmap< string, PT(EggVertexUV) > UVMap;
   typedef pmap< string, PT(EggVertexUV) > UVMap;
+  typedef pmap< string, PT(EggVertexAux) > AuxMap;
 
 
   typedef second_of_pair_iterator<UVMap::const_iterator> uv_iterator;
   typedef second_of_pair_iterator<UVMap::const_iterator> uv_iterator;
   typedef uv_iterator const_uv_iterator;
   typedef uv_iterator const_uv_iterator;
   typedef UVMap::size_type uv_size_type;
   typedef UVMap::size_type uv_size_type;
 
 
+  typedef second_of_pair_iterator<AuxMap::const_iterator> aux_iterator;
+  typedef aux_iterator const_aux_iterator;
+  typedef AuxMap::size_type aux_size_type;
+
+
 PUBLISHED:
 PUBLISHED:
   EggVertex();
   EggVertex();
   EggVertex(const EggVertex &copy);
   EggVertex(const EggVertex &copy);
@@ -92,11 +99,25 @@ PUBLISHED:
   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);
 
 
+  INLINE bool has_aux() const;
+  INLINE void clear_aux();
+  bool has_aux(const string &name) const;
+  const LVecBase4d &get_aux(const string &name) const;
+  void set_aux(const string &name, const LVecBase4d &aux);
+  const EggVertexAux *get_aux_obj(const string &name) const;
+  EggVertexAux *modify_aux_obj(const string &name);
+  void set_aux_obj(EggVertexAux *vertex_aux);
+  void clear_aux(const string &name);
+
 public:
 public:
   INLINE const_uv_iterator uv_begin() const;
   INLINE const_uv_iterator uv_begin() const;
   INLINE const_uv_iterator uv_end() const;
   INLINE const_uv_iterator uv_end() const;
   INLINE uv_size_type uv_size() const;
   INLINE uv_size_type uv_size() const;
 
 
+  INLINE const_aux_iterator aux_begin() const;
+  INLINE const_aux_iterator aux_end() const;
+  INLINE aux_size_type aux_size() const;
+
 PUBLISHED:
 PUBLISHED:
   INLINE int get_index() const;
   INLINE int get_index() const;
 
 
@@ -152,6 +173,7 @@ private:
   PrimitiveRef _pref;
   PrimitiveRef _pref;
 
 
   UVMap _uv_map;
   UVMap _uv_map;
+  AuxMap _aux_map;
 
 
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {

+ 44 - 0
panda/src/egg/eggVertexPool.cxx

@@ -327,6 +327,25 @@ has_uvs() const {
   return false;
   return false;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexPool::has_aux
+//       Access: Public
+//  Description: Returns true if any vertex in the pool has
+//               auxiliary data defined, false if none of them do.
+////////////////////////////////////////////////////////////////////
+bool EggVertexPool::
+has_aux() const {
+  IndexVertices::const_iterator ivi;
+  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
+    EggVertex *vertex = (*ivi).second;
+    if (vertex->has_aux()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexPool::get_uv_names
 //     Function: EggVertexPool::get_uv_names
 //       Access: Public
 //       Access: Public
@@ -370,6 +389,31 @@ get_uv_names(vector_string &uv_names, vector_string &uvw_names,
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexPool::get_aux_names
+//       Access: Public
+//  Description: Returns the list of auxiliary data names that are
+//               defined by any vertices in the pool.
+////////////////////////////////////////////////////////////////////
+void EggVertexPool::
+get_aux_names(vector_string &aux_names) const {
+  pset<string> aux_names_set;
+  IndexVertices::const_iterator ivi;
+  for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
+    EggVertex *vertex = (*ivi).second;
+    EggVertex::const_aux_iterator uvi;
+    for (uvi = vertex->aux_begin(); uvi != vertex->aux_end(); ++uvi) {
+      EggVertexAux *aux_obj = (*uvi);
+      aux_names_set.insert(aux_obj->get_name());
+    }
+  }
+
+  pset<string>::const_iterator si;
+  for (si = aux_names_set.begin(); si != aux_names_set.end(); ++si) {
+    aux_names.push_back(*si);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: EggVertexPool::begin()
 //     Function: EggVertexPool::begin()
 //       Access: Public
 //       Access: Public

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

@@ -96,8 +96,10 @@ PUBLISHED:
   bool has_nonwhite_colors() const;
   bool has_nonwhite_colors() const;
   void check_overall_color(bool &has_overall_color, LColor &overall_color) const;
   void check_overall_color(bool &has_overall_color, LColor &overall_color) const;
   bool has_uvs() const;
   bool has_uvs() const;
+  bool has_aux() const;
   void get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
   void get_uv_names(vector_string &uv_names, vector_string &uvw_names, 
                     vector_string &tbn_names) const;
                     vector_string &tbn_names) const;
+  void get_aux_names(vector_string &aux_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.

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

@@ -20,6 +20,7 @@
 #include "eggVertex.cxx"
 #include "eggVertex.cxx"
 #include "eggVertexPool.cxx"
 #include "eggVertexPool.cxx"
 #include "eggVertexUV.cxx"
 #include "eggVertexUV.cxx"
+#include "eggVertexAux.cxx"
 #include "eggXfmAnimData.cxx"
 #include "eggXfmAnimData.cxx"
 #include "eggXfmSAnim.cxx"
 #include "eggXfmSAnim.cxx"
 #include "pt_EggMaterial.cxx"
 #include "pt_EggMaterial.cxx"

+ 4 - 0
panda/src/egg/lexer.lxx

@@ -351,6 +351,10 @@ NUMERIC         ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
   accept();
   accept();
   return ANIMPRELOAD;
   return ANIMPRELOAD;
 }
 }
+"<AUX>" {
+  accept();
+  return AUX;
+}
 "<BEZIERCURVE>" {
 "<BEZIERCURVE>" {
   accept();
   accept();
   return BEZIERCURVE;
   return BEZIERCURVE;

+ 31 - 1
panda/src/egg/parser.yxx

@@ -14,6 +14,7 @@
 #include "eggVertex.h"
 #include "eggVertex.h"
 #include "eggVertexPool.h"
 #include "eggVertexPool.h"
 #include "eggVertexUV.h"
 #include "eggVertexUV.h"
+#include "eggVertexAux.h"
 #include "eggPolygon.h"
 #include "eggPolygon.h"
 #include "eggCompositePrimitive.h"
 #include "eggCompositePrimitive.h"
 #include "eggTriangleFan.h"
 #include "eggTriangleFan.h"
@@ -172,7 +173,7 @@ egg_cleanup_parser() {
 %token SANIM SCALAR SCALE SEQUENCE SHADING SWITCH SWITCHCONDITION
 %token SANIM SCALAR SCALE SEQUENCE SHADING SWITCH SWITCHCONDITION
 %token TABLE TABLE_V TAG TANGENT TEXLIST TEXTURE TLENGTHS TRANSFORM TRANSLATE
 %token TABLE TABLE_V TAG TANGENT TEXLIST TEXTURE TLENGTHS TRANSFORM TRANSLATE
 %token TREF TRIANGLEFAN TRIANGLESTRIP 
 %token TREF TRIANGLEFAN TRIANGLESTRIP 
-%token TRIM TXT UKNOTS UV VKNOTS VERTEX VERTEXANIM
+%token TRIM TXT UKNOTS UV AUX VKNOTS VERTEX VERTEXANIM
 %token VERTEXPOOL VERTEXREF
 %token VERTEXPOOL VERTEXREF
 %token XFMANIM XFMSANIM
 %token XFMANIM XFMSANIM
 
 
@@ -999,6 +1000,21 @@ vertex_body:
          vertex_uv_body '}'
          vertex_uv_body '}'
 {
 {
   egg_stack.pop_back();
   egg_stack.pop_back();
+}
+        | vertex_body AUX required_name '{'
+{
+  EggVertex *vertex = DCAST(EggVertex, egg_stack.back());
+  EggVertexAux *aux = new EggVertexAux($3, LVecBase4d::zero());
+  egg_stack.push_back(aux);
+  if (vertex->has_aux($3)) {
+    eggyywarning("Ignoring repeated Aux name " + $3);
+  } else {
+    vertex->set_aux_obj(aux);
+  }
+}
+         vertex_aux_body '}'
+{
+  egg_stack.pop_back();
 }
 }
         | vertex_body NORMAL '{' vertex_normal_body '}'
         | vertex_body NORMAL '{' vertex_normal_body '}'
         | vertex_body RGBA '{' vertex_color_body '}'
         | vertex_body RGBA '{' vertex_color_body '}'
@@ -1087,6 +1103,20 @@ vertex_uv_body:
 }
 }
         ;
         ;
 
 
+/*
+ * vertex_aux_body
+ *
+ * enter: TOS is EggVertex.
+ * exit: vertex Aux value has been filled.
+ *
+ */
+vertex_aux_body:
+        | real real real real
+{
+  DCAST(EggVertexAux, egg_stack.back())->set_aux(LVecBase4d($1, $2, $3, $4));
+}
+        ;
+
 /*
 /*
  * vertex_normal_body
  * vertex_normal_body
  *
  *

+ 21 - 0
panda/src/egg2pg/eggLoader.cxx

@@ -2243,6 +2243,15 @@ make_vertex_data(const EggRenderState *render_state,
       (iname, 3, Geom::NT_stdfloat, Geom::C_vector);
       (iname, 3, Geom::NT_stdfloat, Geom::C_vector);
   }
   }
 
 
+  vector_string aux_names;
+  vertex_pool->get_aux_names(aux_names);
+  for (ni = aux_names.begin(); ni != aux_names.end(); ++ni) {
+    string name = (*ni);
+    PT(InternalName) iname = InternalName::make(name);
+    array_format->add_column
+      (iname, 4, Geom::NT_stdfloat, Geom::C_other);
+  }
+
   PT(GeomVertexFormat) temp_format = new GeomVertexFormat(array_format);
   PT(GeomVertexFormat) temp_format = new GeomVertexFormat(array_format);
 
 
   PT(TransformBlendTable) blend_table;
   PT(TransformBlendTable) blend_table;
@@ -2454,6 +2463,18 @@ make_vertex_data(const EggRenderState *render_state,
       }
       }
     }
     }
 
 
+    EggVertex::const_aux_iterator auxi;
+    for (auxi = vertex->aux_begin(); auxi != vertex->aux_end(); ++auxi) {
+      EggVertexAux *egg_aux = (*auxi);
+      LVecBase4d aux = egg_aux->get_aux();
+
+      string name = egg_aux->get_name();
+      PT(InternalName) iname = InternalName::make(name);
+      gvw.set_column(iname);
+
+      gvw.set_data4d(aux);
+    }
+
     if (is_dynamic) {
     if (is_dynamic) {
       // Figure out the transforms affecting this particular vertex.
       // Figure out the transforms affecting this particular vertex.
       TransformBlend blend;
       TransformBlend blend;