Code refactor: add ProjectionTransform separate from regular Transform.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 8 Mar 2018 04:33:55 +0000 (05:33 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 10 Mar 2018 03:54:04 +0000 (04:54 +0100)
This is in preparation of making Transform affine only.

12 files changed:
intern/cycles/blender/blender_object_cull.cpp
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/geom/geom_primitive.h
intern/cycles/kernel/kernel_camera.h
intern/cycles/kernel/kernel_math.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
intern/cycles/util/CMakeLists.txt
intern/cycles/util/util_projection.h [new file with mode: 0644]
intern/cycles/util/util_transform.h

index 1d747de..bdf7dc4 100644 (file)
@@ -96,7 +96,7 @@ bool BlenderObjectCulling::test(Scene *scene, BL::Object& b_ob, Transform& tfm)
 bool BlenderObjectCulling::test_camera(Scene *scene, float3 bb[8])
 {
        Camera *cam = scene->camera;
-       Transform& worldtondc = cam->worldtondc;
+       const ProjectionTransform& worldtondc = cam->worldtondc;
        float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
               bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
        bool all_behind = true;
index 50ea03a..9b7f4e0 100644 (file)
@@ -254,6 +254,7 @@ set(SRC_UTIL_HEADERS
        ../util/util_math_int3.h
        ../util/util_math_int4.h
        ../util/util_math_matrix.h
+       ../util/util_projection.h
        ../util/util_rect.h
        ../util/util_static_assert.h
        ../util/util_transform.h
index 60a1e48..6a8ea79 100644 (file)
@@ -204,14 +204,14 @@ ccl_device_inline float4 primitive_motion_vector(KernelGlobals *kg, ShaderData *
        /* camera motion, for perspective/orthographic motion.pre/post will be a
         * world-to-raster matrix, for panorama it's world-to-camera */
        if(kernel_data.cam.type != CAMERA_PANORAMA) {
-               tfm = kernel_data.cam.worldtoraster;
-               motion_center = transform_perspective(&tfm, center);
+               ProjectionTransform projection = kernel_data.cam.worldtoraster;
+               motion_center = transform_perspective(&projection, center);
 
-               tfm = kernel_data.cam.motion.pre;
-               motion_pre = transform_perspective(&tfm, motion_pre);
+               projection = kernel_data.cam.perspective_motion.pre;
+               motion_pre = transform_perspective(&projection, motion_pre);
 
-               tfm = kernel_data.cam.motion.post;
-               motion_post = transform_perspective(&tfm, motion_post);
+               projection = kernel_data.cam.perspective_motion.post;
+               motion_post = transform_perspective(&projection, motion_post);
        }
        else {
                tfm = kernel_data.cam.worldtocamera;
index 66ed9f5..5b102ea 100644 (file)
@@ -42,7 +42,7 @@ ccl_device float2 camera_sample_aperture(ccl_constant KernelCamera *cam, float u
 ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
 {
        /* create ray form raster position */
-       Transform rastertocamera = kernel_data.cam.rastertocamera;
+       ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
        float3 raster = make_float3(raster_x, raster_y, 0.0f);
        float3 Pcamera = transform_perspective(&rastertocamera, raster);
 
@@ -54,13 +54,13 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
                 * interpolated field of view.
                 */
                if(ray->time < 0.5f) {
-                       Transform rastertocamera_pre = kernel_data.cam.perspective_motion.pre;
+                       ProjectionTransform rastertocamera_pre = kernel_data.cam.perspective_motion.pre;
                        float3 Pcamera_pre =
                                transform_perspective(&rastertocamera_pre, raster);
                        Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f);
                }
                else {
-                       Transform rastertocamera_post = kernel_data.cam.perspective_motion.post;
+                       ProjectionTransform rastertocamera_post = kernel_data.cam.perspective_motion.post;
                        float3 Pcamera_post =
                                transform_perspective(&rastertocamera_post, raster);
                        Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f);
@@ -169,7 +169,7 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
 ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray)
 {
        /* create ray form raster position */
-       Transform rastertocamera = kernel_data.cam.rastertocamera;
+       ProjectionTransform rastertocamera = kernel_data.cam.rastertocamera;
        float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
 
        float3 P;
@@ -231,7 +231,7 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam,
                                               float lens_u, float lens_v,
                                               ccl_addr_space Ray *ray)
 {
-       Transform rastertocamera = cam->rastertocamera;
+       ProjectionTransform rastertocamera = cam->rastertocamera;
        float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f));
 
        /* create ray form raster position */
@@ -442,7 +442,7 @@ ccl_device_inline float3 camera_world_to_ndc(KernelGlobals *kg, ShaderData *sd,
                if(sd->object == PRIM_NONE && kernel_data.cam.type == CAMERA_PERSPECTIVE)
                        P += camera_position(kg);
 
-               Transform tfm = kernel_data.cam.worldtondc;
+               ProjectionTransform tfm = kernel_data.cam.worldtondc;
                return transform_perspective(&tfm, P);
        }
        else {
index bd0e23b..96391db 100644 (file)
@@ -21,6 +21,7 @@
 #include "util/util_math.h"
 #include "util/util_math_fast.h"
 #include "util/util_math_intersect.h"
+#include "util/util_projection.h"
 #include "util/util_texture.h"
 #include "util/util_transform.h"
 
index 2cab63c..87faa0d 100644 (file)
@@ -1159,7 +1159,7 @@ typedef struct KernelCamera {
 
        /* matrices */
        Transform cameratoworld;
-       Transform rastertocamera;
+       ProjectionTransform rastertocamera;
 
        /* differentials */
        float4 dx;
@@ -1193,21 +1193,18 @@ typedef struct KernelCamera {
        int is_inside_volume;
 
        /* more matrices */
-       Transform screentoworld;
-       Transform rastertoworld;
-       /* work around cuda sm 2.0 crash, this seems to
-        * cross some limit in combination with motion 
-        * Transform ndctoworld; */
-       Transform worldtoscreen;
-       Transform worldtoraster;
-       Transform worldtondc;
+       ProjectionTransform screentoworld;
+       ProjectionTransform rastertoworld;
+       ProjectionTransform ndctoworld;
+       ProjectionTransform worldtoscreen;
+       ProjectionTransform worldtoraster;
+       ProjectionTransform worldtondc;
        Transform worldtocamera;
 
        MotionTransform motion;
 
-       /* Denotes changes in the projective matrix, namely in rastertocamera.
-        * Used for camera zoom motion blur,
-        */
+       /* Stores changes in the projeciton matrix. Use for camera zoom motion
+        * blur and motion pass output for perspective camera. */
        PerspectiveMotionTransform perspective_motion;
 
        int shutter_table_offset;
index ae4c521..dec56c6 100644 (file)
@@ -62,11 +62,18 @@ CCL_NAMESPACE_BEGIN
 
 /* RenderServices implementation */
 
-#define COPY_MATRIX44(m1, m2)  { \
-       CHECK_TYPE(m1, OSL::Matrix44*); \
-       CHECK_TYPE(m2, Transform*); \
-       memcpy(m1, m2, sizeof(*m2)); \
-} (void)0
+static void copy_matrix(OSL::Matrix44& m, const Transform& tfm)
+{
+       // TODO: remember when making affine
+       Transform t = transform_transpose(tfm);
+       memcpy(&m, &t, sizeof(m));
+}
+
+static void copy_matrix(OSL::Matrix44& m, const ProjectionTransform& tfm)
+{
+       ProjectionTransform t = projection_transpose(tfm);
+       memcpy(&m, &t, sizeof(m));
+}
 
 /* static ustrings */
 ustring OSLRenderServices::u_distance("distance");
@@ -167,14 +174,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
 #else
                        Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
 #endif
-                       tfm = transform_transpose(tfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, tfm);
 
                        return true;
                }
                else if(sd->type == PRIMITIVE_LAMP) {
-                       Transform tfm = transform_transpose(sd->ob_tfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, sd->ob_tfm);
 
                        return true;
                }
@@ -203,14 +208,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
 #else
                        Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
 #endif
-                       itfm = transform_transpose(itfm);
-                       COPY_MATRIX44(&result, &itfm);
+                       copy_matrix(result, itfm);
 
                        return true;
                }
                else if(sd->type == PRIMITIVE_LAMP) {
-                       Transform tfm = transform_transpose(sd->ob_itfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, sd->ob_itfm);
 
                        return true;
                }
@@ -224,23 +227,19 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
        KernelGlobals *kg = kernel_globals;
 
        if(from == u_ndc) {
-               Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.ndctoworld);
                return true;
        }
        else if(from == u_raster) {
-               Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.rastertoworld);
                return true;
        }
        else if(from == u_screen) {
-               Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.screentoworld);
                return true;
        }
        else if(from == u_camera) {
-               Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.cameratoworld);
                return true;
        }
        else if(from == u_world) {
@@ -256,23 +255,19 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
        KernelGlobals *kg = kernel_globals;
 
        if(to == u_ndc) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtondc);
                return true;
        }
        else if(to == u_raster) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtoraster);
                return true;
        }
        else if(to == u_screen) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtoscreen);
                return true;
        }
        else if(to == u_camera) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtocamera);
                return true;
        }
        else if(to == u_world) {
@@ -298,14 +293,12 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
                        KernelGlobals *kg = sd->osl_globals;
                        Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM);
 #endif
-                       tfm = transform_transpose(tfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, tfm);
 
                        return true;
                }
                else if(sd->type == PRIMITIVE_LAMP) {
-                       Transform tfm = transform_transpose(sd->ob_tfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, sd->ob_tfm);
 
                        return true;
                }
@@ -329,14 +322,12 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
                        KernelGlobals *kg = sd->osl_globals;
                        Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM);
 #endif
-                       tfm = transform_transpose(tfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, tfm);
 
                        return true;
                }
                else if(sd->type == PRIMITIVE_LAMP) {
-                       Transform tfm = transform_transpose(sd->ob_itfm);
-                       COPY_MATRIX44(&result, &tfm);
+                       copy_matrix(result, sd->ob_itfm);
 
                        return true;
                }
@@ -350,23 +341,19 @@ bool OSLRenderServices::get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result
        KernelGlobals *kg = kernel_globals;
 
        if(from == u_ndc) {
-               Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc));
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.ndctoworld);
                return true;
        }
        else if(from == u_raster) {
-               Transform tfm = transform_transpose(kernel_data.cam.rastertoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.rastertoworld);
                return true;
        }
        else if(from == u_screen) {
-               Transform tfm = transform_transpose(kernel_data.cam.screentoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.screentoworld);
                return true;
        }
        else if(from == u_camera) {
-               Transform tfm = transform_transpose(kernel_data.cam.cameratoworld);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.cameratoworld);
                return true;
        }
 
@@ -378,23 +365,19 @@ bool OSLRenderServices::get_inverse_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44
        KernelGlobals *kg = kernel_globals;
        
        if(to == u_ndc) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtondc);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtondc);
                return true;
        }
        else if(to == u_raster) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtoraster);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtoraster);
                return true;
        }
        else if(to == u_screen) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtoscreen);
                return true;
        }
        else if(to == u_camera) {
-               Transform tfm = transform_transpose(kernel_data.cam.worldtocamera);
-               COPY_MATRIX44(&result, &tfm);
+               copy_matrix(result, kernel_data.cam.worldtocamera);
                return true;
        }
        
index a2fda12..e6585b2 100644 (file)
@@ -163,12 +163,12 @@ Camera::Camera()
 
        compute_auto_viewplane();
 
-       screentoworld = transform_identity();
-       rastertoworld = transform_identity();
-       ndctoworld = transform_identity();
-       rastertocamera = transform_identity();
+       screentoworld = projection_identity();
+       rastertoworld = projection_identity();
+       ndctoworld = projection_identity();
+       rastertocamera = projection_identity();
        cameratoworld = transform_identity();
-       worldtoraster = transform_identity();
+       worldtoraster = projection_identity();
 
        dx = make_float3(0.0f, 0.0f, 0.0f);
        dy = make_float3(0.0f, 0.0f, 0.0f);
@@ -241,18 +241,18 @@ void Camera::update(Scene *scene)
        Transform full_rastertoscreen = transform_inverse(full_screentoraster);
 
        /* screen to camera */
-       Transform cameratoscreen;
+       ProjectionTransform cameratoscreen;
        if(type == CAMERA_PERSPECTIVE)
-               cameratoscreen = transform_perspective(fov, nearclip, farclip);
+               cameratoscreen = projection_perspective(fov, nearclip, farclip);
        else if(type == CAMERA_ORTHOGRAPHIC)
-               cameratoscreen = transform_orthographic(nearclip, farclip);
+               cameratoscreen = projection_orthographic(nearclip, farclip);
        else
-               cameratoscreen = transform_identity();
+               cameratoscreen = projection_identity();
        
-       Transform screentocamera = transform_inverse(cameratoscreen);
+       ProjectionTransform screentocamera = projection_inverse(cameratoscreen);
 
        rastertocamera = screentocamera * rastertoscreen;
-       Transform full_rastertocamera = screentocamera * full_rastertoscreen;
+       ProjectionTransform full_rastertocamera = screentocamera * full_rastertoscreen;
        cameratoraster = screentoraster * cameratoscreen;
 
        cameratoworld = matrix;
@@ -270,10 +270,10 @@ void Camera::update(Scene *scene)
 
        /* differentials */
        if(type == CAMERA_ORTHOGRAPHIC) {
-               dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
-               dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
-               full_dx = transform_direction(&full_rastertocamera, make_float3(1, 0, 0));
-               full_dy = transform_direction(&full_rastertocamera, make_float3(0, 1, 0));
+               dx = transform_perspective_direction(&rastertocamera, make_float3(1, 0, 0));
+               dy = transform_perspective_direction(&rastertocamera, make_float3(0, 1, 0));
+               full_dx = transform_perspective_direction(&full_rastertocamera, make_float3(1, 0, 0));
+               full_dy = transform_perspective_direction(&full_rastertocamera, make_float3(0, 1, 0));
        }
        else if(type == CAMERA_PERSPECTIVE) {
                dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
@@ -307,14 +307,14 @@ void Camera::update(Scene *scene)
                /* TODO(sergey): Move to an utility function and de-duplicate with
                 * calculation above.
                 */
-               Transform screentocamera_pre =
-                       transform_inverse(transform_perspective(fov_pre,
-                                                               nearclip,
-                                                               farclip));
-               Transform screentocamera_post =
-                       transform_inverse(transform_perspective(fov_post,
-                                                               nearclip,
-                                                               farclip));
+               ProjectionTransform screentocamera_pre =
+                       projection_inverse(projection_perspective(fov_pre,
+                                                                 nearclip,
+                                                                 farclip));
+               ProjectionTransform screentocamera_post =
+                       projection_inverse(projection_perspective(fov_post,
+                                                                 nearclip,
+                                                                 farclip));
                perspective_motion.pre = screentocamera_pre * rastertoscreen;
                perspective_motion.post = screentocamera_post * rastertoscreen;
        }
@@ -331,6 +331,7 @@ void Camera::update(Scene *scene)
        kcam->worldtoscreen = worldtoscreen;
        kcam->worldtoraster = worldtoraster;
        kcam->worldtondc = worldtondc;
+       kcam->ndctoworld = ndctoworld;
 
        /* camera motion */
        kcam->have_motion = 0;
@@ -350,12 +351,12 @@ void Camera::update(Scene *scene)
                }
                else {
                        if(use_motion) {
-                               kcam->motion.pre = cameratoraster * transform_inverse(motion.pre);
-                               kcam->motion.post = cameratoraster * transform_inverse(motion.post);
+                               kcam->perspective_motion.pre = cameratoraster * transform_inverse(motion.pre);
+                               kcam->perspective_motion.post = cameratoraster * transform_inverse(motion.post);
                        }
                        else {
-                               kcam->motion.pre = worldtoraster;
-                               kcam->motion.post = worldtoraster;
+                               kcam->perspective_motion.pre = worldtoraster;
+                               kcam->perspective_motion.post = worldtoraster;
                        }
                }
        }
@@ -606,7 +607,7 @@ float Camera::world_to_raster_size(float3 P)
                res = min(len(full_dx), len(full_dy));
 
                if(offscreen_dicing_scale > 1.0f) {
-                       float3 p = transform_perspective(&worldtocamera, P);
+                       float3 p = transform_point(&worldtocamera, P);
                        float3 v = transform_perspective(&rastertocamera, make_float3(width, height, 0.0f));
 
                        /* Create point clamped to frustum */
index 4ec0fe3..aa4e53a 100644 (file)
@@ -22,6 +22,7 @@
 #include "graph/node.h"
 
 #include "util/util_boundbox.h"
+#include "util/util_projection.h"
 #include "util/util_transform.h"
 #include "util/util_types.h"
 
@@ -146,18 +147,18 @@ public:
        PerspectiveMotionTransform perspective_motion;
 
        /* computed camera parameters */
-       Transform screentoworld;
-       Transform rastertoworld;
-       Transform ndctoworld;
+       ProjectionTransform screentoworld;
+       ProjectionTransform rastertoworld;
+       ProjectionTransform ndctoworld;
        Transform cameratoworld;
 
-       Transform worldtoraster;
-       Transform worldtoscreen;
-       Transform worldtondc;
+       ProjectionTransform worldtoraster;
+       ProjectionTransform worldtoscreen;
+       ProjectionTransform worldtondc;
        Transform worldtocamera;
 
-       Transform rastertocamera;
-       Transform cameratoraster;
+       ProjectionTransform rastertocamera;
+       ProjectionTransform cameratoraster;
 
        float3 dx;
        float3 dy;
index 66c4f22..24043e2 100644 (file)
@@ -67,6 +67,7 @@ set(SRC_HEADERS
        util_param.h
        util_path.h
        util_progress.h
+       util_projection.h
        util_queue.h
        util_rect.h
        util_set.h
diff --git a/intern/cycles/util/util_projection.h b/intern/cycles/util/util_projection.h
new file mode 100644 (file)
index 0000000..0b8ff03
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2011-2018 Blender Foundation
+ *
+ * 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.
+ */
+
+#ifndef __UTIL_PROJECTION_H__
+#define __UTIL_PROJECTION_H__
+
+#include "util/util_transform.h"
+
+CCL_NAMESPACE_BEGIN
+
+/* Data Types */
+
+typedef struct ProjectionTransform {
+       float4 x, y, z, w; /* rows */
+
+#ifndef __KERNEL_GPU__
+       ProjectionTransform()
+       {
+       }
+
+       explicit ProjectionTransform(const Transform& tfm)
+       : x(tfm.x),
+         y(tfm.y),
+         z(tfm.z),
+         w(tfm.w)
+       {
+       }
+#endif
+} ProjectionTransform;
+
+typedef struct PerspectiveMotionTransform {
+       ProjectionTransform pre;
+       ProjectionTransform post;
+} PerspectiveMotionTransform;
+
+/* Functions */
+
+ccl_device_inline float3 transform_perspective(const ProjectionTransform *t, const float3 a)
+{
+       float4 b = make_float4(a.x, a.y, a.z, 1.0f);
+       float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
+       float w = dot(t->w, b);
+
+       return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f);
+}
+
+ccl_device_inline float3 transform_perspective_direction(const ProjectionTransform *t, const float3 a)
+{
+       float3 c = make_float3(
+               a.x*t->x.x + a.y*t->x.y + a.z*t->x.z,
+               a.x*t->y.x + a.y*t->y.y + a.z*t->y.z,
+               a.x*t->z.x + a.y*t->z.y + a.z*t->z.z);
+
+       return c;
+}
+
+#ifndef __KERNEL_GPU__
+
+ccl_device_inline ProjectionTransform projection_transpose(const ProjectionTransform& a)
+{
+       ProjectionTransform t;
+
+       t.x.x = a.x.x; t.x.y = a.y.x; t.x.z = a.z.x; t.x.w = a.w.x;
+       t.y.x = a.x.y; t.y.y = a.y.y; t.y.z = a.z.y; t.y.w = a.w.y;
+       t.z.x = a.x.z; t.z.y = a.y.z; t.z.z = a.z.z; t.z.w = a.w.z;
+       t.w.x = a.x.w; t.w.y = a.y.w; t.w.z = a.z.w; t.w.w = a.w.w;
+
+       return t;
+}
+
+ccl_device_inline ProjectionTransform projection_inverse(const ProjectionTransform& a)
+{
+       Transform t = {a.x, a.y, a.z, a.w};
+       t = transform_inverse(t);
+       return ProjectionTransform(t);
+}
+
+ccl_device_inline ProjectionTransform make_projection(
+       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)
+{
+       ProjectionTransform 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;
+}
+ccl_device_inline ProjectionTransform projection_identity()
+{
+       return make_projection(
+               1.0f, 0.0f, 0.0f, 0.0f,
+               0.0f, 1.0f, 0.0f, 0.0f,
+               0.0f, 0.0f, 1.0f, 0.0f,
+               0.0f, 0.0f, 0.0f, 1.0f);
+}
+
+ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const ProjectionTransform& b)
+{
+       ProjectionTransform c = projection_transpose(b);
+       ProjectionTransform t;
+
+       t.x = make_float4(dot(a.x, c.x), dot(a.x, c.y), dot(a.x, c.z), dot(a.x, c.w));
+       t.y = make_float4(dot(a.y, c.x), dot(a.y, c.y), dot(a.y, c.z), dot(a.y, c.w));
+       t.z = make_float4(dot(a.z, c.x), dot(a.z, c.y), dot(a.z, c.z), dot(a.z, c.w));
+       t.w = make_float4(dot(a.w, c.x), dot(a.w, c.y), dot(a.w, c.z), dot(a.w, c.w));
+
+       return t;
+}
+
+ccl_device_inline ProjectionTransform operator*(const ProjectionTransform& a, const Transform& b)
+{
+       return a * ProjectionTransform(b);
+}
+
+ccl_device_inline ProjectionTransform operator*(const Transform& a, const ProjectionTransform& b)
+{
+       return ProjectionTransform(a) * b;
+}
+
+ccl_device_inline void print_projection(const char *label, const ProjectionTransform& t)
+{
+       print_float4(label, t.x);
+       print_float4(label, t.y);
+       print_float4(label, t.z);
+       print_float4(label, t.w);
+       printf("\n");
+}
+
+ccl_device_inline ProjectionTransform projection_perspective(float fov, float n, float f)
+{
+       ProjectionTransform persp = make_projection(
+               1, 0, 0, 0,
+               0, 1, 0, 0,
+               0, 0, f / (f - n), -f*n / (f - n),
+               0, 0, 1, 0);
+
+       float inv_angle = 1.0f/tanf(0.5f*fov);
+
+       Transform scale = transform_scale(inv_angle, inv_angle, 1);
+
+       return scale * persp;
+}
+
+ccl_device_inline ProjectionTransform projection_orthographic(float znear, float zfar)
+{
+       Transform t =
+               transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) *
+               transform_translate(0.0f, 0.0f, -znear);
+
+       return ProjectionTransform(t);
+}
+
+#endif /* __KERNEL_GPU__ */
+
+CCL_NAMESPACE_END
+
+#endif /* __UTIL_PROJECTION_H__ */
+
index 1efe001..5202229 100644 (file)
@@ -47,22 +47,8 @@ typedef struct ccl_may_alias MotionTransform {
        Transform post;
 } MotionTransform;
 
-typedef struct PerspectiveMotionTransform {
-       Transform pre;
-       Transform post;
-} PerspectiveMotionTransform;
-
 /* Functions */
 
-ccl_device_inline float3 transform_perspective(const Transform *t, const float3 a)
-{
-       float4 b = make_float4(a.x, a.y, a.z, 1.0f);
-       float3 c = make_float3(dot(t->x, b), dot(t->y, b), dot(t->z, b));
-       float w = dot(t->w, b);
-
-       return (w != 0.0f)? c/w: make_float3(0.0f, 0.0f, 0.0f);
-}
-
 ccl_device_inline float3 transform_point(const Transform *t, const float3 a)
 {
        /* TODO(sergey): Disabled for now, causes crashes in certain cases. */
@@ -221,21 +207,6 @@ ccl_device_inline Transform transform_scale(float x, float y, float z)
        return transform_scale(make_float3(x, y, z));
 }
 
-ccl_device_inline Transform transform_perspective(float fov, float n, float f)
-{
-       Transform persp = make_transform(
-               1, 0, 0, 0,
-               0, 1, 0, 0,
-               0, 0, f / (f - n), -f*n / (f - n),
-               0, 0, 1, 0);
-
-       float inv_angle = 1.0f/tanf(0.5f*fov);
-
-       Transform scale = transform_scale(inv_angle, inv_angle, 1);
-
-       return scale * persp;
-}
-
 ccl_device_inline Transform transform_rotate(float angle, float3 axis)
 {
        float s = sinf(angle);
@@ -272,12 +243,6 @@ ccl_device_inline Transform transform_euler(float3 euler)
                transform_rotate(euler.x, make_float3(1.0f, 0.0f, 0.0f));
 }
 
-ccl_device_inline Transform transform_orthographic(float znear, float zfar)
-{
-       return transform_scale(1.0f, 1.0f, 1.0f / (zfar-znear)) *
-               transform_translate(0.0f, 0.0f, -znear);
-}
-
 ccl_device_inline Transform transform_identity()
 {
        return transform_scale(1.0f, 1.0f, 1.0f);