Merged revision(s) 58452-58584 from trunk/blender into soc-2013-dingto.
[blender-staging.git] / intern / cycles / util / util_transform.h
index 65162ebf4e6c8a17f49d56b9c49d4fa243736515..66801e90b56d601e6759063da71d3efd924a6463 100644 (file)
@@ -41,14 +41,22 @@ typedef struct Transform {
 
 /* transform decomposed in rotation/translation/scale. we use the same data
  * structure as Transform, and tightly pack decomposition into it. first the
- * rotation (4), then translation (3), then 3x3 scale matrix (9) */
+ * rotation (4), then translation (3), then 3x3 scale matrix (9).
+ *
+ * For the DecompMotionTransform we drop scale from pre/post. */
 
-typedef struct MotionTransform {
+typedef struct __may_alias MotionTransform {
        Transform pre;
        Transform mid;
        Transform post;
 } MotionTransform;
 
+typedef struct DecompMotionTransform {
+       Transform mid;
+       float4 pre_x, pre_y;
+       float4 post_x, post_y;
+} DecompMotionTransform;
+
 /* Functions */
 
 __device_inline float3 transform_perspective(const Transform *t, const float3 a)
@@ -89,17 +97,6 @@ __device_inline float3 transform_direction_transposed(const Transform *t, const
        return make_float3(dot(x, a), dot(y, a), dot(z, a));
 }
 
-#ifndef __KERNEL_GPU__
-
-__device_inline void print_transform(const char *label, const Transform& t)
-{
-       print_float4(label, t.x);
-       print_float4(label, t.y);
-       print_float4(label, t.z);
-       print_float4(label, t.w);
-       printf("\n");
-}
-
 __device_inline Transform transform_transpose(const Transform a)
 {
        Transform t;
@@ -112,6 +109,23 @@ __device_inline Transform transform_transpose(const Transform a)
        return t;
 }
 
+__device_inline Transform make_transform(float a, float b, float c, float d,
+                                                                       float e, float f, float g, float h,
+                                                                       float i, float j, float k, float l,
+                                                                       float m, float n, float o, float p)
+{
+       Transform t;
+
+       t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d;
+       t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h;
+       t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l;
+       t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p;
+
+       return t;
+}
+
+#ifndef __KERNEL_GPU__
+
 __device_inline Transform operator*(const Transform a, const Transform b)
 {
        Transform c = transform_transpose(b);
@@ -125,19 +139,13 @@ __device_inline Transform operator*(const Transform a, const Transform b)
        return t;
 }
 
-__device_inline Transform make_transform(float a, float b, float c, float d,
-                                                                       float e, float f, float g, float h,
-                                                                       float i, float j, float k, float l,
-                                                                       float m, float n, float o, float p)
+__device_inline void print_transform(const char *label, const Transform& t)
 {
-       Transform t;
-
-       t.x.x = a; t.x.y = b; t.x.z = c; t.x.w = d;
-       t.y.x = e; t.y.y = f; t.y.z = g; t.y.w = h;
-       t.z.x = i; t.z.y = j; t.z.z = k; t.z.w = l;
-       t.w.x = m; t.w.y = n; t.w.z = o; t.w.w = p;
-
-       return t;
+       print_float4(label, t.x);
+       print_float4(label, t.y);
+       print_float4(label, t.z);
+       print_float4(label, t.w);
+       printf("\n");
 }
 
 __device_inline Transform transform_translate(float3 t)
@@ -187,7 +195,7 @@ __device_inline Transform transform_rotate(float angle, float3 axis)
 {
        float s = sinf(angle);
        float c = cosf(angle);
-       float t = 1.f - c;
+       float t = 1.0f - c;
 
        axis = normalize(axis);
 
@@ -303,6 +311,10 @@ __device_inline Transform transform_clear_scale(const Transform& tfm)
 
 __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
 {
+       /* use simpe nlerp instead of slerp. it's faster and almost the same */
+       return normalize((1.0f - t)*q1 + t*q2);
+
+#if 0
        /* note: this does not ensure rotation around shortest angle, q1 and q2
         * are assumed to be matched already in transform_motion_decompose */
        float costheta = dot(q1, q2);
@@ -320,6 +332,7 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
                float thetap = theta * t;
                return q1 * cosf(thetap) + qperp * sinf(thetap);
        }
+#endif
 }
 
 __device_inline Transform transform_quick_inverse(Transform M)
@@ -384,7 +397,7 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp)
 /* Disabled for now, need arc-length parametrization for constant speed motion.
  * #define CURVED_MOTION_INTERPOLATE */
 
-__device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t)
+__device void transform_motion_interpolate(Transform *tfm, const DecompMotionTransform *motion, float t)
 {
        /* possible optimization: is it worth it adding a check to skip scaling?
         * it's probably quite uncommon to have scaling objects. or can we skip
@@ -393,9 +406,9 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
 
 #ifdef CURVED_MOTION_INTERPOLATE
        /* 3 point bezier curve interpolation for position */
-       float3 Ppre = float4_to_float3(motion->pre.y);
+       float3 Ppre = float4_to_float3(motion->pre_y);
        float3 Pmid = float4_to_float3(motion->mid.y);
-       float3 Ppost = float4_to_float3(motion->post.y);
+       float3 Ppost = float4_to_float3(motion->post_y);
 
        float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost);
        float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t);
@@ -409,28 +422,27 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
        if(t < 0.5f) {
                t *= 2.0f;
 
-               decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
+               decomp.x = quat_interpolate(motion->pre_x, motion->mid.x, t);
 #ifdef CURVED_MOTION_INTERPOLATE
-               decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
+               decomp.y.w = (1.0f - t)*motion->pre_y.w + t*motion->mid.y.w;
 #else
-               decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y;
+               decomp.y = (1.0f - t)*motion->pre_y + t*motion->mid.y;
 #endif
-               decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
-               decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
        }
        else {
                t = (t - 0.5f)*2.0f;
 
-               decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
+               decomp.x = quat_interpolate(motion->mid.x, motion->post_x, t);
 #ifdef CURVED_MOTION_INTERPOLATE
-               decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
+               decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post_y.w;
 #else
-               decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y;
+               decomp.y = (1.0f - t)*motion->mid.y + t*motion->post_y;
 #endif
-               decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
-               decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
        }
 
+       decomp.z = motion->mid.z;
+       decomp.w = motion->mid.w;
+
        /* compose rotation, translation, scale into matrix */
        transform_compose(tfm, &decomp);
 }
@@ -442,7 +454,8 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform&
        return (A.pre == B.pre && A.post == B.post);
 }
 
-void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
+float4 transform_to_quat(const Transform& tfm);
+void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
 
 #endif