Panda3D
Loading...
Searching...
No Matches
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"
22#include "sceneGraphReducer.h"
23#include "omniBoundingVolume.h"
24#include "cullTraverserData.h"
25
26TypeHandle RigidBodyCombiner::_type_handle;
27
28
29/**
30 *
31 */
32RigidBodyCombiner::
33RigidBodyCombiner(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 */
49RigidBodyCombiner::
50RigidBodyCombiner(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 */
62PandaNode *RigidBodyCombiner::
63make_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 */
85collect() {
86 _internal_root = new GeomNode(get_name());
87 _internal_transforms.clear();
88 _vd_table.clear();
89
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 */
160void RigidBodyCombiner::
161r_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 */
201PT(GeomVertexData) RigidBodyCombiner::
202convert_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}
This collects together the pieces of data that are accumulated for each node while walking the scene ...
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
void traverse(const NodePath &root)
Begins the traversal from the indicated node.
A node that holds Geom objects, renderable pieces of geometry.
Definition geomNode.h:34
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition geomNode.cxx:612
get_num_geoms
Returns the number of geoms in the node.
Definition geomNode.h:71
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Definition geomNode.h:75
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
void set_panda()
Specifies that vertex animation is to be performed by Panda.
This describes the structure of a single array within a Geom data.
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
get_format
Returns a pointer to the GeomVertexFormat structure that defines this data.
This class defines the physical layout of the vertex data stored within a Geom.
A container for geometry primitives.
Definition geom.h:54
This node is placed at key points within the scene graph to indicate the roots of "models": subtrees ...
Definition modelNode.h:31
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
This VertexTransform gets its matrix from the Transform stored on a node.
This is a special kind of GeometricBoundingVolume that fills all of space.
PandaNode * get_child(size_t n) const
Returns the nth child of the node.
Definition pandaNode.I:962
size_t get_num_children() const
Returns the number of children of the node.
Definition pandaNode.I:953
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
virtual bool is_geom_node() const
A simple downcast check.
get_children
Returns an object that can be used to walk through the list of children of the node.
Definition pandaNode.h:782
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition renderState.h:47
This is a special node that combines multiple independently-moving rigid nodes into one Geom internal...
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
void collect()
Walks through the entire subgraph of nodes rooted at this node, accumulates all of the RenderAttribs ...
get_internal_scene
Returns a special NodePath that represents the internal node of this object.
An interface for simplifying ("flattening") scene graphs by eliminating unneeded nodes and collapsing...
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...
void unify(PandaNode *root, bool preserve_order)
Calls unify() on every GeomNode at this level and below.
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,...
static SparseArray range(int low_bit, int size)
Returns a SparseArray whose size bits, beginning at low_bit, are on.
Definition sparseArray.I:65
A thread; that is, a lightweight process.
Definition thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition thread.h:109
This structure collects together the different combinations of transforms and blend amounts used by a...
size_t add_blend(const TransformBlend &blend)
Adds a new blend to the table, and returns its index number.
This defines a single entry in a TransformBlendTable.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition typedObject.I:28
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.