From 29d51a723b5e5475b0c101c0afcb6a2f26dbdc02 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 28 Mar 2005 16:15:26 +0000 Subject: [PATCH] VertexRewriter; animation stats in cull --- panda/src/char/character.cxx | 83 +++++--- panda/src/char/character.h | 7 +- panda/src/gobj/Sources.pp | 3 + panda/src/gobj/gobj_composite1.cxx | 1 + panda/src/gobj/qpgeomVertexData.I | 42 +++- panda/src/gobj/qpgeomVertexData.cxx | 113 +++++----- panda/src/gobj/qpgeomVertexData.h | 14 +- panda/src/gobj/qpgeomVertexReader.I | 5 +- panda/src/gobj/qpgeomVertexReader.h | 17 +- panda/src/gobj/qpgeomVertexRewriter.I | 261 ++++++++++++++++++++++++ panda/src/gobj/qpgeomVertexRewriter.cxx | 19 ++ panda/src/gobj/qpgeomVertexRewriter.h | 73 +++++++ panda/src/gobj/qpgeomVertexWriter.I | 5 +- panda/src/gobj/qpgeomVertexWriter.h | 16 +- panda/src/pgraph/cullableObject.cxx | 2 +- 15 files changed, 557 insertions(+), 104 deletions(-) create mode 100644 panda/src/gobj/qpgeomVertexRewriter.I create mode 100644 panda/src/gobj/qpgeomVertexRewriter.cxx create mode 100644 panda/src/gobj/qpgeomVertexRewriter.h diff --git a/panda/src/char/character.cxx b/panda/src/char/character.cxx index 63fd019c50..d9e28c4b48 100644 --- a/panda/src/char/character.cxx +++ b/panda/src/char/character.cxx @@ -33,7 +33,8 @@ TypeHandle Character::_type_handle; -PStatCollector Character::_anim_pcollector("App:Animation"); +PStatCollector Character::_app_animation_pcollector("App:Animation"); +PStatCollector Character::_cull_animation_pcollector("Cull:Animation"); //////////////////////////////////////////////////////////////////// // Function: Character::Copy Constructor @@ -46,7 +47,8 @@ Character(const Character ©) : _cv(DynamicVertices::deep_copy(copy._cv)), _computed_vertices(copy._computed_vertices), _parts(copy._parts), - _char_pcollector(copy._char_pcollector) + _app_char_pcollector(copy._app_char_pcollector), + _cull_char_pcollector(copy._cull_char_pcollector) { // Now make a copy of the joint/slider hierarchy. We could just use // the copy_subgraph feature of the PartBundleNode's copy @@ -64,7 +66,8 @@ Character(const Character ©) : Character:: Character(const string &name) : PartBundleNode(name, new CharacterJointBundle(name)), - _char_pcollector(_anim_pcollector, name) + _app_char_pcollector(PStatCollector(_app_animation_pcollector, name), "Joints"), + _cull_char_pcollector(PStatCollector(_cull_animation_pcollector, name), "Joints") { } @@ -158,7 +161,18 @@ cull_callback(CullTraverser *, CullTraverserData &) { // the view frustum. We may need a better way to do this // optimization later, to handle characters that might animate // themselves in front of the view frustum. - update_to_now(); + + PStatTimer timer(_cull_char_pcollector); + + double now = ClockObject::get_global_clock()->get_frame_time(); + get_bundle()->advance_time(now); + + if (char_cat.is_spam()) { + char_cat.spam() << "Animating " << *this << " at time " << now << "\n"; + } + + do_update(); + return true; } @@ -193,9 +207,38 @@ update_to_now() { //////////////////////////////////////////////////////////////////// void Character:: update() { - // Statistics - PStatTimer timer(_char_pcollector); + PStatTimer timer(_app_char_pcollector); + do_update(); +} +//////////////////////////////////////////////////////////////////// +// Function: Character::force_update +// Access: Published +// Description: Recalculates the character even if we think it +// doesn't need it. +//////////////////////////////////////////////////////////////////// +void Character:: +force_update() { + // Statistics + PStatTimer timer(_app_char_pcollector); + + // First, update all the joints and sliders. + get_bundle()->force_update(); + + // Now update the vertices. + if (_computed_vertices != (ComputedVertices *)NULL) { + _computed_vertices->update(this); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Character::do_update +// Access: Private +// Description: The actual implementation of update(). Assumes the +// appropriate PStatCollector has already been started. +//////////////////////////////////////////////////////////////////// +void Character:: +do_update() { // First, update all the joints and sliders. bool any_changed; if (even_animation) { @@ -213,26 +256,6 @@ update() { } } -//////////////////////////////////////////////////////////////////// -// Function: Character::force_update -// Access: Published -// Description: Recalculates the character even if we think it -// doesn't need it. -//////////////////////////////////////////////////////////////////// -void Character:: -force_update() { - // Statistics - PStatTimer timer(_char_pcollector); - - // First, update all the joints and sliders. - get_bundle()->force_update(); - - // Now update the vertices. - if (_computed_vertices != (ComputedVertices *)NULL) { - _computed_vertices->update(this); - } -} - //////////////////////////////////////////////////////////////////// // Function: Character::copy_joints // Access: Private @@ -551,10 +574,12 @@ fillin(DatagramIterator &scan, BamReader *manager) { } #ifdef DO_PSTATS - // Reinitialize our collector with our name, now that we know it. + // Reinitialize our collectors with our name, now that we know it. if (has_name()) { - _char_pcollector = - PStatCollector(_anim_pcollector, get_name()); + _app_char_pcollector = + PStatCollector(PStatCollector(_app_animation_pcollector, get_name()), "Joints"); + _cull_char_pcollector = + PStatCollector(PStatCollector(_cull_animation_pcollector, get_name()), "Joints"); } #endif } diff --git a/panda/src/char/character.h b/panda/src/char/character.h index 8954a0749f..617fa29495 100644 --- a/panda/src/char/character.h +++ b/panda/src/char/character.h @@ -67,6 +67,7 @@ PUBLISHED: void force_update(); private: + void do_update(); void copy_joints(PartGroup *copy, PartGroup *orig); typedef pmap NodeMap; @@ -94,8 +95,10 @@ private: Parts _parts; // Statistics - PStatCollector _char_pcollector; - static PStatCollector _anim_pcollector; + PStatCollector _app_char_pcollector; + PStatCollector _cull_char_pcollector; + static PStatCollector _app_animation_pcollector; + static PStatCollector _cull_animation_pcollector; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/Sources.pp b/panda/src/gobj/Sources.pp index a9c4780db0..14be2e667e 100644 --- a/panda/src/gobj/Sources.pp +++ b/panda/src/gobj/Sources.pp @@ -36,6 +36,7 @@ qpgeomVertexDataType.h qpgeomVertexDataType.I \ qpgeomVertexFormat.h qpgeomVertexFormat.I \ qpgeomVertexReader.h qpgeomVertexReader.I \ + qpgeomVertexRewriter.h qpgeomVertexRewriter.I \ qpgeomVertexWriter.h qpgeomVertexWriter.I \ indexBufferContext.I indexBufferContext.h \ internalName.I internalName.h \ @@ -82,6 +83,7 @@ qpgeomVertexDataType.cxx \ qpgeomVertexFormat.cxx \ qpgeomVertexReader.cxx \ + qpgeomVertexRewriter.cxx \ qpgeomVertexWriter.cxx \ indexBufferContext.cxx \ material.cxx \ @@ -126,6 +128,7 @@ qpgeomVertexDataType.h qpgeomVertexDataType.I \ qpgeomVertexFormat.h qpgeomVertexFormat.I \ qpgeomVertexReader.h qpgeomVertexReader.I \ + qpgeomVertexRewriter.h qpgeomVertexRewriter.I \ qpgeomVertexWriter.h qpgeomVertexWriter.I \ indexBufferContext.I indexBufferContext.h \ internalName.I internalName.h \ diff --git a/panda/src/gobj/gobj_composite1.cxx b/panda/src/gobj/gobj_composite1.cxx index 23d169deb7..f33fa04dbc 100644 --- a/panda/src/gobj/gobj_composite1.cxx +++ b/panda/src/gobj/gobj_composite1.cxx @@ -28,4 +28,5 @@ #include "qpgeomVertexDataType.cxx" #include "qpgeomVertexFormat.cxx" #include "qpgeomVertexReader.cxx" +#include "qpgeomVertexRewriter.cxx" #include "qpgeomVertexWriter.cxx" diff --git a/panda/src/gobj/qpgeomVertexData.I b/panda/src/gobj/qpgeomVertexData.I index fd2d7afe9a..04c6f6718f 100644 --- a/panda/src/gobj/qpgeomVertexData.I +++ b/panda/src/gobj/qpgeomVertexData.I @@ -38,7 +38,10 @@ get_name() const { INLINE void qpGeomVertexData:: set_name(const string &name) { _name = name; - _this_animate_vertices_pcollector = PStatCollector(_animate_vertices_pcollector, name); + _app_char_pcollector = + PStatCollector(PStatCollector(_app_animation_pcollector, name), "Vertices"); + _cull_char_pcollector = + PStatCollector(PStatCollector(_cull_animation_pcollector, name), "Vertices"); } //////////////////////////////////////////////////////////////////// @@ -160,6 +163,43 @@ get_modified() const { return cdata->_modified; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::animate_vertices +// Access: Published +// Description: Returns a GeomVertexData that represents the results +// of computing the vertex animation on the CPU for this +// GeomVertexData. +// +// If there is no CPU-defined vertex animation on this +// object, this just returns the original object. +// +// If there is vertex animation, but the VertexTransform +// values have not changed since last time, this may +// return the same pointer it returned previously. Even +// if the VertexTransform values have changed, it may +// still return the same pointer, but with its contents +// modified (this is preferred, since it allows the +// graphics backend to update vertex buffers optimally). +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexData) qpGeomVertexData:: +animate_vertices() const { + return do_animate_vertices(true); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::animate_vertices_cull +// Access: Public +// Description: Does exactly the same thing as animate_vertices(), +// but when PStats is enabled, it records the time spent +// as during the cull step instead of the app step. +// This is intended to be called from the cull callback, +// rather the called directly by the user. +//////////////////////////////////////////////////////////////////// +INLINE CPT(qpGeomVertexData) qpGeomVertexData:: +animate_vertices_cull() const { + return do_animate_vertices(false); +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::pack_8888 // Access: Public, Static diff --git a/panda/src/gobj/qpgeomVertexData.cxx b/panda/src/gobj/qpgeomVertexData.cxx index 068f3a12e6..d49935634a 100644 --- a/panda/src/gobj/qpgeomVertexData.cxx +++ b/panda/src/gobj/qpgeomVertexData.cxx @@ -30,7 +30,8 @@ TypeHandle qpGeomVertexData::_type_handle; PStatCollector qpGeomVertexData::_convert_pcollector("Cull:Munge:Convert"); PStatCollector qpGeomVertexData::_scale_color_pcollector("Cull:Munge:Scale color"); PStatCollector qpGeomVertexData::_set_color_pcollector("Cull:Munge:Set color"); -PStatCollector qpGeomVertexData::_animate_vertices_pcollector("Cull:Animate vertices"); +PStatCollector qpGeomVertexData::_app_animation_pcollector("App:Animation"); +PStatCollector qpGeomVertexData::_cull_animation_pcollector("Cull:Animation"); //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::Default Constructor @@ -40,7 +41,8 @@ PStatCollector qpGeomVertexData::_animate_vertices_pcollector("Cull:Animate vert //////////////////////////////////////////////////////////////////// qpGeomVertexData:: qpGeomVertexData() : - _this_animate_vertices_pcollector(_animate_vertices_pcollector) + _app_char_pcollector(_app_animation_pcollector), + _cull_char_pcollector(_cull_animation_pcollector) { } @@ -56,7 +58,8 @@ qpGeomVertexData(const string &name, _name(name), _format(format), _usage_hint(usage_hint), - _this_animate_vertices_pcollector(_animate_vertices_pcollector, name) + _app_char_pcollector(PStatCollector(_app_animation_pcollector, name), "Vertices"), + _cull_char_pcollector(PStatCollector(_cull_animation_pcollector, name), "Vertices") { nassertv(_format->is_registered()); @@ -82,7 +85,8 @@ qpGeomVertexData(const qpGeomVertexData ©) : _name(copy._name), _format(copy._format), _cycler(copy._cycler), - _this_animate_vertices_pcollector(copy._this_animate_vertices_pcollector) + _app_char_pcollector(copy._app_char_pcollector), + _cull_char_pcollector(copy._cull_char_pcollector) { } @@ -97,7 +101,8 @@ operator = (const qpGeomVertexData ©) { _name = copy._name; _format = copy._format; _cycler = copy._cycler; - _this_animate_vertices_pcollector = copy._this_animate_vertices_pcollector; + _app_char_pcollector = copy._app_char_pcollector; + _cull_char_pcollector = copy._cull_char_pcollector; } //////////////////////////////////////////////////////////////////// @@ -374,10 +379,10 @@ convert_to(const qpGeomVertexFormat *new_format) const { << "generic copy " << *new_data_type << " from " << *data_type << "\n"; } - qpGeomVertexReader from(this); - from.set_data_type(i, data_type); qpGeomVertexWriter to(new_data); to.set_data_type(new_i, new_data_type); + qpGeomVertexReader from(this); + from.set_data_type(i, data_type); while (!from.is_at_end()) { to.set_data4f(from.get_data4f()); @@ -424,8 +429,8 @@ scale_color(const LVecBase4f &color_scale, int num_components, contents, get_usage_hint(), true); // Now go through and apply the scale, copying it to the new data. - qpGeomVertexReader from(this, InternalName::get_color()); qpGeomVertexWriter to(new_data, InternalName::get_color()); + qpGeomVertexReader from(this, InternalName::get_color()); for (int i = 0; i < num_vertices; i++) { Colorf color = from.get_data4f(); @@ -475,49 +480,6 @@ set_color(const Colorf &color, int num_components, return new_data; } -//////////////////////////////////////////////////////////////////// -// Function: qpGeomVertexData::animate_vertices -// Access: Published -// Description: Returns a GeomVertexData that represents the results -// of computing the vertex animation on the CPU for this -// GeomVertexData. -// -// If there is no CPU-defined vertex animation on this -// object, this just returns the original object. -// -// If there is vertex animation, but the VertexTransform -// values have not changed since last time, this may -// return the same pointer it returned previously. Even -// if the VertexTransform values have changed, it may -// still return the same pointer, but with its contents -// modified (this is preferred, since it allows the -// graphics backend to update vertex buffers optimally). -//////////////////////////////////////////////////////////////////// -CPT(qpGeomVertexData) qpGeomVertexData:: -animate_vertices() const { - CDReader cdata(_cycler); - if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) { - // No vertex animation. - return this; - } - - if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) { - CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); - ((qpGeomVertexData *)this)->make_animated_vertices(cdataw); - return cdataw->_animated_vertices; - } else { - UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified(); - if (cdata->_animated_vertices_modified == blend_modified) { - // No changes. - return cdata->_animated_vertices; - } - CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); - cdataw->_animated_vertices_modified = blend_modified; - ((qpGeomVertexData *)this)->update_animated_vertices(cdataw); - return cdataw->_animated_vertices; - } -} - //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::replace_data_type // Access: Published @@ -673,6 +635,38 @@ get_array_info(const InternalName *name, return false; } +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexData::do_animate_vertices +// Access: Private +// Description: This is the private implementation of +// animate_vertices() and animate_vertices_cull(). +//////////////////////////////////////////////////////////////////// +CPT(qpGeomVertexData) qpGeomVertexData:: +do_animate_vertices(bool from_app) const { + CDReader cdata(_cycler); + if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) { + // No vertex animation. + return this; + } + + if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) { + CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); + ((qpGeomVertexData *)this)->make_animated_vertices(cdataw); + ((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app); + return cdataw->_animated_vertices; + } else { + UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified(); + if (cdata->_animated_vertices_modified == blend_modified) { + // No changes. + return cdata->_animated_vertices; + } + CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata); + cdataw->_animated_vertices_modified = blend_modified; + ((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app); + return cdataw->_animated_vertices; + } +} + //////////////////////////////////////////////////////////////////// // Function: qpGeomVertexData::bytewise_copy // Access: Private, Static @@ -807,9 +801,6 @@ make_animated_vertices(qpGeomVertexData::CDWriter &cdata) { (InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16, qpGeomVertexDataType::C_index, min(get_usage_hint(), qpGeomUsageHint::UH_dynamic), false); - - // Now fill it up with the appropriate data. - update_animated_vertices(cdata); } //////////////////////////////////////////////////////////////////// @@ -820,7 +811,7 @@ make_animated_vertices(qpGeomVertexData::CDWriter &cdata) { // existing animated_vertices object. //////////////////////////////////////////////////////////////////// void qpGeomVertexData:: -update_animated_vertices(qpGeomVertexData::CDWriter &cdata) { +update_animated_vertices(qpGeomVertexData::CDWriter &cdata, bool from_app) { int num_vertices = get_num_vertices(); if (gobj_cat.is_debug()) { @@ -829,12 +820,16 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata) { << "\n"; } - PStatTimer timer(_this_animate_vertices_pcollector); +#ifdef DO_PSTATS + PStatCollector &collector = from_app ? _app_char_pcollector : _cull_char_pcollector; + PStatTimer timer(collector); +#endif CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette; nassertv(palette != (TransformBlendPalette *)NULL); - // Recompute all the blends up front. + // Recompute all the blends up front, so we don't have to test each + // one for staleness at each vertex. int num_blends = palette->get_num_blends(); int bi; for (bi = 0; bi < num_blends; bi++) { @@ -843,10 +838,10 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata) { PT(qpGeomVertexData) new_data = cdata->_animated_vertices; - // Now go through and apply the scale, copying it to the new data. + // Now go through and compute the animation. + qpGeomVertexWriter to(new_data, InternalName::get_vertex()); qpGeomVertexReader from(this, InternalName::get_vertex()); qpGeomVertexReader blendi(this, InternalName::get_transform_blend()); - qpGeomVertexWriter to(new_data, InternalName::get_vertex()); if (from.get_data_type()->get_num_values() == 4) { for (int i = 0; i < num_vertices; i++) { diff --git a/panda/src/gobj/qpgeomVertexData.h b/panda/src/gobj/qpgeomVertexData.h index 71ac91b4ea..65650deae8 100644 --- a/panda/src/gobj/qpgeomVertexData.h +++ b/panda/src/gobj/qpgeomVertexData.h @@ -104,7 +104,7 @@ PUBLISHED: qpGeomVertexDataType::NumericType numeric_type, qpGeomVertexDataType::Contents contents) const; - CPT(qpGeomVertexData) animate_vertices() const; + INLINE CPT(qpGeomVertexData) animate_vertices() const; PT(qpGeomVertexData) replace_data_type(const InternalName *name, int num_components, @@ -117,6 +117,8 @@ PUBLISHED: void write(ostream &out, int indent_level = 0) const; public: + INLINE CPT(qpGeomVertexData) animate_vertices_cull() const; + bool get_array_info(const InternalName *name, const qpGeomVertexArrayData *&array_data, int &num_components, @@ -131,6 +133,8 @@ public: static INLINE unsigned int unpack_8888_d(PN_uint32 data); private: + CPT(qpGeomVertexData) do_animate_vertices(bool from_app) const; + static void bytewise_copy(unsigned char *to, int to_stride, const unsigned char *from, int from_stride, const qpGeomVertexDataType *from_type, @@ -175,14 +179,16 @@ private: private: bool do_set_num_vertices(int n, CDWriter &cdata); void make_animated_vertices(CDWriter &cdata); - void update_animated_vertices(CDWriter &cdata); + void update_animated_vertices(CDWriter &cdata, bool from_app); static PStatCollector _convert_pcollector; static PStatCollector _scale_color_pcollector; static PStatCollector _set_color_pcollector; - static PStatCollector _animate_vertices_pcollector; + static PStatCollector _app_animation_pcollector; + static PStatCollector _cull_animation_pcollector; - PStatCollector _this_animate_vertices_pcollector; + PStatCollector _app_char_pcollector; + PStatCollector _cull_char_pcollector; public: static void register_with_read_factory(); diff --git a/panda/src/gobj/qpgeomVertexReader.I b/panda/src/gobj/qpgeomVertexReader.I index e9b01d0016..8800cbc3cd 100644 --- a/panda/src/gobj/qpgeomVertexReader.I +++ b/panda/src/gobj/qpgeomVertexReader.I @@ -331,8 +331,7 @@ set_pointer(int vertex) { nassertv(_data_type != (qpGeomVertexDataType *)NULL); _read_vertex = vertex; CPT(qpGeomVertexArrayData) array_data = _vertex_data->get_array(_array); - _data = array_data->get_data(); - _pointer = _data.p() + _data_type->get_start() + _stride * _read_vertex; + _pointer = array_data->get_data() + _data_type->get_start() + _stride * _read_vertex; _num_vertices = array_data->get_num_vertices(); } @@ -345,7 +344,7 @@ set_pointer(int vertex) { INLINE const unsigned char *qpGeomVertexReader:: inc_pointer() { nassertr(_read_vertex < _num_vertices, NULL); - nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _read_vertex, NULL); + nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _data_type->get_start() + _stride * _read_vertex, NULL); const unsigned char *orig_pointer = _pointer; _pointer += _stride; diff --git a/panda/src/gobj/qpgeomVertexReader.h b/panda/src/gobj/qpgeomVertexReader.h index 0de178e227..0d4c0c6a0d 100644 --- a/panda/src/gobj/qpgeomVertexReader.h +++ b/panda/src/gobj/qpgeomVertexReader.h @@ -40,6 +40,22 @@ // for each vertex, it is faster to use a different // GeomVertexReader for each data type. // +// Note that a GeomVertexReader does not keep a +// reference count to the actual vertex data buffer (it +// grabs the current data buffer from the GeomVertexData +// whenever set_data_type() is called). This means that +// it is important not to keep a GeomVertexReader object +// around over a long period of time in which the data +// buffer is likely to be deallocated; it is intended +// for making a quick pass over the data in one session. +// +// It also means that you should create any +// GeomVertexWriters *before* creating GeomVertexReaders +// on the same data, since the writer itself might cause +// the vertex buffer to be deallocated. Better yet, use +// a GeomVertexRewriter if you are going to create both +// of them anyway. +// // This is part of the experimental Geom rewrite. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomVertexReader { @@ -88,7 +104,6 @@ private: const qpGeomVertexDataType *_data_type; int _stride; - CPTA_uchar _data; const unsigned char *_pointer; int _start_vertex; diff --git a/panda/src/gobj/qpgeomVertexRewriter.I b/panda/src/gobj/qpgeomVertexRewriter.I new file mode 100644 index 0000000000..6066e21909 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexRewriter.I @@ -0,0 +1,261 @@ +// Filename: qpgeomVertexRewriter.I +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Constructor +// Access: Published +// Description: Constructs a new rewriter to process the vertices of +// the indicated data object. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +qpGeomVertexRewriter(qpGeomVertexData *vertex_data) : + qpGeomVertexWriter(vertex_data), + qpGeomVertexReader(vertex_data) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Constructor +// Access: Published +// Description: Constructs a new rewriter to process the vertices of +// the indicated data object. This flavor creates the +// rewriter specifically to process the named data type. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +qpGeomVertexRewriter(qpGeomVertexData *vertex_data, const string &name) : + qpGeomVertexWriter(vertex_data), + qpGeomVertexReader(vertex_data) +{ + set_data_type(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Constructor +// Access: Published +// Description: Constructs a new rewriter to process the vertices of +// the indicated data object. This flavor creates the +// rewriter specifically to process the named data type. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +qpGeomVertexRewriter(qpGeomVertexData *vertex_data, const InternalName *name) : + qpGeomVertexWriter(vertex_data), + qpGeomVertexReader(vertex_data) +{ + set_data_type(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::Destructor +// Access: Published +// Description: +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexRewriter:: +~qpGeomVertexRewriter() { +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_vertex_data +// Access: Published +// Description: Returns the vertex data object that the +// rewriter is processing. +//////////////////////////////////////////////////////////////////// +INLINE qpGeomVertexData *qpGeomVertexRewriter:: +get_vertex_data() const { + nassertr(qpGeomVertexWriter::get_vertex_data() == + qpGeomVertexReader::get_vertex_data(), NULL); + return qpGeomVertexWriter::get_vertex_data(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::set_data_type +// Access: Published +// Description: Sets up the rewriter to use the nth data type of the +// GeomVertexFormat, numbering from 0. +// +// This also resets both the read and write vertex +// numbers to the start vertex (the same value passed to +// a previous call to set_vertex(), or 0 if set_vertex() +// was never called.) +// +// The return value is true if the data type is valid, +// false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexRewriter:: +set_data_type(int data_type) { + // It's important to invoke the writer first, then the reader. See + // set_vertex(). + qpGeomVertexWriter::set_data_type(data_type); + return qpGeomVertexReader::set_data_type(data_type); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::set_data_type +// Access: Published +// Description: Sets up the rewriter to use the data type with the +// indicated name. +// +// This also resets both the read and write vertex +// numbers to the start vertex (the same value passed to +// a previous call to set_vertex(), or 0 if set_vertex() +// was never called.) +// +// The return value is true if the data type is valid, +// false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexRewriter:: +set_data_type(const string &name) { + return set_data_type(InternalName::make(name)); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::set_data_type +// Access: Published +// Description: Sets up the rewriter to use the data type with the +// indicated name. +// +// This also resets both the read and write vertex +// numbers to the start vertex (the same value passed to +// a previous call to set_vertex(), or 0 if set_vertex() +// was never called.) +// +// The return value is true if the data type is valid, +// false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexRewriter:: +set_data_type(const InternalName *name) { + // It's important to invoke the writer first, then the reader. See + // set_vertex(). + qpGeomVertexWriter::set_data_type(name); + return qpGeomVertexReader::set_data_type(name); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::set_data_type +// Access: Published +// Description: Sets up the rewriter to use the indicated data_type +// description on the given array. +// +// This also resets both the read and write vertex +// numbers to the start vertex (the same value passed to +// a previous call to set_vertex(), or 0 if set_vertex() +// was never called.) +// +// The return value is true if the data type is valid, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool qpGeomVertexRewriter:: +set_data_type(int array, const qpGeomVertexDataType *data_type) { + // It's important to invoke the writer first, then the reader. See + // set_vertex(). + qpGeomVertexWriter::set_data_type(array, data_type); + return qpGeomVertexReader::set_data_type(array, data_type); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::has_data_type +// Access: Published +// Description: Returns true if a valid data type has been +// successfully set, or false if the data type does not +// exist. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexRewriter:: +has_data_type() const { + nassertr(qpGeomVertexWriter::get_data_type() == + qpGeomVertexReader::get_data_type(), false); + return qpGeomVertexWriter::has_data_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_array +// Access: Published +// Description: Returns the array index containing the data type that +// the rewriter is working on. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexRewriter:: +get_array() const { + nassertr(qpGeomVertexWriter::get_array() == + qpGeomVertexReader::get_array(), -1); + return qpGeomVertexWriter::get_array(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_data_type +// Access: Published +// Description: Returns the description of the data type that the +// rewriter is working on. +//////////////////////////////////////////////////////////////////// +INLINE const qpGeomVertexDataType *qpGeomVertexRewriter:: +get_data_type() const { + nassertr(qpGeomVertexWriter::get_data_type() == + qpGeomVertexReader::get_data_type(), NULL); + return qpGeomVertexWriter::get_data_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::set_vertex +// Access: Published +// Description: Sets the start, write, and write index to the +// indicated value. The rewriter will begin traversing +// from the given vertex. +//////////////////////////////////////////////////////////////////// +INLINE void qpGeomVertexRewriter:: +set_vertex(int vertex) { + // It's important to invoke the Writer first, since that might force + // a recopy of the array, which might invalidate the pointer already + // stored by the Reader if we invoked the Reader first. + qpGeomVertexWriter::set_vertex(vertex); + qpGeomVertexReader::set_vertex(vertex); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_start_vertex +// Access: Published +// Description: Returns the vertex index at which the rewriter +// started. It will return to this vertex if you reset +// the current data_type. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexRewriter:: +get_start_vertex() const { + nassertr(qpGeomVertexWriter::get_start_vertex() == + qpGeomVertexReader::get_start_vertex(), 0); + return qpGeomVertexWriter::get_start_vertex(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::get_num_vertices +// Access: Published +// Description: Returns the number of vertices in the vertex data. +//////////////////////////////////////////////////////////////////// +INLINE int qpGeomVertexRewriter:: +get_num_vertices() const { + nassertr(qpGeomVertexWriter::get_num_vertices() == + qpGeomVertexReader::get_num_vertices(), 0); + return qpGeomVertexWriter::get_num_vertices(); +} + +//////////////////////////////////////////////////////////////////// +// Function: qpGeomVertexRewriter::is_at_end +// Access: Published +// Description: Returns true if the reader or writer is currently at +// the end of the list of vertices, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool qpGeomVertexRewriter:: +is_at_end() const { + return qpGeomVertexWriter::is_at_end() || qpGeomVertexReader::is_at_end(); +} diff --git a/panda/src/gobj/qpgeomVertexRewriter.cxx b/panda/src/gobj/qpgeomVertexRewriter.cxx new file mode 100644 index 0000000000..43cd8c4776 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexRewriter.cxx @@ -0,0 +1,19 @@ +// Filename: qpgeomVertexRewriter.cxx +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "qpgeomVertexRewriter.h" diff --git a/panda/src/gobj/qpgeomVertexRewriter.h b/panda/src/gobj/qpgeomVertexRewriter.h new file mode 100644 index 0000000000..9f85256059 --- /dev/null +++ b/panda/src/gobj/qpgeomVertexRewriter.h @@ -0,0 +1,73 @@ +// Filename: qpgeomVertexRewriter.h +// Created by: drose (28Mar05) +// +//////////////////////////////////////////////////////////////////// +// +// 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 +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef qpGEOMVERTEXREWRITER_H +#define qpGEOMVERTEXREWRITER_H + +#include "pandabase.h" +#include "qpgeomVertexReader.h" +#include "qpgeomVertexWriter.h" + +//////////////////////////////////////////////////////////////////// +// Class : qpGeomVertexRewriter +// Description : This object provides the functionality of both a +// GeomVertexReader and a GeomVertexWriter, combined +// together into one convenient package. It is designed +// for making a single pass over a GeomVertexData +// object, modifying vertices as it goes. +// +// Although it doesn't provide any real performance +// benefit over using a separate reader and writer +// object, it should probably be used in preference to +// separate objects, because it makes an effort to +// manage the reference counts properly between the +// reader and the writer to avoid accidentally +// dereferencing either array while recopying. +// +// This is part of the experimental Geom rewrite. +//////////////////////////////////////////////////////////////////// +class EXPCL_PANDA qpGeomVertexRewriter : public qpGeomVertexWriter, public qpGeomVertexReader { +PUBLISHED: + INLINE qpGeomVertexRewriter(qpGeomVertexData *vertex_data); + INLINE qpGeomVertexRewriter(qpGeomVertexData *vertex_data, + const string &name); + INLINE qpGeomVertexRewriter(qpGeomVertexData *vertex_data, + const InternalName *name); + INLINE ~qpGeomVertexRewriter(); + + INLINE qpGeomVertexData *get_vertex_data() const; + + INLINE bool set_data_type(int data_type); + INLINE bool set_data_type(const string &name); + INLINE bool set_data_type(const InternalName *name); + INLINE bool set_data_type(int array, const qpGeomVertexDataType *data_type); + + INLINE bool has_data_type() const; + INLINE int get_array() const; + INLINE const qpGeomVertexDataType *get_data_type() const; + + INLINE void set_vertex(int vertex); + + INLINE int get_start_vertex() const; + INLINE int get_num_vertices() const; + INLINE bool is_at_end() const; +}; + +#include "qpgeomVertexRewriter.I" + +#endif diff --git a/panda/src/gobj/qpgeomVertexWriter.I b/panda/src/gobj/qpgeomVertexWriter.I index 048577614e..77433cc05f 100644 --- a/panda/src/gobj/qpgeomVertexWriter.I +++ b/panda/src/gobj/qpgeomVertexWriter.I @@ -500,8 +500,7 @@ set_pointer(int vertex) { nassertv(_data_type != (qpGeomVertexDataType *)NULL); _write_vertex = vertex; PT(qpGeomVertexArrayData) array_data = _vertex_data->modify_array(_array); - _data = array_data->modify_data(); - _pointer = _data.p() + _data_type->get_start() + _stride * _write_vertex; + _pointer = array_data->modify_data() + _data_type->get_start() + _stride * _write_vertex; _num_vertices = array_data->get_num_vertices(); } @@ -514,7 +513,7 @@ set_pointer(int vertex) { INLINE unsigned char *qpGeomVertexWriter:: inc_pointer() { nassertr(_write_vertex < _num_vertices, NULL); - nassertr(_pointer == _vertex_data->get_array(_array)->get_data().p() + _data_type->get_start() + _stride * _write_vertex, NULL); + nassertr(_pointer == _vertex_data->get_array(_array)->get_data() + _data_type->get_start() + _stride * _write_vertex, NULL); unsigned char *orig_pointer = _pointer; _pointer += _stride; diff --git a/panda/src/gobj/qpgeomVertexWriter.h b/panda/src/gobj/qpgeomVertexWriter.h index 75c8180566..4bfdfd93db 100644 --- a/panda/src/gobj/qpgeomVertexWriter.h +++ b/panda/src/gobj/qpgeomVertexWriter.h @@ -53,6 +53,21 @@ // vertex, it is faster to use a different // GeomVertexWriter for each data type. // +// Note that, like a GeomVertexReader, a +// GeomVertexWriter does not keep a reference count to +// the actual vertex data buffer. This means that it is +// important not to keep a GeomVertexWriter object +// around over a long period of time in which the data +// buffer is likely to be deallocated; it is intended +// for making a quick pass over the data in one session. +// +// It also means that you should create any +// GeomVertexWriters *before* creating GeomVertexReaders +// on the same data, since the writer itself might cause +// the vertex buffer to be deallocated. Better yet, use +// a GeomVertexRewriter if you are going to create both +// of them anyway. +// // This is part of the experimental Geom rewrite. //////////////////////////////////////////////////////////////////// class EXPCL_PANDA qpGeomVertexWriter { @@ -115,7 +130,6 @@ private: const qpGeomVertexDataType *_data_type; int _stride; - PTA_uchar _data; unsigned char *_pointer; int _start_vertex; diff --git a/panda/src/pgraph/cullableObject.cxx b/panda/src/pgraph/cullableObject.cxx index c5c897af7b..1e99f9ed2e 100644 --- a/panda/src/pgraph/cullableObject.cxx +++ b/panda/src/pgraph/cullableObject.cxx @@ -38,7 +38,7 @@ munge_geom(const qpGeomMunger *munger) { _munger = munger; CPT(qpGeom) qpgeom = DCAST(qpGeom, _geom); qpgeom->munge_geom(munger, qpgeom, _munged_data); - _munged_data = _munged_data->animate_vertices(); + _munged_data = _munged_data->animate_vertices_cull(); _geom = qpgeom; } }