Cycles: Code cleanup, spaces around keywords
[blender-staging.git] / intern / cycles / kernel / geom / geom_primitive.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 /* Primitive Utilities
18  *
19  * Generic functions to look up mesh, curve and volume primitive attributes for
20  * shading and render passes. */
21
22 CCL_NAMESPACE_BEGIN
23
24 /* Generic primitive attribute reading functions */
25
26 ccl_device float primitive_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
27 {
28         if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
29                 return triangle_attribute_float(kg, sd, elem, offset, dx, dy);
30         }
31 #ifdef __HAIR__
32         else if(sd->type & PRIMITIVE_ALL_CURVE) {
33                 return curve_attribute_float(kg, sd, elem, offset, dx, dy);
34         }
35 #endif
36 #ifdef __VOLUME__
37         else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
38                 return volume_attribute_float(kg, sd, elem, offset, dx, dy);
39         }
40 #endif
41         else {
42                 if(dx) *dx = 0.0f;
43                 if(dy) *dy = 0.0f;
44                 return 0.0f;
45         }
46 }
47
48 ccl_device float3 primitive_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
49 {
50         if(sd->type & PRIMITIVE_ALL_TRIANGLE) {
51                 return triangle_attribute_float3(kg, sd, elem, offset, dx, dy);
52         }
53 #ifdef __HAIR__
54         else if(sd->type & PRIMITIVE_ALL_CURVE) {
55                 return curve_attribute_float3(kg, sd, elem, offset, dx, dy);
56         }
57 #endif
58 #ifdef __VOLUME__
59         else if(sd->object != OBJECT_NONE && elem == ATTR_ELEMENT_VOXEL) {
60                 return volume_attribute_float3(kg, sd, elem, offset, dx, dy);
61         }
62 #endif
63         else {
64                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
65                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
66                 return make_float3(0.0f, 0.0f, 0.0f);
67         }
68 }
69
70 /* Default UV coordinate */
71
72 ccl_device float3 primitive_uv(KernelGlobals *kg, ShaderData *sd)
73 {
74         AttributeElement elem_uv;
75         int offset_uv = find_attribute(kg, sd, ATTR_STD_UV, &elem_uv);
76
77         if(offset_uv == ATTR_STD_NOT_FOUND)
78                 return make_float3(0.0f, 0.0f, 0.0f);
79
80         float3 uv = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
81         uv.z = 1.0f;
82         return uv;
83 }
84
85 /* Ptex coordinates */
86
87 ccl_device bool primitive_ptex(KernelGlobals *kg, ShaderData *sd, float2 *uv, int *face_id)
88 {
89         /* storing ptex data as attributes is not memory efficient but simple for tests */
90         AttributeElement elem_face_id, elem_uv;
91         int offset_face_id = find_attribute(kg, sd, ATTR_STD_PTEX_FACE_ID, &elem_face_id);
92         int offset_uv = find_attribute(kg, sd, ATTR_STD_PTEX_UV, &elem_uv);
93
94         if(offset_face_id == ATTR_STD_NOT_FOUND || offset_uv == ATTR_STD_NOT_FOUND)
95                 return false;
96
97         float3 uv3 = primitive_attribute_float3(kg, sd, elem_uv, offset_uv, NULL, NULL);
98         float face_id_f = primitive_attribute_float(kg, sd, elem_face_id, offset_face_id, NULL, NULL);
99
100         *uv = make_float2(uv3.x, uv3.y);
101         *face_id = (int)face_id_f;
102
103         return true;
104 }
105
106 /* Surface tangent */
107
108 ccl_device float3 primitive_tangent(KernelGlobals *kg, ShaderData *sd)
109 {
110 #ifdef __HAIR__
111         if(sd->type & PRIMITIVE_ALL_CURVE)
112 #ifdef __DPDU__
113                 return normalize(sd->dPdu);
114 #else
115                 return make_float3(0.0f, 0.0f, 0.0f);
116 #endif
117 #endif
118
119         /* try to create spherical tangent from generated coordinates */
120         AttributeElement attr_elem;
121         int attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED, &attr_elem);
122
123         if(attr_offset != ATTR_STD_NOT_FOUND) {
124                 float3 data = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
125                 data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f);
126                 object_normal_transform(kg, sd, &data);
127                 return cross(sd->N, normalize(cross(data, sd->N)));
128         }
129         else {
130                 /* otherwise use surface derivatives */
131 #ifdef __DPDU__
132                 return normalize(sd->dPdu);
133 #else
134                 return make_float3(0.0f, 0.0f, 0.0f);
135 #endif
136         }
137 }
138
139 /* Motion vector for motion pass */
140
141 ccl_device float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *sd)
142 {
143         /* center position */
144         float3 center;
145
146 #ifdef __HAIR__
147         bool is_curve_primitive = sd->type & PRIMITIVE_ALL_CURVE;
148         if(is_curve_primitive) {
149                 center = curve_motion_center_location(kg, sd);
150
151                 if(!(sd->flag & SD_TRANSFORM_APPLIED))
152                         object_position_transform(kg, sd, &center);
153         }
154         else
155 #endif
156                 center = sd->P;
157
158         float3 motion_pre = center, motion_post = center;
159
160         /* deformation motion */
161         AttributeElement elem;
162         int offset = find_attribute(kg, sd, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
163
164         if(offset != ATTR_STD_NOT_FOUND) {
165                 /* get motion info */
166                 int numverts, numkeys;
167                 object_motion_info(kg, sd->object, NULL, &numverts, &numkeys);
168
169                 /* lookup attributes */
170                 int offset_next = (sd->type & PRIMITIVE_ALL_TRIANGLE)? offset + numverts: offset + numkeys;
171
172                 motion_pre = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
173                 motion_post = primitive_attribute_float3(kg, sd, elem, offset_next, NULL, NULL);
174
175 #ifdef __HAIR__
176                 if(is_curve_primitive && (sd->flag & SD_OBJECT_HAS_VERTEX_MOTION) == 0) {
177                         object_position_transform(kg, sd, &motion_pre);
178                         object_position_transform(kg, sd, &motion_post);
179                 }
180 #endif
181         }
182
183         /* object motion. note that depending on the mesh having motion vectors, this
184          * transformation was set match the world/object space of motion_pre/post */
185         Transform tfm;
186         
187         tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_PRE);
188         motion_pre = transform_point(&tfm, motion_pre);
189
190         tfm = object_fetch_vector_transform(kg, sd->object, OBJECT_VECTOR_MOTION_POST);
191         motion_post = transform_point(&tfm, motion_post);
192
193         float3 motion_center;
194
195         /* camera motion, for perspective/orthographic motion.pre/post will be a
196          * world-to-raster matrix, for panorama it's world-to-camera */
197         if(kernel_data.cam.type != CAMERA_PANORAMA) {
198                 tfm = kernel_data.cam.worldtoraster;
199                 motion_center = transform_perspective(&tfm, center);
200
201                 tfm = kernel_data.cam.motion.pre;
202                 motion_pre = transform_perspective(&tfm, motion_pre);
203
204                 tfm = kernel_data.cam.motion.post;
205                 motion_post = transform_perspective(&tfm, motion_post);
206         }
207         else {
208                 tfm = kernel_data.cam.worldtocamera;
209                 motion_center = normalize(transform_point(&tfm, center));
210                 motion_center = float2_to_float3(direction_to_panorama(kg, motion_center));
211                 motion_center.x *= kernel_data.cam.width;
212                 motion_center.y *= kernel_data.cam.height;
213
214                 tfm = kernel_data.cam.motion.pre;
215                 motion_pre = normalize(transform_point(&tfm, motion_pre));
216                 motion_pre = float2_to_float3(direction_to_panorama(kg, motion_pre));
217                 motion_pre.x *= kernel_data.cam.width;
218                 motion_pre.y *= kernel_data.cam.height;
219
220                 tfm = kernel_data.cam.motion.post;
221                 motion_post = normalize(transform_point(&tfm, motion_post));
222                 motion_post = float2_to_float3(direction_to_panorama(kg, motion_post));
223                 motion_post.x *= kernel_data.cam.width;
224                 motion_post.y *= kernel_data.cam.height;
225         }
226
227         motion_pre = motion_pre - motion_center;
228         motion_post = motion_center - motion_post;
229
230         return make_float4(motion_pre.x, motion_pre.y, motion_post.x, motion_post.y);
231 }
232
233 CCL_NAMESPACE_END
234