Panda3D
rigidBodyCombiner.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file rigidBodyCombiner.cxx
10  * @author drose
11  * @date 2007-02-22
12  */
13 
14 #include "rigidBodyCombiner.h"
15 #include "nodePath.h"
16 #include "geomNode.h"
17 #include "modelNode.h"
18 #include "geomVertexData.h"
19 #include "geomVertexFormat.h"
20 #include "geomVertexArrayFormat.h"
22 #include "sceneGraphReducer.h"
23 #include "omniBoundingVolume.h"
24 #include "cullTraverserData.h"
25 
26 TypeHandle RigidBodyCombiner::_type_handle;
27 
28 
29 /**
30  *
31  */
32 RigidBodyCombiner::
33 RigidBodyCombiner(const std::string &name) : PandaNode(name) {
34  set_cull_callback();
35 
36  _internal_root = new PandaNode(name);
37 
38  // We don't want to perform any additional culling once we get within the
39  // RigidBodyCombiner. The internal Geom's bounding volume is not updated
40  // and might not be accurate. However, the bounding volume of the
41  // RigidBodyCombiner itself should be accurate, and this is sufficient.
42  _internal_root->set_bounds(new OmniBoundingVolume);
43  _internal_root->set_final(true);
44 }
45 
46 /**
47  *
48  */
49 RigidBodyCombiner::
50 RigidBodyCombiner(const RigidBodyCombiner &copy) : PandaNode(copy) {
51  set_cull_callback();
52 
53  _internal_root = copy._internal_root;
54  _internal_transforms = copy._internal_transforms;
55 }
56 
57 /**
58  * Returns a newly-allocated PandaNode that is a shallow copy of this one. It
59  * will be a different pointer, but its internal data may or may not be shared
60  * with that of the original PandaNode. No children will be copied.
61  */
62 PandaNode *RigidBodyCombiner::
63 make_copy() const {
64  return new RigidBodyCombiner(*this);
65 }
66 
67 /**
68  * Walks through the entire subgraph of nodes rooted at this node, accumulates
69  * all of the RenderAttribs and Geoms below this node, flattening them into
70  * just one Geom (or as few as possible, if there are multiple different
71  * states).
72  *
73  * Nodes that have transforms on them at the time of collect(), or any
74  * ModelNodes with the preserve_transform flag, will be identified as "moving"
75  * nodes, and their transforms will be monitored as they change in future
76  * frames and each new transform directly applied to the vertices.
77  *
78  * This call must be made after adding any nodes to or removing any nodes from
79  * the subgraph rooted at this node. It should not be made too often, as it
80  * is a relatively expensive call. If you need to hide children of this node,
81  * consider scaling them to zero (or very near zero), or moving them behind
82  * the camera, instead.
83  */
86  _internal_root = new GeomNode(get_name());
87  _internal_transforms.clear();
88  _vd_table.clear();
89 
90  Children cr = get_children();
91  int num_children = cr.get_num_children();
92  for (int i = 0; i < num_children; i++) {
93  r_collect(cr.get_child(i), RenderState::make_empty(), nullptr);
94  }
95 
96  _vd_table.clear();
97 
99  gr.apply_attribs(_internal_root);
100  gr.collect_vertex_data(_internal_root, ~(SceneGraphReducer::CVD_format | SceneGraphReducer::CVD_name | SceneGraphReducer::CVD_animation_type));
101  gr.unify(_internal_root, false);
102 }
103 
104 /**
105  * Returns a special NodePath that represents the internal node of this
106  * object. This is the node that is actually sent to the graphics card for
107  * rendering; it contains the collection of the children of this node into as
108  * few Geoms as possible.
109  *
110  * This node is filled up by the last call to collect().
111  */
114  return NodePath(_internal_root);
115 }
116 
117 /**
118  * This function will be called during the cull traversal to perform any
119  * additional operations that should be performed at cull time. This may
120  * include additional manipulation of render state or additional
121  * visible/invisible decisions, or any other arbitrary operation.
122  *
123  * Note that this function will *not* be called unless set_cull_callback() is
124  * called in the constructor of the derived class. It is necessary to call
125  * set_cull_callback() to indicated that we require cull_callback() to be
126  * called.
127  *
128  * By the time this function is called, the node has already passed the
129  * bounding-volume test for the viewing frustum, and the node's transform and
130  * state have already been applied to the indicated CullTraverserData object.
131  *
132  * The return value is true if this node should be visible, or false if it
133  * should be culled.
134  */
137  // Pretend that all of our transforms have been modified (since we don't
138  // really know which ones have).
139  Thread *current_thread = Thread::get_current_thread();
140  Transforms::iterator ti;
141  for (ti = _internal_transforms.begin();
142  ti != _internal_transforms.end();
143  ++ti) {
144  (*ti)->mark_modified(current_thread);
145  }
146 
147  // Render the internal scene only--this is the optimized scene.
148  CullTraverserData next_data(data, _internal_root);
149  trav->traverse(next_data);
150 
151  // Do not directly render the nodes beneath this node.
152  return false;
153 }
154 
155 /**
156  * Recursively visits each child or descedant of this node, accumulating state
157  * and transform as we go. When GeomNodes are encountered, their Geoms are
158  * extracted and added to the _internal_root node.
159  */
160 void RigidBodyCombiner::
161 r_collect(PandaNode *node, const RenderState *state,
162  const VertexTransform *transform) {
163  CPT(RenderState) next_state = state->compose(node->get_state());
164  CPT(VertexTransform) next_transform = transform;
165  if (!node->get_transform()->is_identity() ||
166  (node->is_of_type(ModelNode::get_class_type()) &&
167  DCAST(ModelNode, node)->get_preserve_transform() != ModelNode::PT_none)) {
168  // This node has a transform we need to keep.
169  PT(NodeVertexTransform) new_transform = new NodeVertexTransform(node, transform);
170  _internal_transforms.push_back(new_transform);
171  next_transform = new_transform.p();
172 
173  }
174 
175  if (node->is_geom_node()) {
176  GeomNode *gnode = DCAST(GeomNode, node);
177  GeomNode *root_gnode = DCAST(GeomNode, _internal_root);
178 
179  int num_geoms = gnode->get_num_geoms();
180  for (int i = 0; i < num_geoms; ++i) {
181  PT(Geom) geom = gnode->get_geom(i)->make_copy();
182  if (next_transform != nullptr) {
183  geom->set_vertex_data(convert_vd(next_transform, geom->get_vertex_data()));
184  }
185  CPT(RenderState) gstate = next_state->compose(gnode->get_geom_state(i));
186  root_gnode->add_geom(geom, gstate);
187  }
188  }
189 
190  Children cr = node->get_children();
191  int num_children = cr.get_num_children();
192  for (int i = 0; i < num_children; i++) {
193  r_collect(cr.get_child(i), next_state, next_transform);
194  }
195 }
196 
197 /**
198  * Converts a GeomVertexData to a new form in which all of the vertices are
199  * transformed by the node's transform.
200  */
201 PT(GeomVertexData) RigidBodyCombiner::
202 convert_vd(const VertexTransform *transform, const GeomVertexData *orig) {
203  // First, unify this operation for unique transformdata combinations. If we
204  // encounter a given GeomVertexData more than once under the same transform,
205  // we should return exactly the same GeomVertexData.
206  VDTable::iterator vdti = _vd_table.find(VDUnifier(transform, orig));
207  if (vdti != _vd_table.end()) {
208  return (*vdti).second;
209  }
210 
211  PT(GeomVertexFormat) format = new GeomVertexFormat(*orig->get_format());
212  if (!orig->get_format()->has_column(InternalName::get_transform_blend())) {
214  af->add_column(InternalName::get_transform_blend(), 1,
215  Geom::NT_uint16, Geom::C_index, 0, 2);
216  format->add_array(af);
217  }
218 
220  spec.set_panda();
221  format->set_animation(spec);
222  format->maybe_align_columns_for_animation();
223 
224  CPT(GeomVertexFormat) new_format = GeomVertexFormat::register_format(format);
225  CPT(GeomVertexData) converted = orig->convert_to(new_format);
226  PT(GeomVertexData) new_data = new GeomVertexData(*converted);
227 
228  if (new_data->get_transform_blend_table() == nullptr) {
229  // Create a new table that has just the one blend: all vertices hard-
230  // assigned to the indicated transform.
231  PT(TransformBlendTable) new_table = new TransformBlendTable;
232  new_table->add_blend(TransformBlend(transform, 1.0f));
233  new_table->set_rows(SparseArray::range(0, new_data->get_num_rows()));
234  new_data->set_transform_blend_table(new_table);
235  } else {
236  // The GeomVertexData already has a TransformBlendTable. In this case,
237  // we'll have to adjust it. TODO.
238  }
239 
240  // Store the result for the next time.
241  _vd_table[VDUnifier(transform, orig)] = new_data;
242 
243  return new_data;
244 }
Geom
A container for geometry primitives.
Definition: geom.h:54
geomVertexData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodeVertexTransform
This VertexTransform gets its matrix from the Transform stored on a node.
Definition: nodeVertexTransform.h:29
RigidBodyCombiner::get_internal_scene
get_internal_scene
Returns a special NodePath that represents the internal node of this object.
Definition: rigidBodyCombiner.h:55
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::is_geom_node
virtual bool is_geom_node() const
A simple downcast check.
Definition: pandaNode.cxx:2062
SceneGraphReducer
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
Definition: sceneGraphReducer.h:39
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
TransformBlend
This defines a single entry in a TransformBlendTable.
Definition: transformBlend.h:32
PT
PT(GeomVertexData) RigidBodyCombiner
Converts a GeomVertexData to a new form in which all of the vertices are transformed by the node's tr...
Definition: rigidBodyCombiner.cxx:201
sceneGraphReducer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
RigidBodyCombiner::collect
void collect()
Walks through the entire subgraph of nodes rooted at this node, accumulates all of the RenderAttribs ...
Definition: rigidBodyCombiner.cxx:85
GeomVertexData::get_format
get_format
Returns a pointer to the GeomVertexFormat structure that defines this data.
Definition: geomVertexData.h:98
SceneGraphReducer::collect_vertex_data
int collect_vertex_data(PandaNode *root, int collect_bits=~0)
Collects all different GeomVertexData blocks that have compatible formats at this node and below into...
Definition: sceneGraphReducer.I:139
modelNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PandaNode::Children::get_child
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition: pandaNode.I:962
RigidBodyCombiner
This is a special node that combines multiple independently-moving rigid nodes into one Geom internal...
Definition: rigidBodyCombiner.h:44
geomVertexArrayFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexAnimationSpec::set_panda
void set_panda()
Specifies that vertex animation is to be performed by Panda.
Definition: geomVertexAnimationSpec.I:88
RigidBodyCombiner::cull_callback
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
Definition: rigidBodyCombiner.cxx:136
PandaNode::get_children
get_children
Returns an object that can be used to walk through the list of children of the node.
Definition: pandaNode.h:782
GeomNode::get_num_geoms
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
SceneGraphReducer::unify
void unify(PandaNode *root, bool preserve_order)
Calls unify() on every GeomNode at this level and below.
Definition: sceneGraphReducer.cxx:178
Thread::get_current_thread
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
cullTraverserData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomVertexAnimationSpec
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
Definition: geomVertexAnimationSpec.h:38
PandaNode::Children
Definition: pandaNode.h:706
geomVertexAnimationSpec.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::Children::get_num_children
size_t get_num_children() const
Returns the number of children of the node.
Definition: pandaNode.I:953
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
OmniBoundingVolume
This is a special kind of GeometricBoundingVolume that fills all of space.
Definition: omniBoundingVolume.h:24
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
ModelNode
This node is placed at key points within the scene graph to indicate the roots of "models": subtrees ...
Definition: modelNode.h:31
SceneGraphReducer::apply_attribs
void apply_attribs(PandaNode *node, int attrib_types=~(TT_clip_plane|TT_cull_face|TT_apply_texture_color))
Walks the scene graph, accumulating attribs of the indicated types, applying them to the vertices,...
Definition: sceneGraphReducer.I:78
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
SparseArray::range
static SparseArray range(int low_bit, int size)
Returns a SparseArray whose size bits, beginning at low_bit, are on.
Definition: sparseArray.I:65
omniBoundingVolume.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GeomNode::get_geom_state
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Definition: geomNode.h:75
TransformBlendTable::add_blend
size_t add_blend(const TransformBlend &blend)
Adds a new blend to the table, and returns its index number.
Definition: transformBlendTable.cxx:87
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomVertexFormat.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CullTraverser::traverse
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
Definition: cullTraverser.cxx:106
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
GeomNode::add_geom
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:584
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
TransformBlendTable
This structure collects together the different combinations of transforms and blend amounts used by a...
Definition: transformBlendTable.h:45
GeomVertexArrayFormat
This describes the structure of a single array within a Geom data.
Definition: geomVertexArrayFormat.h:47
VertexTransform
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
Definition: vertexTransform.h:35
rigidBodyCombiner.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28