151 LASS_ASSERT(!(isInversed_ && !pimpl_->hasInverse));
152 return isInversed_ ? pimpl_->inverse : pimpl_->forward;
160template <
typename T>
inline
161const typename Transformation3D<T>::TValue*
165 LASS_ASSERT(pimpl_->hasInverse);
166 return isInversed_ ? pimpl_->forward : pimpl_->inverse;
172bool Transformation3D<T>::isIdentity()
const
174 if (pimpl_ == identity_)
178 const TValue*
const forward = pimpl_->forward;
179 for (
size_t i = 0; i < 4; ++i)
181 for (
size_t j = 0; j < 4; ++j)
183 if (forward[i * 4 + j] != (i == j ? TNumTraits::one : TNumTraits::zero))
195bool Transformation3D<T>::isTranslation()
const
197 if (pimpl_->isTranslation)
201 const TValue*
const forward = pimpl_->forward;
202 for (
size_t i = 0; i < 4; ++i)
204 for (
size_t j = 0; j < 4; ++j)
206 if (j < 3 && forward[i * 4 + j] != (i == j ? TNumTraits::one : TNumTraits::zero))
218void Transformation3D<T>::swap(TSelf& other)
220 pimpl_.swap(other.pimpl_);
221 std::swap(isInversed_, other.isInversed_);
241 TImplPtr pimpl(TImplPtr::allocate());
243 TMatrix& forward = pimpl->forward;
245 forward[ 3] = offset.x;
246 forward[ 7] = offset.y;
247 forward[11] = offset.z;
249 TMatrix&
inverse = pimpl->inverse;
255 pimpl->hasInverse =
true;
256 pimpl->isTranslation =
true;
268 TImplPtr pimpl(TImplPtr::allocate());
270 TMatrix& forward = pimpl->forward;
272 forward[ 0] = forward[ 5] = forward[10] = scale;
274 TMatrix&
inverse = pimpl->inverse;
278 pimpl->hasInverse =
true;
290 TImplPtr pimpl(TImplPtr::allocate());
292 TMatrix& forward = pimpl->forward;
294 forward[ 0] = scale.x;
295 forward[ 5] = scale.y;
296 forward[10] = scale.z;
298 TMatrix&
inverse = pimpl->inverse;
304 pimpl->hasInverse =
true;
316 TImplPtr pimpl(TImplPtr::allocate());
318 const T c = num::cos(radians);
319 const T s = num::sin(radians);
320 const int a = (axis + 1);
321 const int b = (axis + 2);
322 LASS_ASSERT(a < 3 && b < 3);
324 TMatrix& forward = pimpl->forward;
328 forward[4 * a + b] = -s;
329 forward[4 * b + a] = s;
331 TMatrix&
inverse = pimpl->inverse;
338 pimpl->hasInverse =
true;
350 TImplPtr pimpl(TImplPtr::allocate());
352 const TVector a = axis.
normal();
353 const T c = num::cos(radians);
354 const T s = num::sin(radians);
355 const TValue oneMinusC = TNumTraits::one - c;
357 TMatrix& forward = pimpl->forward;
359 forward[ 0] = a.x * a.x * oneMinusC + c;
360 forward[ 1] = a.x * a.y * oneMinusC - a.z * s;
361 forward[ 2] = a.x * a.z * oneMinusC + a.y * s;
362 forward[ 4] = a.y * a.x * oneMinusC + a.z * s;
363 forward[ 5] = a.y * a.y * oneMinusC + c;
364 forward[ 6] = a.y * a.z * oneMinusC - a.x * s;
365 forward[ 8] = a.z * a.x * oneMinusC - a.y * s;
366 forward[ 9] = a.z * a.y * oneMinusC + a.x * s;
367 forward[10] = a.z * a.z * oneMinusC + c;
369 translate(pimpl->forward, pimpl->inverse);
371 pimpl->hasInverse =
true;
379const Transformation3D<T> Transformation3D<T>::lookAt(
const TPoint& eye,
const TPoint& target,
const TVector& sky)
381 const TVector dir = target - eye;
382 const TVector right = cross(dir, sky);
383 const TVector up = cross(right, dir);
395template <
typename T>
inline
398 isInversed_(isInversed)
405void Transformation3D<T>::computeInverse()
const
407 if (pimpl_->hasInverse.load(std::memory_order_acquire))
414 if (pimpl_->hasInverse.load(std::memory_order_relaxed))
419 const TConstMatrix& mat = pimpl_->forward;
420 TMatrix&
inv = pimpl_->inverse;
422 const TValue v1015 = mat[10] * mat[15];
423 const TValue v1411 = mat[14] * mat[11];
424 const TValue v0615 = mat[ 6] * mat[15];
425 const TValue v1407 = mat[14] * mat[ 7];
426 const TValue v0611 = mat[ 6] * mat[11];
427 const TValue v1007 = mat[10] * mat[ 7];
428 const TValue v0215 = mat[ 2] * mat[15];
429 const TValue v1403 = mat[14] * mat[ 3];
430 const TValue v0211 = mat[ 2] * mat[11];
431 const TValue v1003 = mat[10] * mat[ 3];
432 const TValue v0207 = mat[ 2] * mat[ 7];
433 const TValue v0603 = mat[ 6] * mat[ 3];
435 inv[0] = v1015 * mat[ 5] + v1407 * mat[ 9] + v0611 * mat[13]
436 - v1411 * mat[ 5] - v0615 * mat[ 9] - v1007 * mat[13];
437 inv[1] = v1411 * mat[ 1] + v0215 * mat[ 9] + v1003 * mat[13]
438 - v1015 * mat[ 1] - v1403 * mat[ 9] - v0211 * mat[13];
439 inv[2] = v0615 * mat[ 1] + v1403 * mat[ 5] + v0207 * mat[13]
440 - v1407 * mat[ 1] - v0215 * mat[ 5] - v0603 * mat[13];
441 inv[3] = v1007 * mat[ 1] + v0211 * mat[ 5] + v0603 * mat[ 9]
442 - v0611 * mat[ 1] - v1003 * mat[ 5] - v0207 * mat[ 9];
443 inv[4] = v1411 * mat[ 4] + v0615 * mat[ 8] + v1007 * mat[12]
444 - v1015 * mat[ 4] - v1407 * mat[ 8] - v0611 * mat[12];
445 inv[5] = v1015 * mat[ 0] + v1403 * mat[ 8] + v0211 * mat[12]
446 - v1411 * mat[ 0] - v0215 * mat[ 8] - v1003 * mat[12];
447 inv[6] = v1407 * mat[ 0] + v0215 * mat[ 4] + v0603 * mat[12]
448 - v0615 * mat[ 0] - v1403 * mat[ 4] - v0207 * mat[12];
449 inv[7] = v0611 * mat[ 0] + v1003 * mat[ 4] + v0207 * mat[ 8]
450 - v1007 * mat[ 0] - v0211 * mat[ 4] - v0603 * mat[ 8];
452 const TValue v0813 = mat[ 8] * mat[13];
453 const TValue v1209 = mat[12] * mat[ 9];
454 const TValue v0413 = mat[ 4] * mat[13];
455 const TValue v1205 = mat[12] * mat[ 5];
456 const TValue v0409 = mat[ 4] * mat[ 9];
457 const TValue v0805 = mat[ 8] * mat[ 5];
458 const TValue v0013 = mat[ 0] * mat[13];
459 const TValue v1201 = mat[12] * mat[ 1];
460 const TValue v0009 = mat[ 0] * mat[ 9];
461 const TValue v0801 = mat[ 8] * mat[ 1];
462 const TValue v0005 = mat[ 0] * mat[ 5];
463 const TValue v0401 = mat[ 4] * mat[ 1];
465 inv[ 8] = v0813 * mat[ 7] + v1205 * mat[11] + v0409 * mat[15]
466 - v1209 * mat[ 7] - v0413 * mat[11] - v0805 * mat[15];
467 inv[ 9] = v1209 * mat[ 3] + v0013 * mat[11] + v0801 * mat[15]
468 - v0813 * mat[ 3] - v1201 * mat[11] - v0009 * mat[15];
469 inv[10] = v0413 * mat[ 3] + v1201 * mat[ 7] + v0005 * mat[15]
470 - v1205 * mat[ 3] - v0013 * mat[ 7] - v0401 * mat[15];
471 inv[11] = v0805 * mat[ 3] + v0009 * mat[ 7] + v0401 * mat[11]
472 - v0409 * mat[ 3] - v0801 * mat[ 7] - v0005 * mat[11];
473 inv[12] = v0413 * mat[10] + v0805 * mat[14] + v1209 * mat[ 6]
474 - v0409 * mat[14] - v0813 * mat[ 6] - v1205 * mat[10];
475 inv[13] = v0009 * mat[14] + v0813 * mat[ 2] + v1201 * mat[10]
476 - v0013 * mat[10] - v0801 * mat[14] - v1209 * mat[ 2];
477 inv[14] = v0013 * mat[ 6] + v0401 * mat[14] + v1205 * mat[ 2]
478 - v0005 * mat[14] - v0413 * mat[ 2] - v1201 * mat[ 6];
479 inv[15] = v0005 * mat[10] + v0409 * mat[ 2] + v0801 * mat[ 6]
480 - v0009 * mat[ 6] - v0401 * mat[10] - v0805 * mat[ 2];
482 const TValue det = mat[0] *
inv[0] + mat[4] *
inv[1] + mat[8] *
inv[2] + mat[12] *
inv[3];
483 if (det == TNumTraits::zero)
485 LASS_THROW_EX(util::SingularityError,
"transformation not invertible");
487 const TValue invDet =
num::inv(det);
488 for (
size_t i = 0; i < matrixSize_; ++i)
493 pimpl_->hasInverse.store(
true, std::memory_order_release);
500void Transformation3D<T>::translate(
const TConstMatrix& source, TMatrix& dest)
502 for(
size_t i = 0; i < 4; ++i)
504 for(
size_t j = 0; j < 4; ++j)
506 dest[4 * i + j] = source[4 * j + i];
516 static TConstMatrix mat =
523 std::copy(mat, mat + matrixSize_, dest);
529typename Transformation3D<T>::TImplPtr Transformation3D<T>::makeIdentity()
531 TImplPtr pimpl(TImplPtr::allocate());
532 identity(pimpl->forward);
533 identity(pimpl->inverse);
534 pimpl->hasInverse =
true;
535 pimpl->isTranslation =
true;
558 const T*
const a = second.
matrix();
559 const T*
const b = first.
matrix();
561 for (
size_t i = 0; i < 16; i += 4)
563 for (
size_t j = 0; j < 4; ++j)
567 a[i + 1] * b[ 4 + j] +
568 a[i + 2] * b[ 8 + j] +
569 a[i + 3] * b[12 + j];
583 const T*
const mat = transformation.
matrix();
585 mat[ 0] * subject.x + mat[ 1] * subject.y + mat[ 2] * subject.z,
586 mat[ 4] * subject.x + mat[ 5] * subject.y + mat[ 6] * subject.z,
587 mat[ 8] * subject.x + mat[ 9] * subject.y + mat[10] * subject.z);
598 const T*
const mat = transformation.
matrix();
599 const T weight =
num::inv(mat[12] * subject.x + mat[13] * subject.y + mat[14] * subject.z + mat[15]);
601 weight * (mat[ 0] * subject.x + mat[ 1] * subject.y + mat[ 2] * subject.z + mat[ 3]),
602 weight * (mat[ 4] * subject.x + mat[ 5] * subject.y + mat[ 6] * subject.z + mat[ 7]),
603 weight * (mat[ 8] * subject.x + mat[ 9] * subject.y + mat[10] * subject.z + mat[11]));
619 invMat[ 0] * subject.x + invMat[ 4] * subject.y + invMat[ 8] * subject.z,
620 invMat[ 1] * subject.x + invMat[ 5] * subject.y + invMat[ 9] * subject.z,
621 invMat[ 2] * subject.x + invMat[ 6] * subject.y + invMat[10] * subject.z);
645 const T d = subject.second;
647 invMat[ 0] * n.x + invMat[ 4] * n.y + invMat[ 8] * n.z + invMat[12] * d,
648 invMat[ 1] * n.x + invMat[ 5] * n.y + invMat[ 9] * n.z + invMat[13] * d,
649 invMat[ 2] * n.x + invMat[ 6] * n.y + invMat[10] * n.z + invMat[14] * d);
650 const T transformedD =
651 invMat[ 3] * n.x + invMat[ 7] * n.y + invMat[11] * n.z + invMat[15] * d;
652 return std::make_pair(transformedN, transformedD);
659template<
typename T,
typename Char,
typename Traits>
660std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& stream,
663 const T*
const mat = transformation.
matrix();
664 LASS_ENFORCE_STREAM(stream) <<
"(("
665 << mat[ 0] <<
", " << mat[ 1] <<
", " << mat[ 2] <<
", " << mat[ 3] <<
"), ("
666 << mat[ 4] <<
", " << mat[ 5] <<
", " << mat[ 6] <<
", " << mat[ 7] <<
"), ("
667 << mat[ 8] <<
", " << mat[ 9] <<
", " << mat[10] <<
", " << mat[11] <<
"), ("
668 << mat[12] <<
", " << mat[13] <<
", " << mat[14] <<
", " << mat[15] <<
"))";
679 const T*
const mat = transformation.matrix();
680 LASS_ENFORCE_STREAM(stream) <<
"<Transformation3D>"
681 << mat[ 0] <<
" " << mat[ 1] <<
" " << mat[ 2] <<
" " << mat[ 3] <<
" "
682 << mat[ 4] <<
" " << mat[ 5] <<
" " << mat[ 6] <<
" " << mat[ 7] <<
" "
683 << mat[ 8] <<
" " << mat[ 9] <<
" " << mat[10] <<
" " << mat[11] <<
" "
684 << mat[12] <<
" " << mat[13] <<
" " << mat[14] <<
" " << mat[15]
685 <<
"</Transformation3D>\n";