ClangFormat: apply to source, most of intern
[blender.git] / intern / cycles / kernel / geom / geom_triangle.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /* Triangle Primitive
18  *
19  * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH
20  * ray intersection we use a precomputed triangle storage to accelerate
21  * intersection at the cost of more memory usage */
22
23 CCL_NAMESPACE_BEGIN
24
25 /* normal on triangle  */
26 ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
27 {
28   /* load triangle vertices */
29   const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
30   const float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
31   const float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
32   const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
33
34   /* return normal */
35   if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
36     return normalize(cross(v2 - v0, v1 - v0));
37   }
38   else {
39     return normalize(cross(v1 - v0, v2 - v0));
40   }
41 }
42
43 /* point and normal on triangle  */
44 ccl_device_inline void triangle_point_normal(
45     KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
46 {
47   /* load triangle vertices */
48   const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
49   float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
50   float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
51   float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
52   /* compute point */
53   float t = 1.0f - u - v;
54   *P = (u * v0 + v * v1 + t * v2);
55   /* get object flags */
56   int object_flag = kernel_tex_fetch(__object_flag, object);
57   /* compute normal */
58   if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
59     *Ng = normalize(cross(v2 - v0, v1 - v0));
60   }
61   else {
62     *Ng = normalize(cross(v1 - v0, v2 - v0));
63   }
64   /* shader`*/
65   *shader = kernel_tex_fetch(__tri_shader, prim);
66 }
67
68 /* Triangle vertex locations */
69
70 ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
71 {
72   const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
73   P[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
74   P[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
75   P[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
76 }
77
78 /* Interpolate smooth vertex normal from vertices */
79
80 ccl_device_inline float3
81 triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
82 {
83   /* load triangle vertices */
84   const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
85   float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
86   float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
87   float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
88
89   float3 N = safe_normalize((1.0f - u - v) * n2 + u * n0 + v * n1);
90
91   return is_zero(N) ? Ng : N;
92 }
93
94 /* Ray differentials on triangle */
95
96 ccl_device_inline void triangle_dPdudv(KernelGlobals *kg,
97                                        int prim,
98                                        ccl_addr_space float3 *dPdu,
99                                        ccl_addr_space float3 *dPdv)
100 {
101   /* fetch triangle vertex coordinates */
102   const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
103   const float3 p0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
104   const float3 p1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
105   const float3 p2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
106
107   /* compute derivatives of P w.r.t. uv */
108   *dPdu = (p0 - p2);
109   *dPdv = (p1 - p2);
110 }
111
112 /* Reading attributes on various triangle elements */
113
114 ccl_device float triangle_attribute_float(
115     KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
116 {
117   if (desc.element == ATTR_ELEMENT_FACE) {
118     if (dx)
119       *dx = 0.0f;
120     if (dy)
121       *dy = 0.0f;
122
123     return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
124   }
125   else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
126     uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
127
128     float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
129     float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
130     float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
131
132 #ifdef __RAY_DIFFERENTIALS__
133     if (dx)
134       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
135     if (dy)
136       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
137 #endif
138
139     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
140   }
141   else if (desc.element == ATTR_ELEMENT_CORNER) {
142     int tri = desc.offset + sd->prim * 3;
143     float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
144     float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
145     float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
146
147 #ifdef __RAY_DIFFERENTIALS__
148     if (dx)
149       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
150     if (dy)
151       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
152 #endif
153
154     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
155   }
156   else {
157     if (dx)
158       *dx = 0.0f;
159     if (dy)
160       *dy = 0.0f;
161
162     return 0.0f;
163   }
164 }
165
166 ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
167                                             const ShaderData *sd,
168                                             const AttributeDescriptor desc,
169                                             float2 *dx,
170                                             float2 *dy)
171 {
172   if (desc.element == ATTR_ELEMENT_FACE) {
173     if (dx)
174       *dx = make_float2(0.0f, 0.0f);
175     if (dy)
176       *dy = make_float2(0.0f, 0.0f);
177
178     return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
179   }
180   else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
181     uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
182
183     float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
184     float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
185     float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
186
187 #ifdef __RAY_DIFFERENTIALS__
188     if (dx)
189       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
190     if (dy)
191       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
192 #endif
193
194     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
195   }
196   else if (desc.element == ATTR_ELEMENT_CORNER) {
197     int tri = desc.offset + sd->prim * 3;
198     float2 f0, f1, f2;
199
200     if (desc.element == ATTR_ELEMENT_CORNER) {
201       f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
202       f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
203       f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
204     }
205
206 #ifdef __RAY_DIFFERENTIALS__
207     if (dx)
208       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
209     if (dy)
210       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
211 #endif
212
213     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
214   }
215   else {
216     if (dx)
217       *dx = make_float2(0.0f, 0.0f);
218     if (dy)
219       *dy = make_float2(0.0f, 0.0f);
220
221     return make_float2(0.0f, 0.0f);
222   }
223 }
224
225 ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
226                                             const ShaderData *sd,
227                                             const AttributeDescriptor desc,
228                                             float3 *dx,
229                                             float3 *dy)
230 {
231   if (desc.element == ATTR_ELEMENT_FACE) {
232     if (dx)
233       *dx = make_float3(0.0f, 0.0f, 0.0f);
234     if (dy)
235       *dy = make_float3(0.0f, 0.0f, 0.0f);
236
237     return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
238   }
239   else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
240     uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
241
242     float3 f0 = float4_to_float3(
243         kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
244     float3 f1 = float4_to_float3(
245         kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
246     float3 f2 = float4_to_float3(
247         kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
248
249 #ifdef __RAY_DIFFERENTIALS__
250     if (dx)
251       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
252     if (dy)
253       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
254 #endif
255
256     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
257   }
258   else if (desc.element == ATTR_ELEMENT_CORNER || desc.element == ATTR_ELEMENT_CORNER_BYTE) {
259     int tri = desc.offset + sd->prim * 3;
260     float3 f0, f1, f2;
261
262     if (desc.element == ATTR_ELEMENT_CORNER) {
263       f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
264       f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
265       f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
266     }
267     else {
268       f0 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 0));
269       f1 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 1));
270       f2 = color_byte_to_float(kernel_tex_fetch(__attributes_uchar4, tri + 2));
271     }
272
273 #ifdef __RAY_DIFFERENTIALS__
274     if (dx)
275       *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
276     if (dy)
277       *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
278 #endif
279
280     return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
281   }
282   else {
283     if (dx)
284       *dx = make_float3(0.0f, 0.0f, 0.0f);
285     if (dy)
286       *dy = make_float3(0.0f, 0.0f, 0.0f);
287
288     return make_float3(0.0f, 0.0f, 0.0f);
289   }
290 }
291
292 CCL_NAMESPACE_END