/src/alembic/lib/Alembic/AbcGeom/XformOp.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //-***************************************************************************** |
2 | | // |
3 | | // Copyright (c) 2009-2012, |
4 | | // Sony Pictures Imageworks, Inc. and |
5 | | // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd. |
6 | | // |
7 | | // All rights reserved. |
8 | | // |
9 | | // Redistribution and use in source and binary forms, with or without |
10 | | // modification, are permitted provided that the following conditions are |
11 | | // met: |
12 | | // * Redistributions of source code must retain the above copyright |
13 | | // notice, this list of conditions and the following disclaimer. |
14 | | // * Redistributions in binary form must reproduce the above |
15 | | // copyright notice, this list of conditions and the following disclaimer |
16 | | // in the documentation and/or other materials provided with the |
17 | | // distribution. |
18 | | // * Neither the name of Sony Pictures Imageworks, nor |
19 | | // Industrial Light & Magic nor the names of their contributors may be used |
20 | | // to endorse or promote products derived from this software without specific |
21 | | // prior written permission. |
22 | | // |
23 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
24 | | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
25 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
26 | | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
27 | | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
28 | | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
29 | | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
30 | | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
31 | | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
32 | | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
33 | | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
34 | | // |
35 | | //-***************************************************************************** |
36 | | |
37 | | #include <Alembic/AbcGeom/XformOp.h> |
38 | | |
39 | | namespace Alembic { |
40 | | namespace AbcGeom { |
41 | | namespace ALEMBIC_VERSION_NS { |
42 | | |
43 | | //-***************************************************************************** |
44 | | XformOp::XformOp() |
45 | 0 | : m_type( kTranslateOperation ) |
46 | 0 | , m_hint( 0 ) |
47 | 0 | { |
48 | 0 | m_channels.clear(); |
49 | 0 | m_channels.resize( 3 ); |
50 | 0 | } |
51 | | |
52 | | //-***************************************************************************** |
53 | | XformOp::XformOp( const XformOperationType iType, |
54 | | const Alembic::Util::uint8_t iHint ) |
55 | 0 | : m_type( iType ) |
56 | 0 | { |
57 | 0 | m_channels.clear(); |
58 | |
|
59 | 0 | switch ( m_type ) |
60 | 0 | { |
61 | 0 | case kRotateXOperation: |
62 | 0 | case kRotateYOperation: |
63 | 0 | case kRotateZOperation: |
64 | 0 | m_channels.resize( 1 ); |
65 | 0 | break; |
66 | 0 | case kScaleOperation: |
67 | 0 | case kTranslateOperation: |
68 | 0 | m_channels.resize( 3 ); |
69 | 0 | break; |
70 | 0 | case kRotateOperation: |
71 | 0 | m_channels.resize( 4 ); |
72 | 0 | break; |
73 | 0 | case kMatrixOperation: |
74 | 0 | m_channels.resize( 16 ); |
75 | 0 | break; |
76 | 0 | } |
77 | | |
78 | 0 | setHint( iHint ); |
79 | 0 | } |
80 | | |
81 | | //-***************************************************************************** |
82 | | XformOp::XformOp( const Alembic::Util::uint8_t iEncodedOp ) |
83 | 0 | { |
84 | |
|
85 | 0 | m_type = (XformOperationType)(iEncodedOp >> 4); |
86 | 0 | setHint( iEncodedOp & 0xF ); |
87 | |
|
88 | 0 | switch ( m_type ) |
89 | 0 | { |
90 | 0 | case kRotateXOperation: |
91 | 0 | case kRotateYOperation: |
92 | 0 | case kRotateZOperation: |
93 | 0 | m_channels.resize( 1 ); |
94 | 0 | break; |
95 | 0 | case kScaleOperation: |
96 | 0 | case kTranslateOperation: |
97 | 0 | m_channels.resize( 3 ); |
98 | 0 | break; |
99 | 0 | case kRotateOperation: |
100 | 0 | m_channels.resize( 4 ); |
101 | 0 | break; |
102 | 0 | case kMatrixOperation: |
103 | 0 | m_channels.resize( 16 ); |
104 | 0 | break; |
105 | 0 | } |
106 | 0 | } |
107 | | |
108 | | //-***************************************************************************** |
109 | | XformOperationType XformOp::getType() const |
110 | 0 | { |
111 | 0 | return m_type; |
112 | 0 | } |
113 | | |
114 | | //-***************************************************************************** |
115 | | void XformOp::setType( const XformOperationType iType ) |
116 | 0 | { |
117 | 0 | m_type = iType; |
118 | 0 | m_hint = 0; |
119 | |
|
120 | 0 | switch ( m_type ) |
121 | 0 | { |
122 | 0 | case kRotateXOperation: |
123 | 0 | case kRotateYOperation: |
124 | 0 | case kRotateZOperation: |
125 | 0 | m_channels.resize( 1 ); |
126 | 0 | break; |
127 | 0 | case kScaleOperation: |
128 | 0 | case kTranslateOperation: |
129 | 0 | m_channels.resize( 3 ); |
130 | 0 | break; |
131 | 0 | case kRotateOperation: |
132 | 0 | m_channels.resize( 4 ); |
133 | 0 | break; |
134 | 0 | case kMatrixOperation: |
135 | 0 | m_channels.resize( 16 ); |
136 | 0 | break; |
137 | 0 | } |
138 | 0 | } |
139 | | |
140 | | //-***************************************************************************** |
141 | | uint8_t XformOp::getHint() const |
142 | 0 | { |
143 | 0 | return m_hint; |
144 | 0 | } |
145 | | |
146 | | //-***************************************************************************** |
147 | | void XformOp::setHint( const Alembic::Util::uint8_t iHint ) |
148 | 0 | { |
149 | | // if a non-existant hint value is set, default it to 0 |
150 | 0 | if ( m_type == kScaleOperation && iHint > kScaleHint ) |
151 | 0 | { |
152 | 0 | m_hint = 0; |
153 | 0 | } |
154 | 0 | else if ( m_type == kTranslateOperation && iHint > |
155 | 0 | kRotatePivotTranslationHint ) |
156 | 0 | { |
157 | 0 | m_hint = 0; |
158 | 0 | } |
159 | 0 | else if ( ( m_type == kRotateOperation || m_type == kRotateXOperation || |
160 | 0 | m_type == kRotateYOperation || m_type == kRotateZOperation ) |
161 | 0 | && iHint > kRotateOrientationHint ) |
162 | 0 | { |
163 | 0 | m_hint = 0; |
164 | 0 | } |
165 | 0 | else if ( m_type == kMatrixOperation && iHint > kMayaShearHint ) |
166 | 0 | { |
167 | 0 | m_hint = 0; |
168 | 0 | } |
169 | 0 | else |
170 | 0 | { |
171 | 0 | m_hint = iHint; |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | | //-***************************************************************************** |
176 | | bool XformOp::isXAnimated() const |
177 | 0 | { |
178 | 0 | if ( m_type == kRotateXOperation || m_type == kRotateYOperation || |
179 | 0 | m_type == kRotateZOperation ) |
180 | 0 | { |
181 | 0 | return false; |
182 | 0 | } |
183 | | |
184 | 0 | return m_animChannels.count( 0 ) > 0; |
185 | 0 | } |
186 | | |
187 | | //-***************************************************************************** |
188 | | bool XformOp::isYAnimated() const |
189 | 0 | { |
190 | 0 | if ( m_type == kRotateXOperation || m_type == kRotateYOperation || |
191 | 0 | m_type == kRotateZOperation ) |
192 | 0 | { |
193 | 0 | return false; |
194 | 0 | } |
195 | | |
196 | 0 | return m_animChannels.count( 1 ) > 0; |
197 | 0 | } |
198 | | |
199 | | //-***************************************************************************** |
200 | | bool XformOp::isZAnimated() const |
201 | 0 | { |
202 | 0 | if ( m_type == kRotateXOperation || m_type == kRotateYOperation || |
203 | 0 | m_type == kRotateZOperation ) |
204 | 0 | { |
205 | 0 | return false; |
206 | 0 | } |
207 | | |
208 | 0 | return m_animChannels.count( 2 ) > 0; |
209 | 0 | } |
210 | | |
211 | | //-***************************************************************************** |
212 | | bool XformOp::isAngleAnimated() const |
213 | 0 | { |
214 | 0 | if ( m_type == kRotateXOperation || m_type == kRotateYOperation || |
215 | 0 | m_type == kRotateZOperation ) |
216 | 0 | { |
217 | 0 | return m_animChannels.count( 0 ) > 0; |
218 | 0 | } |
219 | | |
220 | 0 | return m_animChannels.count( 3 ) > 0; |
221 | 0 | } |
222 | | |
223 | | //-***************************************************************************** |
224 | | bool XformOp::isChannelAnimated( std::size_t iIndex ) const |
225 | 0 | { |
226 | 0 | return m_animChannels.count( iIndex ) > 0; |
227 | 0 | } |
228 | | |
229 | | //-***************************************************************************** |
230 | | std::size_t XformOp::getNumChannels() const |
231 | 0 | { |
232 | 0 | return m_channels.size(); |
233 | 0 | } |
234 | | |
235 | | //-***************************************************************************** |
236 | | double XformOp::getDefaultChannelValue( std::size_t iIndex ) const |
237 | 0 | { |
238 | 0 | switch ( m_type ) |
239 | 0 | { |
240 | 0 | case kTranslateOperation: |
241 | 0 | case kRotateOperation: |
242 | 0 | case kRotateXOperation: |
243 | 0 | case kRotateYOperation: |
244 | 0 | case kRotateZOperation: |
245 | 0 | return 0.0; |
246 | 0 | case kScaleOperation: |
247 | 0 | return 1.0; |
248 | 0 | case kMatrixOperation: |
249 | 0 | switch ( iIndex ) |
250 | 0 | { |
251 | 0 | case 0: |
252 | 0 | case 5: |
253 | 0 | case 10: |
254 | 0 | case 15: |
255 | 0 | return 1.0; |
256 | 0 | default: |
257 | 0 | return 0.0; |
258 | 0 | } |
259 | 0 | default: |
260 | 0 | return 0.0; |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | //-***************************************************************************** |
265 | | double XformOp::getChannelValue( std::size_t iIndex ) const |
266 | 0 | { |
267 | 0 | return m_channels[iIndex]; |
268 | 0 | } |
269 | | |
270 | | //-***************************************************************************** |
271 | | void XformOp::setChannelValue( std::size_t iIndex, double iVal ) |
272 | 0 | { |
273 | 0 | m_channels[iIndex] = iVal; |
274 | 0 | } |
275 | | |
276 | | //-***************************************************************************** |
277 | | Alembic::Util::uint8_t XformOp::getOpEncoding() const |
278 | 0 | { |
279 | 0 | return ( m_type << 4 ) | ( m_hint & 0xF ); |
280 | 0 | } |
281 | | |
282 | | //-***************************************************************************** |
283 | | bool XformOp::isTranslateOp() const |
284 | 0 | { |
285 | 0 | return m_type == kTranslateOperation; |
286 | 0 | } |
287 | | |
288 | | //-***************************************************************************** |
289 | | bool XformOp::isScaleOp() const |
290 | 0 | { |
291 | 0 | return m_type == kScaleOperation; |
292 | 0 | } |
293 | | |
294 | | //-***************************************************************************** |
295 | | bool XformOp::isRotateOp() const |
296 | 0 | { |
297 | 0 | return m_type == kRotateOperation; |
298 | 0 | } |
299 | | |
300 | | //-***************************************************************************** |
301 | | bool XformOp::isMatrixOp() const |
302 | 0 | { |
303 | 0 | return m_type == kMatrixOperation; |
304 | 0 | } |
305 | | |
306 | | //-***************************************************************************** |
307 | | bool XformOp::isRotateXOp() const |
308 | 0 | { |
309 | 0 | return m_type == kRotateXOperation; |
310 | 0 | } |
311 | | |
312 | | //-***************************************************************************** |
313 | | bool XformOp::isRotateYOp() const |
314 | 0 | { |
315 | 0 | return m_type == kRotateYOperation; |
316 | 0 | } |
317 | | |
318 | | //-***************************************************************************** |
319 | | bool XformOp::isRotateZOp() const |
320 | 0 | { |
321 | 0 | return m_type == kRotateZOperation; |
322 | 0 | } |
323 | | |
324 | | //-***************************************************************************** |
325 | | void XformOp::setVector( const Abc::V3d &iVec ) |
326 | 0 | { |
327 | 0 | ABCA_ASSERT( m_type != kMatrixOperation, |
328 | 0 | "Meaningless to set Abc::V3d on matrix op" ); |
329 | | |
330 | 0 | m_channels[0] = iVec.x; |
331 | 0 | m_channels[1] = iVec.y; |
332 | 0 | m_channels[2] = iVec.z; |
333 | 0 | } |
334 | | |
335 | | //-***************************************************************************** |
336 | | void XformOp::setTranslate( const Abc::V3d &iTrans ) |
337 | 0 | { |
338 | 0 | ABCA_ASSERT( m_type == kTranslateOperation, |
339 | 0 | "Meaningless to set translate on non-translate op." ); |
340 | | |
341 | 0 | this->setVector( iTrans ); |
342 | 0 | } |
343 | | |
344 | | //-***************************************************************************** |
345 | | void XformOp::setScale( const Abc::V3d &iScale ) |
346 | 0 | { |
347 | 0 | ABCA_ASSERT( m_type == kScaleOperation, |
348 | 0 | "Meaningless to set scale on non-scale op." ); |
349 | | |
350 | 0 | this->setVector( iScale ); |
351 | 0 | } |
352 | | |
353 | | //-***************************************************************************** |
354 | | void XformOp::setAxis( const Abc::V3d &iAxis ) |
355 | 0 | { |
356 | 0 | ABCA_ASSERT( m_type == kRotateOperation, |
357 | 0 | "Meaningless to set rotation axis on non-rotation or fixed " |
358 | 0 | "angle rotation op." ); |
359 | | |
360 | 0 | this->setVector( iAxis ); |
361 | 0 | } |
362 | | |
363 | | //-***************************************************************************** |
364 | | void XformOp::setAngle( const double iAngle ) |
365 | 0 | { |
366 | 0 | switch ( m_type ) |
367 | 0 | { |
368 | 0 | case kRotateOperation: |
369 | 0 | m_channels[3] = iAngle; |
370 | 0 | break; |
371 | 0 | case kRotateXOperation: |
372 | 0 | case kRotateYOperation: |
373 | 0 | case kRotateZOperation: |
374 | 0 | m_channels[0] = iAngle; |
375 | 0 | break; |
376 | 0 | default: |
377 | 0 | ABCA_THROW( "Meaningless to set rotation angle on non-rotation op." ); |
378 | 0 | } |
379 | 0 | } |
380 | | |
381 | | //-***************************************************************************** |
382 | | void XformOp::setMatrix( const Abc::M44d &iMatrix ) |
383 | 0 | { |
384 | 0 | ABCA_ASSERT( m_type == kMatrixOperation, |
385 | 0 | "Cannot set non-matrix op from Abc::M44d" ); |
386 | | |
387 | 0 | for ( size_t i = 0 ; i < 4 ; ++i ) |
388 | 0 | { |
389 | 0 | for ( size_t j = 0 ; j < 4 ; ++j ) |
390 | 0 | { |
391 | 0 | m_channels[( i * 4 ) + j] = iMatrix.x[i][j]; |
392 | 0 | } |
393 | 0 | } |
394 | 0 | } |
395 | | |
396 | | //-***************************************************************************** |
397 | | Abc::V3d XformOp::getVector() const |
398 | 0 | { |
399 | 0 | ABCA_ASSERT( m_type != kMatrixOperation, |
400 | 0 | "Meaningless to get Abc::V3d from matrix op" ); |
401 | | |
402 | 0 | return Abc::V3d( m_channels[0], m_channels[1], m_channels[2] ); |
403 | 0 | } |
404 | | |
405 | | //-***************************************************************************** |
406 | | Abc::V3d XformOp::getTranslate() const |
407 | 0 | { |
408 | 0 | ABCA_ASSERT( m_type == kTranslateOperation, |
409 | 0 | "Meaningless to get translate vector from non-translate op." ); |
410 | | |
411 | 0 | return this->getVector(); |
412 | 0 | } |
413 | | |
414 | | //-***************************************************************************** |
415 | | Abc::V3d XformOp::getScale() const |
416 | 0 | { |
417 | 0 | ABCA_ASSERT( m_type == kScaleOperation, |
418 | 0 | "Meaningless to get scaling vector from non-scale op." ); |
419 | | |
420 | 0 | return this->getVector(); |
421 | 0 | } |
422 | | |
423 | | //-***************************************************************************** |
424 | | Abc::V3d XformOp::getAxis() const |
425 | 0 | { |
426 | 0 | switch ( m_type ) |
427 | 0 | { |
428 | 0 | case kRotateOperation: |
429 | 0 | return this->getVector(); |
430 | 0 | case kRotateXOperation: |
431 | 0 | return Abc::V3d(1.0, 0.0, 0.0); |
432 | 0 | case kRotateYOperation: |
433 | 0 | return Abc::V3d(0.0, 1.0, 0.0); |
434 | 0 | case kRotateZOperation: |
435 | 0 | return Abc::V3d(0.0, 0.0, 1.0); |
436 | 0 | default: |
437 | 0 | ABCA_THROW( "Meaningless to get rotation axis from non-rotation op." ); |
438 | 0 | } |
439 | | |
440 | 0 | return Abc::V3d(0.0, 0.0, 0.0); |
441 | 0 | } |
442 | | |
443 | | //-***************************************************************************** |
444 | | double XformOp::getAngle() const |
445 | 0 | { |
446 | 0 | switch ( m_type ) |
447 | 0 | { |
448 | 0 | case kRotateOperation: |
449 | 0 | return m_channels[3]; |
450 | 0 | case kRotateXOperation: |
451 | 0 | case kRotateYOperation: |
452 | 0 | case kRotateZOperation: |
453 | 0 | return m_channels[0]; |
454 | 0 | default: |
455 | 0 | ABCA_THROW( "Meaningless to get rotation angle from non-rotation op." ); |
456 | 0 | } |
457 | | |
458 | 0 | return 0.0; |
459 | 0 | } |
460 | | |
461 | | //-***************************************************************************** |
462 | | double XformOp::getXRotation() const |
463 | 0 | { |
464 | 0 | ABCA_ASSERT( m_type == kRotateOperation || m_type == kRotateXOperation, |
465 | 0 | "Meaningless to get rotation angle from non-rotation op." ); |
466 | | |
467 | 0 | if ( m_type == kRotateXOperation ) |
468 | 0 | { |
469 | 0 | return m_channels[0]; |
470 | 0 | } |
471 | 0 | else |
472 | 0 | { |
473 | 0 | Abc::M44d m; |
474 | 0 | Abc::V3d rot; |
475 | 0 | m.makeIdentity(); |
476 | 0 | m.setAxisAngle( this->getVector(), DegreesToRadians( m_channels[3] ) ); |
477 | 0 | Imath::extractEulerXYZ( m, rot ); |
478 | 0 | return RadiansToDegrees( rot[0] ); |
479 | 0 | } |
480 | 0 | } |
481 | | |
482 | | //-***************************************************************************** |
483 | | double XformOp::getYRotation() const |
484 | 0 | { |
485 | 0 | ABCA_ASSERT( m_type == kRotateOperation || m_type == kRotateYOperation, |
486 | 0 | "Meaningless to get rotation angle from non-rotation op." ); |
487 | | |
488 | 0 | if ( m_type == kRotateYOperation ) |
489 | 0 | { |
490 | 0 | return m_channels[0]; |
491 | 0 | } |
492 | 0 | else |
493 | 0 | { |
494 | 0 | Abc::M44d m; |
495 | 0 | Abc::V3d rot; |
496 | 0 | m.makeIdentity(); |
497 | 0 | m.setAxisAngle( this->getVector(), DegreesToRadians( m_channels[3] ) ); |
498 | 0 | Imath::extractEulerXYZ( m, rot ); |
499 | 0 | return RadiansToDegrees( rot[1] ); |
500 | 0 | } |
501 | 0 | } |
502 | | |
503 | | //-***************************************************************************** |
504 | | double XformOp::getZRotation() const |
505 | 0 | { |
506 | 0 | ABCA_ASSERT( m_type == kRotateOperation || m_type == kRotateZOperation, |
507 | 0 | "Meaningless to get rotation angle from non-rotation op." ); |
508 | | |
509 | 0 | if ( m_type == kRotateZOperation ) |
510 | 0 | { |
511 | 0 | return m_channels[0]; |
512 | 0 | } |
513 | 0 | else |
514 | 0 | { |
515 | 0 | Abc::M44d m; |
516 | 0 | Abc::V3d rot; |
517 | 0 | m.makeIdentity(); |
518 | 0 | m.setAxisAngle( this->getVector(), DegreesToRadians( m_channels[3] ) ); |
519 | 0 | Imath::extractEulerXYZ( m, rot ); |
520 | 0 | return RadiansToDegrees( rot[2] ); |
521 | 0 | } |
522 | 0 | } |
523 | | |
524 | | //-***************************************************************************** |
525 | | Abc::M44d XformOp::getMatrix() const |
526 | 0 | { |
527 | 0 | ABCA_ASSERT( m_type == kMatrixOperation, |
528 | 0 | "Can't get matrix from non-matrix op." ); |
529 | | |
530 | 0 | Abc::M44d ret; |
531 | |
|
532 | 0 | for ( size_t i = 0 ; i < 4 ; ++i ) |
533 | 0 | { |
534 | 0 | for ( size_t j = 0 ; j < 4 ; ++j ) |
535 | 0 | { |
536 | 0 | ret.x[i][j] = m_channels[( i * 4 ) + j]; |
537 | 0 | } |
538 | 0 | } |
539 | |
|
540 | 0 | return ret; |
541 | 0 | } |
542 | | |
543 | | } // End namespace ALEMBIC_VERSION_NS |
544 | | } // End namespace AbcGeom |
545 | | } // End namespace Alembic |