mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 12:12:10 -04:00
support forward-referenced vertex pools
This commit is contained in:
parent
3110e8c5ef
commit
29cfd81978
@ -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
|
||||
|
@ -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 ©)
|
||||
_num_dimensions(copy._num_dimensions)
|
||||
{
|
||||
_pool = NULL;
|
||||
_forward_reference = false;
|
||||
_index = -1;
|
||||
test_pref_integrity();
|
||||
test_gref_integrity();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -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 ©) {
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -77,10 +77,18 @@ PUBLISHED:
|
||||
EggVertexPool(const EggVertexPool ©);
|
||||
~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:
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user