David Rose 15 năm trước cách đây
mục cha
commit
6f69411aac

+ 105 - 24
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);

+ 12 - 3
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 &copy);
 
   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;

+ 92 - 0
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;
+}

+ 6 - 0
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: