This commit is contained in:
David Rose 2010-10-08 21:11:39 +00:00
parent dcdbe1b699
commit 6f69411aac
4 changed files with 215 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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