support forward-referenced vertex pools

This commit is contained in:
David Rose 2003-11-21 23:02:52 +00:00
parent 3110e8c5ef
commit 29cfd81978
7 changed files with 237 additions and 39 deletions

View File

@ -21,13 +21,32 @@
////////////////////////////////////////////////////////////////////
// Function: EggVertex::get_pool
// Access: Public
// Description:
// Description: Returns the vertex pool this vertex belongs in. This
// may be NULL if the vertex has not been added to a
// pool.
////////////////////////////////////////////////////////////////////
INLINE EggVertexPool *EggVertex::
get_pool() const {
return _pool;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertex::is_forward_reference
// Access: Public
// Description: Returns true if the vertex is a forward reference to
// some vertex that hasn't been defined yet. In this
// case, the vertex may not have any properties filled
// in yet.
//
// This can only happen if you implicitly create a
// vertex via EggVertexPool::get_forward_vertex().
// Presumably, when the vertex pool is later filled in,
// this vertex will be replaced with real data.
////////////////////////////////////////////////////////////////////
INLINE bool EggVertex::
is_forward_reference() const {
return _forward_reference;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertex::set_pos

View File

@ -42,6 +42,7 @@ TypeHandle EggVertex::_type_handle;
EggVertex::
EggVertex() {
_pool = NULL;
_forward_reference = false;
_index = -1;
_external_index = -1;
set_pos(LPoint3d(0.0, 0.0, 0.0));
@ -64,6 +65,7 @@ EggVertex(const EggVertex &copy)
_num_dimensions(copy._num_dimensions)
{
_pool = NULL;
_forward_reference = false;
_index = -1;
test_pref_integrity();
test_gref_integrity();

View File

@ -52,6 +52,8 @@ PUBLISHED:
INLINE EggVertexPool *get_pool() const;
INLINE bool is_forward_reference() const;
// The pos might have 1, 2, 3, or 4 dimensions. That complicates
// things a bit.
INLINE void set_pos(double pos);
@ -116,6 +118,7 @@ PUBLISHED:
private:
EggVertexPool *_pool;
bool _forward_reference;
int _index;
int _external_index;
LPoint4d _pos;

View File

@ -17,6 +17,18 @@
////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::has_vertex
// Access: Public
// Description: Returns true if the indicated vertex has been defined
// in the vertex pool, false otherwise. This does not
// include forward references.
////////////////////////////////////////////////////////////////////
INLINE bool EggVertexPool::
has_vertex(int index) const {
return get_vertex(index) != (EggVertex *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::indexing operator
// Access: Public
@ -39,8 +51,7 @@ operator [](int index) const {
INLINE EggVertex *EggVertexPool::
make_new_vertex() {
PT(EggVertex) vertex = new EggVertex;
add_vertex(vertex);
return vertex;
return add_vertex(vertex);
}
////////////////////////////////////////////////////////////////////

View File

@ -20,7 +20,7 @@
#include "eggPrimitive.h"
#include "eggUtilities.h"
#include <indent.h>
#include "indent.h"
TypeHandle EggVertexPool::_type_handle;
@ -31,6 +31,7 @@ TypeHandle EggVertexPool::_type_handle;
////////////////////////////////////////////////////////////////////
EggVertexPool::
EggVertexPool(const string &name) : EggNode(name) {
_highest_index = 0;
}
////////////////////////////////////////////////////////////////////
@ -62,20 +63,62 @@ EggVertexPool::
// Sanity check.
nassertv(_index_vertices.size() == _unique_vertices.size());
iterator i;
for (i = begin(); i != end(); ++i) {
// Sanity checks on our internal data structures.
nassertv((*i)->_pool == this);
nassertv(get_vertex((*i)->_index) == (*i));
IndexVertices::iterator ivi;
for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
int index = (*ivi).first;
EggVertex *vertex = (*ivi).second;
(*i)->_pool = NULL;
(*i)->_index = -1;
// Sanity checks on our internal data structures.
nassertv(vertex->_pool == this);
nassertv(vertex->get_index() == index);
vertex->_pool = NULL;
vertex->_index = -1;
}
_index_vertices.erase(_index_vertices.begin(), _index_vertices.end());
_unique_vertices.erase(_unique_vertices.begin(), _unique_vertices.end());
_index_vertices.clear();
_unique_vertices.clear();
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::has_forward_vertices
// Access: Published
// Description: Returns true if any vertices in the pool are
// undefined forward-reference vertices, false if all
// vertices are defined.
////////////////////////////////////////////////////////////////////
bool EggVertexPool::
has_forward_vertices() const {
IndexVertices::const_iterator ivi;
for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
EggVertex *vertex = (*ivi).second;
if (vertex->is_forward_reference()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::has_defined_vertices
// Access: Published
// Description: Returns true if any vertices in the pool are
// fully defined vertices, false if all vertices are
// forward references.
////////////////////////////////////////////////////////////////////
bool EggVertexPool::
has_defined_vertices() const {
IndexVertices::const_iterator ivi;
for (ivi = _index_vertices.begin(); ivi != _index_vertices.end(); ++ivi) {
EggVertex *vertex = (*ivi).second;
if (!vertex->is_forward_reference()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::get_vertex
@ -90,6 +133,35 @@ get_vertex(int index) const {
if (ivi == _index_vertices.end()) {
return NULL;
} else {
EggVertex *vertex = (*ivi).second;
if (vertex->is_forward_reference()) {
return NULL;
}
return vertex;
}
}
////////////////////////////////////////////////////////////////////
// Function: EggVertexPool::get_forward_vertex
// Access: Public
// Description: Returns the vertex in the pool with the indicated
// index number. If there is not a vertex in the pool
// with the indicated index number, creates a special
// forward-reference EggVertex that has no data, on the
// assumption that the vertex pool has not yet been
// fully read and more data will be available later.
////////////////////////////////////////////////////////////////////
EggVertex *EggVertexPool::
get_forward_vertex(int index) {
nassertr(index >= 0, NULL);
IndexVertices::const_iterator ivi = _index_vertices.find(index);
if (ivi == _index_vertices.end()) {
PT(EggVertex) forward = new EggVertex;
forward->_forward_reference = true;
return add_vertex(forward, index);
} else {
return (*ivi).second;
}
@ -99,16 +171,11 @@ get_vertex(int index) const {
// Function: EggVertexPool::get_highest_index
// Access: Public
// Description: Returns the highest index number used by any vertex
// in the pool.
// in the pool (except forward references).
////////////////////////////////////////////////////////////////////
int EggVertexPool::
get_highest_index() const {
if (_index_vertices.empty()) {
return 0;
}
IndexVertices::const_reverse_iterator ivi = _index_vertices.rbegin();
nassertr((*ivi).first == (*ivi).second->get_index(), 0);
return (*ivi).first;
return _highest_index;
}
////////////////////////////////////////////////////////////////////
@ -166,26 +233,59 @@ size() const {
// the vertex pool. If the index number is supplied,
// tries to assign that index number; it is an error if
// the index number is already in use.
//
// It is possible that a forward reference to this
// vertex was requested in the past; if so, the data
// from the supplied vertex is copied onto the forward
// reference, which becomes the actual vertex. In this
// case, a different pointer is saved (and returned)
// than the one actually passed in. In the usual case,
// however, the vertex pointer passed in is the one that
// is saved in the vertex pool and returned from this
// method.
////////////////////////////////////////////////////////////////////
void EggVertexPool::
EggVertex *EggVertexPool::
add_vertex(EggVertex *vertex, int index) {
// Save a pointer to the vertex.
PT(EggVertex) vertex_keep = vertex;
// Don't try to add a vertex while it still belongs to another pool.
nassertv(vertex->_pool == NULL);
nassertr(vertex->_pool == NULL, NULL);
if (index == -1) {
index = get_highest_index() + 1;
}
// Always supply an index number >= 0.
nassertv(index >= 0);
nassertr(index >= 0, NULL);
// Don't try to duplicate index numbers within a vertex pool.
nassertv(_index_vertices.find(index) == _index_vertices.end());
// Check for a forward reference.
IndexVertices::const_iterator ivi = _index_vertices.find(index);
if (ivi != _index_vertices.end()) {
EggVertex *orig_vertex = (*ivi).second;
if (orig_vertex->is_forward_reference() &&
!vertex->is_forward_reference()) {
(*orig_vertex) = (*vertex);
orig_vertex->_forward_reference = false;
_highest_index = max(_highest_index, index);
return orig_vertex;
}
// Oops, you duplicated a vertex index.
nassertr(false, NULL);
}
_unique_vertices.insert(vertex);
_index_vertices[index] = vertex;
if (!vertex->is_forward_reference()) {
_highest_index = max(_highest_index, index);
}
vertex->_pool = this;
vertex->_index = index;
return vertex;
}
@ -208,9 +308,7 @@ create_unique_vertex(const EggVertex &copy) {
}
// Create a new vertex.
EggVertex *vtx = new EggVertex(copy);
add_vertex(vtx);
return vtx;
return add_vertex(new EggVertex(copy));
}
@ -231,6 +329,24 @@ remove_vertex(EggVertex *vertex) {
// Removing the vertex from the indexed list is simple.
_index_vertices.erase(vertex->_index);
if (_highest_index == vertex->_index) {
// Find the new highest vertex index.
if (_index_vertices.empty()) {
_highest_index = 0;
} else {
IndexVertices::reverse_iterator ivi = _index_vertices.rbegin();
while (ivi != _index_vertices.rend() &&
(*ivi).second->is_forward_reference()) {
++ivi;
}
if (ivi != _index_vertices.rend()) {
_highest_index = (*ivi).first;
} else {
_highest_index = 0;
}
}
}
// Removing the vertex from the unique list is a bit trickier--there
// might be several other vertices that are considered identical to
// this one, and so we have to walk through all the identical
@ -289,6 +405,7 @@ remove_unused_vertices() {
// All done. Lose the old lists.
_unique_vertices.swap(new_unique_vertices);
_index_vertices.swap(new_index_vertices);
_highest_index = _index_vertices.size() - 1;
nassertr(_index_vertices.size() == _unique_vertices.size(), num_removed);

View File

@ -77,10 +77,18 @@ PUBLISHED:
EggVertexPool(const EggVertexPool &copy);
~EggVertexPool();
INLINE bool has_vertex(int index) const;
bool has_forward_vertices() const;
bool has_defined_vertices() const;
// Returns NULL if there is no such vertex.
EggVertex *get_vertex(int index) const;
INLINE EggVertex *operator [](int index) const;
// Returns a forward reference if there is no such vertex.
EggVertex *get_forward_vertex(int index);
// Returns 0 if the pool is empty.
int get_highest_index() const;
@ -94,7 +102,7 @@ public:
PUBLISHED:
// add_vertex() adds a freshly-allocated vertex. It is up to the
// user to allocate the vertex.
void add_vertex(EggVertex *vertex, int index = -1);
EggVertex *add_vertex(EggVertex *vertex, int index = -1);
// make_new_vertex() allocates and returns a new vertex from the
// pool.
@ -124,6 +132,7 @@ protected:
private:
UniqueVertices _unique_vertices;
IndexVertices _index_vertices;
int _highest_index;
public:

View File

@ -5,7 +5,8 @@
%{
#include <pandabase.h>
#include "pandabase.h"
#include "config_egg.h"
#include "parserDefs.h"
#include "lexerDefs.h"
#include "eggObject.h"
@ -101,6 +102,32 @@ egg_init_parser(istream &in, const string &filename,
void
egg_cleanup_parser() {
// Check for undefined vertex pools.
VertexPools::const_iterator vpi;
for (vpi = vertex_pools.begin(); vpi != vertex_pools.end(); ++vpi) {
EggVertexPool *pool = (*vpi).second;
if (pool->has_forward_vertices()) {
if (!pool->has_defined_vertices()) {
eggyyerror("Undefined vertex pool " + pool->get_name());
} else {
eggyyerror("Undefined vertices in pool " + pool->get_name());
egg_cat.error(false)
<< "Undefined vertex index numbers:";
EggVertexPool::const_iterator vi;
for (vi = pool->begin(); vi != pool->end(); ++vi) {
EggVertex *vertex = (*vi);
if (vertex->is_forward_reference()) {
egg_cat.error(false)
<< " " << vertex->get_index();
}
}
egg_cat.error(false)
<< "\n";
}
}
}
// Clean these out after we're done, so we don't keep big memory
// structures around needlessly.
egg_stack.clear();
@ -580,12 +607,20 @@ vertex_pool:
VERTEXPOOL required_name
{
string name = $2;
EggVertexPool *pool = new EggVertexPool(name);
EggVertexPool *pool = NULL;
if (vertex_pools.find(name) != vertex_pools.end()) {
eggyywarning("Duplicate vertex pool name " + name);
VertexPools::const_iterator vpi = vertex_pools.find(name);
if (vpi != vertex_pools.end()) {
pool = (*vpi).second;
if (pool->has_defined_vertices()) {
eggyywarning("Duplicate vertex pool name " + name);
pool = new EggVertexPool(name);
vertex_pools[name] = pool;
}
} else {
pool = new EggVertexPool(name);
vertex_pools[name] = pool;
}
vertex_pools[name] = pool;
egg_stack.push_back(pool);
}
@ -640,7 +675,7 @@ vertex:
eggyywarning(errmsg);
vertex_index = -1;
} else if (pool->get_vertex(vertex_index) != NULL) {
} else if (pool->has_vertex(vertex_index)) {
ostringstream errmsg;
errmsg << "Ignoring duplicate vertex index " << vertex_index
<< " in vertex pool " << pool->get_name() << ends;
@ -1271,7 +1306,7 @@ group_vertex_ref:
for (int i = 0; i < (int)nums.size(); i++) {
int index = (int)nums[i];
EggVertex *vertex = pool->get_vertex(index);
EggVertex *vertex = pool->get_forward_vertex(index);
if (vertex == NULL) {
ostringstream errmsg;
errmsg << "No vertex " << index << " in pool " << pool->get_name()
@ -1840,7 +1875,7 @@ primitive_vertex_ref:
for (int i = 0; i < (int)nums.size(); i++) {
int index = (int)nums[i];
EggVertex *vertex = pool->get_vertex(index);
EggVertex *vertex = pool->get_forward_vertex(index);
if (vertex == NULL) {
ostringstream errmsg;
errmsg << "No vertex " << index << " in pool " << pool->get_name()
@ -2310,8 +2345,10 @@ vertex_pool_name:
string name = $1;
VertexPools::iterator vpi = vertex_pools.find(name);
if (vpi == vertex_pools.end()) {
eggyyerror("Unknown vertex pool " + name);
$$ = PT(EggObject)();
// This will become a forward reference.
EggVertexPool *pool = new EggVertexPool(name);
vertex_pools[name] = pool;
$$ = pool;
} else {
$$ = (*vpi).second;
}