add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[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 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 /* Return 3 triangle vertex locations */
69 __device_inline void triangle_vertices(KernelGlobals *kg, int tri_index, float3 P[3])
70 {
71         /* load triangle vertices */
72         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
73
74         P[0] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
75         P[1] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
76         P[2] = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
77 }
78
79 __device_inline float3 triangle_smooth_normal(KernelGlobals *kg, int tri_index, float u, float v)
80 {
81         /* load triangle vertices */
82         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri_index));
83
84         float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.x)));
85         float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.y)));
86         float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, __float_as_int(tri_vindex.z)));
87
88         return normalize((1.0f - u - v)*n2 + u*n0 + v*n1);
89 }
90
91 __device_inline void triangle_dPdudv(KernelGlobals *kg, float3 *dPdu, float3 *dPdv, int tri)
92 {
93         /* fetch triangle vertex coordinates */
94         float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, tri));
95
96         float3 p0 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.x)));
97         float3 p1 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.y)));
98         float3 p2 = float4_to_float3(kernel_tex_fetch(__tri_verts, __float_as_int(tri_vindex.z)));
99
100         /* compute derivatives of P w.r.t. uv */
101         *dPdu = (p0 - p2);
102         *dPdv = (p1 - p2);
103 }
104
105 /* attributes */
106
107 __device float triangle_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
108 {
109         if(elem == ATTR_ELEMENT_FACE) {
110                 if(dx) *dx = 0.0f;
111                 if(dy) *dy = 0.0f;
112
113                 return kernel_tex_fetch(__attributes_float, offset + sd->prim);
114         }
115         else if(elem == ATTR_ELEMENT_VERTEX) {
116                 float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
117
118                 float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.x));
119                 float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.y));
120                 float f2 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(tri_vindex.z));
121
122 #ifdef __RAY_DIFFERENTIALS__
123                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
124                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
125 #endif
126
127                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
128         }
129         else if(elem == ATTR_ELEMENT_CORNER) {
130                 int tri = offset + sd->prim*3;
131                 float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
132                 float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
133                 float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
134
135 #ifdef __RAY_DIFFERENTIALS__
136                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
137                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
138 #endif
139
140                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
141         }
142         else {
143                 if(dx) *dx = 0.0f;
144                 if(dy) *dy = 0.0f;
145
146                 return 0.0f;
147         }
148 }
149
150 __device float3 triangle_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
151 {
152         if(elem == ATTR_ELEMENT_FACE) {
153                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
154                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
155
156                 return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->prim));
157         }
158         else if(elem == ATTR_ELEMENT_VERTEX) {
159                 float3 tri_vindex = float4_to_float3(kernel_tex_fetch(__tri_vindex, sd->prim));
160
161                 float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.x)));
162                 float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.y)));
163                 float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(tri_vindex.z)));
164
165 #ifdef __RAY_DIFFERENTIALS__
166                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
167                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
168 #endif
169
170                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
171         }
172         else if(elem == ATTR_ELEMENT_CORNER) {
173                 int tri = offset + sd->prim*3;
174                 float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
175                 float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
176                 float3 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
177
178 #ifdef __RAY_DIFFERENTIALS__
179                 if(dx) *dx = sd->du.dx*f0 + sd->dv.dx*f1 - (sd->du.dx + sd->dv.dx)*f2;
180                 if(dy) *dy = sd->du.dy*f0 + sd->dv.dy*f1 - (sd->du.dy + sd->dv.dy)*f2;
181 #endif
182
183                 return sd->u*f0 + sd->v*f1 + (1.0f - sd->u - sd->v)*f2;
184         }
185         else {
186                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
187                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
188
189                 return make_float3(0.0f, 0.0f, 0.0f);
190         }
191 }
192
193 CCL_NAMESPACE_END
194