Cycles: svn merge -r36747:36777 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender-staging.git] / intern / cycles / util / util_transform.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #ifndef __UTIL_TRANSFORM_H__
20 #define __UTIL_TRANSFORM_H__
21
22 #ifndef __KERNEL_GPU__
23 #include <string.h>
24 #endif
25
26 #include "util_math.h"
27 #include "util_types.h"
28
29 CCL_NAMESPACE_BEGIN
30
31 typedef struct Transform {
32         float4 x, y, z, w; /* rows */
33 } Transform;
34
35 __device_inline float3 transform(const Transform *t, const float3 a)
36 {
37         float4 b = {a.x, a.y, a.z, 1.0f};
38         float3 c = {dot(t->x, b), dot(t->y, b), dot(t->z, b)};
39
40         return c/dot(t->w, b);
41 }
42
43 __device_inline float3 transform_direction(const Transform *t, const float3 a)
44 {
45         float4 b = {a.x, a.y, a.z, 0.0f};
46         float3 c = {dot(t->x, b), dot(t->y, b), dot(t->z, b)};
47
48         return c;
49 }
50
51 #ifndef __KERNEL_GPU__
52
53 __device_inline void print_transform(const char *label, const Transform& t)
54 {
55         print_float4(label, t.x);
56         print_float4(label, t.y);
57         print_float4(label, t.z);
58         print_float4(label, t.w);
59         printf("\n");
60 }
61
62 __device_inline Transform transform_transpose(const Transform a)
63 {
64         Transform t;
65
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;
70
71         return t;
72 }
73
74 __device_inline Transform operator*(const Transform a, const Transform b)
75 {
76         Transform c = transform_transpose(b);
77         Transform t;
78
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));
83
84         return t;
85 }
86
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)
91 {
92         Transform t;
93
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;
98
99         return t;
100 }
101
102 __device_inline Transform transform_translate(float3 t)
103 {
104         return make_transform(
105                 1, 0, 0, t.x,
106                 0, 1, 0, t.y,
107                 0, 0, 1, t.z,
108                 0, 0, 0, 1);
109 }
110
111 __device_inline Transform transform_translate(float x, float y, float z)
112 {
113         return transform_translate(make_float3(x, y, z));
114 }
115
116 __device_inline Transform transform_scale(float3 s)
117 {
118         return make_transform(
119                 s.x, 0, 0, 0,
120                 0, s.y, 0, 0,
121                 0, 0, s.z, 0,
122                 0, 0, 0, 1);
123 }
124
125 __device_inline Transform transform_scale(float x, float y, float z)
126 {
127         return transform_scale(make_float3(x, y, z));
128 }
129
130 __device_inline Transform transform_perspective(float fov, float n, float f)
131 {
132         Transform persp = make_transform(
133                 1, 0, 0, 0,
134                 0, 1, 0, 0,
135                 0, 0, f / (f - n), -f*n / (f - n),
136                 0, 0, 1, 0);
137
138         float inv_angle = 1.0f/tanf(0.5f*fov);
139
140         Transform scale = transform_scale(inv_angle, inv_angle, 1);
141
142         return scale * persp;
143 }
144
145 __device_inline Transform transform_rotate(float angle, float3 axis)
146 {
147         float s = sinf(angle);
148         float c = cosf(angle);
149         float t = 1.f - c;
150
151         axis = normalize(axis);
152
153         return make_transform(
154                 axis.x*axis.x*t + c,
155                 axis.x*axis.y*t - s*axis.z,
156                 axis.x*axis.z*t + s*axis.y,
157                 0.0f,
158
159                 axis.y*axis.x*t + s*axis.z,
160                 axis.y*axis.y*t + c,
161                 axis.y*axis.z*t - s*axis.x,
162                 0.0f,
163
164                 axis.z*axis.x*t - s*axis.y,
165                 axis.z*axis.y*t + s*axis.x,
166                 axis.z*axis.z*t + c,
167                 0.0f,
168
169                 0.0f, 0.0f, 0.0f, 1.0f);
170 }
171
172 __device_inline Transform transform_euler(float3 euler)
173 {
174         return
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));
178 }
179
180 __device_inline Transform transform_orthographic(float znear, float zfar)
181 {
182         return transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) *
183                 transform_translate(0.0f, 0.0f, -znear);
184 }
185
186 __device_inline Transform transform_identity()
187 {
188         return transform_scale(1.0f, 1.0f, 1.0f);
189 }
190
191 __device_inline bool operator==(const Transform& A, const Transform& B)
192 {
193         return memcmp(&A, &B, sizeof(Transform)) == 0;
194 }
195
196 __device_inline bool operator!=(const Transform& A, const Transform& B)
197 {
198         return !(A == B);
199 }
200
201 __device_inline float3 transform_get_column(const Transform *t, int column)
202 {
203         return make_float3(t->x[column], t->y[column], t->z[column]);
204 }
205
206 Transform transform_inverse(const Transform& a);
207
208 #endif
209
210 CCL_NAMESPACE_END
211
212 #endif /* __UTIL_TRANSFORM_H__ */
213