add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / kernel / kernel_object.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 CCL_NAMESPACE_BEGIN
20
21 enum ObjectTransform {
22         OBJECT_TRANSFORM = 0,
23         OBJECT_TRANSFORM_MOTION_PRE = 0,
24         OBJECT_INVERSE_TRANSFORM = 4,
25         OBJECT_TRANSFORM_MOTION_POST = 4,
26         OBJECT_PROPERTIES = 8,
27         OBJECT_DUPLI = 9
28 };
29
30 enum ObjectVectorTransform {
31         OBJECT_VECTOR_MOTION_PRE = 0,
32         OBJECT_VECTOR_MOTION_POST = 3
33 };
34
35 __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
36 {
37         int offset = object*OBJECT_SIZE + (int)type;
38
39         Transform tfm;
40         tfm.x = kernel_tex_fetch(__objects, offset + 0);
41         tfm.y = kernel_tex_fetch(__objects, offset + 1);
42         tfm.z = kernel_tex_fetch(__objects, offset + 2);
43         tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
44
45         return tfm;
46 }
47
48 __device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int object, enum ObjectVectorTransform type)
49 {
50         int offset = object*OBJECT_VECTOR_SIZE + (int)type;
51
52         Transform tfm;
53         tfm.x = kernel_tex_fetch(__objects_vector, offset + 0);
54         tfm.y = kernel_tex_fetch(__objects_vector, offset + 1);
55         tfm.z = kernel_tex_fetch(__objects_vector, offset + 2);
56         tfm.w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
57
58         return tfm;
59 }
60
61 #ifdef __OBJECT_MOTION__
62 __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
63 {
64         DecompMotionTransform motion;
65
66         int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE;
67
68         motion.mid.x = kernel_tex_fetch(__objects, offset + 0);
69         motion.mid.y = kernel_tex_fetch(__objects, offset + 1);
70         motion.mid.z = kernel_tex_fetch(__objects, offset + 2);
71         motion.mid.w = kernel_tex_fetch(__objects, offset + 3);
72
73         motion.pre_x = kernel_tex_fetch(__objects, offset + 4);
74         motion.pre_y = kernel_tex_fetch(__objects, offset + 5);
75         motion.post_x = kernel_tex_fetch(__objects, offset + 6);
76         motion.post_y = kernel_tex_fetch(__objects, offset + 7);
77
78         Transform tfm;
79         transform_motion_interpolate(&tfm, &motion, time);
80
81         return tfm;
82 }
83
84 __device_inline Transform object_fetch_transform_motion_test(KernelGlobals *kg, int object, float time, Transform *itfm)
85 {
86         int object_flag = kernel_tex_fetch(__object_flag, object);
87
88         if(object_flag & SD_OBJECT_MOTION) {
89                 /* if we do motion blur */
90                 Transform tfm = object_fetch_transform_motion(kg, object, time);
91
92                 if(itfm)
93                         *itfm = transform_quick_inverse(tfm);
94
95                 return tfm;
96         }
97         else {
98                 Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
99                 if(itfm)
100                         *itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
101
102                 return tfm;
103         }
104 }
105 #endif
106
107 __device_inline void object_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P)
108 {
109 #ifdef __OBJECT_MOTION__
110         *P = transform_point(&sd->ob_tfm, *P);
111 #else
112         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
113         *P = transform_point(&tfm, *P);
114 #endif
115 }
116
117 __device_inline void object_inverse_position_transform(KernelGlobals *kg, ShaderData *sd, float3 *P)
118 {
119 #ifdef __OBJECT_MOTION__
120         *P = transform_point(&sd->ob_itfm, *P);
121 #else
122         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
123         *P = transform_point(&tfm, *P);
124 #endif
125 }
126
127 __device_inline void object_inverse_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N)
128 {
129 #ifdef __OBJECT_MOTION__
130         *N = normalize(transform_direction_transposed(&sd->ob_tfm, *N));
131 #else
132         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
133         *N = normalize(transform_direction_transposed(&tfm, *N));
134 #endif
135 }
136
137 __device_inline void object_normal_transform(KernelGlobals *kg, ShaderData *sd, float3 *N)
138 {
139 #ifdef __OBJECT_MOTION__
140         *N = normalize(transform_direction_transposed(&sd->ob_itfm, *N));
141 #else
142         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_INVERSE_TRANSFORM);
143         *N = normalize(transform_direction_transposed(&tfm, *N));
144 #endif
145 }
146
147 __device_inline void object_dir_transform(KernelGlobals *kg, ShaderData *sd, float3 *D)
148 {
149 #ifdef __OBJECT_MOTION__
150         *D = transform_direction(&sd->ob_tfm, *D);
151 #else
152         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
153         *D = transform_direction(&tfm, *D);
154 #endif
155 }
156
157 __device_inline float3 object_location(KernelGlobals *kg, ShaderData *sd)
158 {
159         if(sd->object == ~0)
160                 return make_float3(0.0f, 0.0f, 0.0f);
161
162 #ifdef __OBJECT_MOTION__
163         return make_float3(sd->ob_tfm.x.w, sd->ob_tfm.y.w, sd->ob_tfm.z.w);
164 #else
165         Transform tfm = object_fetch_transform(kg, sd->object, OBJECT_TRANSFORM);
166         return make_float3(tfm.x.w, tfm.y.w, tfm.z.w);
167 #endif
168 }
169
170 __device_inline float object_surface_area(KernelGlobals *kg, int object)
171 {
172         int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
173         float4 f = kernel_tex_fetch(__objects, offset);
174         return f.x;
175 }
176
177 __device_inline float object_pass_id(KernelGlobals *kg, int object)
178 {
179         if(object == ~0)
180                 return 0.0f;
181
182         int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
183         float4 f = kernel_tex_fetch(__objects, offset);
184         return f.y;
185 }
186
187 __device_inline float object_random_number(KernelGlobals *kg, int object)
188 {
189         if(object == ~0)
190                 return 0.0f;
191
192         int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
193         float4 f = kernel_tex_fetch(__objects, offset);
194         return f.z;
195 }
196
197 __device_inline uint object_particle_id(KernelGlobals *kg, int object)
198 {
199         if(object == ~0)
200                 return 0.0f;
201
202         int offset = object*OBJECT_SIZE + OBJECT_PROPERTIES;
203         float4 f = kernel_tex_fetch(__objects, offset);
204         return __float_as_uint(f.w);
205 }
206
207 __device_inline float3 object_dupli_generated(KernelGlobals *kg, int object)
208 {
209         if(object == ~0)
210                 return make_float3(0.0f, 0.0f, 0.0f);
211
212         int offset = object*OBJECT_SIZE + OBJECT_DUPLI;
213         float4 f = kernel_tex_fetch(__objects, offset);
214         return make_float3(f.x, f.y, f.z);
215 }
216
217 __device_inline float3 object_dupli_uv(KernelGlobals *kg, int object)
218 {
219         if(object == ~0)
220                 return make_float3(0.0f, 0.0f, 0.0f);
221
222         int offset = object*OBJECT_SIZE + OBJECT_DUPLI;
223         float4 f = kernel_tex_fetch(__objects, offset + 1);
224         return make_float3(f.x, f.y, 0.0f);
225 }
226
227
228 __device int shader_pass_id(KernelGlobals *kg, ShaderData *sd)
229 {
230         return kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2 + 1);
231 }
232
233 __device_inline float particle_index(KernelGlobals *kg, int particle)
234 {
235         int offset = particle*PARTICLE_SIZE;
236         float4 f = kernel_tex_fetch(__particles, offset + 0);
237         return f.x;
238 }
239
240 __device float particle_age(KernelGlobals *kg, int particle)
241 {
242         int offset = particle*PARTICLE_SIZE;
243         float4 f = kernel_tex_fetch(__particles, offset + 0);
244         return f.y;
245 }
246
247 __device float particle_lifetime(KernelGlobals *kg, int particle)
248 {
249         int offset = particle*PARTICLE_SIZE;
250         float4 f = kernel_tex_fetch(__particles, offset + 0);
251         return f.z;
252 }
253
254 __device float particle_size(KernelGlobals *kg, int particle)
255 {
256         int offset = particle*PARTICLE_SIZE;
257         float4 f = kernel_tex_fetch(__particles, offset + 0);
258         return f.w;
259 }
260
261 __device float4 particle_rotation(KernelGlobals *kg, int particle)
262 {
263         int offset = particle*PARTICLE_SIZE;
264         float4 f = kernel_tex_fetch(__particles, offset + 1);
265         return f;
266 }
267
268 __device float3 particle_location(KernelGlobals *kg, int particle)
269 {
270         int offset = particle*PARTICLE_SIZE;
271         float4 f = kernel_tex_fetch(__particles, offset + 2);
272         return make_float3(f.x, f.y, f.z);
273 }
274
275 __device float3 particle_velocity(KernelGlobals *kg, int particle)
276 {
277         int offset = particle*PARTICLE_SIZE;
278         float4 f2 = kernel_tex_fetch(__particles, offset + 2);
279         float4 f3 = kernel_tex_fetch(__particles, offset + 3);
280         return make_float3(f2.w, f3.x, f3.y);
281 }
282
283 __device float3 particle_angular_velocity(KernelGlobals *kg, int particle)
284 {
285         int offset = particle*PARTICLE_SIZE;
286         float4 f3 = kernel_tex_fetch(__particles, offset + 3);
287         float4 f4 = kernel_tex_fetch(__particles, offset + 4);
288         return make_float3(f3.z, f3.w, f4.x);
289 }
290
291 CCL_NAMESPACE_END
292