diff options
Diffstat (limited to 'intern/cycles/kernel/geom/motion_curve.h')
-rw-r--r-- | intern/cycles/kernel/geom/motion_curve.h | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/intern/cycles/kernel/geom/motion_curve.h b/intern/cycles/kernel/geom/motion_curve.h new file mode 100644 index 00000000000..2dd213d43f6 --- /dev/null +++ b/intern/cycles/kernel/geom/motion_curve.h @@ -0,0 +1,155 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +CCL_NAMESPACE_BEGIN + +/* Motion Curve Primitive + * + * These are stored as regular curves, plus extra positions and radii at times + * other than the frame center. Computing the curve keys at a given ray time is + * a matter of interpolation of the two steps between which the ray time lies. + * + * The extra curve keys are stored as ATTR_STD_MOTION_VERTEX_POSITION. + */ + +#ifdef __HAIR__ + +ccl_device_inline void motion_curve_keys_for_step_linear(KernelGlobals kg, + int offset, + int numkeys, + int numsteps, + int step, + int k0, + int k1, + float4 keys[2]) +{ + if (step == numsteps) { + /* center step: regular key location */ + keys[0] = kernel_tex_fetch(__curve_keys, k0); + keys[1] = kernel_tex_fetch(__curve_keys, k1); + } + else { + /* center step is not stored in this array */ + if (step > numsteps) + step--; + + offset += step * numkeys; + + keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0); + keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1); + } +} + +/* return 2 curve key locations */ +ccl_device_inline void motion_curve_keys_linear( + KernelGlobals kg, int object, int prim, float time, int k0, int k1, float4 keys[2]) +{ + /* get motion info */ + int numsteps, numkeys; + object_motion_info(kg, object, &numsteps, NULL, &numkeys); + + /* figure out which steps we need to fetch and their interpolation factor */ + const int maxstep = numsteps * 2; + const int step = min((int)(time * maxstep), maxstep - 1); + const float t = time * maxstep - step; + + /* find attribute */ + const int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION); + kernel_assert(offset != ATTR_STD_NOT_FOUND); + + /* fetch key coordinates */ + float4 next_keys[2]; + + motion_curve_keys_for_step_linear(kg, offset, numkeys, numsteps, step, k0, k1, keys); + motion_curve_keys_for_step_linear(kg, offset, numkeys, numsteps, step + 1, k0, k1, next_keys); + + /* interpolate between steps */ + keys[0] = (1.0f - t) * keys[0] + t * next_keys[0]; + keys[1] = (1.0f - t) * keys[1] + t * next_keys[1]; +} + +ccl_device_inline void motion_curve_keys_for_step(KernelGlobals kg, + int offset, + int numkeys, + int numsteps, + int step, + int k0, + int k1, + int k2, + int k3, + float4 keys[4]) +{ + if (step == numsteps) { + /* center step: regular key location */ + keys[0] = kernel_tex_fetch(__curve_keys, k0); + keys[1] = kernel_tex_fetch(__curve_keys, k1); + keys[2] = kernel_tex_fetch(__curve_keys, k2); + keys[3] = kernel_tex_fetch(__curve_keys, k3); + } + else { + /* center step is not stored in this array */ + if (step > numsteps) + step--; + + offset += step * numkeys; + + keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0); + keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1); + keys[2] = kernel_tex_fetch(__attributes_float3, offset + k2); + keys[3] = kernel_tex_fetch(__attributes_float3, offset + k3); + } +} + +/* return 2 curve key locations */ +ccl_device_inline void motion_curve_keys(KernelGlobals kg, + int object, + int prim, + float time, + int k0, + int k1, + int k2, + int k3, + float4 keys[4]) +{ + /* get motion info */ + int numsteps, numkeys; + object_motion_info(kg, object, &numsteps, NULL, &numkeys); + + /* figure out which steps we need to fetch and their interpolation factor */ + const int maxstep = numsteps * 2; + const int step = min((int)(time * maxstep), maxstep - 1); + const float t = time * maxstep - step; + + /* find attribute */ + const int offset = intersection_find_attribute(kg, object, ATTR_STD_MOTION_VERTEX_POSITION); + kernel_assert(offset != ATTR_STD_NOT_FOUND); + + /* fetch key coordinates */ + float4 next_keys[4]; + + motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys); + motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step + 1, k0, k1, k2, k3, next_keys); + + /* interpolate between steps */ + keys[0] = (1.0f - t) * keys[0] + t * next_keys[0]; + keys[1] = (1.0f - t) * keys[1] + t * next_keys[1]; + keys[2] = (1.0f - t) * keys[2] + t * next_keys[2]; + keys[3] = (1.0f - t) * keys[3] + t * next_keys[3]; +} + +#endif + +CCL_NAMESPACE_END |