beginning morph animations

This commit is contained in:
David Rose 2005-03-28 22:24:04 +00:00
parent bc56b6467b
commit 19ef896a9b
26 changed files with 1757 additions and 184 deletions

View File

@ -50,9 +50,10 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
const qpGeomVertexDataType *color_type =
format->get_data_type(InternalName::get_color());
if (color_type != (qpGeomVertexDataType *)NULL &&
color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_8888) {
(color_type->get_numeric_type() == qpGeomVertexDataType::NT_packed_8888 ||
color_type->get_contents() != qpGeomVertexDataType::NT_rgba)) {
// We need to convert the color format; OpenGL doesn't support the
// byte order of DirectX's packed_argb format.
// byte order of DirectX's packed ARGB format.
int color_array = format->get_array_with(InternalName::get_color());
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*format);

View File

@ -2676,7 +2676,7 @@ prepare_index_buffer(qpGeomPrimitive *data) {
if (GLCAT.is_debug()) {
GLCAT.debug()
<< "creating vertex buffer " << gibc->_index << "\n";
<< "creating index buffer " << gibc->_index << "\n";
}
report_my_gl_errors();

View File

@ -47,6 +47,7 @@
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
savedContext.I savedContext.h \
sliderTable.I sliderTable.h \
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
@ -54,8 +55,10 @@
transformBlend.I transformBlend.h \
transformBlendPalette.I transformBlendPalette.h \
transformPalette.I transformPalette.h \
userVertexSlider.I userVertexSlider.h \
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexSlider.I vertexSlider.h \
vertexTransform.I vertexTransform.h
#define INCLUDED_SOURCES \
@ -92,13 +95,17 @@
perspectiveLens.cxx \
preparedGraphicsObjects.cxx \
lens.cxx \
savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \
savedContext.cxx \
sliderTable.cxx \
texture.cxx textureContext.cxx texturePool.cxx \
textureStage.cxx \
transformBlend.cxx \
transformBlendPalette.cxx \
transformPalette.cxx \
userVertexSlider.cxx \
userVertexTransform.cxx \
vertexBufferContext.cxx \
vertexSlider.cxx \
vertexTransform.cxx
#define INSTALL_HEADERS \
@ -139,6 +146,7 @@
preparedGraphicsObjects.I preparedGraphicsObjects.h \
lens.h lens.I \
savedContext.I savedContext.h \
sliderTable.I sliderTable.h \
texture.I texture.h \
textureContext.I textureContext.h \
texturePool.I texturePool.h \
@ -146,8 +154,10 @@
transformBlend.I transformBlend.h \
transformBlendPalette.I transformBlendPalette.h \
transformPalette.I transformPalette.h \
userVertexSlider.I userVertexSlider.h \
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexSlider.I vertexSlider.h \
vertexTransform.I vertexTransform.h

View File

@ -40,13 +40,16 @@
#include "matrixLens.h"
#include "perspectiveLens.h"
#include "lens.h"
#include "sliderTable.h"
#include "texture.h"
#include "textureStage.h"
#include "textureContext.h"
#include "transformBlendPalette.h"
#include "transformPalette.h"
#include "userVertexSlider.h"
#include "userVertexTransform.h"
#include "vertexTransform.h"
#include "vertexSlider.h"
#include "geomContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
@ -212,13 +215,16 @@ ConfigureFn(config_gobj) {
MatrixLens::init_type();
PerspectiveLens::init_type();
Lens::init_type();
SliderTable::init_type();
Texture::init_type();
dDrawable::init_type();
TextureStage::init_type();
TransformBlendPalette::init_type();
TransformPalette::init_type();
UserVertexSlider::init_type();
UserVertexTransform::init_type();
VertexTransform::init_type();
VertexSlider::init_type();
InternalName::init_type();
//Registration of writeable object's creation
@ -248,10 +254,12 @@ ConfigureFn(config_gobj) {
OrthographicLens::register_with_read_factory();
MatrixLens::register_with_read_factory();
PerspectiveLens::register_with_read_factory();
SliderTable::register_with_read_factory();
Texture::register_with_read_factory();
TextureStage::register_with_read_factory();
TransformBlendPalette::register_with_read_factory();
TransformPalette::register_with_read_factory();
UserVertexSlider::register_with_read_factory();
UserVertexTransform::register_with_read_factory();
InternalName::register_with_read_factory();
}

View File

@ -12,6 +12,7 @@
#include "perspectiveLens.cxx"
#include "preparedGraphicsObjects.cxx"
#include "savedContext.cxx"
#include "sliderTable.cxx"
#include "texture.cxx"
#include "textureContext.cxx"
#include "texturePool.cxx"
@ -19,6 +20,8 @@
#include "transformBlend.cxx"
#include "transformBlendPalette.cxx"
#include "transformPalette.cxx"
#include "userVertexSlider.cxx"
#include "userVertexTransform.cxx"
#include "vertexBufferContext.cxx"
#include "vertexSlider.cxx"
#include "vertexTransform.cxx"

View File

@ -111,6 +111,74 @@ get_name() const {
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::find_ancestor
// Access: Published
// Description: Returns the index of the ancestor with the indicated
// basename, or -1 if no ancestor has that basename.
// Returns 0 if this name has the basename.
//
// This index value may be passed to get_ancestor() or
// get_net_basename() to retrieve more information about
// the indicated name.
////////////////////////////////////////////////////////////////////
int InternalName::
find_ancestor(const string &basename) const {
if (_basename == basename) {
return 0;
} else if (_parent != (InternalName *)NULL) {
int index = _parent->find_ancestor(basename);
if (index >= 0) {
return index + 1;
}
}
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_ancestor
// Access: Published
// Description: Returns the ancestor with the indicated index number.
// 0 is this name itself, 1 is the name's parent, 2 is
// the parent's parent, and so on. If there are not
// enough ancestors, returns the root InternalName.
////////////////////////////////////////////////////////////////////
const InternalName *InternalName::
get_ancestor(int n) const {
if (n == 0) {
return this;
} else if (_parent != (InternalName *)NULL) {
return _parent->get_ancestor(n - 1);
} else {
return get_root();
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_net_basename
// Access: Published
// Description: Returns the basename of this name prefixed by the
// indicated number of ancestors. 0 is this name's
// basename, 1 is parent.basename, 2 is
// grandparent.parent.basename, and so on.
////////////////////////////////////////////////////////////////////
string InternalName::
get_net_basename(int n) const {
if (n == 0) {
return _basename;
} else if (_parent != (InternalName *)NULL && _parent != get_root()) {
return _parent->get_net_basename(n - 1) + "." + _basename;
} else {
return _basename;
}
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::output
// Access: Published

View File

@ -55,6 +55,10 @@ PUBLISHED:
string get_name() const;
INLINE const string &get_basename() const;
int find_ancestor(const string &basename) const;
const InternalName *get_ancestor(int n) const;
string get_net_basename(int n) const;
void output(ostream &out) const;
// Some predefined built-in names.

View File

@ -150,6 +150,35 @@ clear_transform_blend_palette() {
set_transform_blend_palette(NULL);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_slider_table
// Access: Published
// Description: Returns a const pointer to the SliderTable
// assigned to this data. Vertices within the vertex
// data will look up their morph offsets, if any, within
// this table.
//
// This will return NULL if the vertex data does not
// have a SliderTable assigned.
////////////////////////////////////////////////////////////////////
INLINE const SliderTable *qpGeomVertexData::
get_slider_table() const {
CDReader cdata(_cycler);
return cdata->_slider_table;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::clear_slider_table
// Access: Published
// Description: Sets the SliderTable pointer to NULL,
// removing the table from the vertex data. This
// disables morph (blend shape) animation.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexData::
clear_slider_table() {
set_slider_table(NULL);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_modified
// Access: Published

View File

@ -19,6 +19,7 @@
#include "qpgeomVertexData.h"
#include "qpgeomVertexReader.h"
#include "qpgeomVertexWriter.h"
#include "qpgeomVertexRewriter.h"
#include "pStatTimer.h"
#include "bamReader.h"
#include "bamWriter.h"
@ -241,6 +242,51 @@ set_transform_blend_palette(const TransformBlendPalette *palette) {
cdata->_animated_vertices_modified = UpdateSeq();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::modify_slider_table
// Access: Published
// Description: Returns a modifiable pointer to the current
// SliderTable on this vertex data, if any, or
// NULL if there is not a SliderTable. See
// get_slider_table().
////////////////////////////////////////////////////////////////////
SliderTable *qpGeomVertexData::
modify_slider_table() {
// Perform copy-on-write: if the reference count on the table is
// greater than 1, assume some other GeomVertexData has the same
// pointer, so make a copy of it first.
CDWriter cdata(_cycler);
if (cdata->_slider_table->get_ref_count() > 1) {
cdata->_slider_table = new SliderTable(*cdata->_slider_table);
}
cdata->_modified = qpGeom::get_next_modified();
cdata->_animated_vertices_modified = UpdateSeq();
return cdata->_slider_table;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_slider_table
// Access: Published
// Description: Replaces the SliderTable on this vertex
// data with the indicated table. There should be an
// entry in this table for each kind of morph offset
// defined in the vertex data.
//
// The SliderTable object must have been registered
// prior to setting it on the GeomVertexData.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_slider_table(const SliderTable *table) {
nassertv(table == (SliderTable *)NULL || table->is_registered());
CDWriter cdata(_cycler);
cdata->_slider_table = (SliderTable *)table;
cdata->_modified = qpGeom::get_next_modified();
cdata->_animated_vertices_modified = UpdateSeq();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_num_bytes
// Access: Published
@ -261,13 +307,149 @@ get_num_bytes() const {
return num_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::copy_from
// Access: Published
// Description: Copies all the data from the other array into the
// corresponding data types in this array, by matching
// data types name-by-name.
//
// keep_data_objects specifies what to do when one or
// more of the arrays can be copied without the need to
// apply any conversion operation. If it is true, the
// original GeomVertexArrayData objects in this object
// are retained, but their data arrays are copied
// pointerwise from the source; if it is false, then the
// GeomVertexArrayData objects themselves are copied
// pointerwise from the source.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
copy_from(const qpGeomVertexData &source, bool keep_data_objects) {
const qpGeomVertexFormat *source_format = source.get_format();
const qpGeomVertexFormat *dest_format = get_format();
int num_vertices = source.get_num_vertices();
int num_arrays = source_format->get_num_arrays();
int source_i;
// First, check to see if any arrays can be simply appropriated for
// the new format, without changing the data.
pset<int> done_arrays;
for (source_i = 0; source_i < num_arrays; ++source_i) {
const qpGeomVertexArrayFormat *source_array_format =
source_format->get_array(source_i);
bool array_done = false;
int dest_num_arrays = dest_format->get_num_arrays();
for (int dest_i = 0;
dest_i < dest_num_arrays && !array_done;
++dest_i) {
const qpGeomVertexArrayFormat *dest_array_format =
dest_format->get_array(dest_i);
if (dest_array_format->is_data_subset_of(*source_array_format)) {
// Great! Just use the same data for this one.
if (keep_data_objects) {
// Copy the data, but keep the same GeomVertexArrayData object.
// Maybe it even has the same data pointer already. If so,
// avoid flipping the modified flag.
CPTA_uchar source_data = source.get_array(source_i)->get_data();
if (get_array(dest_i)->get_data() != source_data) {
modify_array(dest_i)->set_data(source_data);
}
} else {
// Copy the GeomVertexArrayData object.
if (get_array(dest_i) != source.get_array(source_i)) {
set_array(dest_i, source.get_array(source_i));
}
}
array_done = true;
done_arrays.insert(dest_i);
}
}
}
// Now make sure the arrays we didn't share are all filled in.
set_num_vertices(num_vertices);
// Now go back through and copy any data that's left over.
for (source_i = 0; source_i < num_arrays; ++source_i) {
CPTA_uchar array_data = source.get_array(source_i)->get_data();
const qpGeomVertexArrayFormat *source_array_format = source_format->get_array(source_i);
int num_data_types = source_array_format->get_num_data_types();
for (int di = 0; di < num_data_types; ++di) {
const qpGeomVertexDataType *source_data_type = source_array_format->get_data_type(di);
int dest_i = dest_format->get_array_with(source_data_type->get_name());
if (dest_i >= 0 && done_arrays.count(dest_i) == 0) {
// The data type exists in the new format; we have to copy it.
const qpGeomVertexArrayFormat *dest_array_format =
dest_format->get_array(dest_i);
const qpGeomVertexDataType *dest_data_type =
dest_array_format->get_data_type(source_data_type->get_name());
if (dest_data_type->is_bytewise_equivalent(*source_data_type)) {
// We can do a quick bytewise copy.
PTA_uchar dest_array_data = modify_array(dest_i)->modify_data();
bytewise_copy(dest_array_data + dest_data_type->get_start(),
dest_array_format->get_stride(),
array_data + source_data_type->get_start(), source_array_format->get_stride(),
source_data_type, num_vertices);
} else if (dest_data_type->is_packed_argb() &&
source_data_type->is_uint8_rgba()) {
// A common special case: OpenGL color to DirectX color.
PTA_uchar dest_array_data = modify_array(dest_i)->modify_data();
uint8_rgba_to_packed_argb
(dest_array_data + dest_data_type->get_start(),
dest_array_format->get_stride(),
array_data + source_data_type->get_start(), source_array_format->get_stride(),
num_vertices);
} else if (dest_data_type->is_uint8_rgba() &&
source_data_type->is_packed_argb()) {
// Another common special case: DirectX color to OpenGL
// color.
PTA_uchar dest_array_data = modify_array(dest_i)->modify_data();
packed_argb_to_uint8_rgba
(dest_array_data + dest_data_type->get_start(),
dest_array_format->get_stride(),
array_data + source_data_type->get_start(), source_array_format->get_stride(),
num_vertices);
} else {
// A generic copy.
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "generic copy " << *dest_data_type << " from "
<< *source_data_type << "\n";
}
qpGeomVertexWriter to(this);
to.set_data_type(dest_i, dest_data_type);
qpGeomVertexReader from(&source);
from.set_data_type(source_i, source_data_type);
while (!from.is_at_end()) {
to.set_data4f(from.get_data4f());
}
}
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::convert_to
// Access: Published
// Description: Matches up the data types of this format with the
// data types of the other format by name, and copies
// the data vertex-by-vertex to a new set of data arrays
// in the new format.
// Description: Returns a new GeomVertexData that represents the same
// contents as this one, with all data types matched up
// name-by-name to the indicated new format.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexData) qpGeomVertexData::
convert_to(const qpGeomVertexFormat *new_format) const {
@ -277,121 +459,18 @@ convert_to(const qpGeomVertexFormat *new_format) const {
}
// Okay, convert the data to the new format.
int num_vertices = get_num_vertices();
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Converting " << num_vertices << " vertices.\n";
<< "Converting " << get_num_vertices() << " vertices.\n";
}
PStatTimer timer(_convert_pcollector);
PT(qpGeomVertexData) new_data =
new qpGeomVertexData(get_name(), new_format, get_usage_hint());
new_data->set_transform_blend_palette(get_transform_blend_palette());
new_data->set_slider_table(get_slider_table());
pset<int> done_arrays;
int num_arrays = _format->get_num_arrays();
int i;
// First, check to see if any arrays can be simply appropriated for
// the new format, without changing the data.
for (i = 0; i < num_arrays; ++i) {
const qpGeomVertexArrayFormat *array_format =
_format->get_array(i);
bool array_done = false;
int new_num_arrays = new_format->get_num_arrays();
for (int new_i = 0;
new_i < new_num_arrays && !array_done;
++new_i) {
const qpGeomVertexArrayFormat *new_array_format =
new_format->get_array(new_i);
if (new_array_format->is_data_subset_of(*array_format)) {
// Great! Just use the same data for this one.
new_data->set_array(new_i, get_array(i));
array_done = true;
done_arrays.insert(new_i);
}
}
}
// Now make sure the arrays we didn't share are all filled in.
new_data->set_num_vertices(num_vertices);
// Now go back through and copy any data that's left over.
for (i = 0; i < num_arrays; ++i) {
CPTA_uchar array_data = get_array(i)->get_data();
const qpGeomVertexArrayFormat *array_format = _format->get_array(i);
int num_data_types = array_format->get_num_data_types();
for (int di = 0; di < num_data_types; ++di) {
const qpGeomVertexDataType *data_type = array_format->get_data_type(di);
int new_i = new_format->get_array_with(data_type->get_name());
if (new_i >= 0 && done_arrays.count(new_i) == 0) {
// The data type exists in the new format; we have to copy it.
const qpGeomVertexArrayFormat *new_array_format =
new_format->get_array(new_i);
const qpGeomVertexDataType *new_data_type =
new_array_format->get_data_type(data_type->get_name());
if (new_data_type->is_bytewise_equivalent(*data_type)) {
// We can do a quick bytewise copy.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
bytewise_copy(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
data_type, num_vertices);
} else if (new_data_type->is_packed_argb() &&
data_type->is_uint8_rgba()) {
// A common special case: OpenGL color to DirectX color.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
uint8_rgba_to_packed_argb
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
num_vertices);
} else if (new_data_type->is_uint8_rgba() &&
data_type->is_packed_argb()) {
// Another common special case: DirectX color to OpenGL
// color.
PTA_uchar new_array_data =
new_data->modify_array(new_i)->modify_data();
packed_argb_to_uint8_rgba
(new_array_data + new_data_type->get_start(),
new_array_format->get_stride(),
array_data + data_type->get_start(), array_format->get_stride(),
num_vertices);
} else {
// A generic copy.
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "generic copy " << *new_data_type << " from "
<< *data_type << "\n";
}
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());
}
}
}
}
}
new_data->copy_from(*this, false);
return new_data;
}
@ -542,6 +621,7 @@ replace_data_type(const InternalName *name, int num_components,
new qpGeomVertexData(get_name(), format, usage_hint);
if (keep_animation) {
new_data->set_transform_blend_palette(get_transform_blend_palette());
new_data->set_slider_table(get_slider_table());
}
int j = 0;
@ -644,27 +724,35 @@ get_array_info(const InternalName *name,
CPT(qpGeomVertexData) qpGeomVertexData::
do_animate_vertices(bool from_app) const {
CDReader cdata(_cycler);
if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) {
// No vertex animation.
UpdateSeq modified;
if (cdata->_transform_blend_palette != (TransformBlendPalette *)NULL) {
if (cdata->_slider_table != (SliderTable *)NULL) {
modified =
max(cdata->_transform_blend_palette->get_modified(),
cdata->_slider_table->get_modified());
} else {
modified = cdata->_transform_blend_palette->get_modified();
}
} else if (cdata->_slider_table != (SliderTable *)NULL) {
modified = cdata->_slider_table->get_modified();
} else {
// No transform blend palette or slider table--ergo, 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;
if (cdata->_animated_vertices_modified == modified &&
cdata->_animated_vertices != (qpGeomVertexData *)NULL) {
// No changes.
return cdata->_animated_vertices;
}
CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata);
cdataw->_animated_vertices_modified = modified;
((qpGeomVertexData *)this)->update_animated_vertices(cdataw, from_app);
return cdataw->_animated_vertices;
}
////////////////////////////////////////////////////////////////////
@ -787,22 +875,6 @@ do_set_num_vertices(int n, qpGeomVertexData::CDWriter &cdata) {
return any_changed;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::make_animated_vertices
// Access: Private
// Description: Creates the GeomVertexData that represents the
// results of computing the vertex animation on the CPU.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
make_animated_vertices(qpGeomVertexData::CDWriter &cdata) {
// First, make a new format that doesn't have the transform_blend
// array.
cdata->_animated_vertices = replace_data_type
(InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16,
qpGeomVertexDataType::C_index,
min(get_usage_hint(), qpGeomUsageHint::UH_dynamic), false);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::update_animated_vertices
// Access: Private
@ -825,46 +897,133 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata, bool from_app) {
PStatTimer timer(collector);
#endif
CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette;
nassertv(palette != (TransformBlendPalette *)NULL);
// 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++) {
palette->get_blend(bi).update_blend();
if (cdata->_animated_vertices == (qpGeomVertexData *)NULL) {
CPT(qpGeomVertexFormat) animated_format = get_post_animated_format();
cdata->_animated_vertices =
new qpGeomVertexData(get_name(), animated_format,
min(get_usage_hint(), qpGeomUsageHint::UH_dynamic));
}
PT(qpGeomVertexData) new_data = cdata->_animated_vertices;
// 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());
// We have to make a complete copy of data first so we can modify
// it. If we were clever, we could maybe just figure out the subset
// of the data that might have changed since last frame, but that's
// too much trouble (and isn't obviously faster than just copying
// the whole thing).
new_data->copy_from(*this, true);
if (!blendi.has_data_type()) {
gobj_cat.warning()
<< "Vertex data " << get_name()
<< " has a transform_blend_palette, but no transform_blend data.\n";
return;
}
// First, apply all of the morphs.
CPT(SliderTable) table = cdata->_slider_table;
if (table != (SliderTable *)NULL) {
int num_morphs = _format->get_num_morphs();
for (int mi = 0; mi < num_morphs; mi++) {
CPT(InternalName) slider_name = _format->get_morph_slider(mi);
const VertexSlider *slider = table->get_slider(slider_name);
if (slider != (VertexSlider *)NULL) {
float slider_value = slider->get_slider();
if (slider_value != 0.0f) {
CPT(InternalName) base_name = _format->get_morph_base(mi);
CPT(InternalName) delta_name = _format->get_morph_delta(mi);
qpGeomVertexRewriter data(new_data, base_name);
qpGeomVertexReader delta(this, delta_name);
if (from.get_data_type()->get_num_values() == 4) {
for (int i = 0; i < num_vertices; i++) {
LPoint4f vertex = from.get_data4f();
int bi = blendi.get_data1i();
palette->get_blend(bi).transform_point(vertex);
to.set_data4f(vertex);
}
} else {
for (int i = 0; i < num_vertices; i++) {
LPoint3f vertex = from.get_data3f();
int bi = blendi.get_data1i();
palette->get_blend(bi).transform_point(vertex);
to.set_data3f(vertex);
if (data.get_data_type()->get_num_values() == 4) {
if (data.get_data_type()->has_homogeneous_coord()) {
for (int i = 0; i < num_vertices; i++) {
// Scale the delta by the homogeneous coordinate.
LPoint4f vertex = data.get_data4f();
LPoint3f d = delta.get_data3f();
d *= slider_value * vertex[3];
data.set_data4f(vertex[0] + d[0],
vertex[1] + d[1],
vertex[2] + d[2],
vertex[3]);
}
} else {
// Just apply the four-component delta.
for (int i = 0; i < num_vertices; i++) {
const LPoint4f &vertex = data.get_data4f();
LPoint4f d = delta.get_data4f();
data.set_data4f(vertex + d * slider_value);
}
}
} else {
// 3-component or smaller values; don't worry about a
// homogeneous coordinate.
for (int i = 0; i < num_vertices; i++) {
const LPoint3f &vertex = data.get_data3f();
LPoint3f d = delta.get_data3f();
data.set_data3f(vertex + d * slider_value);
}
}
}
}
}
}
// Then apply the transforms.
CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette;
if (palette != (TransformBlendPalette *)NULL) {
// 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++) {
palette->get_blend(bi).update_blend();
}
// Now go through and apply the transforms.
qpGeomVertexRewriter data(new_data, InternalName::get_vertex());
qpGeomVertexReader blendi(this, InternalName::get_transform_blend());
if (!blendi.has_data_type()) {
gobj_cat.warning()
<< "Vertex data " << get_name()
<< " has a transform_blend_palette, but no transform_blend data.\n";
return;
}
if (data.get_data_type()->get_num_values() == 4) {
for (int i = 0; i < num_vertices; i++) {
LPoint4f vertex = data.get_data4f();
int bi = blendi.get_data1i();
palette->get_blend(bi).transform_point(vertex);
data.set_data4f(vertex);
}
} else {
for (int i = 0; i < num_vertices; i++) {
LPoint3f vertex = data.get_data3f();
int bi = blendi.get_data1i();
palette->get_blend(bi).transform_point(vertex);
data.set_data3f(vertex);
}
}
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_post_animated_format
// Access: Private
// Description: Returns a suitable vertex format for sending the
// animated vertices to the graphics backend. This is
// the same format as the source format, with the
// CPU-animation data elements removed.
////////////////////////////////////////////////////////////////////
CPT(qpGeomVertexFormat) qpGeomVertexData::
get_post_animated_format() const {
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format);
new_format->remove_data_type(InternalName::get_transform_blend());
int num_morphs = _format->get_num_morphs();
for (int mi = 0; mi < num_morphs; mi++) {
CPT(InternalName) delta_name = _format->get_morph_delta(mi);
new_format->remove_data_type(delta_name);
}
return qpGeomVertexFormat::register_format(new_format);
}
////////////////////////////////////////////////////////////////////

View File

@ -26,6 +26,7 @@
#include "qpgeomVertexArrayData.h"
#include "qpgeomUsageHint.h"
#include "transformBlendPalette.h"
#include "sliderTable.h"
#include "internalName.h"
#include "cycleData.h"
#include "cycleDataReader.h"
@ -91,9 +92,15 @@ PUBLISHED:
void set_transform_blend_palette(const TransformBlendPalette *palette);
INLINE void clear_transform_blend_palette();
INLINE const SliderTable *get_slider_table() const;
SliderTable *modify_slider_table();
void set_slider_table(const SliderTable *palette);
INLINE void clear_slider_table();
int get_num_bytes() const;
INLINE UpdateSeq get_modified() const;
void copy_from(const qpGeomVertexData &source, bool keep_data_objects);
CPT(qpGeomVertexData) convert_to(const qpGeomVertexFormat *new_format) const;
CPT(qpGeomVertexData)
scale_color(const LVecBase4f &color_scale, int num_components,
@ -167,6 +174,7 @@ private:
Arrays _arrays;
PT(TransformBlendPalette) _transform_blend_palette;
PT(SliderTable) _slider_table;
PT(qpGeomVertexData) _animated_vertices;
UpdateSeq _animated_vertices_modified;
UpdateSeq _modified;
@ -178,8 +186,8 @@ private:
private:
bool do_set_num_vertices(int n, CDWriter &cdata);
void make_animated_vertices(CDWriter &cdata);
void update_animated_vertices(CDWriter &cdata, bool from_app);
CPT(qpGeomVertexFormat) get_post_animated_format() const;
static PStatCollector _convert_pcollector;
static PStatCollector _scale_color_pcollector;

View File

@ -151,6 +151,30 @@ get_total_bytes() const {
return _total_bytes;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::has_homogeneous_coord
// Access: Published
// Description: Returns true if this Contents type is one that
// includes a homogeneous coordinate in the fourth
// component, or false otherwise. If this is true,
// correct operation on the vertex data may require
// scaling by the homogeneous coordinate from time to
// time (but in general this is handled automatically if
// you use the 3-component or smaller forms of
// get_data() and set_data()).
////////////////////////////////////////////////////////////////////
INLINE bool qpGeomVertexDataType::
has_homogeneous_coord() const {
switch (_contents) {
case C_point:
case C_texcoord:
return true;
default:
return false;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexDataType::overlaps_with
// Access: Published

View File

@ -49,6 +49,7 @@ PUBLISHED:
C_rgba, // RGB or RGBA, OpenGL-style order
C_argb, // RGBA, DirectX-style packed color
C_index, // An index value into some other table
C_morph_delta, // A delta from some base value, defining a blend shape
};
INLINE qpGeomVertexDataType(const InternalName *name, int num_components,
@ -67,6 +68,7 @@ PUBLISHED:
INLINE int get_start() const;
INLINE int get_component_bytes() const;
INLINE int get_total_bytes() const;
INLINE bool has_homogeneous_coord() const;
INLINE bool overlaps_with(int start_byte, int num_bytes) const;
INLINE bool is_bytewise_equivalent(const qpGeomVertexDataType &other) const;

View File

@ -93,6 +93,81 @@ get_array(int array) const {
return _arrays[array];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_num_morphs
// Access: Published
// Description: Returns the number of data types within the format
// that represent morph deltas.
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexFormat::
get_num_morphs() const {
nassertr(_is_registered, 0);
return _morphs.size();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_morph_slider
// Access: Published
// Description: Returns the slider name associated with the nth morph
// data type. This is the name of the slider that will
// control the morph, and should be defined within the
// SliderTable associated with the GeomVertexData.
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
INLINE const InternalName *qpGeomVertexFormat::
get_morph_slider(int n) const {
nassertr(_is_registered, NULL);
nassertr(n >= 0 && n < (int)_morphs.size(), NULL);
return _morphs[n]._slider;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_morph_base
// Access: Published
// Description: Returns the name of the base data type that the nth
// morph modifies. This data type will also be defined
// within the format, and can be retrieved via
// get_array_with() and/or get_data_type().
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
INLINE const InternalName *qpGeomVertexFormat::
get_morph_base(int n) const {
nassertr(_is_registered, NULL);
nassertr(n >= 0 && n < (int)_morphs.size(), NULL);
return _morphs[n]._base;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_morph_delta
// Access: Published
// Description: Returns the name of the data type that defines the
// nth morph. This contains the delta offsets that are
// to be applied to the data type defined by
// get_morph_base(). This data type will be defined
// within the format, and can be retrieved via
// get_array_with() and/or get_data_type().
//
// This may only be called after the format has been
// registered.
////////////////////////////////////////////////////////////////////
INLINE const InternalName *qpGeomVertexFormat::
get_morph_delta(int n) const {
nassertr(_is_registered, NULL);
nassertr(n >= 0 && n < (int)_morphs.size(), NULL);
return _morphs[n]._delta;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexFormat::get_v3
// Access: Published, Static

View File

@ -506,6 +506,42 @@ do_register() {
}
}
// Go back through the index now and look for morph descriptions.
DataTypesByName::iterator ni;
for (ni = _data_types_by_name.begin();
ni != _data_types_by_name.end();
++ni) {
const DataTypeRecord &record = (*ni).second;
const qpGeomVertexDataType *data_type = _arrays[record._array_index]->get_data_type(record._data_type_index);
// Is it a morph description?
if (data_type->get_contents() == qpGeomVertexDataType::C_morph_delta) {
MorphRecord morph;
morph._delta = data_type->get_name();
// The delta name must be of the form "basename.morph.slidername".
int n = morph._delta->find_ancestor("morph");
if (n < 0) {
gobj_cat.warning()
<< "vertex format defines " << *data_type->get_name()
<< ", which is stored as a C_morph_delta, but its name does not include \"morph\".\n";
} else {
morph._slider = InternalName::make(morph._delta->get_net_basename(n - 1));
morph._base = morph._delta->get_ancestor(n + 1);
if (_data_types_by_name.find(morph._base) == _data_types_by_name.end()) {
gobj_cat.warning()
<< "vertex format defines "
<< *data_type->get_name() << " but does not define "
<< *morph._base << "\n";
} else {
_morphs.push_back(morph);
}
}
}
}
_is_registered = true;
}

View File

@ -84,6 +84,11 @@ PUBLISHED:
void remove_data_type(const InternalName *name);
INLINE int get_num_morphs() const;
INLINE const InternalName *get_morph_slider(int n) const;
INLINE const InternalName *get_morph_base(int n) const;
INLINE const InternalName *get_morph_delta(int n) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
void write_with_data(ostream &out, int indent_level,
@ -146,6 +151,15 @@ private:
typedef pmap<const InternalName *, DataTypeRecord> DataTypesByName;
DataTypesByName _data_types_by_name;
class MorphRecord {
public:
CPT(InternalName) _slider;
CPT(InternalName) _base;
CPT(InternalName) _delta;
};
typedef pvector<MorphRecord> Morphs;
Morphs _morphs;
// This set keeps track of things that need to be told when we
// destruct, and it is protected by the mutex.
Mutex _cache_lock;

View File

@ -0,0 +1,126 @@
// Filename: sliderTable.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: SliderTable::is_registered
// Access: Published
// Description: Returns true if this table has been registered.
// Once it has been registered, the set of sliders in
// a SliderTable may not be further modified; but
// it must be registered before it can be assigned to a
// Geom.
////////////////////////////////////////////////////////////////////
INLINE bool SliderTable::
is_registered() const {
return _is_registered;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::register_table
// Access: Published, Static
// Description: Registers a SliderTable for use. This is
// similar to GeomVertexFormat::register_format(). Once
// registered, a SliderTable may no longer be
// modified (although the individual VertexSlider
// objects may modify their reported sliders).
//
// This must be called before a table may be used in a
// Geom. After this call, you should discard the
// original pointer you passed in (which may or may not
// now be invalid) and let its reference count decrement
// normally; you should use only the returned value from
// this point on.
////////////////////////////////////////////////////////////////////
INLINE CPT(SliderTable) SliderTable::
register_table(SliderTable *table) {
// We don't actually bother adding the table object to a registry.
// This means there may be multiple copies of identical registered
// SliderTables. Big deal. We can always go back and make a
// registry later if we really need it.
if (table->is_registered()) {
return table;
}
table->do_register();
return table;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::get_slider
// Access: Published
// Description: Returns the slider with the indicated name, or NULL
// if no slider in the table has that name.
////////////////////////////////////////////////////////////////////
INLINE const VertexSlider *SliderTable::
get_slider(const InternalName *name) const {
Sliders::const_iterator si;
si = _sliders.find(name);
if (si != _sliders.end()) {
return (*si).second;
}
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::get_modified
// Access: Published
// Description: Returns a sequence number that's guaranteed to change
// at least when any VertexSliders in the table
// change. (However, this is only true for a registered
// table. An unregistered table may or may not
// reflect an update here when a VertexSlider
// changes.)
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq SliderTable::
get_modified() const {
CDReader cdata(_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::update_modified
// Access: Private
// Description: Called internally whenever a nested VertexSlider
// reports that it has been modified.
////////////////////////////////////////////////////////////////////
INLINE void SliderTable::
update_modified(UpdateSeq modified) {
CDWriter cdata(_cycler);
cdata->_modified = modified;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE SliderTable::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE SliderTable::CData::
CData(const SliderTable::CData &copy) :
_modified(copy._modified)
{
}

View File

@ -0,0 +1,249 @@
// Filename: sliderTable.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 "sliderTable.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle SliderTable::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: SliderTable::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
SliderTable::
SliderTable() :
_is_registered(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
SliderTable::
SliderTable(const SliderTable &copy) :
_is_registered(false),
_sliders(copy._sliders)
{
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void SliderTable::
operator = (const SliderTable &copy) {
nassertv(!_is_registered);
_sliders = copy._sliders;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
SliderTable::
~SliderTable() {
if (_is_registered) {
do_unregister();
}
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::remove_slider
// Access: Published
// Description: Removes the named slider. Only valid for
// unregistered tables.
////////////////////////////////////////////////////////////////////
void SliderTable::
remove_slider(const InternalName *name) {
nassertv(!_is_registered);
Sliders::iterator si = _sliders.find(name);
if (si != _sliders.end()) {
_sliders.erase(si);
}
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::add_slider
// Access: Published
// Description: Adds a new slider to the table, or replaces an
// existing slider with the same name. Only valid for
// unregistered tables.
////////////////////////////////////////////////////////////////////
void SliderTable::
add_slider(VertexSlider *slider) {
nassertv(!_is_registered);
_sliders[slider->get_name()] = slider;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void SliderTable::
write(ostream &out) const {
Sliders::const_iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++si) {
out << *(*si).second << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::do_register
// Access: Private
// Description: Called internally when the table is registered.
////////////////////////////////////////////////////////////////////
void SliderTable::
do_register() {
nassertv(!_is_registered);
Sliders::iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++si) {
bool inserted = (*si).second->_tables.insert(this).second;
nassertv(inserted);
}
_is_registered = true;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::do_unregister
// Access: Private
// Description: Called internally when the table is unregistered
// (i.e. right before destruction).
////////////////////////////////////////////////////////////////////
void SliderTable::
do_unregister() {
nassertv(_is_registered);
Sliders::iterator si;
for (si = _sliders.begin(); si != _sliders.end(); ++si) {
(*si).second->_tables.erase(this);
}
_is_registered = false;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// SliderTable.
////////////////////////////////////////////////////////////////////
void SliderTable::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void SliderTable::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type SliderTable is encountered
// in the Bam file. It should create the SliderTable
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *SliderTable::
make_from_bam(const FactoryParams &params) {
SliderTable *object = new SliderTable;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new SliderTable.
////////////////////////////////////////////////////////////////////
void SliderTable::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *SliderTable::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void SliderTable::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int SliderTable::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: SliderTable::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new SliderTable.
////////////////////////////////////////////////////////////////////
void SliderTable::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,126 @@
// Filename: sliderTable.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 SLIDERTABLE_H
#define SLIDERTABLE_H
#include "pandabase.h"
#include "vertexSlider.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "pmap.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : SliderTable
// Description : Stores the total set of VertexSliders that the
// vertices in a particular GeomVertexData object might
// depend on.
//
// This is similar to a TransformPalette, but it stores
// VertexSliders instead of VertexTransforms, and it
// stores them by name instead of by index number.
// Also, it is only used when animating vertices on the
// CPU, since GPU's don't support morphs at this point
// in time.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA SliderTable : public TypedWritableReferenceCount {
PUBLISHED:
SliderTable();
SliderTable(const SliderTable &copy);
void operator = (const SliderTable &copy);
virtual ~SliderTable();
INLINE bool is_registered() const;
INLINE static CPT(SliderTable) register_table(SliderTable *table);
INLINE const VertexSlider *get_slider(const InternalName *name) const;
INLINE UpdateSeq get_modified() const;
void remove_slider(const InternalName *name);
void add_slider(VertexSlider *slider);
void write(ostream &out) const;
private:
void do_register();
void do_unregister();
INLINE void update_modified(UpdateSeq modified);
private:
bool _is_registered;
typedef pmap< const InternalName *, PT(VertexSlider) > Sliders;
Sliders _sliders;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
UpdateSeq _modified;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "SliderTable",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class VertexSlider;
};
INLINE ostream &operator << (ostream &out, const SliderTable &obj);
#include "sliderTable.I"
#endif

View File

@ -105,9 +105,9 @@ get_modified() const {
// reports that it has been modified.
////////////////////////////////////////////////////////////////////
INLINE void TransformPalette::
update_modified(UpdateSeq) {
update_modified(UpdateSeq modified) {
CDWriter cdata(_cycler);
++(cdata->_modified);
cdata->_modified = modified;
}
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,52 @@
// Filename: userVertexSlider.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: UserVertexSlider::set_slider
// Access: Published
// Description: Stores the indicated slider value.
////////////////////////////////////////////////////////////////////
INLINE void UserVertexSlider::
set_slider(float slider) {
CDWriter cdata(_cycler);
cdata->_slider = slider;
mark_modified();
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE UserVertexSlider::CData::
CData() :
_slider(0.0f)
{
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE UserVertexSlider::CData::
CData(const UserVertexSlider::CData &copy) :
_slider(copy._slider)
{
}

View File

@ -0,0 +1,145 @@
// Filename: userVertexSlider.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 "userVertexSlider.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle UserVertexSlider::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
UserVertexSlider::
UserVertexSlider(const string &name) :
VertexSlider(InternalName::make(name))
{
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
UserVertexSlider::
UserVertexSlider(const InternalName *name) :
VertexSlider(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::get_slider
// Access: Published, Virtual
// Description: Returns the current slider value.
////////////////////////////////////////////////////////////////////
float UserVertexSlider::
get_slider() const {
CDReader cdata(_cycler);
return cdata->_slider;
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *UserVertexSlider::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// UserVertexSlider.
////////////////////////////////////////////////////////////////////
void UserVertexSlider::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void UserVertexSlider::
write_datagram(BamWriter *manager, Datagram &dg) {
VertexSlider::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type UserVertexSlider is encountered
// in the Bam file. It should create the UserVertexSlider
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *UserVertexSlider::
make_from_bam(const FactoryParams &params) {
UserVertexSlider *object = new UserVertexSlider("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new UserVertexSlider.
////////////////////////////////////////////////////////////////////
void UserVertexSlider::
fillin(DatagramIterator &scan, BamReader *manager) {
VertexSlider::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void UserVertexSlider::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexSlider::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new UserVertexSlider.
////////////////////////////////////////////////////////////////////
void UserVertexSlider::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,91 @@
// Filename: userVertexSlider.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 USERVERTEXSLIDER_H
#define USERVERTEXSLIDER_H
#include "pandabase.h"
#include "vertexSlider.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : UserVertexSlider
// Description : This is a specialization on VertexSlider that
// allows the user to specify any arbitrary slider
// valie he likes. This is rarely used except for
// testing.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA UserVertexSlider : public VertexSlider {
PUBLISHED:
UserVertexSlider(const string &name);
UserVertexSlider(const InternalName *name);
INLINE void set_slider(float slider);
virtual float get_slider() const;
private:
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual void fillin(DatagramIterator &scan, BamReader *manager);
float _slider;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
VertexSlider::init_type();
register_type(_type_handle, "UserVertexSlider",
VertexSlider::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
};
#include "userVertexSlider.I"
#endif

View File

@ -51,7 +51,7 @@ get_matrix(LMatrix4f &matrix) const {
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
output(ostream &out) const {
out << get_name();
out << get_type() << " " << get_name();
}
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,70 @@
// Filename: vertexSlider.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: VertexSlider::get_name
// Access: Published
// Description: Returns the name of this particular slider. Every
// unique blend shape within a particular Geom must be
// identified with a different name, which is shared by
// the slider that controls it.
////////////////////////////////////////////////////////////////////
INLINE const InternalName *VertexSlider::
get_name() const {
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::get_modified
// Access: Published
// Description: Returns a sequence number that's guaranteed to change
// at least every time the value reported by
// get_slider() changes.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq VertexSlider::
get_modified() const {
CDReader cdata(_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexSlider::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexSlider::CData::
CData(const VertexSlider::CData &copy) :
_modified(copy._modified)
{
}
INLINE ostream &
operator << (ostream &out, const VertexSlider &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,154 @@
// Filename: vertexSlider.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 "vertexSlider.h"
#include "vertexTransform.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indent.h"
TypeHandle VertexSlider::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
VertexSlider::
VertexSlider(const InternalName *name) : _name(name) {
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
VertexSlider::
~VertexSlider() {
// We shouldn't destruct while any SliderTables are holding our
// pointer.
nassertv(_tables.empty());
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VertexSlider::
output(ostream &out) const {
out << get_type() << " " << get_name();
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VertexSlider::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< *this << " = " << get_slider() << "\n";
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::mark_modified
// Access: Protected
// Description: Intended to be called by a derived class whenever the
// reported transform might have changed. Without
// calling this method, changes to get_slider() may not
// be propagated through the system.
////////////////////////////////////////////////////////////////////
void VertexSlider::
mark_modified() {
CDWriter cdata(_cycler);
cdata->_modified = VertexTransform::get_next_modified();
Tables::iterator ti;
for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
(*ti)->update_modified(cdata->_modified);
}
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void VertexSlider::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::fillin
// Access: Protected
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new VertexSlider.
////////////////////////////////////////////////////////////////////
void VertexSlider::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *VertexSlider::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void VertexSlider::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::complete_pointers
// Access: Public, Virtual
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int VertexSlider::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: VertexSlider::CData::fillin
// Access: Public, Virtual
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new VertexSlider.
////////////////////////////////////////////////////////////////////
void VertexSlider::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,119 @@
// Filename: vertexSlider.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 VERTEXSLIDER_H
#define VERTEXSLIDER_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "internalName.h"
#include "updateSeq.h"
#include "pset.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
class SliderTable;
////////////////////////////////////////////////////////////////////
// Class : VertexSlider
// Description : This is an abstract base class that retains some
// slider value, which is a linear value that typically
// ranges from 0.0 to 1.0, and is used to control the
// animation of morphs (blend shapes).
//
// It is similar to VertexTransform, which keeps a full
// 4x4 transform matrix, but the VertexSlider only keeps
// a single float value.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VertexSlider : public TypedWritableReferenceCount {
PUBLISHED:
VertexSlider(const InternalName *name);
virtual ~VertexSlider();
INLINE const InternalName *get_name() const;
virtual float get_slider() const=0;
INLINE UpdateSeq get_modified() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
protected:
void mark_modified();
private:
CPT(InternalName) _name;
typedef pset<SliderTable *> Tables;
Tables _tables;
// This is the data that must be cycled between pipeline stages.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
virtual void write_datagram(BamWriter *manager, Datagram &dg) const;
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
virtual void fillin(DatagramIterator &scan, BamReader *manager);
UpdateSeq _modified;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
static PipelineCycler<CData> _global_cycler;
static UpdateSeq _next_modified;
public:
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
TypedWritableReferenceCount::init_type();
register_type(_type_handle, "VertexSlider",
TypedWritableReferenceCount::get_class_type());
}
virtual TypeHandle get_type() const {
return get_class_type();
}
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
private:
static TypeHandle _type_handle;
friend class SliderTable;
};
INLINE ostream &operator << (ostream &out, const VertexSlider &obj);
#include "vertexSlider.I"
#endif