diff --git a/panda/src/doc/eggSyntax.txt b/panda/src/doc/eggSyntax.txt index 2db88bf114..f748bc5434 100644 --- a/panda/src/doc/eggSyntax.txt +++ b/panda/src/doc/eggSyntax.txt @@ -720,6 +720,18 @@ appear before they are referenced. [name] { u v [w] { x y z } { x y z } } + 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. + + + name { vertices } A dynamic vertex pool is similar to a vertex pool in most respects, diff --git a/panda/src/egg/config_egg.cxx b/panda/src/egg/config_egg.cxx index ee8e505719..2ae07a00a1 100644 --- a/panda/src/egg/config_egg.cxx +++ b/panda/src/egg/config_egg.cxx @@ -52,6 +52,7 @@ #include "eggVertex.h" #include "eggVertexPool.h" #include "eggVertexUV.h" +#include "eggVertexAux.h" #include "eggXfmAnimData.h" #include "eggXfmSAnim.h" @@ -207,6 +208,7 @@ init_libegg() { EggVertex::init_type(); EggVertexPool::init_type(); EggVertexUV::init_type(); + EggVertexAux::init_type(); EggXfmAnimData::init_type(); EggXfmSAnim::init_type(); } diff --git a/panda/src/egg/eggVertex.I b/panda/src/egg/eggVertex.I index 24327e6197..f32582d5e3 100644 --- a/panda/src/egg/eggVertex.I +++ b/panda/src/egg/eggVertex.I @@ -195,6 +195,17 @@ has_uv() const { 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 // Access: Published @@ -239,6 +250,16 @@ clear_uv() { _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 // Access: Public @@ -253,6 +274,20 @@ uv_begin() const { 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 // Access: Public @@ -267,6 +302,20 @@ uv_end() const { 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 // Access: Public @@ -277,6 +326,16 @@ uv_size() const { 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 // Access: Published diff --git a/panda/src/egg/eggVertex.cxx b/panda/src/egg/eggVertex.cxx index fe0937c1e9..a0b5ff19b2 100644 --- a/panda/src/egg/eggVertex.cxx +++ b/panda/src/egg/eggVertex.cxx @@ -59,7 +59,8 @@ EggVertex(const EggVertex ©) _external_index(copy._external_index), _pos(copy._pos), _num_dimensions(copy._num_dimensions), - _uv_map(copy._uv_map) + _uv_map(copy._uv_map), + _aux_map(copy._aux_map) { _pool = NULL; _forward_reference = false; @@ -84,6 +85,7 @@ operator = (const EggVertex ©) { _pos = copy._pos; _num_dimensions = copy._num_dimensions; _uv_map = copy._uv_map; + _aux_map = copy._aux_map; test_pref_integrity(); test_gref_integrity(); @@ -143,11 +145,27 @@ has_uvw(const string &name) const { 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 // Access: Published // 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. //////////////////////////////////////////////////////////////////// LTexCoordd EggVertex:: @@ -161,7 +179,7 @@ get_uv(const string &name) const { // 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) +// It is an error to call this if has_uvw(name) // returned false. //////////////////////////////////////////////////////////////////// const LTexCoord3d &EggVertex:: @@ -171,6 +189,20 @@ get_uvw(const string &name) const { 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 // Access: Published @@ -216,6 +248,27 @@ set_uvw(const string &name, const LTexCoord3d &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 // Access: Published @@ -235,6 +288,24 @@ get_uv_obj(const string &name) const { 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 // Access: Published @@ -257,6 +328,28 @@ modify_uv_obj(const string &name) { 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 // Access: Published @@ -269,6 +362,18 @@ set_uv_obj(EggVertexUV *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 // Access: Published @@ -280,6 +385,16 @@ clear_uv(const string &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 @@ -335,6 +450,11 @@ write(ostream &out, int indent_level) const { (*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); _dxyzs.write(out, indent_level + 2, "", 3); @@ -427,6 +547,33 @@ compare_to(const EggVertex &other) const { 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); } diff --git a/panda/src/egg/eggVertex.h b/panda/src/egg/eggVertex.h index ba1386a530..7825da3829 100644 --- a/panda/src/egg/eggVertex.h +++ b/panda/src/egg/eggVertex.h @@ -21,6 +21,7 @@ #include "eggAttributes.h" #include "eggMorphList.h" #include "eggVertexUV.h" +#include "eggVertexAux.h" #include "referenceCount.h" #include "luse.h" @@ -42,11 +43,17 @@ public: typedef pset GroupRef; typedef pmultiset PrimitiveRef; typedef pmap< string, PT(EggVertexUV) > UVMap; + typedef pmap< string, PT(EggVertexAux) > AuxMap; typedef second_of_pair_iterator uv_iterator; typedef uv_iterator const_uv_iterator; typedef UVMap::size_type uv_size_type; + typedef second_of_pair_iterator aux_iterator; + typedef aux_iterator const_aux_iterator; + typedef AuxMap::size_type aux_size_type; + + PUBLISHED: EggVertex(); EggVertex(const EggVertex ©); @@ -92,11 +99,25 @@ PUBLISHED: void set_uv_obj(EggVertexUV *vertex_uv); 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: INLINE const_uv_iterator uv_begin() const; INLINE const_uv_iterator uv_end() 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: INLINE int get_index() const; @@ -152,6 +173,7 @@ private: PrimitiveRef _pref; UVMap _uv_map; + AuxMap _aux_map; public: static TypeHandle get_class_type() { diff --git a/panda/src/egg/eggVertexPool.cxx b/panda/src/egg/eggVertexPool.cxx index 500fc278fb..84869fa27e 100644 --- a/panda/src/egg/eggVertexPool.cxx +++ b/panda/src/egg/eggVertexPool.cxx @@ -327,6 +327,25 @@ has_uvs() const { 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 // 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 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::const_iterator si; + for (si = aux_names_set.begin(); si != aux_names_set.end(); ++si) { + aux_names.push_back(*si); + } +} + //////////////////////////////////////////////////////////////////// // Function: EggVertexPool::begin() // Access: Public diff --git a/panda/src/egg/eggVertexPool.h b/panda/src/egg/eggVertexPool.h index 42bea2eff0..7a5c6b1f17 100644 --- a/panda/src/egg/eggVertexPool.h +++ b/panda/src/egg/eggVertexPool.h @@ -96,8 +96,10 @@ PUBLISHED: bool has_nonwhite_colors() const; void check_overall_color(bool &has_overall_color, LColor &overall_color) const; bool has_uvs() const; + bool has_aux() const; void get_uv_names(vector_string &uv_names, vector_string &uvw_names, vector_string &tbn_names) const; + void get_aux_names(vector_string &aux_names) const; public: // Can be used to traverse all the vertices in index number order. diff --git a/panda/src/egg/egg_composite2.cxx b/panda/src/egg/egg_composite2.cxx index 03edeb8a75..8f29c3bd8f 100644 --- a/panda/src/egg/egg_composite2.cxx +++ b/panda/src/egg/egg_composite2.cxx @@ -20,6 +20,7 @@ #include "eggVertex.cxx" #include "eggVertexPool.cxx" #include "eggVertexUV.cxx" +#include "eggVertexAux.cxx" #include "eggXfmAnimData.cxx" #include "eggXfmSAnim.cxx" #include "pt_EggMaterial.cxx" diff --git a/panda/src/egg/lexer.lxx b/panda/src/egg/lexer.lxx index 9671a15f9b..d4eb9a8cf5 100644 --- a/panda/src/egg/lexer.lxx +++ b/panda/src/egg/lexer.lxx @@ -351,6 +351,10 @@ NUMERIC ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?) accept(); return ANIMPRELOAD; } +"" { + accept(); + return AUX; +} "" { accept(); return BEZIERCURVE; diff --git a/panda/src/egg/parser.yxx b/panda/src/egg/parser.yxx index a8eb016589..7bf6bda552 100644 --- a/panda/src/egg/parser.yxx +++ b/panda/src/egg/parser.yxx @@ -14,6 +14,7 @@ #include "eggVertex.h" #include "eggVertexPool.h" #include "eggVertexUV.h" +#include "eggVertexAux.h" #include "eggPolygon.h" #include "eggCompositePrimitive.h" #include "eggTriangleFan.h" @@ -172,7 +173,7 @@ egg_cleanup_parser() { %token SANIM SCALAR SCALE SEQUENCE SHADING SWITCH SWITCHCONDITION %token TABLE TABLE_V TAG TANGENT TEXLIST TEXTURE TLENGTHS TRANSFORM TRANSLATE %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 XFMANIM XFMSANIM @@ -999,6 +1000,21 @@ vertex_body: vertex_uv_body '}' { 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 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 * diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index eedb974cd9..93c7b30f60 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -2243,6 +2243,15 @@ make_vertex_data(const EggRenderState *render_state, (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(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) { // Figure out the transforms affecting this particular vertex. TransformBlend blend;