Panda3D
transformBlend.I
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 transformBlend.I
10  * @author drose
11  * @date 2005-03-24
12  */
13 
14 /**
15  *
16  */
17 INLINE TransformBlend::
18 TransformBlend() {
19 }
20 
21 /**
22  *
23  */
24 INLINE TransformBlend::
25 TransformBlend(const VertexTransform *transform0, PN_stdfloat) {
26  add_transform(transform0, 1.0f);
27 }
28 
29 /**
30  *
31  */
32 INLINE TransformBlend::
33 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
34  const VertexTransform *transform1, PN_stdfloat weight1) {
35  add_transform(transform0, weight0);
36  add_transform(transform1, weight1);
38 }
39 
40 /**
41  *
42  */
43 INLINE TransformBlend::
44 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
45  const VertexTransform *transform1, PN_stdfloat weight1,
46  const VertexTransform *transform2, PN_stdfloat weight2) {
47  add_transform(transform0, weight0);
48  add_transform(transform1, weight1);
49  add_transform(transform2, weight2);
51 }
52 
53 /**
54  *
55  */
56 INLINE TransformBlend::
57 TransformBlend(const VertexTransform *transform0, PN_stdfloat weight0,
58  const VertexTransform *transform1, PN_stdfloat weight1,
59  const VertexTransform *transform2, PN_stdfloat weight2,
60  const VertexTransform *transform3, PN_stdfloat weight3) {
61  add_transform(transform0, weight0);
62  add_transform(transform1, weight1);
63  add_transform(transform2, weight2);
64  add_transform(transform3, weight3);
66 }
67 
68 /**
69  *
70  */
71 INLINE TransformBlend::
72 TransformBlend(const TransformBlend &copy) :
73  _entries(copy._entries)
74 {
75 }
76 
77 /**
78  *
79  */
80 INLINE void TransformBlend::
81 operator = (const TransformBlend &copy) {
82  _entries = copy._entries;
83  Thread *current_thread = Thread::get_current_thread();
84  clear_result(current_thread);
85 }
86 
87 /**
88  *
89  */
90 INLINE TransformBlend::
91 ~TransformBlend() {
92 }
93 
94 /**
95  *
96  */
97 INLINE bool TransformBlend::
98 operator < (const TransformBlend &other) const {
99  return compare_to(other) < 0;
100 }
101 
102 /**
103  *
104  */
105 INLINE bool TransformBlend::
106 operator == (const TransformBlend &other) const {
107  return compare_to(other) == 0;
108 }
109 
110 /**
111  *
112  */
113 INLINE bool TransformBlend::
114 operator != (const TransformBlend &other) const {
115  return compare_to(other) != 0;
116 }
117 
118 /**
119  * Returns the number of transforms stored in the blend object.
120  */
121 INLINE size_t TransformBlend::
122 get_num_transforms() const {
123  return _entries.size();
124 }
125 
126 /**
127  * Returns the nth transform stored in the blend object.
128  */
129 INLINE const VertexTransform *TransformBlend::
130 get_transform(size_t n) const {
131  nassertr(n < _entries.size(), nullptr);
132  return _entries[n]._transform;
133 }
134 
135 /**
136  * Returns the weight associated with the nth transform stored in the blend
137  * object.
138  */
139 INLINE PN_stdfloat TransformBlend::
140 get_weight(size_t n) const {
141  nassertr(n < _entries.size(), 0.0f);
142  return _entries[n]._weight;
143 }
144 
145 /**
146  * Removes the nth transform stored in the blend object.
147  */
148 INLINE void TransformBlend::
149 remove_transform(size_t n) {
150  nassertv(n < _entries.size());
151  _entries.erase(_entries.begin() + n);
152  Thread *current_thread = Thread::get_current_thread();
153  clear_result(current_thread);
154 }
155 
156 /**
157  * Replaces the nth transform stored in the blend object.
158  */
159 INLINE void TransformBlend::
160 set_transform(size_t n, const VertexTransform *transform) {
161  nassertv(n < _entries.size());
162  _entries[n]._transform = transform;
163 }
164 
165 /**
166  * Replaces the weight associated with the nth transform stored in the blend
167  * object.
168  */
169 INLINE void TransformBlend::
170 set_weight(size_t n, PN_stdfloat weight) {
171  nassertv(n < _entries.size());
172  _entries[n]._weight = weight;
173 }
174 
175 /**
176  * Recomputes the internal representation of the blend value, if necessary.
177  * You should call this before calling get_blend() or transform_point().
178  */
179 INLINE void TransformBlend::
180 update_blend(Thread *current_thread) const {
181  CDLockedReader cdata(_cycler, current_thread);
182  if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
183  CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
184  ((TransformBlend *)this)->recompute_result(cdataw, current_thread);
185  }
186 }
187 
188 /**
189  * Returns the current value of the blend, based on the current value of all
190  * of the nested transform objects and their associated weights.
191  *
192  * You should call update_blend() to ensure that the cache is up-to-date
193  * before calling this.
194  */
195 INLINE void TransformBlend::
196 get_blend(LMatrix4 &result, Thread *current_thread) const {
197  CDReader cdata(_cycler, current_thread);
198  result = cdata->_result;
199 }
200 
201 /**
202  * Transforms the indicated point by the blend matrix.
203  *
204  * You should call update_blend() to ensure that the cache is up-to-date
205  * before calling this.
206  */
207 INLINE void TransformBlend::
208 transform_point(LPoint4 &point, Thread *current_thread) const {
209  if (!_entries.empty()) {
210  CDReader cdata(_cycler, current_thread);
211  point = point * cdata->_result;
212  }
213 }
214 
215 /**
216  * Transforms the indicated point by the blend matrix.
217  *
218  * You should call update_blend() to ensure that the cache is up-to-date
219  * before calling this.
220  */
221 INLINE void TransformBlend::
222 transform_point(LPoint3 &point, Thread *current_thread) const {
223  if (!_entries.empty()) {
224  CDReader cdata(_cycler, current_thread);
225  point = point * cdata->_result;
226  }
227 }
228 
229 /**
230  * Transforms the indicated vector by the blend matrix.
231  *
232  * You should call update_blend() to ensure that the cache is up-to-date
233  * before calling this.
234  */
235 INLINE void TransformBlend::
236 transform_vector(LVector3 &vector, Thread *current_thread) const {
237  if (!_entries.empty()) {
238  CDReader cdata(_cycler, current_thread);
239  vector = vector * cdata->_result;
240  }
241 }
242 
243 #ifndef STDFLOAT_DOUBLE
244 /**
245  * Transforms the indicated point by the blend matrix.
246  *
247  * You should call update_blend() to ensure that the cache is up-to-date
248  * before calling this.
249  */
250 INLINE void TransformBlend::
251 transform_point(LPoint4d &point, Thread *current_thread) const {
252  if (!_entries.empty()) {
253  CDReader cdata(_cycler, current_thread);
254  point = point * LCAST(double, cdata->_result);
255  }
256 }
257 #else // STDFLOAT_DOUBLE
258 /**
259  * Transforms the indicated point by the blend matrix.
260  *
261  * You should call update_blend() to ensure that the cache is up-to-date
262  * before calling this.
263  */
264 INLINE void TransformBlend::
265 transform_point(LPoint4f &point, Thread *current_thread) const {
266  if (!_entries.empty()) {
267  CDReader cdata(_cycler, current_thread);
268  point = point * LCAST(float, cdata->_result);
269  }
270 }
271 #endif // STDFLOAT_DOUBLE
272 
273 #ifndef STDFLOAT_DOUBLE
274 /**
275  * Transforms the indicated point by the blend matrix.
276  *
277  * You should call update_blend() to ensure that the cache is up-to-date
278  * before calling this.
279  */
280 INLINE void TransformBlend::
281 transform_point(LPoint3d &point, Thread *current_thread) const {
282  if (!_entries.empty()) {
283  CDReader cdata(_cycler, current_thread);
284  point = point * LCAST(double, cdata->_result);
285  }
286 }
287 #else // STDFLOAT_DOUBLE
288 /**
289  * Transforms the indicated point by the blend matrix.
290  *
291  * You should call update_blend() to ensure that the cache is up-to-date
292  * before calling this.
293  */
294 INLINE void TransformBlend::
295 transform_point(LPoint3f &point, Thread *current_thread) const {
296  if (!_entries.empty()) {
297  CDReader cdata(_cycler, current_thread);
298  point = point * LCAST(float, cdata->_result);
299  }
300 }
301 #endif // STDFLOAT_DOUBLE
302 
303 #ifndef STDFLOAT_DOUBLE
304 /**
305  * Transforms the indicated vector by the blend matrix.
306  *
307  * You should call update_blend() to ensure that the cache is up-to-date
308  * before calling this.
309  */
310 INLINE void TransformBlend::
311 transform_vector(LVector3d &vector, Thread *current_thread) const {
312  if (!_entries.empty()) {
313  CDReader cdata(_cycler, current_thread);
314  vector = vector * LCAST(double, cdata->_result);
315  }
316 }
317 #else // STDFLOAT_DOUBLE
318 /**
319  * Transforms the indicated vector by the blend matrix.
320  *
321  * You should call update_blend() to ensure that the cache is up-to-date
322  * before calling this.
323  */
324 INLINE void TransformBlend::
325 transform_vector(LVector3f &vector, Thread *current_thread) const {
326  if (!_entries.empty()) {
327  CDReader cdata(_cycler, current_thread);
328  vector = vector * LCAST(float, cdata->_result);
329  }
330 }
331 #endif // STDFLOAT_DOUBLE
332 
333 /**
334  * Returns a counter which is guaranteed to increment at least as often as the
335  * result of get_blend() changes.
336  */
338 get_modified(Thread *current_thread) const {
339  CDLockedReader cdata(_cycler, current_thread);
340  if (cdata->_global_modified != VertexTransform::get_global_modified(current_thread)) {
341  CDWriter cdataw(((TransformBlend *)this)->_cycler, cdata, false);
342  ((TransformBlend *)this)->recompute_result(cdataw, current_thread);
343  return cdataw->_modified;
344  } else {
345  return cdata->_modified;
346  }
347 }
348 
349 /**
350  * Provides an ordering of TransformEntries by the VertexTransform pointer
351  * only, so we can easily look up in the set to see if a particular transform
352  * exists.
353  */
354 INLINE bool TransformBlend::TransformEntry::
355 operator < (const TransformBlend::TransformEntry &other) const {
356  return _transform < other._transform;
357 }
358 
359 /**
360  *
361  */
362 INLINE TransformBlend::CData::
363 CData() :
364  _result(LMatrix4::ident_mat())
365 {
366 }
367 
368 /**
369  *
370  */
371 INLINE TransformBlend::CData::
372 CData(const TransformBlend::CData &copy) :
373  _result(copy._result),
374  _modified(copy._modified),
375  _global_modified(copy._global_modified)
376 {
377 }
378 
379 INLINE std::ostream &
380 operator << (std::ostream &out, const TransformBlend &obj) {
381  obj.output(out);
382  return out;
383 }
size_type_0 size() const
Returns the number of elements in the ordered vector.
void update_blend(Thread *current_thread) const
Recomputes the internal representation of the blend value, if necessary.
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
set_transform
Replaces the nth transform stored in the blend object.
get_weight
Returns the weight associated with the indicated transform, or 0 if there is no entry for the transfo...
remove_transform
Removes the indicated transform from the blend.
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...
get_transform
Returns the nth transform stored in the blend object.
bool empty() const
Returns true if the ordered vector is empty, false otherwise.
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.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
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...
static UpdateSeq get_global_modified(Thread *current_thread)
Returns the currently highest VertexTransform::get_modified() value in the world.
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...
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.
A thread; that is, a lightweight process.
Definition: thread.h:46
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:37
void set_weight(size_t n, PN_stdfloat weight)
Replaces the weight associated with the nth transform stored in the blend object.
void add_transform(const VertexTransform *transform, PN_stdfloat weight)
Adds a new transform to the blend.
get_modified
Returns a counter which is guaranteed to increment at least as often as the result of get_blend() cha...