From 6f69411aac8a6be0048c55bc0066c421edc02f8e Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 8 Oct 2010 21:11:39 +0000 Subject: [PATCH] flatten --- panda/src/speedtree/speedTreeNode.cxx | 129 +++++++++++++++++++++----- panda/src/speedtree/speedTreeNode.h | 15 ++- panda/src/speedtree/stTransform.I | 92 ++++++++++++++++++ panda/src/speedtree/stTransform.h | 6 ++ 4 files changed, 215 insertions(+), 27 deletions(-) diff --git a/panda/src/speedtree/speedTreeNode.cxx b/panda/src/speedtree/speedTreeNode.cxx index 212503e144..656faf4916 100644 --- a/panda/src/speedtree/speedTreeNode.cxx +++ b/panda/src/speedtree/speedTreeNode.cxx @@ -30,6 +30,7 @@ #include "directionalLight.h" #include "loader.h" #include "deg_2_rad.h" +#include "sceneGraphReducer.h" #ifdef SPEEDTREE_OPENGL #include "glew/glew.h" @@ -280,6 +281,54 @@ add_instances(const NodePath &root, const TransformState *transform) { Thread::get_current_thread()); } +//////////////////////////////////////////////////////////////////// +// Function: SpeedTreeNode::add_instances_from +// Access: Published +// Description: Adds all of the instances defined within the +// indicated SpeedTreeNode as instances of this node. +// Does not recurse to children. +//////////////////////////////////////////////////////////////////// +void SpeedTreeNode:: +add_instances_from(const SpeedTreeNode *other) { + int num_trees = other->get_num_trees(); + for (int ti = 0; ti < num_trees; ++ti) { + const InstanceList &other_instance_list = other->get_instance_list(ti); + const STTree *tree = other_instance_list.get_tree(); + InstanceList &this_instance_list = add_tree(tree); + + int num_instances = other_instance_list.get_num_instances(); + for (int i = 0; i < num_instances; ++i) { + STTransform other_trans = other_instance_list.get_instance(i); + this_instance_list.add_instance(other_trans); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: SpeedTreeNode::add_instances_from +// Access: Published +// Description: Adds all of the instances defined within the +// indicated SpeedTreeNode as instances of this node, +// after applying the indicated scene-graph transform. +// Does not recurse to children. +//////////////////////////////////////////////////////////////////// +void SpeedTreeNode:: +add_instances_from(const SpeedTreeNode *other, const TransformState *transform) { + int num_trees = other->get_num_trees(); + for (int ti = 0; ti < num_trees; ++ti) { + const InstanceList &other_instance_list = other->get_instance_list(ti); + const STTree *tree = other_instance_list.get_tree(); + InstanceList &this_instance_list = add_tree(tree); + + int num_instances = other_instance_list.get_num_instances(); + for (int i = 0; i < num_instances; ++i) { + CPT(TransformState) other_trans = other_instance_list.get_instance(i); + CPT(TransformState) new_trans = transform->compose(other_trans); + this_instance_list.add_instance(new_trans.p()); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: SpeedTreeNode::add_from_stf // Access: Published @@ -507,18 +556,63 @@ make_copy() const { } //////////////////////////////////////////////////////////////////// -// Function: SpeedTreeNode::safe_to_combine +// Function: SpeedTreeNode::combine_with // Access: Public, Virtual -// Description: Returns true if it is generally safe to combine this -// particular kind of PandaNode with other kinds of -// PandaNodes of compatible type, adding children or -// whatever. For instance, an LODNode should not be -// combined with any other PandaNode, because its set of -// children is meaningful. +// Description: Collapses this node with the other node, if possible, +// and returns a pointer to the combined node, or NULL +// if the two nodes cannot safely be combined. +// +// The return value may be this, other, or a new node +// altogether. +// +// This function is called from GraphReducer::flatten(), +// and need not deal with children; its job is just to +// decide whether to collapse the two nodes and what the +// collapsed node should look like. //////////////////////////////////////////////////////////////////// -bool SpeedTreeNode:: -safe_to_combine() const { - return false; +PandaNode *SpeedTreeNode:: +combine_with(PandaNode *other) { + if (is_exact_type(get_class_type()) && + other->is_exact_type(get_class_type())) { + // Two SpeedTreeNodes can combine by moving trees from one to the + // other, similar to the way GeomNodes combine. + SpeedTreeNode *gother = DCAST(SpeedTreeNode, other); + add_instances_from(gother); + return this; + } + + return PandaNode::combine_with(other); +} + +//////////////////////////////////////////////////////////////////// +// Function: SpeedTreeNode::apply_attribs_to_vertices +// Access: Public, Virtual +// Description: Applies whatever attributes are specified in the +// AccumulatedAttribs object (and by the attrib_types +// bitmask) to the vertices on this node, if +// appropriate. If this node uses geom arrays like a +// GeomNode, the supplied GeomTransformer may be used to +// unify shared arrays across multiple different nodes. +// +// This is a generalization of xform(). +//////////////////////////////////////////////////////////////////// +void SpeedTreeNode:: +apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types, + GeomTransformer &transformer) { + if ((attrib_types & SceneGraphReducer::TT_transform) != 0) { + STTransform xform = attribs._transform; + Trees::iterator ti; + for (ti = _trees.begin(); ti != _trees.end(); ++ti) { + InstanceList *instance_list = (*ti); + STInstances &instances = instance_list->_instances; + STInstances::iterator sti; + for (sti = instances.begin(); sti != instances.end(); ++sti) { + STTransform orig_transform = *sti; + (*sti) = orig_transform * xform; + } + } + } + mark_internal_bounds_stale(); } //////////////////////////////////////////////////////////////////// @@ -795,20 +889,7 @@ r_add_instances(PandaNode *node, const TransformState *transform, Thread *current_thread) { if (node->is_of_type(SpeedTreeNode::get_class_type()) && node != this) { SpeedTreeNode *other = DCAST(SpeedTreeNode, node); - - int num_trees = other->get_num_trees(); - for (int ti = 0; ti < num_trees; ++ti) { - const InstanceList &other_instance_list = other->get_instance_list(ti); - const STTree *tree = other_instance_list.get_tree(); - InstanceList &this_instance_list = add_tree(tree); - - int num_instances = other_instance_list.get_num_instances(); - for (int i = 0; i < num_instances; ++i) { - CPT(TransformState) other_trans = other_instance_list.get_instance(i); - CPT(TransformState) new_trans = transform->compose(other_trans); - this_instance_list.add_instance(new_trans.p()); - } - } + add_instances_from(other, transform); } Children children = node->get_children(current_thread); diff --git a/panda/src/speedtree/speedTreeNode.h b/panda/src/speedtree/speedTreeNode.h index 949cc10619..664feab5e1 100644 --- a/panda/src/speedtree/speedTreeNode.h +++ b/panda/src/speedtree/speedTreeNode.h @@ -39,8 +39,12 @@ class Loader; //////////////////////////////////////////////////////////////////// // Class : SpeedTreeNode // Description : Interfaces with the SpeedTree library to render -// SpeedTree objects like a collection of trees, -// terrain, or grass within the Panda3D scene graph. +// SpeedTree objects, especially trees, within the +// Panda3D scene graph. +// +// SpeedTree also includes some support for simple +// terrain and grass systems, but that support is not +// (yet) implemented within this layer. //////////////////////////////////////////////////////////////////// class EXPCL_PANDASPEEDTREE SpeedTreeNode : public PandaNode { private: @@ -100,6 +104,8 @@ PUBLISHED: void add_instance(const STTree *tree, const STTransform &transform); void add_instances(const NodePath &root, const TransformState *transform = TransformState::make_identity()); + void add_instances_from(const SpeedTreeNode *other); + void add_instances_from(const SpeedTreeNode *other, const TransformState *transform); bool add_from_stf(const Filename &pathname, const LoaderOptions &options = LoaderOptions()); bool add_from_stf(istream &in, const Filename &pathname, @@ -112,7 +118,10 @@ public: SpeedTreeNode(const SpeedTreeNode ©); virtual PandaNode *make_copy() const; - virtual bool safe_to_combine() const; + virtual PandaNode *combine_with(PandaNode *other); + virtual void apply_attribs_to_vertices(const AccumulatedAttribs &attribs, + int attrib_types, + GeomTransformer &transformer); virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data); virtual bool is_renderable() const; diff --git a/panda/src/speedtree/stTransform.I b/panda/src/speedtree/stTransform.I index 9ee81c86af..5dea85de3c 100644 --- a/panda/src/speedtree/stTransform.I +++ b/panda/src/speedtree/stTransform.I @@ -128,3 +128,95 @@ INLINE const STTransform &STTransform:: ident_mat() { return _ident_mat; } + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::set_pos +// Access: Published +// Description: Replaces the translation component. +//////////////////////////////////////////////////////////////////// +INLINE void STTransform:: +set_pos(const LPoint3f &pos) { + _pos = pos; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::get_pos +// Access: Published +// Description: Returns the translation component. +//////////////////////////////////////////////////////////////////// +INLINE const LPoint3f &STTransform:: +get_pos() const { + return _pos; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::set_rotate +// Access: Published +// Description: Replaces the rotation component. Accepts a rotation +// in degrees counter-clockwise around the vertical +// axis. +//////////////////////////////////////////////////////////////////// +INLINE void STTransform:: +set_rotate(float rotate) { + _rotate = rotate; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::get_rotate +// Access: Published +// Description: Returns the rotation component, in degrees +// counter-clockwise around the vertical axis. +//////////////////////////////////////////////////////////////////// +INLINE float STTransform:: +get_rotate() const { + return _rotate; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::set_scale +// Access: Published +// Description: Replaces the scale component. Accepts a uniform +// scale value. +//////////////////////////////////////////////////////////////////// +INLINE void STTransform:: +set_scale(float scale) { + _scale = scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::get_scale +// Access: Published +// Description: Returns the scale component, as a uniform scale +// value. +//////////////////////////////////////////////////////////////////// +INLINE float STTransform:: +get_scale() const { + return _scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::operator *= +// Access: Published +// Description: Composes these transforms and stores the result +// in-place. +//////////////////////////////////////////////////////////////////// +INLINE void STTransform:: +operator *= (const STTransform &other) { + LQuaternionf quat; + quat.set_hpr(LVecBase3f(_rotate, 0.0f, 0.0f)); + _pos += quat.xform(other.get_pos()) * _scale; + _rotate += other._rotate; + _scale *= other._scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: STTransform::operator * +// Access: Published +// Description: Composes these transforms and returns the result/ +//////////////////////////////////////////////////////////////////// +INLINE STTransform STTransform:: +operator * (const STTransform &other) const { + STTransform result = *this; + result *= other; + return result; +} diff --git a/panda/src/speedtree/stTransform.h b/panda/src/speedtree/stTransform.h index 83d91c9428..72e8373c5a 100644 --- a/panda/src/speedtree/stTransform.h +++ b/panda/src/speedtree/stTransform.h @@ -43,10 +43,16 @@ public: PUBLISHED: INLINE static const STTransform &ident_mat(); + INLINE void set_pos(const LPoint3f &pos); INLINE const LPoint3f &get_pos() const; + INLINE void set_rotate(float rotate); INLINE float get_rotate() const; + INLINE void set_scale(float scale); INLINE float get_scale() const; + INLINE void operator *= (const STTransform &other); + INLINE STTransform operator * (const STTransform &other) const; + void output(ostream &out) const; private: