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