1 /* Copyright Jukka Jyl�nki
2
3    Licensed under the Apache License, Version 2.0 (the "License");
4    you may not use this file except in compliance with the License.
5    You may obtain a copy of the License at
6
7        http://www.apache.org/licenses/LICENSE-2.0
8
9    Unless required by applicable law or agreed to in writing, software
10    distributed under the License is distributed on an "AS IS" BASIS,
11    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12    See the License for the specific language governing permissions and
13    limitations under the License. */
14
15 /** @file TransformOps.cpp
16         @author Jukka Jyl�nki
17         @brief */
18 #include "TransformOps.h"
19 #include "MathFunc.h"
20 #include "float4.h"
21 #include "float3x3.h"
22 #include "float3x4.h"
23 #include "float4x4.h"
24
25 MATH_BEGIN_NAMESPACE
26
27 TranslateOp::TranslateOp(float tx, float ty, float tz)
28 :offset(DIR_VEC(tx, ty, tz))
29 {
30 }
31
32 TranslateOp::TranslateOp(const float3 &trans)
33 :offset(DIR_VEC(trans))
34 {
35 }
36
37 TranslateOp::operator float3x4() const
38 {
39         return ToFloat3x4();
40 }
41
42 TranslateOp::operator float4x4() const
43 {
44         return ToFloat4x4();
45 }
46
47
48 float3x4 TranslateOp::ToFloat3x4() const
49 {
50         float3x4 m;
51         m.SetRow(0, 1, 0, 0, offset.x);
52         m.SetRow(1, 0, 1, 0, offset.y);
53         m.SetRow(2, 0, 0, 1, offset.z);
54         return m;
55 }
56
57 float4x4 TranslateOp::ToFloat4x4() const
58 {
59         float4x4 m;
60         m.SetRow(0, 1, 0, 0, offset.x);
61         m.SetRow(1, 0, 1, 0, offset.y);
62         m.SetRow(2, 0, 0, 1, offset.z);
63         m.SetRow(3, 0, 0, 0, 1.f);
64         return m;
65 }
66
67 vec TranslateOp::Offset() const
68 {
69         return offset;
70 }
71
72 #ifdef MATH_ENABLE_STL_SUPPORT
73 std::string TranslateOp::ToString() const
74 {
75         char str[256];
76         sprintf(str, "(%.3f, %.3f, %.3f)"offset.xoffset.yoffset.z);
77         return std::string(str);
78 }
79 #endif
80
81 float3x4 operator *(const TranslateOp &lhs, const float3x4 &rhs)
82 {
83         float3x4 r = rhs;
84         r.SetTranslatePart(r.TranslatePart() + DIR_TO_FLOAT3(lhs.Offset()));
85
86         // Our optimized form of multiplication must be the same as this.
87         mathassert(r.Equals((float3x4)lhs * rhs));
88         return r;
89 }
90
91 float3x4 operator *(const float3x4 &lhs, const TranslateOp &rhs)
92 {
93         float3x4 r = lhs;
94         r.SetTranslatePart(lhs.TransformPos(DIR_TO_FLOAT3(rhs.Offset())));
95
96         // Our optimized form of multiplication must be the same as this.
97         assume4(r.Equals(lhs * (float3x4)rhs), lhs, rhs, r, lhs * (float3x4)rhs);
98         return r;
99 }
100
101 float4x4 operator *(const TranslateOp &lhs, const float4x4 &rhs)
102 {
103         // This function is based on the optimized assumption that the last row of rhs is [0,0,0,1].
104         // If this does not hold and you are hitting the check below, explicitly cast TranslateOp lhs to float4x4 before multiplication!
105         assume(rhs.Row(3).Equals(0.f, 0.f, 0.f, 1.f));
106
107         float4x4 r = rhs;
108         r.SetTranslatePart(r.TranslatePart() + DIR_TO_FLOAT3(lhs.Offset()));
109         return r;
110 }
111
112 float4x4 operator *(const float4x4 &lhs, const TranslateOp &rhs)
113 {
114         float4x4 r = lhs;
115         r.SetTranslatePart(lhs.TransformPos(DIR_TO_FLOAT3(rhs.Offset())));
116         return r;
117 }
118
119 ScaleOp::ScaleOp(float sx, float sy, float sz)
120 :scale(DIR_VEC(sx, sy, sz))
121 {
122 }
123
124 ScaleOp::ScaleOp(const float3 &scale)
125 :scale(DIR_VEC(scale))
126 {
127 }
128
129 ScaleOp::ScaleOp(const float4 &scale)
130 :scale(FLOAT4_TO_DIR(scale))
131 {
132 }
133
134 ScaleOp::operator float3x3() const
135 {
136         return ToFloat3x3();
137 }
138
139 ScaleOp::operator float3x4() const
140 {
141         return ToFloat3x4();
142 }
143
144 ScaleOp::operator float4x4() const
145 {
146         return ToFloat4x4();
147 }
148
149 float3x3 ScaleOp::ToFloat3x3() const
150 {
151         float3x3 m;
152         m.SetRow(0, scale.x, 0, 0);
153         m.SetRow(1, 0, scale.y, 0);
154         m.SetRow(2, 0, 0, scale.z);
155         return m;
156 }
157
158 float3x4 ScaleOp::ToFloat3x4() const
159 {
160         float3x4 m;
161         m.SetRow(0, scale.x, 0, 0, 0);
162         m.SetRow(1, 0, scale.y, 0, 0);
163         m.SetRow(2, 0, 0, scale.z, 0);
164         return m;
165 }
166
167 float4x4 ScaleOp::ToFloat4x4() const
168 {
169         float4x4 m;
170         m.SetRow(0, scale.x, 0, 0, 0);
171         m.SetRow(1, 0, scale.y, 0, 0);
172         m.SetRow(2, 0, 0, scale.z, 0);
173         m.SetRow(3, 0, 0, 0, 1.f);
174         return m;
175 }
176
177 float3x3 operator *(const ScaleOp &lhs, const float3x3 &rhs)
178 {
179         float3x3 ret = rhs;
180         ret.ScaleRow(0, lhs.scale.x);
181         ret.ScaleRow(1, lhs.scale.y);
182         ret.ScaleRow(2, lhs.scale.z);
183
184         // Our optimized form of multiplication must be the same as this.
185         mathassert(ret.Equals((float3x3)lhs * rhs));
186         return ret;
187 }
188
189 float3x3 operator *(const float3x3 &lhs, const ScaleOp &rhs)
190 {
191         float3x3 ret = lhs;
192         ret.ScaleCol(0, rhs.scale.x);
193         ret.ScaleCol(1, rhs.scale.y);
194         ret.ScaleCol(2, rhs.scale.z);
195
196         // Our optimized form of multiplication must be the same as this.
197         mathassert(ret.Equals(lhs * (float3x3)rhs));
198         return ret;
199 }
200
201 float3x4 operator *(const ScaleOp &lhs, const float3x4 &rhs)
202 {
203         float3x4 ret;
204         ret[0][0] = rhs[0][0] * lhs.scale.x; ret[0][1] = rhs[0][1] * lhs.scale.x; ret[0][2] = rhs[0][2] * lhs.scale.x; ret[0][3] = rhs[0][3] * lhs.scale.x;
205         ret[1][0] = rhs[1][0] * lhs.scale.y; ret[1][1] = rhs[1][1] * lhs.scale.y; ret[1][2] = rhs[1][2] * lhs.scale.y; ret[1][3] = rhs[1][3] * lhs.scale.y;
206         ret[2][0] = rhs[2][0] * lhs.scale.z; ret[2][1] = rhs[2][1] * lhs.scale.z; ret[2][2] = rhs[2][2] * lhs.scale.z; ret[2][3] = rhs[2][3] * lhs.scale.z;
207
208         mathassert(ret.Equals(lhs.ToFloat3x4() * rhs));
209         return ret;
210 }
211
212 float3x4 operator *(const float3x4 &lhs, const ScaleOp &rhs)
213 {
214         float3x4 ret;
215         ret[0][0] = lhs[0][0] * rhs.scale.x; ret[0][1] = lhs[0][1] * rhs.scale.y; ret[0][2] = lhs[0][2] * rhs.scale.z; ret[0][3] = lhs[0][3];
216         ret[1][0] = lhs[1][0] * rhs.scale.x; ret[1][1] = lhs[1][1] * rhs.scale.y; ret[1][2] = lhs[1][2] * rhs.scale.z; ret[1][3] = lhs[1][3];
217         ret[2][0] = lhs[2][0] * rhs.scale.x; ret[2][1] = lhs[2][1] * rhs.scale.y; ret[2][2] = lhs[2][2] * rhs.scale.z; ret[2][3] = lhs[2][3];
218
219         mathassert(ret.Equals(lhs * rhs.ToFloat3x4()));
220         return ret;
221 }
222
223 float4x4 operator *(const ScaleOp &lhs, const float4x4 &rhs)
224 {
225         float4x4 ret;
226 #if defined(MATH_AUTOMATIC_SSE) && defined(MATH_SSE)
227         simd4f x = xxxx_ps(lhs.scale.v);
228         simd4f y = yyyy_ps(lhs.scale.v);
229         simd4f z = zzzz_ps(lhs.scale.v);
230         ret.row[0] = _mm_mul_ps(rhs.row[0], x);
231         ret.row[1] = _mm_mul_ps(rhs.row[1], y);
232         ret.row[2] = _mm_mul_ps(rhs.row[2], z);
233         ret.row[3] = rhs.row[3];
234 #else
235         ret[0][0] = rhs[0][0] * lhs.scale.x; ret[0][1] = rhs[0][1] * lhs.scale.x; ret[0][2] = rhs[0][2] * lhs.scale.x; ret[0][3] = rhs[0][3] * lhs.scale.x;
236         ret[1][0] = rhs[1][0] * lhs.scale.y; ret[1][1] = rhs[1][1] * lhs.scale.y; ret[1][2] = rhs[1][2] * lhs.scale.y; ret[1][3] = rhs[1][3] * lhs.scale.y;
237         ret[2][0] = rhs[2][0] * lhs.scale.z; ret[2][1] = rhs[2][1] * lhs.scale.z; ret[2][2] = rhs[2][2] * lhs.scale.z; ret[2][3] = rhs[2][3] * lhs.scale.z;
238         ret[3][0] = rhs[3][0];         ret[3][1] = rhs[3][1];         ret[3][2] = rhs[3][2];         ret[3][3] = rhs[3][3];
239 #endif
240         mathassert(ret.Equals(lhs.ToFloat4x4() * rhs));
241         return ret;
242 }
243
244 float4x4 operator *(const float4x4 &lhs, const ScaleOp &rhs)
245 {
246         float4x4 ret;
247         ret[0][0] = lhs[0][0] * rhs.scale.x; ret[0][1] = lhs[0][1] * rhs.scale.y; ret[0][2] = lhs[0][2] * rhs.scale.z; ret[0][3] = lhs[0][3];
248         ret[1][0] = lhs[1][0] * rhs.scale.x; ret[1][1] = lhs[1][1] * rhs.scale.y; ret[1][2] = lhs[1][2] * rhs.scale.z; ret[1][3] = lhs[1][3];
249         ret[2][0] = lhs[2][0] * rhs.scale.x; ret[2][1] = lhs[2][1] * rhs.scale.y; ret[2][2] = lhs[2][2] * rhs.scale.z; ret[2][3] = lhs[2][3];
250         ret[3][0] = lhs[3][0] * rhs.scale.x; ret[3][1] = lhs[3][1] * rhs.scale.y; ret[3][2] = lhs[3][2] * rhs.scale.z; ret[3][3] = lhs[3][3];
251
252         mathassert(ret.Equals(lhs * rhs.ToFloat4x4()));
253         return ret;
254 }
255
256 float3x4 operator *(const ScaleOp &lhs, const TranslateOp &rhs)
257 {
258         float3x4 ret;
259         ret[0][0] = lhs.scale.x; ret[0][1] =           0; ret[0][2] =           0; ret[0][3] = lhs.scale.x * rhs.offset.x;
260         ret[1][0] =               0; ret[1][1] = lhs.scale.y; ret[1][2] =               0; ret[1][3] = lhs.scale.y * rhs.offset.y;
261         ret[2][0] =               0; ret[2][1] =               0; ret[2][2] = lhs.scale.z; ret[2][3] = lhs.scale.z * rhs.offset.z;
262
263         mathassert(ret.Equals(lhs.ToFloat3x4() * rhs));
264         return ret;
265 }
266
267 float3x4 operator *(const TranslateOp &lhs, const ScaleOp &rhs)
268 {
269         float3x4 ret;
270         ret[0][0] = rhs.scale.x; ret[0][1] =     0; ret[0][2] =  0; ret[0][3] = lhs.offset.x;
271         ret[1][0] =      0; ret[1][1] = rhs.scale.y; ret[1][2] =         0; ret[1][3] = lhs.offset.y;
272         ret[2][0] =      0; ret[2][1] =  0; ret[2][2] = rhs.scale.z; ret[2][3] = lhs.offset.z;
273
274         mathassert(ret.Equals(lhs.ToFloat3x4() * rhs));
275         return ret;
276 }
277
278 vec ScaleOp::Offset() const
279 {
280         return scale;
281 }
282
283 #ifdef MATH_ENABLE_STL_SUPPORT
284 std::string ScaleOp::ToString() const
285 {
286         char str[256];
287         sprintf(str, "(%.3f, %.3f, %.3f)"scale.xscale.yscale.z);
288         return std::string(str);
289 }
290 #endif
291
292 MATH_END_NAMESPACE

Go back to previous page