Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.git] / intern / cycles / kernel / kernel_triangle.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 /* Point on triangle for Moller-Trumbore triangles */
22 __device_inline float3 triangle_point_MT(KernelGlobals *kg, int tri_index, float u, float v)
23 {
24         /* load triangle vertices */
25         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
26
27         float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
28         float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
29         float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
30
31         /* compute point */
32         float t = 1.0f - u - v;
33         return (u*v0 + v*v1 + t*v2);
34 }
35
36 /* Sample point on triangle */
37 __device_inline float3 triangle_sample_MT(KernelGlobals *kg, int tri_index, float randu, float randv)
38 {
39         /* compute point */
40         randu = sqrtf(randu);
41
42         float u = 1.0f - randu;
43         float v = randv*randu;
44
45         return triangle_point_MT(kg, tri_index, u, v);
46 }
47
48 /* Normal for Moller-Trumbore triangles */
49 __device_inline float3 triangle_normal_MT(KernelGlobals *kg, int tri_index, int *shader)
50 {
51 #if 0
52         /* load triangle vertices */
53         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
54
55         float3 v0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
56         float3 v1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
57         float3 v2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
58
59         /* compute normal */
60         return normalize(cross(v2 - v0, v1 - v0));
61 #else
62         float4 Nm = kernel_tex_fetch(__tri_normal, tri_index);
63         *shader = __float_as_int(Nm.w);
64         return make_float3(Nm.x, Nm.y, Nm.z);
65 #endif
66 }
67
68 __device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v)
69 {
70         /* load triangle vertices */
71         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
72
73         float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
74         float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
75         float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.z)));
76
77         return normalize((1.0f - u - v)*n2 + u*n0 + v*n1);
78 }
79
80 __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dPdv, int tri)
81 {
82         /* fetch triangle vertex coordinates */
83         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri));
84
85         float3 p0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
86         float3 p1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
87         float3 p2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
88
89         /* compute derivatives of P w.r.t. uv */
90         *dPdu = (p0 - p2);
91         *dPdv = (p1 - p2);
92 }
93
94 /* attributes */
95
96 __device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
97 {
98         if(elem == ATTR_ELEMENT_FACE) {
99                 if(dx) *dx = 0.0f;
100                 if(dy) *dy = 0.0f;
101
102                 return kernel_tex_fetch(__attributes_float, offset + sd->prim);
103         }
104         else if(elem == ATTR_ELEMENT_VERTEX) {
105                 float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
106
107                 float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
108                 float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
109                 float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
110
111 #ifdef __RAY_DIFFERENTIALS__
112                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
113                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
114 #endif
115
116                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
117         }
118         else if(elem == ATTR_ELEMENT_CORNER) {
119                 int tri = offset + sd->prim*3;
120                 float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
121                 float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
122                 float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
123
124 #ifdef __RAY_DIFFERENTIALS__
125                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
126                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
127 #endif
128
129                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
130         }
131         else {
132                 if(dx) *dx = 0.0f;
133                 if(dy) *dy = 0.0f;
134
135                 return 0.0f;
136         }
137 }
138
139 __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
140 {
141         if(elem == ATTR_ELEMENT_FACE) {
142                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
143                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
144
145                 return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
146         }
147         else if(elem == ATTR_ELEMENT_VERTEX) {
148                 float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
149
150                 float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
151                 float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
152                 float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
153
154 #ifdef __RAY_DIFFERENTIALS__
155                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
156                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
157 #endif
158
159                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
160         }
161         else if(elem == ATTR_ELEMENT_CORNER) {
162                 int tri = offset + sd->prim*3;
163                 float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
164                 float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
165                 float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
166
167 #ifdef __RAY_DIFFERENTIALS__
168                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
169                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
170 #endif
171
172                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
173         }
174         else {
175                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
176                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
177
178                 return make_float3(0.0f, 0.0f, 0.0f);
179         }
180 }
181
182 /* motion */
183
184 __device int triangle_find_attribute(KernelGlobals *kg, ShaderData *sd, uint id)
185 {
186         /* find attribute by unique id */
187         uint attr_offset = sd->object*kernel_data.bvh.attributes_map_stride;
188         uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
189
190         while(attr_map.x != id)
191                 attr_map = kernel_tex_fetch(__attributes_map, ++attr_offset);
192
193         /* return result */
194         return (attr_map.y == ATTR_ELEMENT_NONE)? ATTR_STD_NOT_FOUND: attr_map.z;
195 }
196
197 __device float4 triangle_motion_vector(KernelGlobals *kg, ShaderData *sd)
198 {
199         float3 motion_pre = sd->P, motion_post = sd->P;
200
201         /* deformation motion */
202         int offset_pre = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_PRE);
203         int offset_post = triangle_find_attribute(kg, sd, ATTR_STD_MOTION_POST);
204
205         if(offset_pre != ATTR_STD_NOT_FOUND)
206                 motion_pre = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_pre, NULL, NULL);
207         if(offset_post != ATTR_STD_NOT_FOUND)
208                 motion_post = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, offset_post, NULL, NULL);
209
210         /* object motion. note that depending on the mesh having motion vectors, this
211            transformation was set match the world/object space of motion_pre/post */
212         Transform tfm;
213         
214         tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_PRE);
215         motion_pre = transform_point(&tfm, motion_pre);
216
217         tfm = object_fetch_transform(kg, sd->object, TIME_INVALID, OBJECT_TRANSFORM_MOTION_POST);
218         motion_post = transform_point(&tfm, motion_post);
219
220         /* camera motion */
221         tfm = kernel_data.cam.worldtoraster;
222         float3 P = transform_perspective(&tfm, sd->P);
223
224         tfm = kernel_data.cam.motion.pre;
225         motion_pre = transform_perspective(&tfm, motion_pre) - P;
226
227         tfm = kernel_data.cam.motion.post;
228         motion_post = P - transform_perspective(&tfm, motion_post);
229
230         return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
231 }
232
233 __device float3 triangle_uv(KernelGlobals *kg, ShaderData *sd)
234 {
235         int offset_uv = triangle_find_attribute(kg, sd, ATTR_STD_UV);
236
237         if(offset_uv == ATTR_STD_NOT_FOUND)
238                 return make_float3(0.0f, 0.0f, 0.0f);
239
240         float3 uv = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_CORNER, offset_uv, NULL, NULL);
241         uv.z = 1.0f;
242         return uv;
243 }
244
245 CCL_NAMESPACE_END
246