Panda3D
transformBlend.I
1 // Filename: transformBlend.I
2 // Created by: drose (24Mar05)
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 
16 ////////////////////////////////////////////////////////////////////
17 // Function: TransformBlend::Constructor
18 // Access: Published
19 // Description:
20 ////////////////////////////////////////////////////////////////////
21 INLINE TransformBlend::
22 TransformBlend() {
23 }
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: TransformBlend::Constructor
27 // Access: Published
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 INLINE TransformBlend::
31 TransformBlend(const VertexTransform *transform0, PN_stdfloat) {
32  add_transform(transform0, 1.0f);
33 }
34 
35 ////////////////////////////////////////////////////////////////////
36 // Function: TransformBlend::Constructor
37 // Access: Published
38 // Description:
39 ////////////////////////////////////////////////////////////////////
40 INLINE TransformBlend::
41 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
42  const VertexTransform *transform1, PN_stdfloat weight1) {
43  add_transform(transform0, weight0);
44  add_transform(transform1, weight1);
46 }
47 
48 ////////////////////////////////////////////////////////////////////
49 // Function: TransformBlend::Constructor
50 // Access: Published
51 // Description:
52 ////////////////////////////////////////////////////////////////////
53 INLINE TransformBlend::
54 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
55  const VertexTransform *transform1, PN_stdfloat weight1,
56  const VertexTransform *transform2, PN_stdfloat weight2) {
57  add_transform(transform0, weight0);
58  add_transform(transform1, weight1);
59  add_transform(transform2, weight2);
61 }
62 
63 ////////////////////////////////////////////////////////////////////
64 // Function: TransformBlend::Constructor
65 // Access: Published
66 // Description:
67 ////////////////////////////////////////////////////////////////////
68 INLINE TransformBlend::
69 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
70  const VertexTransform *transform1, PN_stdfloat weight1,
71  const VertexTransform *transform2, PN_stdfloat weight2,
72  const VertexTransform *transform3, PN_stdfloat weight3) {
73  add_transform(transform0, weight0);
74  add_transform(transform1, weight1);
75  add_transform(transform2, weight2);
76  add_transform(transform3, weight3);
78 }
79 
80 ////////////////////////////////////////////////////////////////////
81 // Function: TransformBlend::Copy Constructor
82 // Access: Published
83 // Description:
84 ////////////////////////////////////////////////////////////////////
85 INLINE TransformBlend::
86 TransformBlend(const TransformBlend &copy) :
87  _entries(copy._entries)
88 {
89 }
90 
91 ////////////////////////////////////////////////////////////////////
92 // Function: TransformBlend::Copy Assignment Operator
93 // Access: Published
94 // Description:
95 ////////////////////////////////////////////////////////////////////
96 INLINE void TransformBlend::
97 operator = (const TransformBlend &copy) {
98  _entries = copy._entries;
99  Thread *current_thread = Thread::get_current_thread();
100  clear_result(current_thread);
101 }
102 
103 ////////////////////////////////////////////////////////////////////
104 // Function: TransformBlend::Destructor
105 // Access: Published
106 // Description:
107 ////////////////////////////////////////////////////////////////////
108 INLINE TransformBlend::
109 ~TransformBlend() {
110 }
111 
112 ////////////////////////////////////////////////////////////////////
113 // Function: TransformBlend::operator <
114 // Access: Published
115 // Description:
116 ////////////////////////////////////////////////////////////////////
117 INLINE bool TransformBlend::
118 operator < (const TransformBlend &other) const {
119  return compare_to(other) < 0;
120 }
121 
122 ////////////////////////////////////////////////////////////////////
123 // Function: TransformBlend::operator ==
124 // Access: Published
125 // Description:
126 ////////////////////////////////////////////////////////////////////
127 INLINE bool TransformBlend::
128 operator == (const TransformBlend &other) const {
129  return compare_to(other) == 0;
130 }
131 
132 ////////////////////////////////////////////////////////////////////
133 // Function: TransformBlend::operator !=
134 // Access: Published
135 // Description:
136 ////////////////////////////////////////////////////////////////////
137 INLINE bool TransformBlend::
138 operator != (const TransformBlend &other) const {
139  return compare_to(other) != 0;
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 // Function: TransformBlend::get_num_transforms
144 // Access: Published
145 // Description: Returns the number of transforms stored in the blend
146 // object.
147 ////////////////////////////////////////////////////////////////////
148 INLINE int TransformBlend::
150  return _entries.size();
151 }
152 
153 ////////////////////////////////////////////////////////////////////
154 // Function: TransformBlend::get_transform
155 // Access: Published
156 // Description: Returns the nth transform stored in the blend
157 // object.
158 ////////////////////////////////////////////////////////////////////
159 INLINE const VertexTransform *TransformBlend::
160 get_transform(int n) const {
161  nassertr(n >= 0 && n < (int)_entries.size(), NULL);
162  return _entries[n]._transform;
163 }
164 
165 ////////////////////////////////////////////////////////////////////
166 // Function: TransformBlend::get_weight
167 // Access: Published
168 // Description: Returns the weight associated with the nth transform
169 // stored in the blend object.
170 ////////////////////////////////////////////////////////////////////
171 INLINE PN_stdfloat TransformBlend::
172 get_weight(int n) const {
173  nassertr(n >= 0 && n < (int)_entries.size(), 0.0f);
174  return _entries[n]._weight;
175 }
176 
177 ////////////////////////////////////////////////////////////////////
178 // Function: TransformBlend::set_transform
179 // Access: Published
180 // Description: Replaces the nth transform stored in the blend
181 // object.
182 ////////////////////////////////////////////////////////////////////
183 INLINE void TransformBlend::
184 set_transform(int n, const VertexTransform *transform) {
185  nassertv(n >= 0 && n < (int)_entries.size());
186  _entries[n]._transform = transform;
187 }
188 
189 ////////////////////////////////////////////////////////////////////
190 // Function: TransformBlend::set_weight
191 // Access: Published
192 // Description: Replaces the weight associated with the nth transform
193 // stored in the blend object.
194 ////////////////////////////////////////////////////////////////////
195 INLINE void TransformBlend::
196 set_weight(int n, PN_stdfloat weight) {
197  nassertv(n >= 0 && n < (int)_entries.size());
198  _entries[n]._weight = weight;
199 }
200 
201 ////////////////////////////////////////////////////////////////////
202 // Function: TransformBlend::update_blend
203 // Access: Published
204 // Description: Recomputes the internal representation of the blend
205 // value, if necessary. You should call this before
206 // calling get_blend() or transform_point().
207 ////////////////////////////////////////////////////////////////////
208 INLINE void TransformBlend::
209 update_blend(Thread *current_thread) const {
210  CDLockedReader cdata(_cycler, current_thread);
211  if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
212  CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
213  ((TransformBlend *)this)->recompute_result(cdataw, current_thread);
214  }
215 }
216 
217 ////////////////////////////////////////////////////////////////////
218 // Function: TransformBlend::get_blend
219 // Access: Published
220 // Description: Returns the current value of the blend, based on the
221 // current value of all of the nested transform objects
222 // and their associated weights.
223 //
224 // You should call update_blend() to ensure that the
225 // cache is up-to-date before calling this.
226 ////////////////////////////////////////////////////////////////////
227 INLINE void TransformBlend::
228 get_blend(LMatrix4 &result, Thread *current_thread) const {
229  CDReader cdata(_cycler, current_thread);
230  result = cdata->_result;
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: TransformBlend::transform_point
235 // Access: Published
236 // Description: Transforms the indicated point by the blend matrix.
237 //
238 // You should call update_blend() to ensure that the
239 // cache is up-to-date before calling this.
240 ////////////////////////////////////////////////////////////////////
241 INLINE void TransformBlend::
242 transform_point(LPoint4 &point, Thread *current_thread) const {
243  if (!_entries.empty()) {
244  CDReader cdata(_cycler, current_thread);
245  point = point * cdata->_result;
246  }
247 }
248 
249 ////////////////////////////////////////////////////////////////////
250 // Function: TransformBlend::transform_point
251 // Access: Published
252 // Description: Transforms the indicated point by the blend matrix.
253 //
254 // You should call update_blend() to ensure that the
255 // cache is up-to-date before calling this.
256 ////////////////////////////////////////////////////////////////////
257 INLINE void TransformBlend::
258 transform_point(LPoint3 &point, Thread *current_thread) const {
259  if (!_entries.empty()) {
260  CDReader cdata(_cycler, current_thread);
261  point = point * cdata->_result;
262  }
263 }
264 
265 ////////////////////////////////////////////////////////////////////
266 // Function: TransformBlend::transform_vector
267 // Access: Published
268 // Description: Transforms the indicated vector by the blend matrix.
269 //
270 // You should call update_blend() to ensure that the
271 // cache is up-to-date before calling this.
272 ////////////////////////////////////////////////////////////////////
273 INLINE void TransformBlend::
274 transform_vector(LVector3 &vector, Thread *current_thread) const {
275  if (!_entries.empty()) {
276  CDReader cdata(_cycler, current_thread);
277  vector = vector * cdata->_result;
278  }
279 }
280 
281 #ifndef STDFLOAT_DOUBLE
282 ////////////////////////////////////////////////////////////////////
283 // Function: TransformBlend::transform_point (double)
284 // Access: Published
285 // Description: Transforms the indicated point by the blend matrix.
286 //
287 // You should call update_blend() to ensure that the
288 // cache is up-to-date before calling this.
289 ////////////////////////////////////////////////////////////////////
290 INLINE void TransformBlend::
291 transform_point(LPoint4d &point, Thread *current_thread) const {
292  if (!_entries.empty()) {
293  CDReader cdata(_cycler, current_thread);
294  point = point * LCAST(double, cdata->_result);
295  }
296 }
297 #else // STDFLOAT_DOUBLE
298 ////////////////////////////////////////////////////////////////////
299 // Function: TransformBlend::transform_point (float)
300 // Access: Published
301 // Description: Transforms the indicated point by the blend matrix.
302 //
303 // You should call update_blend() to ensure that the
304 // cache is up-to-date before calling this.
305 ////////////////////////////////////////////////////////////////////
306 INLINE void TransformBlend::
307 transform_point(LPoint4f &point, Thread *current_thread) const {
308  if (!_entries.empty()) {
309  CDReader cdata(_cycler, current_thread);
310  point = point * LCAST(float, cdata->_result);
311  }
312 }
313 #endif // STDFLOAT_DOUBLE
314 
315 #ifndef STDFLOAT_DOUBLE
316 ////////////////////////////////////////////////////////////////////
317 // Function: TransformBlend::transform_point (double)
318 // Access: Published
319 // Description: Transforms the indicated point by the blend matrix.
320 //
321 // You should call update_blend() to ensure that the
322 // cache is up-to-date before calling this.
323 ////////////////////////////////////////////////////////////////////
324 INLINE void TransformBlend::
325 transform_point(LPoint3d &point, Thread *current_thread) const {
326  if (!_entries.empty()) {
327  CDReader cdata(_cycler, current_thread);
328  point = point * LCAST(double, cdata->_result);
329  }
330 }
331 #else // STDFLOAT_DOUBLE
332 ////////////////////////////////////////////////////////////////////
333 // Function: TransformBlend::transform_point (float)
334 // Access: Published
335 // Description: Transforms the indicated point by the blend matrix.
336 //
337 // You should call update_blend() to ensure that the
338 // cache is up-to-date before calling this.
339 ////////////////////////////////////////////////////////////////////
340 INLINE void TransformBlend::
341 transform_point(LPoint3f &point, Thread *current_thread) const {
342  if (!_entries.empty()) {
343  CDReader cdata(_cycler, current_thread);
344  point = point * LCAST(float, cdata->_result);
345  }
346 }
347 #endif // STDFLOAT_DOUBLE
348 
349 #ifndef STDFLOAT_DOUBLE
350 ////////////////////////////////////////////////////////////////////
351 // Function: TransformBlend::transform_vector (double)
352 // Access: Published
353 // Description: Transforms the indicated vector by the blend matrix.
354 //
355 // You should call update_blend() to ensure that the
356 // cache is up-to-date before calling this.
357 ////////////////////////////////////////////////////////////////////
358 INLINE void TransformBlend::
359 transform_vector(LVector3d &vector, Thread *current_thread) const {
360  if (!_entries.empty()) {
361  CDReader cdata(_cycler, current_thread);
362  vector = vector * LCAST(double, cdata->_result);
363  }
364 }
365 #else // STDFLOAT_DOUBLE
366 ////////////////////////////////////////////////////////////////////
367 // Function: TransformBlend::transform_vector (float)
368 // Access: Published
369 // Description: Transforms the indicated vector by the blend matrix.
370 //
371 // You should call update_blend() to ensure that the
372 // cache is up-to-date before calling this.
373 ////////////////////////////////////////////////////////////////////
374 INLINE void TransformBlend::
375 transform_vector(LVector3f &vector, Thread *current_thread) const {
376  if (!_entries.empty()) {
377  CDReader cdata(_cycler, current_thread);
378  vector = vector * LCAST(float, cdata->_result);
379  }
380 }
381 #endif // STDFLOAT_DOUBLE
382 
383 ////////////////////////////////////////////////////////////////////
384 // Function: TransformBlend::get_modified
385 // Access: Published
386 // Description: Returns a counter which is guaranteed to increment at
387 // least as often as the result of get_blend() changes.
388 ////////////////////////////////////////////////////////////////////
390 get_modified(Thread *current_thread) const {
391  CDLockedReader cdata(_cycler, current_thread);
392  if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
393  CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
394  ((TransformBlend *)this)->recompute_result(cdataw, current_thread);
395  return cdataw->_modified;
396  } else {
397  return cdata->_modified;
398  }
399 }
400 
401 ////////////////////////////////////////////////////////////////////
402 // Function: TransformBlend::TransformEntry::operator <
403 // Access: Public
404 // Description: Provides an ordering of TransformEntries by the
405 // VertexTransform pointer only, so we can easily look
406 // up in the set to see if a particular transform
407 // exists.
408 ////////////////////////////////////////////////////////////////////
409 INLINE bool TransformBlend::TransformEntry::
410 operator < (const TransformBlend::TransformEntry &other) const {
411  return _transform < other._transform;
412 }
413 
414 ////////////////////////////////////////////////////////////////////
415 // Function: TransformBlend::CData::Constructor
416 // Access: Public
417 // Description:
418 ////////////////////////////////////////////////////////////////////
419 INLINE TransformBlend::CData::
420 CData() :
421  _result(LMatrix4::ident_mat())
422 {
423 }
424 
425 ////////////////////////////////////////////////////////////////////
426 // Function: TransformBlend::CData::Copy Constructor
427 // Access: Public
428 // Description:
429 ////////////////////////////////////////////////////////////////////
430 INLINE TransformBlend::CData::
431 CData(const TransformBlend::CData &copy) :
432  _result(copy._result),
433  _modified(copy._modified),
434  _global_modified(copy._global_modified)
435 {
436 }
437 
438 INLINE ostream &
439 operator << (ostream &out, const TransformBlend &obj) {
440  obj.output(out);
441  return out;
442 }
static const LMatrix4f & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:903
size_type_0 size() const
Returns the number of elements in the ordered vector.
This is a four-component point in space.
Definition: lpoint4.h:457
void update_blend(Thread *current_thread) const
Recomputes the internal representation of the blend value, if necessary.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
void get_blend(LMatrix4 &result, Thread *current_thread) const
Returns the current value of the blend, based on the current value of all of the nested transform obj...
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
static Thread * get_current_thread()
Returns a pointer to the currently-executing Thread object.
Definition: thread.I:145
This template class calls PipelineCycler::read_unlocked(), and then provides a transparent read-only ...
int compare_to(const TransformBlend &other) const
Defines an arbitrary ordering for TransformBlend objects.
PN_stdfloat get_weight(const VertexTransform *transform) const
Returns the weight associated with the indicated transform, or 0 if there is no entry for the transfo...
void transform_point(LPoint4f &point, Thread *current_thread) const
Transforms the indicated point by the blend matrix.
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
void set_transform(int n, const VertexTransform *transform)
Replaces the nth transform stored in the blend object.
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
static UpdateSeq get_global_modified(Thread *current_thread)
Returns the currently highest VertexTransform::get_modified() value in the world. ...
const VertexTransform * get_transform(int n) const
Returns the nth transform stored in the blend object.
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
int get_num_transforms() const
Returns the number of transforms stored in the blend object.
void transform_vector(LVector3f &point, Thread *current_thread) const
Transforms the indicated vector by the blend matrix.
This defines a single entry in a TransformBlendTable.
UpdateSeq get_modified(Thread *current_thread) const
Returns a counter which is guaranteed to increment at least as often as the result of get_blend() cha...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:760
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:544
This is a four-component point in space.
Definition: lpoint4.h:91
A thread; that is, a lightweight process.
Definition: thread.h:51
void set_weight(int n, PN_stdfloat weight)
Replaces the weight associated with the nth transform stored in the blend object. ...
void normalize_weights()
Rescales all of the weights on the various transforms so that they sum to 1.0.
This is a sequence number that increments monotonically.
Definition: updateSeq.h:43
void add_transform(const VertexTransform *transform, PN_stdfloat weight)
Adds a new transform to the blend.