Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:47 +0400
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2014-03-29 16:03:47 +0400
commite2184c653e1f2cc7e05cf9a42a87d23ea3050eac (patch)
treedc39ada14e14259a4cd18c2d5974390a585eb7b8 /intern/cycles/kernel/geom
parent6020d0099039ed18c6a6cd330b68361123c85c1a (diff)
Cycles: add support for curve deformation motion blur.
Diffstat (limited to 'intern/cycles/kernel/geom')
-rw-r--r--intern/cycles/kernel/geom/geom_bvh.h3
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h3
-rw-r--r--intern/cycles/kernel/geom/geom_curve.h95
-rw-r--r--intern/cycles/kernel/geom/geom_motion_curve.h139
4 files changed, 213 insertions, 27 deletions
diff --git a/intern/cycles/kernel/geom/geom_bvh.h b/intern/cycles/kernel/geom/geom_bvh.h
index 20c3c7c19ca..73bf0194d9a 100644
--- a/intern/cycles/kernel/geom/geom_bvh.h
+++ b/intern/cycles/kernel/geom/geom_bvh.h
@@ -41,9 +41,10 @@
#endif
#include "geom_object.h"
-#include "geom_curve.h"
#include "geom_triangle.h"
#include "geom_motion_triangle.h"
+#include "geom_motion_curve.h"
+#include "geom_curve.h"
CCL_NAMESPACE_BEGIN
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index 1fd0772c9ae..e838fba6d46 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -261,7 +261,8 @@ ccl_device bool BVH_FUNCTION_NAME
break;
}
#if FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE: {
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index 484f3ae6eb9..f13f92ed9d7 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -103,9 +103,17 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
int k1 = k0 + 1;
- float4 P1 = kernel_tex_fetch(__curve_keys, k0);
- float4 P2 = kernel_tex_fetch(__curve_keys, k1);
- r = (P2.w - P1.w) * sd->u + P1.w;
+ float4 P_curve[2];
+
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
+
+ r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
}
return r*2.0f;
@@ -226,10 +234,16 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
__m128 P_curve[4];
- P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[ka].x);
- P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
- P_curve[2] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
- P_curve[3] = _mm_load_ps(&kg->__curve_keys.data[kb].x);
+ if(type & PRIMITIVE_CURVE) {
+ P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[ka].x);
+ P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
+ P_curve[2] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
+ P_curve[3] = _mm_load_ps(&kg->__curve_keys.data[kb].x);
+ }
+ else {
+ int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4*)&P_curve);
+ }
__m128 rd_sgn = set_sign_bit<0, 1, 1, 1>(broadcast<0>(rd_ss));
__m128 mul_zxxy = _mm_mul_ps(shuffle<2, 0, 0, 1>(vdir), rd_sgn);
@@ -287,10 +301,16 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
float4 P_curve[4];
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ if(type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
+ }
float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
@@ -593,8 +613,14 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
#ifndef __KERNEL_SSE2__
float4 P_curve[2];
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ if(type & PRIMITIVE_CURVE) {
+ P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
+ }
float or1 = P_curve[0].w;
float or2 = P_curve[1].w;
@@ -620,14 +646,23 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
float sphere_b_tmp = dot3(dir, sphere_dif1);
float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
#else
- const __m128 p1 = _mm_load_ps(&kg->__curve_keys.data[k0].x);
- const __m128 p2 = _mm_load_ps(&kg->__curve_keys.data[k1].x);
- const __m128 or12 = shuffle<3, 3, 3, 3>(p1, p2);
+ __m128 P_curve[2];
+
+ if(type & PRIMITIVE_CURVE) {
+ P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
+ P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
+ }
+ else {
+ int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
+ motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4*)&P_curve);
+ }
+
+ const __m128 or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
__m128 r12 = or12;
const __m128 vP = load_m128(P);
- const __m128 dif = _mm_sub_ps(vP, p1);
- const __m128 dif_second = _mm_sub_ps(vP, p2);
+ const __m128 dif = _mm_sub_ps(vP, P_curve[0]);
+ const __m128 dif_second = _mm_sub_ps(vP, P_curve[1]);
if(difl != 0.0f) {
const __m128 len1_sq = len3_squared_splat(dif);
const __m128 len2_sq = len3_squared_splat(dif_second);
@@ -639,7 +674,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
float r1 = _mm_cvtss_f32(r12), r2 = _mm_cvtss_f32(broadcast<2>(r12));
const __m128 dir = _mm_div_ps(_mm_set1_ps(1.0f), load_m128(idir));
- const __m128 p21_diff = _mm_sub_ps(p2, p1);
+ const __m128 p21_diff = _mm_sub_ps(P_curve[1], P_curve[0]);
const __m128 sphere_dif1 = _mm_mul_ps(_mm_add_ps(dif, dif_second), _mm_set1_ps(0.5f));
const __m128 sphere_b_tmp = dot3_splat(dir, sphere_dif1);
const __m128 sphere_dif2 = fnma(sphere_b_tmp, dir, sphere_dif1);
@@ -854,10 +889,15 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
float4 P_curve[4];
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
+ }
float l = 1.0f;
tg = normalize_len(float4_to_float3(P_curve[2] - P_curve[1]), &l);
@@ -893,8 +933,13 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
else {
float4 P_curve[2];
- P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
- P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
float l = 1.0f;
tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
diff --git a/intern/cycles/kernel/geom/geom_motion_curve.h b/intern/cycles/kernel/geom/geom_motion_curve.h
new file mode 100644
index 00000000000..128e111be2f
--- /dev/null
+++ b/intern/cycles/kernel/geom/geom_motion_curve.h
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+CCL_NAMESPACE_BEGIN
+
+#ifdef __HAIR__
+
+/* todo: find a better (faster) solution for this, maybe store offset per object */
+ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
+{
+ uint attr_offset = object*kernel_data.bvh.attributes_map_stride + ATTR_PRIM_CURVE;
+ uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+
+ while(attr_map.x != id) {
+ attr_offset += ATTR_PRIM_TYPES;
+ attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
+ }
+
+ *elem = (AttributeElement)attr_map.y;
+
+ /* return result */
+ return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
+}
+
+ccl_device_inline void motion_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, float4 keys[2])
+{
+ if(step == numsteps) {
+ /* center step: regular vertex location */
+ keys[0] = kernel_tex_fetch(__curve_keys, k0);
+ keys[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ /* center step not store 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(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 */
+ int maxstep = numsteps*2;
+ int step = min((int)(time*maxstep), maxstep-1);
+ float t = time*maxstep - step;
+
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* fetch key coordinates */
+ float4 next_keys[2];
+
+ motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, keys);
+ motion_curve_keys_for_step(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_cardinal_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 vertex 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 not store 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_cardinal_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 */
+ int maxstep = numsteps*2;
+ int step = min((int)(time*maxstep), maxstep-1);
+ float t = time*maxstep - step;
+
+ /* find attribute */
+ AttributeElement elem;
+ int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
+ kernel_assert(offset != ATTR_STD_NOT_FOUND);
+
+ /* fetch key coordinates */
+ float4 next_keys[4];
+
+ motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
+ motion_cardinal_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
+