From 2ddf137821b704f0d027119c5daf87b01a442c5f Mon Sep 17 00:00:00 2001 From: Valtteri Koskivuori Date: Tue, 12 Dec 2023 22:16:40 +0200 Subject: [PATCH] lib+blender: Fix up coordinate system mismatch My brain has a hard time keeping up with all the different things going on, but I got it to the point that the camera seems to work as expected. I ended up going the easy route, and just adding a toggle to the API to switch a specified camera to use Blender's native coordinate system, and still defaults to c-ray coords (y up, +z forward) so existing json scenes work normally. --- bindings/blender_init.py | 7 +++++-- bindings/c_ray.py | 1 + include/c-ray/c-ray.h | 1 + src/common/vector.h | 2 -- src/lib/api/c-ray.c | 11 +++++++++++ src/lib/datatypes/camera.c | 8 ++------ 6 files changed, 20 insertions(+), 10 deletions(-) diff --git a/bindings/blender_init.py b/bindings/blender_init.py index 39d5b183..d7a50024 100644 --- a/bindings/blender_init.py +++ b/bindings/blender_init.py @@ -22,6 +22,8 @@ import ctypes as ct from array import array +import math +import mathutils from bpy.props import IntProperty from bpy.props import PointerProperty @@ -128,8 +130,8 @@ def sync_scene(self, renderer, depsgraph, b_scene): bl_cam = bl_cam_eval.data cr_cam = cr_scene.camera_new() - mtx = ob_main.matrix_world - euler = mtx.to_euler('ZXY') + mtx = fix_coord(ob_main.matrix_world) + euler = mtx.to_euler('XYZ') loc = mtx.to_translation() cr_cam.set_param(c_ray.cam_param.fov, 80) #todo cr_cam.set_param(c_ray.cam_param.pose_x, loc[0]) @@ -140,6 +142,7 @@ def sync_scene(self, renderer, depsgraph, b_scene): cr_cam.set_param(c_ray.cam_param.pose_yaw, euler[2]) cr_cam.set_param(c_ray.cam_param.res_x, self.size_x) cr_cam.set_param(c_ray.cam_param.res_y, self.size_y) + cr_cam.set_param(c_ray.cam_param.blender_coord, 1) # TODO: We don't tell blender that we support this, so it's not available yet if bl_cam.dof.use_dof: cr_cam.set_param(c_ray.cam_param.fstops, bl_cam.dof.aperture_fstop) diff --git a/bindings/c_ray.py b/bindings/c_ray.py index 79f8b53a..a0464a1f 100644 --- a/bindings/c_ray.py +++ b/bindings/c_ray.py @@ -213,6 +213,7 @@ class cam_param(IntEnum): time = 9 res_x = 10 res_y = 11 + blender_coord = 12 class camera: def __init__(self, scene_ptr): diff --git a/include/c-ray/c-ray.h b/include/c-ray/c-ray.h index 3d12802f..54501837 100644 --- a/include/c-ray/c-ray.h +++ b/include/c-ray/c-ray.h @@ -219,6 +219,7 @@ enum cr_camera_param { cr_camera_res_x, cr_camera_res_y, + cr_camera_blender_coord, }; typedef cr_object cr_camera; diff --git a/src/common/vector.h b/src/common/vector.h index c9278a2c..53e55d12 100644 --- a/src/common/vector.h +++ b/src/common/vector.h @@ -35,8 +35,6 @@ struct intCoord { int x, y; }; -static const struct vector g_world_up = { 0.0f, 1.0f, 0.0f }; - //For defaults static inline struct vector vec_zero() { return (struct vector){ 0.0f, 0.0f, 0.0f }; diff --git a/src/lib/api/c-ray.c b/src/lib/api/c-ray.c index 75960394..5784a4fe 100644 --- a/src/lib/api/c-ray.c +++ b/src/lib/api/c-ray.c @@ -380,6 +380,10 @@ struct camera default_camera = { .fstops = 0.0f, .width = 800, .height = 600, + .look_at = { 0.0f, 0.0f, 1.0f }, + .forward = { 0.0f, 0.0f, 1.0f }, + .right = { 1.0f, 0.0f, 0.0f }, + .up = { 0.0f, 1.0f, 0.0f } }; cr_camera cr_camera_new(struct cr_scene *ext) { @@ -442,6 +446,13 @@ bool cr_camera_set_num_pref(struct cr_scene *ext, cr_camera c, enum cr_camera_pa cam->height = num; return true; } + case cr_camera_blender_coord: { + cam->look_at = (struct vector){0.0f, 0.0f, -1.0f}; + cam->forward = vec_normalize(cam->look_at); + cam->right = (struct vector){1.0f, 0.0f, 0.0f}; + cam->up = (struct vector){0.0f, -1.0f, 0.0f}; + return true; + } } cam_update_pose(cam, &cam->orientation, &cam->position); diff --git a/src/lib/datatypes/camera.c b/src/lib/datatypes/camera.c index 8e9b165c..7bd04205 100644 --- a/src/lib/datatypes/camera.c +++ b/src/lib/datatypes/camera.c @@ -18,16 +18,12 @@ void cam_recompute_optics(struct camera *cam) { cam->aspect_ratio = (float)cam->width / (float)cam->height; cam->sensor_size.x = 2.0f * tanf(deg_to_rad(cam->FOV) / 2.0f); cam->sensor_size.y = cam->sensor_size.x / cam->aspect_ratio; - cam->look_at = (struct vector){0.0f, 0.0f, 1.0f}; //FIXME: This still assumes a 35mm sensor, instead of using the computed //sensor width value from above. Just preserving this so existing configs //work, but do look into a better way to do this here! const float sensor_width_35mm = 0.036f; cam->focal_length = 0.5f * sensor_width_35mm / deg_to_rad(0.5f * cam->FOV); if (cam->fstops != 0.0f) cam->aperture = 0.5f * (cam->focal_length / cam->fstops); - cam->forward = vec_normalize(cam->look_at); - cam->right = vec_cross(g_world_up, cam->forward); - cam->up = vec_cross(cam->forward, cam->right); } void recomputeComposite(struct camera *cam) { @@ -36,7 +32,7 @@ void recomputeComposite(struct camera *cam) { struct vector positionAtT = spline_at(cam->path, cam->time); transforms[0] = tform_new_translate(positionAtT.x, positionAtT.y, positionAtT.z); } else { - transforms[0] = tform_new_translate(-cam->position.x, cam->position.y, cam->position.z); + transforms[0] = tform_new_translate(cam->position.x, cam->position.y, cam->position.z); } transforms[1] = tform_new_rot(cam->orientation.roll, cam->orientation.pitch, cam->orientation.yaw); @@ -77,7 +73,7 @@ struct lightRay cam_get_ray(const struct camera *cam, int x, int y, struct sampl const float jitter_x = triangleDistribution(getDimension(sampler)); const float jitter_y = triangleDistribution(getDimension(sampler)); - const struct vector pix_x = vec_scale(vec_negate(cam->right), (cam->sensor_size.x / cam->width)); + const struct vector pix_x = vec_scale(cam->right, (cam->sensor_size.x / cam->width)); const struct vector pix_y = vec_scale(cam->up, (cam->sensor_size.y / cam->height)); const struct vector pix_v = vec_add( cam->forward,