Panda3D
compassEffect.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 compassEffect.cxx
10  * @author drose
11  * @date 2002-07-16
12  */
13 
14 #include "compassEffect.h"
15 #include "cullTraverserData.h"
16 #include "config_pgraph.h"
17 #include "nodePath.h"
18 #include "bamReader.h"
19 #include "bamWriter.h"
20 #include "datagram.h"
21 #include "datagramIterator.h"
22 
23 TypeHandle CompassEffect::_type_handle;
24 
25 /**
26  * Constructs a new CompassEffect object. If the reference is an empty
27  * NodePath, it means the CompassEffect is relative to the root of the scene
28  * graph; otherwise, it's relative to the indicated node. The properties
29  * bitmask specifies the set of properties that the compass node inherits from
30  * the reference instead of from its parent.
31  */
32 CPT(RenderEffect) CompassEffect::
33 make(const NodePath &reference, int properties) {
34  CompassEffect *effect = new CompassEffect;
35  effect->_reference = reference;
36  effect->_properties = (properties & P_all);
37  return return_new(effect);
38 }
39 
40 /**
41  * Returns true if it is generally safe to transform this particular kind of
42  * RenderEffect by calling the xform() method, false otherwise.
43  */
44 bool CompassEffect::
46  return false;
47 }
48 
49 /**
50  *
51  */
52 void CompassEffect::
53 output(std::ostream &out) const {
54  out << get_type() << ":";
55  if (_properties == 0) {
56  out << " none";
57  }
58  if ((_properties & P_pos) == P_pos) {
59  out << " xyz";
60  } else {
61  if ((_properties & P_x) != 0) {
62  out << " x";
63  }
64  if ((_properties & P_y) != 0) {
65  out << " y";
66  }
67  if ((_properties & P_z) != 0) {
68  out << " z";
69  }
70  }
71  if ((_properties & P_rot) != 0) {
72  out << " rot";
73  }
74  if ((_properties & P_scale) == P_scale) {
75  out << " scale";
76  } else {
77  if ((_properties & P_sx) != 0) {
78  out << " sx";
79  }
80  if ((_properties & P_sy) != 0) {
81  out << " sy";
82  }
83  if ((_properties & P_sz) != 0) {
84  out << " sz";
85  }
86  }
87  if (!_reference.is_empty()) {
88  out << " reference " << _reference;
89  }
90 }
91 
92 /**
93  * Should be overridden by derived classes to return true if cull_callback()
94  * has been defined. Otherwise, returns false to indicate cull_callback()
95  * does not need to be called for this effect during the cull traversal.
96  */
97 bool CompassEffect::
99  return true;
100 }
101 
102 /**
103  * If has_cull_callback() returns true, this function will be called during
104  * the cull traversal to perform any additional operations that should be
105  * performed at cull time. This may include additional manipulation of render
106  * state or additional visible/invisible decisions, or any other arbitrary
107  * operation.
108  *
109  * At the time this function is called, the current node's transform and state
110  * have not yet been applied to the net_transform and net_state. This
111  * callback may modify the node_transform and node_state to apply an effective
112  * change to the render state at this level.
113  */
114 void CompassEffect::
116  CPT(TransformState) &node_transform,
117  CPT(RenderState) &) const {
118  if (_properties == 0) {
119  // Nothing to do.
120  return;
121  }
122 
123  CPT(TransformState) true_net_transform = data.get_net_transform(trav);
124  CPT(TransformState) want_net_transform = true_net_transform;
125  adjust_transform(want_net_transform, node_transform, data.node());
126 
127  // Now compute the transform that will convert true_net_transform to
128  // want_transform. This is inv(true_net_transform) * want_transform.
129  CPT(TransformState) compass_transform =
130  true_net_transform->invert_compose(want_net_transform);
131 
132  // And modify our local node's apparent transform so that
133  // true_net_transform->compose(new_node_transform) produces the same result
134  // we would have gotten had we actually computed
135  // want_transform->compose(orig_node_transform).
136  node_transform = compass_transform->compose(node_transform);
137 }
138 
139 /**
140  * Should be overridden by derived classes to return true if
141  * adjust_transform() has been defined, and therefore the RenderEffect has
142  * some effect on the node's apparent local and net transforms.
143  */
144 bool CompassEffect::
146  return (_properties != 0);
147 }
148 
149 /**
150  * Performs some operation on the node's apparent net and/or local transforms.
151  * This will only be called if has_adjust_transform() is redefined to return
152  * true.
153  *
154  * Both parameters are in/out. The original transforms will be passed in, and
155  * they may (or may not) be modified in-place by the RenderEffect.
156  */
157 void CompassEffect::
159  CPT(TransformState) &node_transform,
160  const PandaNode *) const {
161  if (_properties == 0) {
162  // Nothing to do.
163  return;
164  }
165 
166  // The reference transform: where we are acting as if we inherit from.
167  // Either the root node (identity) or the specified reference node.
168  CPT(TransformState) ref_transform;
169  if (_reference.is_empty()) {
170  ref_transform = TransformState::make_identity();
171  } else {
172  ref_transform = _reference.get_net_transform();
173  }
174 
175  // Now compute the net transform we actually want to achieve. This is all
176  // of the components from the net transform we want to inherit normally from
177  // our parent, with all of the components from the ref transform we want to
178  // inherit from our reference.
179  CPT(TransformState) want_net_transform;
180  if (_properties == P_all) {
181  // If we want to steal the whole transform, that's easy.
182  want_net_transform = ref_transform;
183 
184  } else {
185  // How much of the pos do we want to steal? We can always determine a
186  // transform's pos, even if it's nondecomposable.
187  LVecBase3 want_pos = net_transform->get_pos();
188  const LVecBase3 &ref_pos = ref_transform->get_pos();
189  if ((_properties & P_x) != 0) {
190  want_pos[0] = ref_pos[0];
191  }
192  if ((_properties & P_y) != 0) {
193  want_pos[1] = ref_pos[1];
194  }
195  if ((_properties & P_z) != 0) {
196  want_pos[2] = ref_pos[2];
197  }
198 
199  if ((_properties & ~P_pos) == 0) {
200  // If we only want to steal the pos, that's pretty easy.
201  want_net_transform = net_transform->set_pos(want_pos);
202 
203  } else if ((_properties & (P_rot | P_scale)) == (P_rot | P_scale)) {
204  // If we want to steal everything *but* the pos, also easy.
205  want_net_transform = ref_transform->set_pos(want_pos);
206 
207  } else {
208  // For any other combination, we have to be able to decompose both
209  // transforms.
210  if (!net_transform->has_components() ||
211  !ref_transform->has_components()) {
212  // If we can't decompose, just do the best we can: steal everything
213  // but the pos.
214  want_net_transform = ref_transform->set_pos(want_pos);
215 
216  } else {
217  // If we can decompose, then take only the components we want.
218  LQuaternion want_quat = net_transform->get_quat();
219  if ((_properties & P_rot) != 0) {
220  want_quat = ref_transform->get_quat();
221  }
222 
223  LVecBase3 want_scale = net_transform->get_scale();
224  const LVecBase3 &ref_scale = ref_transform->get_scale();
225  if ((_properties & P_sx) != 0) {
226  want_scale[0] = ref_scale[0];
227  }
228  if ((_properties & P_sy) != 0) {
229  want_scale[1] = ref_scale[1];
230  }
231  if ((_properties & P_sz) != 0) {
232  want_scale[2] = ref_scale[2];
233  }
234 
235  want_net_transform =
236  TransformState::make_pos_quat_scale(want_pos, want_quat, want_scale);
237  }
238  }
239  }
240 
241  net_transform = want_net_transform;
242 }
243 
244 /**
245  * Intended to be overridden by derived CompassEffect types to return a unique
246  * number indicating whether this CompassEffect is equivalent to the other
247  * one.
248  *
249  * This should return 0 if the two CompassEffect objects are equivalent, a
250  * number less than zero if this one should be sorted before the other one,
251  * and a number greater than zero otherwise.
252  *
253  * This will only be called with two CompassEffect objects whose get_type()
254  * functions return the same.
255  */
256 int CompassEffect::
257 compare_to_impl(const RenderEffect *other) const {
258  const CompassEffect *ta;
259  DCAST_INTO_R(ta, other, 0);
260 
261  if (_properties != ta->_properties) {
262  return _properties - ta->_properties;
263  }
264  int compare = _reference.compare_to(ta->_reference);
265  if (compare != 0) {
266  return compare;
267  }
268  return 0;
269 }
270 
271 /**
272  * Tells the BamReader how to create objects of type CompassEffect.
273  */
274 void CompassEffect::
276  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
277 }
278 
279 /**
280  * Writes the contents of this object to the datagram for shipping out to a
281  * Bam file.
282  */
283 void CompassEffect::
285  RenderEffect::write_datagram(manager, dg);
286  dg.add_uint16(_properties);
287 
288  if (manager->get_file_minor_ver() >= 43) {
289  _reference.write_datagram(manager, dg);
290  }
291 }
292 
293 /**
294  * Receives an array of pointers, one for each time manager->read_pointer()
295  * was called in fillin(). Returns the number of pointers processed.
296  */
297 int CompassEffect::
299  int pi = RenderEffect::complete_pointers(p_list, manager);
300 
301  if (manager->get_file_minor_ver() >= 43) {
302  pi += _reference.complete_pointers(p_list + pi, manager);
303  }
304 
305  return pi;
306 }
307 
308 /**
309  * This function is called by the BamReader's factory when a new object of
310  * type CompassEffect is encountered in the Bam file. It should create the
311  * CompassEffect and extract its information from the file.
312  */
313 TypedWritable *CompassEffect::
314 make_from_bam(const FactoryParams &params) {
315  CompassEffect *effect = new CompassEffect;
316  DatagramIterator scan;
317  BamReader *manager;
318 
319  parse_params(params, scan, manager);
320  effect->fillin(scan, manager);
321 
322  return effect;
323 }
324 
325 /**
326  * This internal function is called by make_from_bam to read in all of the
327  * relevant data from the BamFile for the new CompassEffect.
328  */
329 void CompassEffect::
330 fillin(DatagramIterator &scan, BamReader *manager) {
331  RenderEffect::fillin(scan, manager);
332  _properties = scan.get_uint16();
333 
334  if (manager->get_file_minor_ver() >= 43) {
335  _reference.fillin(scan, manager);
336  }
337 }
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of RenderEffect by calling the...
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
Indicates a coordinate-system transform on vertices.
bool has_components() const
Returns true if the transform can be described by separate pos, hpr, and scale components.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void adjust_transform(CPT(TransformState) &net_transform, CPT(TransformState) &node_transform, const PandaNode *node) const
Performs some operation on the node's apparent net and/or local transforms.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
virtual bool has_adjust_transform() const
Should be overridden by derived classes to return true if adjust_transform() has been defined,...
int compare_to(const NodePath &other) const
Returns a number less than zero if this NodePath sorts before the other one, greater than zero if it ...
Definition: nodePath.I:1955
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
This collects together the pieces of data that are accumulated for each node while walking the scene ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void cull_callback(CullTraverser *trav, CullTraverserData &data, CPT(TransformState) &node_transform, CPT(RenderState) &node_state) const
If has_cull_callback() returns true, this function will be called during the cull traversal to perfor...
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being written.
Definition: bamWriter.I:59
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
This is the base class for a number of special render effects that may be set on scene graph nodes to...
Definition: renderEffect.h:48
get_quat
Returns the rotation component of the transform as a quaternion.
int get_file_minor_ver() const
Returns the minor version number of the Bam file currently being read.
Definition: bamReader.I:83
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
get_pos
Returns the pos component of the transform.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
static void register_with_read_factory()
Tells the BamReader how to create objects of type CompassEffect.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
CPT(RenderEffect) CompassEffect
Constructs a new CompassEffect object.
get_scale
Returns the scale component of the transform.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: nodePath.cxx:6753
A class to retrieve the individual data elements previously stored in a Datagram.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
virtual bool has_cull_callback() const
Should be overridden by derived classes to return true if cull_callback() has been defined.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
A CompassEffect causes a node to inherit its rotation (or pos or scale, if specified) from some other...
Definition: compassEffect.h:46
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void write_datagram(BamWriter *manager, Datagram &dg) const
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: nodePath.cxx:6702
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is called by make_from_bam to read in all of the relevant data from the BamFil...
Definition: nodePath.cxx:6813