VertexRewriter; animation stats in cull

This commit is contained in:
David Rose 2005-03-28 16:15:26 +00:00
parent 048f90a297
commit 29d51a723b
15 changed files with 557 additions and 104 deletions

View File

@ -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 &copy) :
_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 &copy) :
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
}

View File

@ -67,6 +67,7 @@ PUBLISHED:
void force_update();
private:
void do_update();
void copy_joints(PartGroup *copy, PartGroup *orig);
typedef pmap<const PandaNode *, PandaNode *> 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();

View File

@ -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 \

View File

@ -28,4 +28,5 @@
#include "qpgeomVertexDataType.cxx"
#include "qpgeomVertexFormat.cxx"
#include "qpgeomVertexReader.cxx"
#include "qpgeomVertexRewriter.cxx"
#include "qpgeomVertexWriter.cxx"

View File

@ -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

View File

@ -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 &copy) :
_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 &copy) {
_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++) {

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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();
}

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}