1
2//
3// This source file is part of appleseed.
4// Visit http://appleseedhq.net/ for additional information and resources.
5//
6// This software is released under the MIT license.
7//
8// Copyright (c) 2012-2013 Esteban Tovagliari, Jupiter Jazz Limited
9// Copyright (c) 2014-2017 Esteban Tovagliari, The appleseedhq Organization
10//
11// Permission is hereby granted, free of charge, to any person obtaining a copy
12// of this software and associated documentation files (the "Software"), to deal
13// in the Software without restriction, including without limitation the rights
14// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15// copies of the Software, and to permit persons to whom the Software is
16// furnished to do so, subject to the following conditions:
17//
18// The above copyright notice and this permission notice shall be included in
19// all copies or substantial portions of the Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27// THE SOFTWARE.
28//
29
30#ifndef APPLESEED_PYTHON_UNALIGNEDTRANSFORM_H
31#define APPLESEED_PYTHON_UNALIGNEDTRANSFORM_H
32
33// appleseed.python headers.
34#include "pyseed.h" // has to be first, to avoid redefinition warnings
35#include "unalignedmatrix44.h"
36
37// appleseed.foundation headers.
38#include "foundation/math/transform.h"
39
40namespace foundation
41{
42
43template <typename T>
44class UnalignedTransform
45{
46 public:
47 UnalignedTransform()
48 : m_local_to_parent(UnalignedMatrix44<T>::identity())
49 , m_parent_to_local(UnalignedMatrix44<T>::identity())
50 {
51 }
52
53 explicit UnalignedTransform(const Transform<T>& xform)
54 : m_local_to_parent(UnalignedMatrix44<T>(xform.get_local_to_parent()))
55 , m_parent_to_local(UnalignedMatrix44<T>(xform.get_parent_to_local()))
56 {
57 }
58
59 explicit UnalignedTransform(const UnalignedMatrix44<T>& local_to_parent)
60 : m_local_to_parent(local_to_parent)
61 , m_parent_to_local(invert_matrix(m_local_to_parent))
62 {
63 }
64
65 template <typename U>
66 explicit UnalignedTransform(const UnalignedTransform<U>& other)
67 : m_local_to_parent(other.get_local_to_parent())
68 , m_parent_to_local(other.get_parent_to_local())
69 {
70 }
71
72 UnalignedTransform(
73 const UnalignedMatrix44<T>& local_to_parent,
74 const UnalignedMatrix44<T>& parent_to_local)
75 {
76 Matrix<T, 4, 4> aligned_local_to_parent = local_to_parent.as_foundation_matrix();
77 Matrix<T, 4, 4> aligned_parent_to_local = parent_to_local.as_foundation_matrix();
78
79 // Check that local_to_parent * aligned_parent_to_local == identity, if not, throw an exception before the assert fires.
80 if (feq(aligned_local_to_parent * aligned_parent_to_local, Matrix<T, 4, 4>::identity(), make_eps<T>(1.0e-6f, 1.0e-9)))
81 {
82 m_local_to_parent = UnalignedMatrix44<T>(local_to_parent);
83 m_parent_to_local = UnalignedMatrix44<T>(parent_to_local);
84 }
85 else
86 {
87 PyErr_SetString(PyExc_RuntimeError, "Matrices passed to appleseed.Transform are not inverses of each other");
88 boost::python::throw_error_already_set();
89 }
90 }
91
92 static UnalignedTransform identity()
93 {
94 return UnalignedTransform(
95 UnalignedMatrix44<T>::identity(),
96 UnalignedMatrix44<T>::identity());
97 }
98
99 Transform<T> as_foundation_transform() const
100 {
101 return Transform<T>(
102 get_local_to_parent().as_foundation_matrix(),
103 get_parent_to_local().as_foundation_matrix());
104 }
105
106 const UnalignedMatrix44<T>& get_local_to_parent() const { return m_local_to_parent;}
107 const UnalignedMatrix44<T>& get_parent_to_local() const { return m_parent_to_local;}
108
109 UnalignedTransform operator*(const UnalignedTransform& rhs) const
110 {
111 return UnalignedTransform(this->as_foundation_transform() * rhs.as_foundation_transform());
112 }
113
114 Vector<T, 3> point_to_local(const Vector<T, 3>& p) const
115 {
116 return m_parent_to_local.transform_point(p);
117 }
118
119 Vector<T, 3> point_to_parent(const Vector<T, 3>& p) const
120 {
121 return m_local_to_parent.transform_point(p);
122 }
123
124 Vector<T, 3> vector_to_local(const Vector<T, 3>& v) const
125 {
126 return m_parent_to_local.transform_vector(v);
127 }
128
129 Vector<T, 3> vector_to_parent(const Vector<T, 3>& v) const
130 {
131 return m_local_to_parent.transform_vector(v);
132 }
133
134 Vector<T, 3> normal_to_local(const Vector<T, 3>& n) const
135 {
136 return m_local_to_parent.transform_normal(n);
137 }
138
139 Vector<T, 3> normal_to_parent(const Vector<T, 3>& n) const
140 {
141 return m_parent_to_local.transform_normal(n);
142 }
143
144 private:
145 UnalignedMatrix44<T> m_local_to_parent;
146 UnalignedMatrix44<T> m_parent_to_local;
147};
148
149template <typename T>
150inline std::ostream& operator<<(std::ostream& s, const UnalignedTransform<T>& xform)
151{
152 return s << xform.as_foundation_transform();
153}
154
155typedef UnalignedTransform<float> UnalignedTransformf;
156typedef UnalignedTransform<double> UnalignedTransformd;
157
158} // namespace foundation
159
160#endif // !APPLESEED_PYTHON_UNALIGNEDTRANSFORM_H
161