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