2 * Copyright 2011, Blender Foundation.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #ifndef __UTIL_TRANSFORM_H__
20 #define __UTIL_TRANSFORM_H__
22 #ifndef __KERNEL_GPU__
26 #include "util_math.h"
27 #include "util_types.h"
31 typedef struct Transform {
32 float4 x, y, z, w; /* rows */
35 __device_inline float3 transform(const Transform *t, const float3 a)
37 float4 b = make_float4(a.x, a.y, a.z, 1.0f);
38 float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
40 return c/dot(t->w, b);
43 __device_inline float3 transform_direction(const Transform *t, const float3 a)
45 float4 b = make_float4(a.x, a.y, a.z, 0.0f);
46 float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
51 #ifndef __KERNEL_GPU__
53 __device_inline void print_transform(const char *label, const Transform& t)
55 print_float4(label, t.x);
56 print_float4(label, t.y);
57 print_float4(label, t.z);
58 print_float4(label, t.w);
62 __device_inline Transform transform_transpose(const Transform a)
66 t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x;
67 t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y;
68 t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z;
69 t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w;
74 __device_inline Transform operator*(const Transform a, const Transform b)
76 Transform c = transform_transpose(b);
79 t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w));
80 t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w));
81 t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w));
82 t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w));
87 __device_inline Transform make_transform(float a, float b, float c, float d,
88 float e, float f, float g, float h,
89 float i, float j, float k, float l,
90 float m, float n, float o, float p)
94 t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d;
95 t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h;
96 t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l;
97 t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p;
102 __device_inline Transform transform_translate(float3 t)
104 return make_transform(
111 __device_inline Transform transform_translate(float x, float y, float z)
113 return transform_translate(make_float3(x, y, z));
116 __device_inline Transform transform_scale(float3 s)
118 return make_transform(
125 __device_inline Transform transform_scale(float x, float y, float z)
127 return transform_scale(make_float3(x, y, z));
130 __device_inline Transform transform_perspective(float fov, float n, float f)
132 Transform persp = make_transform(
135 0, 0, f / (f - n), -f*n / (f - n),
138 float inv_angle = 1.0f/tanf(0.5f*fov);
140 Transform scale = transform_scale(inv_angle, inv_angle, 1);
142 return scale * persp;
145 __device_inline Transform transform_rotate(float angle, float3 axis)
147 float s = sinf(angle);
148 float c = cosf(angle);
151 axis = normalize(axis);
153 return make_transform(
155 axis.x*axis.y*t - s*axis.z,
156 axis.x*axis.z*t + s*axis.y,
159 axis.y*axis.x*t + s*axis.z,
161 axis.y*axis.z*t - s*axis.x,
164 axis.z*axis.x*t - s*axis.y,
165 axis.z*axis.y*t + s*axis.x,
169 0.0f, 0.0f, 0.0f, 1.0f);
172 __device_inline Transform transform_euler(float3 euler)
175 transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f)) *
176 transform_rotate(euler.y, make_float3(0.0f, 1.0f, 0.0f)) *
177 transform_rotate(euler.z, make_float3(0.0f, 0.0f, 1.0f));
180 __device_inline Transform transform_orthographic(float znear, float zfar)
182 return transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) *
183 transform_translate(0.0f, 0.0f, -znear);
186 __device_inline Transform transform_identity()
188 return transform_scale(1.0f, 1.0f, 1.0f);
191 __device_inline bool operator==(const Transform& A, const Transform& B)
193 return memcmp(&A, &B, sizeof(Transform)) == 0;
196 __device_inline bool operator!=(const Transform& A, const Transform& B)
201 __device_inline float3 transform_get_column(const Transform *t, int column)
203 return make_float3(t->x[column], t->y[column], t->z[column]);
206 Transform transform_inverse(const Transform& a);
208 __device_inline bool transform_uniform_scale(const Transform& tfm, float& scale)
210 /* the epsilon here is quite arbitrary, but this function is only used for
211 surface area and bump, where we except it to not be so sensitive */
212 Transform ttfm = transform_transpose(tfm);
215 float sx = len(float4_to_float3(tfm.x));
216 float sy = len(float4_to_float3(tfm.y));
217 float sz = len(float4_to_float3(tfm.z));
218 float stx = len(float4_to_float3(ttfm.x));
219 float sty = len(float4_to_float3(ttfm.y));
220 float stz = len(float4_to_float3(ttfm.z));
222 if(fabsf(sx - sy) < eps && fabsf(sx - sz) < eps &&
223 fabsf(sx - stx) < eps && fabsf(sx - sty) < eps &&
224 fabsf(sx - stz) < eps) {
236 #endif /* __UTIL_TRANSFORM_H__ */