beginning vertex animation in qpgeom

This commit is contained in:
David Rose 2005-03-24 23:48:15 +00:00
parent 985bb2a478
commit bd820acd49
40 changed files with 3113 additions and 142 deletions

View File

@ -45,7 +45,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
if (vertex_type != (const qpGeomVertexDataType *)NULL) {
new_array_format->add_data_type
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float);
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32);
} else {
// If we don't have a vertex type, not much we can do.
return orig;
@ -53,7 +53,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
if (normal_type != (const qpGeomVertexDataType *)NULL) {
new_array_format->add_data_type
(InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float);
(InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32);
}
if (color_type != (const qpGeomVertexDataType *)NULL) {
@ -67,7 +67,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
if (texcoord_type != (const qpGeomVertexDataType *)NULL) {
new_array_format->add_data_type
(InternalName::get_texcoord(), texcoord_type->get_num_values(),
qpGeomVertexDataType::NT_float);
qpGeomVertexDataType::NT_float32);
}
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(new_array_format);

View File

@ -1904,11 +1904,11 @@ make_vertex_data(const EggRenderState *render_state,
PT(qpGeomVertexArrayFormat) array_format = new qpGeomVertexArrayFormat;
array_format->add_data_type
(InternalName::get_vertex(), vertex_pool->get_num_dimensions(),
qpGeomVertexDataType::NT_float);
qpGeomVertexDataType::NT_float32);
if (vertex_pool->has_normals()) {
array_format->add_data_type
(InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float);
(InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32);
}
if (vertex_pool->has_colors()) {
@ -1925,7 +1925,7 @@ make_vertex_data(const EggRenderState *render_state,
name = string();
}
PT(InternalName) iname = InternalName::get_texcoord_name(name);
array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float);
array_format->add_data_type(iname, 2, qpGeomVertexDataType::NT_float32);
}
CPT(qpGeomVertexFormat) format =
@ -1943,16 +1943,16 @@ make_vertex_data(const EggRenderState *render_state,
gvi.set_vertex(vertex->get_index());
gvi.set_data_type(InternalName::get_vertex());
gvi.set_data4(LCAST(float, vertex->get_pos4() * transform));
gvi.set_data4f(LCAST(float, vertex->get_pos4() * transform));
if (vertex->has_normal()) {
gvi.set_data_type(InternalName::get_normal());
gvi.set_data3(LCAST(float, vertex->get_normal() * transform));
gvi.set_data3f(LCAST(float, vertex->get_normal() * transform));
}
if (vertex->has_color()) {
gvi.set_data_type(InternalName::get_color());
gvi.set_data4(vertex->get_color());
gvi.set_data4f(vertex->get_color());
}
EggVertex::const_uv_iterator uvi;
@ -1973,7 +1973,7 @@ make_vertex_data(const EggRenderState *render_state,
uv = uv * (*buv).second->get_transform();
}
gvi.set_data2(LCAST(float, uv));
gvi.set_data2f(LCAST(float, uv));
}
}

View File

@ -428,7 +428,7 @@ p() const {
template<class Element>
INLINE pvector<Element> &PointerToArray<Element>::
v() const {
nassertd((this->_void_ptr) != NULL) {
if ((this->_void_ptr) == NULL) {
((PointerToArray<Element> *)this)->reassign(new RefCountObj<pvector<Element> >);
}
return *((To *)(this->_void_ptr));

View File

@ -640,21 +640,21 @@ load_default_model(const NodePath &parent) {
qpGeomVertexIterator color(vdata, InternalName::get_color());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3(Vertexf::rfu(0.0, 0.0, 0.0));
vertex.set_data3(Vertexf::rfu(1.0, 0.0, 0.0));
vertex.set_data3(Vertexf::rfu(0.0, 0.0, 1.0));
vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 0.0));
vertex.set_data3f(Vertexf::rfu(1.0, 0.0, 0.0));
vertex.set_data3f(Vertexf::rfu(0.0, 0.0, 1.0));
normal.set_data3(Normalf::back());
normal.set_data3(Normalf::back());
normal.set_data3(Normalf::back());
normal.set_data3f(Normalf::back());
normal.set_data3f(Normalf::back());
normal.set_data3f(Normalf::back());
color.set_data4(0.5, 0.5, 1.0, 1.0);
color.set_data4(0.5, 0.5, 1.0, 1.0);
color.set_data4(0.5, 0.5, 1.0, 1.0);
color.set_data4f(0.5, 0.5, 1.0, 1.0);
color.set_data4f(0.5, 0.5, 1.0, 1.0);
color.set_data4f(0.5, 0.5, 1.0, 1.0);
texcoord.set_data2(0.0, 0.0);
texcoord.set_data2(1.0, 0.0);
texcoord.set_data2(0.0, 1.0);
texcoord.set_data2f(0.0, 0.0);
texcoord.set_data2f(1.0, 0.0);
texcoord.set_data2f(0.0, 1.0);
PT(qpGeomTriangles) tri = new qpGeomTriangles(qpGeomUsageHint::UH_static);
tri->add_consecutive_vertices(0, 3);
@ -1065,15 +1065,15 @@ load_image_as_model(const Filename &filename) {
qpGeomVertexIterator vertex(vdata, InternalName::get_vertex());
qpGeomVertexIterator texcoord(vdata, InternalName::get_texcoord());
vertex.set_data3(Vertexf::rfu(left, 0.02f, top));
vertex.set_data3(Vertexf::rfu(left, 0.02f, bottom));
vertex.set_data3(Vertexf::rfu(right, 0.02f, top));
vertex.set_data3(Vertexf::rfu(right, 0.02f, bottom));
vertex.set_data3f(Vertexf::rfu(left, 0.02f, top));
vertex.set_data3f(Vertexf::rfu(left, 0.02f, bottom));
vertex.set_data3f(Vertexf::rfu(right, 0.02f, top));
vertex.set_data3f(Vertexf::rfu(right, 0.02f, bottom));
texcoord.set_data2(0.0f, 1.0f);
texcoord.set_data2(0.0f, 0.0f);
texcoord.set_data2(1.0f, 1.0f);
texcoord.set_data2(1.0f, 0.0f);
texcoord.set_data2f(0.0f, 1.0f);
texcoord.set_data2f(0.0f, 0.0f);
texcoord.set_data2f(1.0f, 1.0f);
texcoord.set_data2f(1.0f, 0.0f);
PT(qpGeomTristrips) strip = new qpGeomTristrips(qpGeomUsageHint::UH_static);
strip->add_consecutive_vertices(0, 4);

View File

@ -24,7 +24,7 @@
////////////////////////////////////////////////////////////////////
INLINE CLP(GeomMunger)::
CLP(GeomMunger)(GraphicsStateGuardian *gsg, const RenderState *state) :
ColorMunger(gsg, state, 4, qpGeomVertexDataType::NT_uint8),
ColorMunger(gsg, state, 4, qpGeomVertexDataType::NT_ufloat8),
_gsg(gsg),
_texture(state->get_texture()),
_tex_gen(state->get_tex_gen())

View File

@ -60,7 +60,7 @@ munge_format_impl(const qpGeomVertexFormat *orig) {
// Replace the existing color format with the new format.
new_array_format->add_data_type
(InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
(InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8,
color_type->get_start());
format = qpGeomVertexFormat::register_format(new_format);

View File

@ -2079,6 +2079,8 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger,
case qpGeomPrimitive::PT_lines:
setup_antialias_line();
break;
case qpGeomPrimitive::PT_none:
break;
}
}
@ -4428,11 +4430,17 @@ upload_texture_image(CLP(TextureContext) *gtc,
GLenum CLP(GraphicsStateGuardian)::
get_numeric_type(qpGeomVertexDataType::NumericType numeric_type) {
switch (numeric_type) {
case qpGeomVertexDataType::NT_uint8:
case qpGeomVertexDataType::NT_uint16:
return GL_UNSIGNED_SHORT;
case qpGeomVertexDataType::NT_ufloat8:
return GL_UNSIGNED_BYTE;
case qpGeomVertexDataType::NT_float:
case qpGeomVertexDataType::NT_float32:
return GL_FLOAT;
case qpGeomVertexDataType::NT_packed_argb:
break;
}
GLCAT.error()

View File

@ -49,7 +49,12 @@
textureContext.I textureContext.h \
texturePool.I texturePool.h \
textureStage.I textureStage.h \
vertexBufferContext.I vertexBufferContext.h
transformBlend.I transformBlend.h \
transformBlendPalette.I transformBlendPalette.h \
transformPalette.I transformPalette.h \
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexTransform.I vertexTransform.h
#define INCLUDED_SOURCES \
boundedObject.cxx \
@ -85,7 +90,12 @@
lens.cxx \
savedContext.cxx texture.cxx textureContext.cxx texturePool.cxx \
textureStage.cxx \
vertexBufferContext.cxx
transformBlend.cxx \
transformBlendPalette.cxx \
transformPalette.cxx \
userVertexTransform.cxx \
vertexBufferContext.cxx \
vertexTransform.cxx
#define INSTALL_HEADERS \
boundedObject.I boundedObject.h \
@ -127,7 +137,12 @@
textureContext.I textureContext.h \
texturePool.I texturePool.h \
textureStage.I textureStage.h \
vertexBufferContext.I vertexBufferContext.h
transformBlend.I transformBlend.h \
transformBlendPalette.I transformBlendPalette.h \
transformPalette.I transformPalette.h \
userVertexTransform.I userVertexTransform.h \
vertexBufferContext.I vertexBufferContext.h \
vertexTransform.I vertexTransform.h
#define IGATESCAN all

View File

@ -43,6 +43,10 @@
#include "texture.h"
#include "textureStage.h"
#include "textureContext.h"
#include "transformBlendPalette.h"
#include "transformPalette.h"
#include "userVertexTransform.h"
#include "vertexTransform.h"
#include "geomContext.h"
#include "vertexBufferContext.h"
#include "indexBufferContext.h"
@ -211,6 +215,10 @@ ConfigureFn(config_gobj) {
Texture::init_type();
dDrawable::init_type();
TextureStage::init_type();
TransformBlendPalette::init_type();
TransformPalette::init_type();
UserVertexTransform::init_type();
VertexTransform::init_type();
InternalName::init_type();
//Registration of writeable object's creation
@ -242,6 +250,9 @@ ConfigureFn(config_gobj) {
PerspectiveLens::register_with_read_factory();
Texture::register_with_read_factory();
TextureStage::register_with_read_factory();
TransformBlendPalette::register_with_read_factory();
TransformPalette::register_with_read_factory();
UserVertexTransform::register_with_read_factory();
InternalName::register_with_read_factory();
}

View File

@ -16,4 +16,9 @@
#include "textureContext.cxx"
#include "texturePool.cxx"
#include "textureStage.cxx"
#include "transformBlend.cxx"
#include "transformBlendPalette.cxx"
#include "transformPalette.cxx"
#include "userVertexTransform.cxx"
#include "vertexBufferContext.cxx"
#include "vertexTransform.cxx"

View File

@ -178,6 +178,19 @@ get_color() {
return _color;
}
////////////////////////////////////////////////////////////////////
// Function: InternalName::get_transform_blend
// Access: Published, Static
// Description: Returns the standard InternalName "transform_blend".
////////////////////////////////////////////////////////////////////
INLINE PT(InternalName) InternalName::
get_transform_blend() {
if (_transform_blend == (InternalName *)NULL) {
_transform_blend = InternalName::make("transform_blend");
}
return _transform_blend;
}
INLINE ostream &
operator << (ostream &out, const InternalName &tcn) {
tcn.output(out);

View File

@ -32,6 +32,7 @@ PT(InternalName) InternalName::_tangent;
PT(InternalName) InternalName::_binormal;
PT(InternalName) InternalName::_texcoord;
PT(InternalName) InternalName::_color;
PT(InternalName) InternalName::_transform_blend;
TypeHandle InternalName::_type_handle;
TypeHandle InternalName::_texcoord_type_handle;

View File

@ -67,6 +67,7 @@ PUBLISHED:
INLINE static PT(InternalName) get_texcoord();
INLINE static PT(InternalName) get_texcoord_name(const string &name);
INLINE static PT(InternalName) get_color();
INLINE static PT(InternalName) get_transform_blend();
private:
PT(InternalName) _parent;
@ -84,6 +85,7 @@ private:
static PT(InternalName) _binormal;
static PT(InternalName) _texcoord;
static PT(InternalName) _color;
static PT(InternalName) _transform_blend;
public:
// Datagram stuff

View File

@ -397,7 +397,7 @@ draw(GraphicsStateGuardianBase *gsg, const qpGeomMunger *munger,
////////////////////////////////////////////////////////////////////
// Function: qpGeom::get_next_modified
// Access: Public
// Access: Public, Static
// Description: Returns a monotonically increasing sequence. Each
// time this is called, a new sequence number is
// returned, higher than the previous value.

View File

@ -114,7 +114,6 @@ CPTA_ushort qpGeomLines::
rotate_impl() const {
// To rotate lines, we just move reverse the pairs of vertices.
CPTA_ushort vertices = get_vertices();
ShadeModel shade_model = get_shade_model();
PTA_ushort new_vertices;
new_vertices.reserve(vertices.size());

View File

@ -151,12 +151,9 @@ rotate_impl() const {
CPTA_int::const_iterator ei;
for (ei = ends.begin(); ei != ends.end(); ++ei) {
int end = (*ei);
int num_vertices = end - begin;
for (int vi = end - 1; vi >= begin; --vi) {
new_vertices.push_back(vertices[vi]);
}
begin = end;
}
nassertr(new_vertices.size() == vertices.size(), vertices);

View File

@ -91,6 +91,38 @@ get_array(int i) const {
return cdata->_arrays[i];
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_transform_blend_palette
// Access: Published
// Description: Returns a const pointer to the TransformBlendPalette
// assigned to this data. Vertices within the table
// will index into this palette to indicate their
// dynamic skinning information; this table is used when
// the vertex animation is to be performed by the CPU
// (but also see get_transform_palette()).
//
// This will return NULL if the vertex data does not
// have a TransformBlendPalette assigned (which implies
// the vertices will not be animated by the CPU).
////////////////////////////////////////////////////////////////////
INLINE const TransformBlendPalette *qpGeomVertexData::
get_transform_blend_palette() const {
CDReader cdata(_cycler);
return cdata->_transform_blend_palette;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::clear_transform_blend_palette
// Access: Published
// Description: Sets the TransformBlendPalette pointer to NULL,
// removing the palette from the vertex data. This
// disables CPU-driven vertex animation.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexData::
clear_transform_blend_palette() {
set_transform_blend_palette(NULL);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_modified
// Access: Published
@ -121,6 +153,9 @@ CData() {
INLINE qpGeomVertexData::CData::
CData(const qpGeomVertexData::CData &copy) :
_arrays(copy._arrays),
_transform_blend_palette(copy._transform_blend_palette),
_computed_vertices(copy._computed_vertices),
_computed_vertices_modified(copy._computed_vertices_modified),
_modified(copy._modified)
{
}

View File

@ -28,6 +28,7 @@ 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::_compute_vertices_pcollector("Cull:Compute vertices");
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::Default Constructor
@ -137,6 +138,7 @@ clear_vertices() {
(*ai)->clear_vertices();
}
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices.clear();
}
////////////////////////////////////////////////////////////////////
@ -160,6 +162,7 @@ modify_array(int i) {
cdata->_arrays[i] = new qpGeomVertexArrayData(*cdata->_arrays[i]);
}
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices_modified = UpdateSeq();
return cdata->_arrays[i];
}
@ -178,6 +181,48 @@ set_array(int i, const qpGeomVertexArrayData *array) {
nassertv(i >= 0 && i < (int)cdata->_arrays.size());
cdata->_arrays[i] = (qpGeomVertexArrayData *)array;
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices_modified = UpdateSeq();
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::modify_transform_blend_palette
// Access: Published
// Description: Returns a modifiable pointer to the current
// TransformBlendPalette on this vertex data, if any, or
// NULL if there is not a TransformBlendPalette. See
// get_transform_blend_palette().
////////////////////////////////////////////////////////////////////
TransformBlendPalette *qpGeomVertexData::
modify_transform_blend_palette() {
// Perform copy-on-write: if the reference count on the palette is
// greater than 1, assume some other GeomVertexData has the same
// pointer, so make a copy of it first.
CDWriter cdata(_cycler);
if (cdata->_transform_blend_palette->get_ref_count() > 1) {
cdata->_transform_blend_palette = new TransformBlendPalette(*cdata->_transform_blend_palette);
}
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices_modified = UpdateSeq();
return cdata->_transform_blend_palette;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_transform_blend_palette
// Access: Published
// Description: Replaces the TransformBlendPalette on this vertex
// data with the indicated palette. The length of this
// palette should be consistent with the maximum palette
// index assigned to the vertices under the
// "transform_blend" name.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_transform_blend_palette(const TransformBlendPalette *palette) {
CDWriter cdata(_cycler);
cdata->_transform_blend_palette = (TransformBlendPalette *)palette;
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices_modified = UpdateSeq();
}
////////////////////////////////////////////////////////////////////
@ -226,6 +271,7 @@ convert_to(const qpGeomVertexFormat *new_format) const {
PT(qpGeomVertexData) new_data =
new qpGeomVertexData(new_format, get_usage_hint());
new_data->set_transform_blend_palette(get_transform_blend_palette());
pset<int> done_arrays;
@ -319,15 +365,16 @@ scale_color(const LVecBase4f &color_scale, int num_components,
PStatTimer timer(_scale_color_pcollector);
PT(qpGeomVertexData) new_data = replace_data_type
(InternalName::get_color(), num_components, numeric_type);
(InternalName::get_color(), num_components, numeric_type,
get_usage_hint(), true);
// Now go through and apply the scale, copying it to the new data.
qpGeomVertexIterator from(this, InternalName::get_color());
qpGeomVertexIterator to(new_data, InternalName::get_color());
for (int i = 0; i < num_vertices; i++) {
Colorf color = from.get_data4();
to.set_data4(color[0] * color_scale[0],
Colorf color = from.get_data4f();
to.set_data4f(color[0] * color_scale[0],
color[1] * color_scale[1],
color[2] * color_scale[2],
color[3] * color_scale[3]);
@ -359,18 +406,62 @@ set_color(const Colorf &color, int num_components,
PStatTimer timer(_set_color_pcollector);
PT(qpGeomVertexData) new_data = replace_data_type
(InternalName::get_color(), num_components, numeric_type);
(InternalName::get_color(), num_components, numeric_type,
get_usage_hint(), true);
// Now go through and set the new color value.
qpGeomVertexIterator to(new_data, InternalName::get_color());
for (int i = 0; i < num_vertices; i++) {
to.set_data4(color);
to.set_data4f(color);
}
return new_data;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::compute_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::
compute_vertices() const {
CDReader cdata(_cycler);
if (cdata->_transform_blend_palette == (TransformBlendPalette *)NULL) {
// No vertex animation.
return this;
}
if (cdata->_computed_vertices == (qpGeomVertexData *)NULL) {
CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata);
((qpGeomVertexData *)this)->make_computed_vertices(cdataw);
return cdataw->_computed_vertices;
} else {
UpdateSeq blend_modified = cdata->_transform_blend_palette->get_modified();
if (cdata->_computed_vertices_modified == blend_modified) {
// No changes.
return cdata->_computed_vertices;
}
CDWriter cdataw(((qpGeomVertexData *)this)->_cycler, cdata);
cdataw->_computed_vertices_modified = blend_modified;
((qpGeomVertexData *)this)->update_computed_vertices(cdataw);
return cdataw->_computed_vertices;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::replace_data_type
// Access: Published
@ -380,10 +471,16 @@ set_color(const Colorf &color, int num_components,
// new table will be added as a new array; if the old
// table was interleaved with a previous array, the
// previous array will not be repacked.
//
// If num_components is 0, the indicated name is simply
// removed from the type, without replacing it with
// anything else.
////////////////////////////////////////////////////////////////////
PT(qpGeomVertexData) qpGeomVertexData::
replace_data_type(const InternalName *name, int num_components,
qpGeomVertexDataType::NumericType numeric_type) const {
qpGeomVertexDataType::NumericType numeric_type,
qpGeomUsageHint::UsageHint usage_hint,
bool keep_animation) const {
PT(qpGeomVertexFormat) new_format = new qpGeomVertexFormat(*_format);
// Remove the old description of the type from the format.
@ -405,13 +502,20 @@ replace_data_type(const InternalName *name, int num_components,
}
// Now define a new array to contain just the type.
PT(qpGeomVertexArrayFormat) type_array_format =
new qpGeomVertexArrayFormat(name, num_components, numeric_type);
int new_type_array = new_format->add_array(type_array_format);
int new_type_array = -1;
if (num_components != 0) {
PT(qpGeomVertexArrayFormat) type_array_format =
new qpGeomVertexArrayFormat(name, num_components, numeric_type);
new_type_array = new_format->add_array(type_array_format);
}
PT(qpGeomVertexData) new_data =
new qpGeomVertexData(qpGeomVertexFormat::register_format(new_format),
get_usage_hint());
usage_hint);
if (keep_animation) {
new_data->set_transform_blend_palette(get_transform_blend_palette());
}
int j = 0;
int num_arrays = get_num_arrays();
@ -431,14 +535,16 @@ replace_data_type(const InternalName *name, int num_components,
}
}
nassertr(j == new_type_array, new_data);
if (new_type_array != -1) {
nassertr(j == new_type_array, new_data);
// For the new type array, we set up a temporary array that has
// room for the right number of vertices.
PT(qpGeomVertexArrayData) new_array = new qpGeomVertexArrayData
(new_format->get_array(j), get_usage_hint());
new_array->set_num_vertices(get_num_vertices());
new_data->set_array(j, new_array);
// For the new type array, we set up a temporary array that has
// room for the right number of vertices.
PT(qpGeomVertexArrayData) new_array = new qpGeomVertexArrayData
(new_format->get_array(j), get_usage_hint());
new_array->set_num_vertices(get_num_vertices());
new_data->set_array(j, new_array);
}
return new_data;
}
@ -496,7 +602,26 @@ set_data(int array, const qpGeomVertexDataType *data_type,
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
case qpGeomVertexDataType::NT_uint16:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_uint16 *)&array_data[element] = (int)data[i];
element += sizeof(PN_uint16);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_uint16 *)&array_data[element] = 0;
element += sizeof(PN_uint16);
++i;
}
}
break;
case qpGeomVertexDataType::NT_ufloat8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
@ -528,7 +653,7 @@ set_data(int array, const qpGeomVertexDataType *data_type,
}
break;
case qpGeomVertexDataType::NT_float:
case qpGeomVertexDataType::NT_float32:
if (num_values == 4 && sizeof(float) == sizeof(PN_float32)) {
// The easy way: we can memcpy the data directly in.
memcpy(&array_data[element], data, data_type->get_total_bytes());
@ -577,7 +702,23 @@ get_data(int array, const qpGeomVertexDataType *data_type,
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint8:
case qpGeomVertexDataType::NT_uint16:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = *(PN_uint16 *)&array_data[element];
element += sizeof(PN_uint16);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_ufloat8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
@ -607,7 +748,7 @@ get_data(int array, const qpGeomVertexDataType *data_type,
}
break;
case qpGeomVertexDataType::NT_float:
case qpGeomVertexDataType::NT_float32:
if (num_values == data_type->get_num_values() &&
sizeof(float) == sizeof(PN_float32)) {
memcpy(data, &array_data[element], num_values * sizeof(PN_float32));
@ -628,7 +769,194 @@ get_data(int array, const qpGeomVertexDataType *data_type,
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::set_data
// Access: Public
// Description: Sets the nth vertex to a particular value. Query the
// format to get the array index and data_type
// parameters for the particular data type you want to
// set.
//
// This flavor of set_data() accepts a generic float
// array and a specific number of dimensions. The new
// data will be copied from the num_values elements
// of data.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const int *data, int num_values) {
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
{
CDReader cdata(_cycler);
int array_size = (int)cdata->_arrays[array]->get_data_size_bytes();
if (element + data_type->get_total_bytes() > array_size) {
// Whoops, we need more vertices!
CDWriter cdataw(_cycler, cdata);
do_set_num_vertices(vertex + 1, cdataw);
}
}
PTA_uchar array_data = modify_array(array)->modify_data();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_uint16 *)&array_data[element] = data[i];
element += sizeof(PN_uint16);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_uint16 *)&array_data[element] = 0;
element += sizeof(PN_uint16);
++i;
}
}
break;
case qpGeomVertexDataType::NT_ufloat8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
array_data[element] = data[i];
element += 1;
++i;
}
while (i < data_type->get_num_values()) {
array_data[element] = 0;
element += 1;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_argb:
{
if (num_values == 4) {
*(PN_uint32 *)&array_data[element] = pack_argb(data);
} else {
// Elevate (or truncate) to 4 components.
int data4[4];
memset(data4, 0, 4 * sizeof(int));
memcpy(data4, data, min(4, num_values) * sizeof(int));
*(PN_uint32 *)&array_data[element] = pack_argb(data4);
}
}
break;
case qpGeomVertexDataType::NT_float32:
{
// Elevate or truncate to the right number of components.
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
*(PN_float32 *)&array_data[element] = data[i];
element += sizeof(PN_float32);
++i;
}
while (i < data_type->get_num_values()) {
*(PN_float32 *)&array_data[element] = 0.0f;
element += sizeof(PN_float32);
++i;
}
}
break;
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::get_data
// Access: Public
// Description: Returns the data associated with the nth vertex for a
// particular value. Query the format to get the array
// index and data_type parameters for the particular
// data type you want to get.
//
// This flavor of get_data() copies its data into a
// generic float array.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, int *data, int num_values) const {
CPTA_uchar array_data = get_array(array)->get_data();
int stride = _format->get_array(array)->get_stride();
int element = vertex * stride + data_type->get_start();
nassertv(element >= 0 && element + data_type->get_total_bytes() <= (int)array_data.size());
switch (data_type->get_numeric_type()) {
case qpGeomVertexDataType::NT_uint16:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = *(PN_uint16 *)&array_data[element];
element += sizeof(PN_uint16);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_ufloat8:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
int value = *(unsigned char *)&array_data[element];
element += 1;
data[i] = value;
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
case qpGeomVertexDataType::NT_packed_argb:
{
if (num_values == 4) {
unpack_argb(data, *(PN_uint32 *)&array_data[element]);
} else {
int data4[4];
unpack_argb(data4, *(PN_uint32 *)&array_data[element]);
memset(data, 0, num_values * sizeof(int));
memcpy(data, data4, min(num_values, 4) * sizeof(int));
}
}
break;
case qpGeomVertexDataType::NT_float32:
{
int i = 0;
int min_values = min(num_values, data_type->get_num_values());
while (i < min_values) {
data[i] = (int)*(PN_float32 *)&array_data[element];
element += sizeof(PN_float32);
++i;
}
while (i < num_values) {
data[i] = 0;
++i;
}
}
break;
}
}
@ -774,6 +1102,35 @@ unpack_argb(float data[4], unsigned int packed_argb) {
data[3] = (float)((packed_argb >> 24) & 0xff) / 255.0f;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::pack_argb
// Access: Public, Static
// Description: Packs four ints, stored R, G, B, A, into a
// packed_argb value.
////////////////////////////////////////////////////////////////////
unsigned int qpGeomVertexData::
pack_argb(const int data[4]) {
unsigned int r = ((unsigned int)data[0]) & 0xff;
unsigned int g = ((unsigned int)data[1]) & 0xff;
unsigned int b = ((unsigned int)data[2]) & 0xff;
unsigned int a = ((unsigned int)data[3]) & 0xff;
return ((a << 24) | (r << 16) | (g << 8) | b);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::unpack_argb
// Access: Public, Static
// Description: Unpacks a packed_argb value into four ints, stored
// R, G, B, A.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
unpack_argb(int data[4], unsigned int packed_argb) {
data[0] = (int)((packed_argb >> 16) & 0xff);
data[1] = (int)((packed_argb >> 8) & 0xff);
data[2] = (int)(packed_argb & 0xff);
data[3] = (int)((packed_argb >> 24) & 0xff);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::do_set_num_vertices
// Access: Private
@ -798,11 +1155,66 @@ do_set_num_vertices(int n, qpGeomVertexData::CDWriter &cdata) {
if (any_changed) {
cdata->_modified = qpGeom::get_next_modified();
cdata->_computed_vertices.clear();
}
return any_changed;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::make_computed_vertices
// Access: Private
// Description: Creates the GeomVertexData that represents the
// results of computing the vertex animation on the CPU.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
make_computed_vertices(qpGeomVertexData::CDWriter &cdata) {
// First, make a new format that doesn't have the transform_blend
// array.
cdata->_computed_vertices = replace_data_type
(InternalName::get_transform_blend(), 0, qpGeomVertexDataType::NT_uint16,
qpGeomUsageHint::UH_dynamic, false);
// Now fill it up with the appropriate data.
update_computed_vertices(cdata);
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::update_computed_vertices
// Access: Private
// Description: Recomputes the results of computing the vertex
// animation on the CPU, and applies them to the
// existing computed_vertices object.
////////////////////////////////////////////////////////////////////
void qpGeomVertexData::
update_computed_vertices(qpGeomVertexData::CDWriter &cdata) {
int num_vertices = get_num_vertices();
if (gobj_cat.is_debug()) {
gobj_cat.debug()
<< "Computing " << num_vertices << " vertices.\n";
}
PStatTimer timer(_compute_vertices_pcollector);
CPT(TransformBlendPalette) palette = cdata->_transform_blend_palette;
nassertv(palette != (TransformBlendPalette *)NULL);
PT(qpGeomVertexData) new_data = cdata->_computed_vertices;
// Now go through and apply the scale, copying it to the new data.
qpGeomVertexIterator from(this, InternalName::get_vertex());
qpGeomVertexIterator blendi(this, InternalName::get_transform_blend());
qpGeomVertexIterator to(new_data, InternalName::get_vertex());
for (int i = 0; i < num_vertices; i++) {
LPoint4f vertex = from.get_data4f();
int bi = blendi.get_data1i();
const TransformBlend &blend = palette->get_blend(bi);
blend.transform_point(vertex);
to.set_data4f(vertex);
}
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexData::register_with_read_factory
// Access: Public, Static

View File

@ -25,6 +25,7 @@
#include "qpgeomVertexDataType.h"
#include "qpgeomVertexArrayData.h"
#include "qpgeomUsageHint.h"
#include "transformBlendPalette.h"
#include "internalName.h"
#include "cycleData.h"
#include "cycleDataReader.h"
@ -81,6 +82,11 @@ PUBLISHED:
qpGeomVertexArrayData *modify_array(int i);
void set_array(int i, const qpGeomVertexArrayData *array);
INLINE const TransformBlendPalette *get_transform_blend_palette() const;
TransformBlendPalette *modify_transform_blend_palette();
void set_transform_blend_palette(const TransformBlendPalette *palette);
INLINE void clear_transform_blend_palette();
int get_num_bytes() const;
INLINE UpdateSeq get_modified() const;
@ -92,9 +98,13 @@ PUBLISHED:
set_color(const Colorf &color, int num_components,
qpGeomVertexDataType::NumericType numeric_type) const;
CPT(qpGeomVertexData) compute_vertices() const;
PT(qpGeomVertexData)
replace_data_type(const InternalName *name, int num_components,
qpGeomVertexDataType::NumericType numeric_type) const;
qpGeomVertexDataType::NumericType numeric_type,
qpGeomUsageHint::UsageHint usage_hint,
bool keep_animation) const;
void output(ostream &out) const;
void write(ostream &out, int indent_level = 0) const;
@ -104,6 +114,10 @@ public:
int vertex, const float *data, int num_values);
void get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, float *data, int num_values) const;
void set_data(int array, const qpGeomVertexDataType *data_type,
int vertex, const int *data, int num_values);
void get_data(int array, const qpGeomVertexDataType *data_type,
int vertex, int *data, int num_values) const;
bool get_array_info(const InternalName *name,
const qpGeomVertexArrayData *&array_data,
@ -117,6 +131,8 @@ public:
static unsigned int pack_argb(const float data[4]);
static void unpack_argb(float data[4], unsigned int packed_argb);
static unsigned int pack_argb(const int data[4]);
static void unpack_argb(int data[4], unsigned int packed_argb);
private:
CPT(qpGeomVertexFormat) _format;
@ -135,6 +151,9 @@ private:
virtual void fillin(DatagramIterator &scan, BamReader *manager);
Arrays _arrays;
PT(TransformBlendPalette) _transform_blend_palette;
PT(qpGeomVertexData) _computed_vertices;
UpdateSeq _computed_vertices_modified;
UpdateSeq _modified;
};
@ -144,10 +163,13 @@ private:
private:
bool do_set_num_vertices(int n, CDWriter &cdata);
void make_computed_vertices(CDWriter &cdata);
void update_computed_vertices(CDWriter &cdata);
static PStatCollector _convert_pcollector;
static PStatCollector _scale_color_pcollector;
static PStatCollector _set_color_pcollector;
static PStatCollector _compute_vertices_pcollector;
public:
static void register_with_read_factory();

View File

@ -35,7 +35,11 @@ qpGeomVertexDataType(const InternalName *name, int num_components,
nassertv(num_components > 0 && start >= 0);
switch (numeric_type) {
case NT_uint8:
case NT_uint16:
_component_bytes = 2; // sizeof(PN_uint16)
break;
case NT_ufloat8:
_component_bytes = 1;
break;
@ -44,7 +48,7 @@ qpGeomVertexDataType(const InternalName *name, int num_components,
_num_values *= 4;
break;
case NT_float:
case NT_float32:
_component_bytes = 4; // sizeof(PN_float32)
break;
}
@ -61,7 +65,7 @@ qpGeomVertexDataType(const InternalName *name, int num_components,
const qpGeomVertexDataType &qpGeomVertexDataType::
error() {
static qpGeomVertexDataType error_result
(InternalName::get_error(), 1, NT_uint8, 0);
(InternalName::get_error(), 1, NT_ufloat8, 0);
return error_result;
}
@ -101,10 +105,10 @@ copy_records(unsigned char *to, int to_stride,
// An easy case.
copy_no_convert(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_uint8 && from_type->get_numeric_type() == NT_packed_argb &&
} else if (get_numeric_type() == NT_ufloat8 && from_type->get_numeric_type() == NT_packed_argb &&
get_num_values() == from_type->get_num_values()) {
copy_argb_to_uint8(to, to_stride, from, from_stride, from_type, num_records);
} else if (get_numeric_type() == NT_packed_argb && from_type->get_numeric_type() == NT_uint8 &&
} else if (get_numeric_type() == NT_packed_argb && from_type->get_numeric_type() == NT_ufloat8 &&
get_num_values() == from_type->get_num_values()) {
copy_uint8_to_argb(to, to_stride, from, from_stride, from_type, num_records);
} else {
@ -223,7 +227,10 @@ copy_generic(unsigned char *to, int to_stride,
float qpGeomVertexDataType::
get_value(const unsigned char *data, int n) const {
switch (get_numeric_type()) {
case NT_uint8:
case NT_uint16:
return (float)data[n];
case NT_ufloat8:
return (float)data[n] / 255.0f;
case qpGeomVertexDataType::NT_packed_argb:
@ -245,7 +252,7 @@ get_value(const unsigned char *data, int n) const {
}
break;
case qpGeomVertexDataType::NT_float:
case qpGeomVertexDataType::NT_float32:
{
const PN_float32 *float_array = (const PN_float32 *)data;
return float_array[n];
@ -263,7 +270,11 @@ get_value(const unsigned char *data, int n) const {
void qpGeomVertexDataType::
set_value(unsigned char *data, int n, float value) const {
switch (get_numeric_type()) {
case NT_uint8:
case NT_uint16:
data[n] = (int)value;
break;
case NT_ufloat8:
data[n] = (int)(value * 255.0f);
break;
@ -301,7 +312,7 @@ set_value(unsigned char *data, int n, float value) const {
}
break;
case qpGeomVertexDataType::NT_float:
case qpGeomVertexDataType::NT_float32:
PN_float32 *float_array = (PN_float32 *)data;
float_array[n] = value;
break;

View File

@ -35,9 +35,10 @@
class EXPCL_PANDA qpGeomVertexDataType {
PUBLISHED:
enum NumericType {
NT_uint8,
NT_packed_argb, // DirectX style
NT_float,
NT_uint16, // A short integer 0..65535
NT_ufloat8, // A floating-point number 0..1 packed into a byte
NT_float32, // A true floating-point number
NT_packed_argb, // DirectX style color specification
};
INLINE qpGeomVertexDataType(const InternalName *name, int num_components,

View File

@ -526,64 +526,64 @@ fillin(DatagramIterator &scan, BamReader *manager) {
qpGeomVertexFormat::Registry::
Registry() {
_v3 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32));
_v3n3 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32));
_v3t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
_v3n3t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
// Define the DirectX-style packed color formats
_v3cp = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb));
_v3n3cp = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb));
_v3cpt2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
_v3n3cpt2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 1, qpGeomVertexDataType::NT_packed_argb,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
// Define the OpenGL-style per-byte color formats. This is not the
// same as a packed format, above, because the resulting byte order
// is endian-independent.
_v3c4 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8));
_v3n3c4 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8));
_v3c4t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
_v3n3c4t2 = register_format(new qpGeomVertexArrayFormat
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_uint8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float));
(InternalName::get_vertex(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_normal(), 3, qpGeomVertexDataType::NT_float32,
InternalName::get_color(), 4, qpGeomVertexDataType::NT_ufloat8,
InternalName::get_texcoord(), 2, qpGeomVertexDataType::NT_float32));
}
////////////////////////////////////////////////////////////////////

View File

@ -291,99 +291,99 @@ get_write_vertex() const {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data1
// Function: qpGeomVertexIterator::set_data1f
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data1(float data) {
set_data1f(float data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, &data, 1);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2
// Function: qpGeomVertexIterator::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2(float x, float y) {
set_data2(LVecBase2f(x, y));
set_data2f(float x, float y) {
set_data2f(LVecBase2f(x, y));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data2
// Function: qpGeomVertexIterator::set_data2f
// Access: Published
// Description: Sets the write vertex to a particular 2-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data2(const LVecBase2f &data) {
set_data2f(const LVecBase2f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 2);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3
// Function: qpGeomVertexIterator::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3(float x, float y, float z) {
set_data3(LVecBase3f(x, y, z));
set_data3f(float x, float y, float z) {
set_data3f(LVecBase3f(x, y, z));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data3
// Function: qpGeomVertexIterator::set_data3f
// Access: Published
// Description: Sets the write vertex to a particular 3-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data3(const LVecBase3f &data) {
set_data3f(const LVecBase3f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 3);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4
// Function: qpGeomVertexIterator::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4(float x, float y, float z, float w) {
set_data4(LVecBase4f(x, y, z, w));
set_data4f(float x, float y, float z, float w) {
set_data4f(LVecBase4f(x, y, z, w));
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data4
// Function: qpGeomVertexIterator::set_data4f
// Access: Published
// Description: Sets the write vertex to a particular 4-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data4(const LVecBase4f &data) {
set_data4f(const LVecBase4f &data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, data.get_data(), 4);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data1
// Function: qpGeomVertexIterator::get_data1f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 1-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE float qpGeomVertexIterator::
get_data1() {
get_data1f() {
float data;
_data->get_data(_array, _data_type, _read_vertex, &data, 1);
++_read_vertex;
@ -391,14 +391,14 @@ get_data1() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data2
// Function: qpGeomVertexIterator::get_data2f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 2-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase2f qpGeomVertexIterator::
get_data2() {
get_data2f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
@ -409,14 +409,14 @@ get_data2() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data3
// Function: qpGeomVertexIterator::get_data3f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 3-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase3f qpGeomVertexIterator::
get_data3() {
get_data3f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
@ -427,14 +427,14 @@ get_data3() {
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data4
// Function: qpGeomVertexIterator::get_data4f
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 4-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE LVecBase4f qpGeomVertexIterator::
get_data4() {
get_data4f() {
float data[4];
int num_values = min(_data_type->get_num_values(), 4);
_data->get_data(_array, _data_type, _read_vertex, data, num_values);
@ -443,3 +443,31 @@ get_data4() {
qpGeomVertexData::to_vec4(result, data, num_values);
return result;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::set_data1i
// Access: Published
// Description: Sets the write vertex to a particular 1-component
// value, and advances the write vertex.
////////////////////////////////////////////////////////////////////
INLINE void qpGeomVertexIterator::
set_data1i(int data) {
nassertv(!_const_data);
_data->set_data(_array, _data_type, _write_vertex, &data, 1);
++_write_vertex;
}
////////////////////////////////////////////////////////////////////
// Function: qpGeomVertexIterator::get_data1i
// Access: Published
// Description: Returns the data associated with the read vertex,
// expressed as a 1-component value, and advances the
// read vertex.
////////////////////////////////////////////////////////////////////
INLINE int qpGeomVertexIterator::
get_data1i() {
int data;
_data->get_data(_array, _data_type, _read_vertex, &data, 1);
++_read_vertex;
return data;
}

View File

@ -41,12 +41,16 @@ PUBLISHED:
const string &name);
INLINE qpGeomVertexIterator(qpGeomVertexData *data,
const InternalName *name);
public:
// These const variants are not published, since our Python layer
// doesn't know the difference between const and non-const anyway.
INLINE qpGeomVertexIterator(const qpGeomVertexData *data);
INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
const string &name);
INLINE qpGeomVertexIterator(const qpGeomVertexData *data,
const InternalName *name);
PUBLISHED:
INLINE const qpGeomVertexData *get_data() const;
INLINE void set_data_type(int data_type);
@ -63,18 +67,21 @@ PUBLISHED:
INLINE int get_read_vertex() const;
INLINE int get_write_vertex() const;
INLINE void set_data1(float data);
INLINE void set_data2(float x, float y);
INLINE void set_data2(const LVecBase2f &data);
INLINE void set_data3(float x, float y, float z);
INLINE void set_data3(const LVecBase3f &data);
INLINE void set_data4(float x, float y, float z, float w);
INLINE void set_data4(const LVecBase4f &data);
INLINE void set_data1f(float data);
INLINE void set_data2f(float x, float y);
INLINE void set_data2f(const LVecBase2f &data);
INLINE void set_data3f(float x, float y, float z);
INLINE void set_data3f(const LVecBase3f &data);
INLINE void set_data4f(float x, float y, float z, float w);
INLINE void set_data4f(const LVecBase4f &data);
INLINE float get_data1();
INLINE LVecBase2f get_data2();
INLINE LVecBase3f get_data3();
INLINE LVecBase4f get_data4();
INLINE float get_data1f();
INLINE LVecBase2f get_data2f();
INLINE LVecBase3f get_data3f();
INLINE LVecBase4f get_data4f();
INLINE void set_data1i(int data);
INLINE int get_data1i();
private:
PT(qpGeomVertexData) _data;

View File

@ -0,0 +1,277 @@
// Filename: transformBlend.I
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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: TransformBlend::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend(const VertexTransform *transform0, float) {
add_transform(transform0, 1.0f);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1) {
add_transform(transform0, weight0);
add_transform(transform1, weight1);
normalize_weights();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1,
const VertexTransform *transform2, float weight2) {
add_transform(transform0, weight0);
add_transform(transform1, weight1);
add_transform(transform2, weight2);
normalize_weights();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1,
const VertexTransform *transform2, float weight2,
const VertexTransform *transform3, float weight3) {
add_transform(transform0, weight0);
add_transform(transform1, weight1);
add_transform(transform2, weight2);
add_transform(transform3, weight3);
normalize_weights();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
TransformBlend(const TransformBlend &copy) :
_entries(copy._entries)
{
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE void TransformBlend::
operator = (const TransformBlend &copy) {
_entries = copy._entries;
clear_result();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::Destructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::
~TransformBlend() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::operator <
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool TransformBlend::
operator < (const TransformBlend &other) const {
return compare_to(other) < 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::operator ==
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool TransformBlend::
operator == (const TransformBlend &other) const {
return compare_to(other) == 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::operator !=
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
INLINE bool TransformBlend::
operator != (const TransformBlend &other) const {
return compare_to(other) != 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_num_transforms
// Access: Published
// Description: Returns the number of transforms stored in the blend
// object.
////////////////////////////////////////////////////////////////////
INLINE int TransformBlend::
get_num_transforms() const {
return _entries.size();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_transform
// Access: Published
// Description: Returns the nth transform stored in the blend
// object.
////////////////////////////////////////////////////////////////////
INLINE const VertexTransform *TransformBlend::
get_transform(int n) const {
nassertr(n >= 0 && n < (int)_entries.size(), NULL);
return _entries[n]._transform;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_weight
// Access: Published
// Description: Returns the weight associated with the nth transform
// stored in the blend object.
////////////////////////////////////////////////////////////////////
INLINE float TransformBlend::
get_weight(int n) const {
nassertr(n >= 0 && n < (int)_entries.size(), 0.0f);
return _entries[n]._weight;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_blend
// Access: Published
// Description: Returns the current value of the blend, based on the
// current value of all of the nested transform objects
// and their associated weights.
////////////////////////////////////////////////////////////////////
INLINE void TransformBlend::
get_blend(LMatrix4f &result) const {
CDReader cdata(_cycler);
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
((TransformBlend *)this)->recompute_result(cdataw);
result = cdataw->_result;
} else {
result = cdata->_result;
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::transform_point
// Access: Published
// Description: Transforms the indicated point by the blend matrix.
////////////////////////////////////////////////////////////////////
INLINE void TransformBlend::
transform_point(LPoint4f &point) const {
if (!_entries.empty()) {
CDReader cdata(_cycler);
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
((TransformBlend *)this)->recompute_result(cdataw);
point = point * cdataw->_result;
} else {
point = point * cdata->_result;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_modified
// Access: Published
// Description: Returns a counter which is guaranteed to increment at
// least as often as the result of get_blend() changes.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq TransformBlend::
get_modified() const {
CDReader cdata(_cycler);
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata);
((TransformBlend *)this)->recompute_result(cdataw);
return cdataw->_modified;
} else {
return cdata->_modified;
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::TransformEntry::operator <
// Access: Public
// Description: Provides an ordering of TransformEntries by the
// VertexTransform pointer only, so we can easily look
// up in the set to see if a particular transform
// exists.
////////////////////////////////////////////////////////////////////
INLINE bool TransformBlend::TransformEntry::
operator < (const TransformBlend::TransformEntry &other) const {
return _transform < other._transform;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::CData::
CData() :
_result(LMatrix4f::ident_mat())
{
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlend::CData::
CData(const TransformBlend::CData &copy) :
_result(copy._result),
_modified(copy._modified),
_global_modified(copy._global_modified)
{
}
INLINE ostream &
operator << (ostream &out, const TransformBlend &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,287 @@
// Filename: transformBlend.cxx
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "transformBlend.h"
#include "indent.h"
#include "bamReader.h"
#include "bamWriter.h"
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::compare_to
// Access: Published
// Description: Defines an arbitrary ordering for TransformBlend
// objects.
////////////////////////////////////////////////////////////////////
int TransformBlend::
compare_to(const TransformBlend &other) const {
if (_entries.size() != other._entries.size()) {
return (int)_entries.size() - (int)other._entries.size();
}
Entries::const_iterator ai, bi;
ai = _entries.begin();
bi = other._entries.begin();
while (ai != _entries.end() && bi != other._entries.end()) {
if ((*ai)._transform != (*bi)._transform) {
return (*ai)._transform < (*bi)._transform ? -1 : 1;
}
if (!IS_NEARLY_EQUAL((*ai)._weight, (*bi)._weight)) {
return (*ai)._weight < (*bi)._weight ? -1 : 1;
}
++ai;
++bi;
}
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::add_transform
// Access: Published
// Description: Adds a new transform to the blend. If the transform
// already existed, increases its weight factor.
////////////////////////////////////////////////////////////////////
void TransformBlend::
add_transform(const VertexTransform *transform, float weight) {
if (!IS_NEARLY_ZERO(weight)) {
TransformEntry entry;
entry._transform = transform;
entry._weight = weight;
pair<Entries::iterator, bool> result = _entries.insert(entry);
if (!result.second) {
// If the new value was not inserted, it was already there;
// increment the existing weight factor.
Entries::iterator ei = result.first;
(*ei)._weight += weight;
if (IS_NEARLY_ZERO((*ei)._weight)) {
// If we have just zeroed out the weight, remove it.
_entries.erase(ei);
}
}
clear_result();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::remove_transform
// Access: Published
// Description: Removes the indicated transform to the blend.
////////////////////////////////////////////////////////////////////
void TransformBlend::
remove_transform(const VertexTransform *transform) {
TransformEntry entry;
entry._transform = transform;
entry._weight = 0.0f;
Entries::iterator ei = _entries.find(entry);
if (ei != _entries.end()) {
_entries.erase(ei);
}
clear_result();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::normalize_weights
// Access: Published
// Description: Rescales all of the weights on the various transforms
// so that they sum to 1.0. It is generally a good idea
// to call this after adding or removing transforms from
// the blend.
////////////////////////////////////////////////////////////////////
void TransformBlend::
normalize_weights() {
float net_weight = 0.0f;
Entries::iterator ei;
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
net_weight += (*ei)._weight;
}
if (net_weight != 0.0f) {
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
(*ei)._weight /= net_weight;
}
}
clear_result();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::has_transform
// Access: Published
// Description: Returns true if the blend has the indicated
// transform, false otherwise.
////////////////////////////////////////////////////////////////////
bool TransformBlend::
has_transform(const VertexTransform *transform) const {
TransformEntry entry;
entry._transform = transform;
entry._weight = 0.0f;
Entries::const_iterator ei = _entries.find(entry);
return (ei != _entries.end());
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::get_weight
// Access: Published
// Description: Returns the weight associated with the indicated
// transform, or 0 if there is no entry for the
// transform.
////////////////////////////////////////////////////////////////////
float TransformBlend::
get_weight(const VertexTransform *transform) const {
TransformEntry entry;
entry._transform = transform;
entry._weight = 0.0f;
Entries::const_iterator ei = _entries.find(entry);
if (ei != _entries.end()) {
return (*ei)._weight;
}
return 0.0f;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::output
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformBlend::
output(ostream &out) const {
if (_entries.empty()) {
out << "empty";
} else {
Entries::const_iterator ei = _entries.begin();
out << *(*ei)._transform << ":" << (*ei)._weight;
++ei;
while (ei != _entries.end()) {
out << " " << *(*ei)._transform << ":" << (*ei)._weight;
++ei;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformBlend::
write(ostream &out, int indent_level) const {
Entries::const_iterator ei;
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
indent(out, indent_level)
<< *(*ei)._transform << ":" << (*ei)._weight << "\n";
LMatrix4f mat;
(*ei)._transform->get_matrix(mat);
mat.write(out, indent_level + 4);
}
LMatrix4f blend;
get_blend(blend);
indent(out, indent_level)
<< "Blended result =\n";
blend.write(out, indent_level + 2);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::recompute_result
// Access: Private
// Description: Recomputes the blend result from the various
// VertexTransform objects, if necessary.
////////////////////////////////////////////////////////////////////
void TransformBlend::
recompute_result(TransformBlend::CDWriter &cdata) {
// Update the global_modified sequence number first, to prevent race
// conditions.
cdata->_global_modified = VertexTransform::get_global_modified();
// Now see if we really need to recompute.
UpdateSeq seq;
Entries::const_iterator ei;
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
seq = max(seq, (*ei)._transform->get_modified());
}
if (cdata->_modified != seq) {
// We do need to recompute.
cdata->_modified = seq;
cdata->_result.set(0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f);
for (ei = _entries.begin(); ei != _entries.end(); ++ei) {
(*ei)._transform->accumulate_matrix(cdata->_result, (*ei)._weight);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::clear_result
// Access: Private
// Description: Removes the computed result to force it to be
// recomputed.
////////////////////////////////////////////////////////////////////
void TransformBlend::
clear_result() {
CDWriter cdata(_cycler);
cdata->_global_modified = UpdateSeq();
if (cdata->_modified != UpdateSeq()) {
cdata->_modified = UpdateSeq();
cdata->_result = LMatrix4f::ident_mat();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::write_datagram
// Access: Public
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TransformBlend::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::complete_pointers
// Access: Public
// Description: Receives an array of pointers, one for each time
// manager->read_pointer() was called in fillin().
// Returns the number of pointers processed.
////////////////////////////////////////////////////////////////////
int TransformBlend::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
return 0;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::fillin
// Access: Public
// Description: This internal function is called by make_from_bam to
// read in all of the relevant data from the BamFile for
// the new PandaNode.
////////////////////////////////////////////////////////////////////
void TransformBlend::
fillin(DatagramIterator &scan, BamReader *manager) {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlend::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *TransformBlend::CData::
make_copy() const {
return new CData(*this);
}

View File

@ -0,0 +1,123 @@
// Filename: transformBlend.h
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 TRANSFORMBLEND_H
#define TRANSFORMBLEND_H
#include "pandabase.h"
#include "vertexTransform.h"
#include "pointerTo.h"
#include "pvector.h"
#include "ordered_vector.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : TransformBlend
// Description : This defines a single entry in a
// TransformBlendPalette. It represents a unique
// combination of VertexTransform pointers and blend
// amounts.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TransformBlend {
PUBLISHED:
INLINE TransformBlend();
INLINE TransformBlend(const VertexTransform *transform0, float weight0);
INLINE TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1);
INLINE TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1,
const VertexTransform *transform2, float weight2);
INLINE TransformBlend(const VertexTransform *transform0, float weight0,
const VertexTransform *transform1, float weight1,
const VertexTransform *transform2, float weight2,
const VertexTransform *transform3, float weight3);
INLINE TransformBlend(const TransformBlend &copy);
INLINE void operator = (const TransformBlend &copy);
INLINE ~TransformBlend();
int compare_to(const TransformBlend &other) const;
INLINE bool operator < (const TransformBlend &other) const;
INLINE bool operator == (const TransformBlend &other) const;
INLINE bool operator != (const TransformBlend &other) const;
void add_transform(const VertexTransform *transform, float weight);
void remove_transform(const VertexTransform *transform);
void normalize_weights();
bool has_transform(const VertexTransform *transform) const;
float get_weight(const VertexTransform *transform) const;
INLINE int get_num_transforms() const;
INLINE const VertexTransform *get_transform(int n) const;
INLINE float get_weight(int n) const;
INLINE void get_blend(LMatrix4f &result) const;
INLINE void transform_point(LPoint4f &point) const;
INLINE UpdateSeq get_modified() const;
void output(ostream &out) const;
void write(ostream &out, int indent_level) const;
private:
class TransformEntry {
public:
INLINE bool operator < (const TransformEntry &other) const;
CPT(VertexTransform) _transform;
float _weight;
};
typedef ov_set<TransformEntry> Entries;
Entries _entries;
// This is the data that must be cycled between pipeline stages; it
// is just a local cache.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
LMatrix4f _result;
UpdateSeq _modified;
UpdateSeq _global_modified;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
void recompute_result(CDWriter &cdata);
void clear_result();
public:
void write_datagram(BamWriter *manager, Datagram &dg) const;
int complete_pointers(TypedWritable **plist, BamReader *manager);
void fillin(DatagramIterator &scan, BamReader *manager);
friend class VertexTransform;
};
INLINE ostream &operator << (ostream &out, const TransformBlend &obj);
#include "transformBlend.I"
#endif

View File

@ -0,0 +1,80 @@
// Filename: transformBlendPalette.I
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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: TransformBlendPalette::get_num_blends
// Access: Published
// Description: Returns the total number of different blend
// combinations in the palette.
////////////////////////////////////////////////////////////////////
INLINE int TransformBlendPalette::
get_num_blends() const {
return _blends.size();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::get_blend
// Access: Published
// Description: Returns the nth blend in the palette.
////////////////////////////////////////////////////////////////////
INLINE const TransformBlend &TransformBlendPalette::
get_blend(int n) const {
nassertr(n >= 0 && n < (int)_blends.size(), _blends[0]);
return _blends[n];
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::get_modified
// Access: Published
// Description: Returns a counter which is guaranteed to increment at
// least when any TransformBlends within the palette
// have changed.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq TransformBlendPalette::
get_modified() const {
CDReader cdata(_cycler);
if (cdata->_global_modified != VertexTransform::get_global_modified()) {
CDWriter cdataw(((TransformBlendPalette *)this)->_cycler, cdata);
((TransformBlendPalette *)this)->recompute_modified(cdataw);
return cdataw->_modified;
} else {
return cdata->_modified;
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlendPalette::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformBlendPalette::CData::
CData(const TransformBlendPalette::CData &copy) :
_modified(copy._modified),
_global_modified(copy._global_modified)
{
}

View File

@ -0,0 +1,269 @@
// Filename: transformBlendPalette.cxx
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "transformBlendPalette.h"
#include "indent.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle TransformBlendPalette::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
TransformBlendPalette::
TransformBlendPalette() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
TransformBlendPalette::
TransformBlendPalette(const TransformBlendPalette &copy) :
_blends(copy._blends)
{
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
operator = (const TransformBlendPalette &copy) {
_blends = copy._blends;
clear_index();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TransformBlendPalette::
~TransformBlendPalette() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::set_blend
// Access: Published
// Description: Replaces the blend at the nth position with the
// indicated value.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
set_blend(int n, const TransformBlend &blend) {
nassertv(n >= 0 && n < (int)_blends.size());
_blends[n] = blend;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::remove_blend
// Access: Published
// Description: Removes the blend at the nth position.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
remove_blend(int n) {
nassertv(n >= 0 && n < (int)_blends.size());
_blends.erase(_blends.begin() + n);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::add_blend
// Access: Published
// Description: Adds a new blend to the palette, and returns its
// index number. If there is already an identical blend
// in the palette, simply returns that number instead.
////////////////////////////////////////////////////////////////////
int TransformBlendPalette::
add_blend(const TransformBlend &blend) {
if (_blend_index.empty()) {
rebuild_index();
}
BlendIndex::iterator bi;
bi = _blend_index.find(&blend);
if (bi != _blend_index.end()) {
// Already had it.
return (*bi).second;
}
int new_position = (int)_blends.size();
_blends.push_back(blend);
clear_index();
return new_position;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
write(ostream &out) const {
for (int i = 0; i < (int)_blends.size(); i++) {
out << i << ". " << _blends[i] << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::clear_index
// Access: Private
// Description: Resets the index so that it will be rebuilt next time
// it is needed.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
clear_index() {
_blend_index.clear();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::rebuild_index
// Access: Private
// Description: Rebuilds the index so that we can easily determine
// what blend combinations are already present in the
// palette.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
rebuild_index() {
_blend_index.clear();
for (int i = 0; i < (int)_blends.size(); i++) {
_blend_index[&_blends[i]] = i;
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::recompute_modified
// Access: Private
// Description: Recomputes the modified stamp from the various
// TransformBlend objects, if necessary.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
recompute_modified(TransformBlendPalette::CDWriter &cdata) {
// Update the global_modified sequence number first, to prevent race
// conditions.
cdata->_global_modified = VertexTransform::get_global_modified();
// Now get the local modified number.
UpdateSeq seq;
Blends::const_iterator bi;
for (bi = _blends.begin(); bi != _blends.end(); ++bi) {
seq = max(seq, (*bi).get_modified());
}
cdata->_modified = seq;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::clear_modified
// Access: Private
// Description: Clears the modified stamp to force it to be
// recomputed.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
clear_modified() {
CDWriter cdata(_cycler);
cdata->_global_modified = UpdateSeq();
cdata->_modified = UpdateSeq();
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// TransformBlendPalette.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::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 TransformBlendPalette::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = TypedWritable::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type TransformBlendPalette is encountered
// in the Bam file. It should create the TransformBlendPalette
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *TransformBlendPalette::
make_from_bam(const FactoryParams &params) {
TransformBlendPalette *object = new TransformBlendPalette;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::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 TransformBlendPalette.
////////////////////////////////////////////////////////////////////
void TransformBlendPalette::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: TransformBlendPalette::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *TransformBlendPalette::CData::
make_copy() const {
return new CData(*this);
}

View File

@ -0,0 +1,141 @@
// Filename: transformBlendPalette.h
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 TRANSFORMBLENDPALETTE_H
#define TRANSFORMBLENDPALETTE_H
#include "pandabase.h"
#include "transformBlend.h"
#include "vertexTransform.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "pvector.h"
#include "pmap.h"
#include "indirectLess.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : TransformBlendPalette
// Description : This structure collects together the different
// combinations of transforms and blend amounts used by
// a GeomVertexData, to facilitate computing dynamic
// vertices on the CPU at runtime. Each vertex has a
// pointer to exactly one of entries in this palette,
// and each entry defines a number of transform/blend
// combinations.
//
// This structure is used for a GeomVertexData set up to
// compute its dynamic vertices on the CPU. See
// TransformPalette for one set up to compute its
// dynamic vertices on the graphics card.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TransformBlendPalette : public TypedWritableReferenceCount {
PUBLISHED:
TransformBlendPalette();
TransformBlendPalette(const TransformBlendPalette &copy);
void operator = (const TransformBlendPalette &copy);
virtual ~TransformBlendPalette();
INLINE int get_num_blends() const;
INLINE const TransformBlend &get_blend(int n) const;
INLINE UpdateSeq get_modified() const;
void set_blend(int n, const TransformBlend &blend);
void remove_blend(int n);
int add_blend(const TransformBlend &blend);
void write(ostream &out) const;
private:
void clear_index();
void rebuild_index();
private:
// We don't bother with registering the palette, or protecting its
// data in a CycleData structure--the interface on GeomVertexData
// guarantees that the pointer will be copied if we modify the
// palette.
typedef pvector<TransformBlend> Blends;
Blends _blends;
// This map indexes directly into the above vector. That means any
// time we add or remove anything from the vector, we must
// completely rebuild the index (since the vector might reallocate,
// invalidating all the pointers into it).
typedef pmap<const TransformBlend *, int, IndirectLess<TransformBlend> > BlendIndex;
BlendIndex _blend_index;
// Even though we don't store the actual blend palette data in a
// CycleData structure, we do need to keep a local cache of the
// relevant modified stamps there, so it can be updated per-thread.
class EXPCL_PANDA CData : public CycleData {
public:
INLINE CData();
INLINE CData(const CData &copy);
virtual CycleData *make_copy() const;
UpdateSeq _modified;
UpdateSeq _global_modified;
};
PipelineCycler<CData> _cycler;
typedef CycleDataReader<CData> CDReader;
typedef CycleDataWriter<CData> CDWriter;
void recompute_modified(CDWriter &cdata);
void clear_modified();
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
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, "TransformBlendPalette",
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 VertexTransform;
};
INLINE ostream &operator << (ostream &out, const TransformBlendPalette &obj);
#include "transformBlendPalette.I"
#endif

View File

@ -0,0 +1,131 @@
// Filename: transformPalette.I
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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: TransformPalette::is_registered
// Access: Published
// Description: Returns true if this palette has been registered.
// Once it has been registered, the set of transforms in
// a TransformPalette may not be further modified; but
// it must be registered before it can be assigned to a
// Geom.
////////////////////////////////////////////////////////////////////
INLINE bool TransformPalette::
is_registered() const {
return _is_registered;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::register_palette
// Access: Published, Static
// Description: Registers a TransformPalette for use. This is
// similar to GeomVertexFormat::register_format(). Once
// registered, a TransformPalette may no longer be
// modified (although the individual VertexTransform
// objects may modify their reported transforms).
//
// This must be called before a palette 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(TransformPalette) TransformPalette::
register_palette(TransformPalette *palette) {
// We don't actually bother adding the palette object to a registry.
// This means there may be multiple copies of identical registered
// TransformPalettes. Big deal. We can always go back and make a
// registry later if we really need it.
if (palette->is_registered()) {
return palette;
}
palette->do_register();
return palette;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::get_num_transforms
// Access: Published
// Description: Returns the number of transforms in the palette.
////////////////////////////////////////////////////////////////////
INLINE int TransformPalette::
get_num_transforms() const {
return _transforms.size();
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::get_transform
// Access: Published
// Description: Returns the nth transform in the palette.
////////////////////////////////////////////////////////////////////
INLINE const VertexTransform *TransformPalette::
get_transform(int n) const {
nassertr(n >= 0 && n < (int)_transforms.size(), NULL);
return _transforms[n];
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::get_modified
// Access: Published
// Description: Returns a sequence number that's guaranteed to change
// at least when any VertexTransforms in the palette
// change. (However, this is only true for a registered
// palette. An unregistered palette may or may not
// reflect an update here when a VertexTransform
// changes.)
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq TransformPalette::
get_modified() const {
CDReader cdata(_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::update_modified
// Access: Private
// Description: Called internally whenever a nested VertexTransform
// reports that it has been modified.
////////////////////////////////////////////////////////////////////
INLINE void TransformPalette::
update_modified(UpdateSeq) {
CDWriter cdata(_cycler);
++(cdata->_modified);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformPalette::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE TransformPalette::CData::
CData(const TransformPalette::CData &copy) :
_modified(copy._modified)
{
}

View File

@ -0,0 +1,259 @@
// Filename: transformPalette.cxx
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "transformPalette.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle TransformPalette::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
TransformPalette::
TransformPalette() :
_is_registered(false)
{
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::Copy Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
TransformPalette::
TransformPalette(const TransformPalette &copy) :
_is_registered(false),
_transforms(copy._transforms)
{
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::Copy Assignment Operator
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformPalette::
operator = (const TransformPalette &copy) {
nassertv(!_is_registered);
_transforms = copy._transforms;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
TransformPalette::
~TransformPalette() {
if (_is_registered) {
do_unregister();
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::set_transform
// Access: Published
// Description: Replaces the nth transform. Only valid for
// unregistered palettes.
////////////////////////////////////////////////////////////////////
void TransformPalette::
set_transform(int n, VertexTransform *transform) {
nassertv(!_is_registered);
nassertv(n >= 0 && n < (int)_transforms.size());
_transforms[n] = transform;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::remove_transform
// Access: Published
// Description: Removes the nth transform. Only valid for
// unregistered palettes.
////////////////////////////////////////////////////////////////////
void TransformPalette::
remove_transform(int n) {
nassertv(!_is_registered);
nassertv(n >= 0 && n < (int)_transforms.size());
_transforms.erase(_transforms.begin() + n);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::add_transform
// Access: Published
// Description: Adds a new transform to the palette and returns the
// index number of the new transform. Only valid for
// unregistered palettes.
////////////////////////////////////////////////////////////////////
int TransformPalette::
add_transform(VertexTransform *transform) {
nassertr(!_is_registered, -1);
int new_index = (int)_transforms.size();
_transforms.push_back(transform);
return new_index;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::write
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
void TransformPalette::
write(ostream &out) const {
for (size_t i = 0; i < _transforms.size(); ++i) {
out << i << ". " << *_transforms[i] << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::do_register
// Access: Private
// Description: Called internally when the palette is registered.
////////////////////////////////////////////////////////////////////
void TransformPalette::
do_register() {
nassertv(!_is_registered);
Transforms::iterator ti;
for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) {
bool inserted = (*ti)->_palettes.insert(this).second;
nassertv(inserted);
}
_is_registered = true;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::do_unregister
// Access: Private
// Description: Called internally when the palette is unregistered
// (i.e. right before destruction).
////////////////////////////////////////////////////////////////////
void TransformPalette::
do_unregister() {
nassertv(_is_registered);
Transforms::iterator ti;
for (ti = _transforms.begin(); ti != _transforms.end(); ++ti) {
(*ti)->_palettes.erase(this);
}
_is_registered = false;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// TransformPalette.
////////////////////////////////////////////////////////////////////
void TransformPalette::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TransformPalette::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type TransformPalette is encountered
// in the Bam file. It should create the TransformPalette
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *TransformPalette::
make_from_bam(const FactoryParams &params) {
TransformPalette *object = new TransformPalette;
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::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 TransformPalette.
////////////////////////////////////////////////////////////////////
void TransformPalette::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *TransformPalette::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void TransformPalette::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::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 TransformPalette::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: TransformPalette::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 TransformPalette.
////////////////////////////////////////////////////////////////////
void TransformPalette::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,127 @@
// Filename: transformPalette.h
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 TRANSFORMPALETTE_H
#define TRANSFORMPALETTE_H
#include "pandabase.h"
#include "vertexTransform.h"
#include "typedWritableReferenceCount.h"
#include "pointerTo.h"
#include "luse.h"
#include "pvector.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : TransformPalette
// Description : Stores the total set of VertexTransforms that the
// vertices in a particular GeomVertexData object might
// depend on.
//
// This structure is used for a GeomVertexData set up to
// compute its dynamic vertices on the graphics card.
// See TransformBlendPalette for one set up to compute
// its dynamic vertices on the CPU.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA TransformPalette : public TypedWritableReferenceCount {
PUBLISHED:
TransformPalette();
TransformPalette(const TransformPalette &copy);
void operator = (const TransformPalette &copy);
virtual ~TransformPalette();
INLINE bool is_registered() const;
INLINE static CPT(TransformPalette) register_palette(TransformPalette *palette);
INLINE int get_num_transforms() const;
INLINE const VertexTransform *get_transform(int n) const;
INLINE UpdateSeq get_modified() const;
void set_transform(int n, VertexTransform *transform);
void remove_transform(int n);
int add_transform(VertexTransform *transform);
void write(ostream &out) const;
private:
void do_register();
void do_unregister();
INLINE void update_modified(UpdateSeq modified);
private:
bool _is_registered;
typedef pvector< PT(VertexTransform) > Transforms;
Transforms _transforms;
// 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, "TransformPalette",
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 VertexTransform;
};
INLINE ostream &operator << (ostream &out, const TransformPalette &obj);
#include "transformPalette.I"
#endif

View File

@ -0,0 +1,63 @@
// Filename: userVertexTransform.I
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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: UserVertexTransform::get_name
// Access: Published
// Description: Returns the name passed to the constructor.
// Completely arbitrary.
////////////////////////////////////////////////////////////////////
INLINE const string &UserVertexTransform::
get_name() const {
return _name;
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::set_matrix
// Access: Published
// Description: Stores the indicated matrix.
////////////////////////////////////////////////////////////////////
INLINE void UserVertexTransform::
set_matrix(const LMatrix4f &matrix) {
CDWriter cdata(_cycler);
cdata->_matrix = matrix;
mark_modified();
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE UserVertexTransform::CData::
CData() :
_matrix(LMatrix4f::ident_mat())
{
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE UserVertexTransform::CData::
CData(const UserVertexTransform::CData &copy) :
_matrix(copy._matrix)
{
}

View File

@ -0,0 +1,144 @@
// Filename: userVertexTransform.cxx
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "userVertexTransform.h"
#include "bamReader.h"
#include "bamWriter.h"
TypeHandle UserVertexTransform::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
UserVertexTransform::
UserVertexTransform(const string &name) :
_name(name)
{
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::get_matrix
// Access: Published, Virtual
// Description: Stores the transform's matrix in the indicated value.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
get_matrix(LMatrix4f &matrix) const {
CDReader cdata(_cycler);
matrix = cdata->_matrix;
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
output(ostream &out) const {
out << get_name();
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *UserVertexTransform::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::register_with_read_factory
// Access: Public, Static
// Description: Tells the BamReader how to create objects of type
// UserVertexTransform.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
manager->write_cdata(dg, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::make_from_bam
// Access: Protected, Static
// Description: This function is called by the BamReader's factory
// when a new object of type UserVertexTransform is encountered
// in the Bam file. It should create the UserVertexTransform
// and extract its information from the file.
////////////////////////////////////////////////////////////////////
TypedWritable *UserVertexTransform::
make_from_bam(const FactoryParams &params) {
UserVertexTransform *object = new UserVertexTransform("");
DatagramIterator scan;
BamReader *manager;
parse_params(params, scan, manager);
object->fillin(scan, manager);
return object;
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::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 UserVertexTransform.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
manager->read_cdata(scan, _cycler);
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: UserVertexTransform::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 UserVertexTransform.
////////////////////////////////////////////////////////////////////
void UserVertexTransform::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,96 @@
// Filename: userVertexTransform.h
// Created by: drose (24Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 USERVERTEXTRANSFORM_H
#define USERVERTEXTRANSFORM_H
#include "pandabase.h"
#include "vertexTransform.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
////////////////////////////////////////////////////////////////////
// Class : UserVertexTransform
// Description : This is a specialization on VertexTransform that
// allows the user to specify any arbitrary transform
// matrix he likes. This is rarely used except for
// testing.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA UserVertexTransform : public VertexTransform {
PUBLISHED:
UserVertexTransform(const string &name);
INLINE const string &get_name() const;
INLINE void set_matrix(const LMatrix4f &matrix);
virtual void get_matrix(LMatrix4f &matrix) const;
virtual void output(ostream &out) const;
private:
string _name;
// 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);
LMatrix4f _matrix;
};
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() {
VertexTransform::init_type();
register_type(_type_handle, "UserVertexTransform",
VertexTransform::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 "userVertexTransform.I"
#endif

View File

@ -0,0 +1,71 @@
// Filename: vertexTransform.I
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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: VertexTransform::get_modified
// Access: Published
// Description: Returns a sequence number that's guaranteed to change
// at least every time the value reported by
// get_matrix() changes.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq VertexTransform::
get_modified() const {
CDReader cdata(_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::get_global_modified
// Access: Published, Static
// Description: Returns the currently highest
// VertexTransform::get_modified() value in the world.
// This can be used as a quick way to determine if any
// VertexTransforms have changed value recently.
////////////////////////////////////////////////////////////////////
INLINE UpdateSeq VertexTransform::
get_global_modified() {
CDReader cdata(_global_cycler);
return cdata->_modified;
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::CData::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexTransform::CData::
CData() {
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::CData::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
INLINE VertexTransform::CData::
CData(const VertexTransform::CData &copy) :
_modified(copy._modified)
{
}
INLINE ostream &
operator << (ostream &out, const VertexTransform &obj) {
obj.output(out);
return out;
}

View File

@ -0,0 +1,217 @@
// Filename: vertexTransform.cxx
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 "vertexTransform.h"
#include "bamReader.h"
#include "bamWriter.h"
#include "indent.h"
PipelineCycler<VertexTransform::CData> VertexTransform::_global_cycler;
UpdateSeq VertexTransform::_next_modified;
TypeHandle VertexTransform::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::Constructor
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
VertexTransform::
VertexTransform() {
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::Destructor
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
VertexTransform::
~VertexTransform() {
// We shouldn't destruct while any TransformPalettes are holding our
// pointer.
nassertv(_palettes.empty());
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::accumulate_matrix
// Access: Published, Virtual
// Description: Adds the value of this transform's matrix, modified
// by the indicated weight, into the indicated
// accumulation matrix. This is used to compute the
// result of several blended transforms.
////////////////////////////////////////////////////////////////////
void VertexTransform::
accumulate_matrix(LMatrix4f &accum, float weight) const {
LMatrix4f me;
get_matrix(me);
accum._m.m._00 += me._m.m._00 * weight;
accum._m.m._01 += me._m.m._01 * weight;
accum._m.m._02 += me._m.m._02 * weight;
accum._m.m._03 += me._m.m._03 * weight;
accum._m.m._10 += me._m.m._10 * weight;
accum._m.m._11 += me._m.m._11 * weight;
accum._m.m._12 += me._m.m._12 * weight;
accum._m.m._13 += me._m.m._13 * weight;
accum._m.m._20 += me._m.m._20 * weight;
accum._m.m._21 += me._m.m._21 * weight;
accum._m.m._22 += me._m.m._22 * weight;
accum._m.m._23 += me._m.m._23 * weight;
accum._m.m._30 += me._m.m._30 * weight;
accum._m.m._31 += me._m.m._31 * weight;
accum._m.m._32 += me._m.m._32 * weight;
accum._m.m._33 += me._m.m._33 * weight;
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::output
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VertexTransform::
output(ostream &out) const {
out << get_type();
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::write
// Access: Published, Virtual
// Description:
////////////////////////////////////////////////////////////////////
void VertexTransform::
write(ostream &out, int indent_level) const {
indent(out, indent_level)
<< *this << ":\n";
LMatrix4f mat;
get_matrix(mat);
mat.write(out, indent_level + 2);
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::get_next_modified
// Access: Public, Static
// Description: Returns a monotonically increasing sequence. Each
// time this is called, a new sequence number is
// returned, higher than the previous value.
//
// This is used to ensure that all
// VertexTransform::get_modified() calls return an
// increasing number in the same space, so that
// TransformBlend::get_modified() is easy to determine.
// It is similar to Geom::get_modified(), but it is in a
// different space.
////////////////////////////////////////////////////////////////////
UpdateSeq VertexTransform::
get_next_modified() {
++_next_modified;
CDWriter cdatag(_global_cycler);
cdatag->_modified = _next_modified;
return _next_modified;
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::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_matrix() may not
// be propagated through the system.
////////////////////////////////////////////////////////////////////
void VertexTransform::
mark_modified() {
CDWriter cdata(_cycler);
cdata->_modified = get_next_modified();
Palettes::iterator pi;
for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) {
(*pi)->update_modified(cdata->_modified);
}
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void VertexTransform::
write_datagram(BamWriter *manager, Datagram &dg) {
TypedWritable::write_datagram(manager, dg);
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::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 VertexTransform.
////////////////////////////////////////////////////////////////////
void VertexTransform::
fillin(DatagramIterator &scan, BamReader *manager) {
TypedWritable::fillin(scan, manager);
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::CData::make_copy
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
CycleData *VertexTransform::CData::
make_copy() const {
return new CData(*this);
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::CData::write_datagram
// Access: Public, Virtual
// Description: Writes the contents of this object to the datagram
// for shipping out to a Bam file.
////////////////////////////////////////////////////////////////////
void VertexTransform::CData::
write_datagram(BamWriter *manager, Datagram &dg) const {
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::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 VertexTransform::CData::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = CycleData::complete_pointers(p_list, manager);
return pi;
}
////////////////////////////////////////////////////////////////////
// Function: VertexTransform::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 VertexTransform.
////////////////////////////////////////////////////////////////////
void VertexTransform::CData::
fillin(DatagramIterator &scan, BamReader *manager) {
}

View File

@ -0,0 +1,118 @@
// Filename: vertexTransform.h
// Created by: drose (23Mar05)
//
////////////////////////////////////////////////////////////////////
//
// 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 VERTEXTRANSFORM_H
#define VERTEXTRANSFORM_H
#include "pandabase.h"
#include "typedWritableReferenceCount.h"
#include "updateSeq.h"
#include "luse.h"
#include "pset.h"
#include "cycleData.h"
#include "cycleDataReader.h"
#include "cycleDataWriter.h"
#include "pipelineCycler.h"
class TransformPalette;
////////////////////////////////////////////////////////////////////
// Class : VertexTransform
// Description : This is an abstract base class that holds a pointer
// to some transform, computed in some arbitrary way,
// that is to be applied to vertices during rendering.
// This is used to implement soft-skinned and animated
// vertices. Derived classes will define how the
// transform is actually computed.
//
// This is part of the experimental Geom rewrite.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA VertexTransform : public TypedWritableReferenceCount {
PUBLISHED:
VertexTransform();
virtual ~VertexTransform();
virtual void get_matrix(LMatrix4f &matrix) const=0;
virtual void accumulate_matrix(LMatrix4f &accum, float weight) const;
INLINE UpdateSeq get_modified() const;
virtual void output(ostream &out) const;
virtual void write(ostream &out, int indent_level) const;
static UpdateSeq get_next_modified();
INLINE static UpdateSeq get_global_modified();
protected:
void mark_modified();
private:
typedef pset<TransformPalette *> Palettes;
Palettes _palettes;
// 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, "VertexTransform",
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 TransformPalette;
};
INLINE ostream &operator << (ostream &out, const VertexTransform &obj);
#include "vertexTransform.I"
#endif

View File

@ -38,6 +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->compute_vertices();
_geom = qpgeom;
}
}