diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index 940123e6645..e4b926653ab 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -206,7 +206,9 @@ class AddPresetCamera(AddPresetBase, Operator): ] preset_values = [ - "cam.sensor_width" + "cam.sensor_width", + "cam.sensor_height", + "cam.fov_mode" ] preset_subdir = "camera" diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 5fbb214f8d5..7a65369285b 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -129,7 +129,11 @@ class DATA_PT_camera(CameraButtonsPanel, Panel): row.operator("camera.preset_add", text="", icon="ZOOMIN") row.operator("camera.preset_add", text="", icon="ZOOMOUT").remove_active = True - layout.prop(cam, "sensor_width") + layout.prop(cam, "fov_mode") + + col = layout.column(align=True) + col.prop(cam, "sensor_width") + col.prop(cam, "sensor_height") layout.label(text="Clipping:") row = layout.row(align=True) diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index b72198674b6..b58f969ed19 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -145,7 +145,8 @@ void object_camera_intrinsics(struct Object *camera, struct Camera **cam_r, shor float *clipsta, float *clipend, float *lens, float *sensor_x); void object_camera_matrix( struct RenderData *rd, struct Object *camera, int winx, int winy, short field_second, - float winmat[][4], struct rctf *viewplane, float *clipsta, float *clipend, float *lens, float *sensor_x, float *ycor, + float winmat[][4], struct rctf *viewplane, float *clipsta, float *clipend, float *lens, + float *sensor_x, float *sensor_y, short *fov_mode, float *ycor, float *viewdx, float *viewdy); void camera_view_frame_ex(struct Scene *scene, struct Camera *camera, float drawsize, const short do_clip, const float scale[3], diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7191a136850..67cef3f3d2b 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2977,13 +2977,17 @@ void object_camera_mode(RenderData *rd, Object *camera) } void object_camera_intrinsics(Object *camera, Camera **cam_r, short *is_ortho, float *shiftx, float *shifty, - float *clipsta, float *clipend, float *lens, float *sensor_x) + float *clipsta, float *clipend, float *lens, float *sensor_x, float *sensor_y, short *fov_mode) { Camera *cam= NULL; (*shiftx)= 0.0f; (*shifty)= 0.0f; + (*sensor_x)= DEFAULT_SENSOR_WIDTH; + (*sensor_y)= DEFAULT_SENSOR_HEIGHT; + (*fov_mode)= CAMERA_FOV_AUTO; + if(camera->type==OB_CAMERA) { cam= camera->data; @@ -3005,8 +3009,10 @@ void object_camera_intrinsics(Object *camera, Camera **cam_r, short *is_ortho, f (*shifty)=cam->shifty; (*lens)= cam->lens; (*sensor_x)= cam->sensor_x; + (*sensor_y)= cam->sensor_y; (*clipsta)= cam->clipsta; (*clipend)= cam->clipend; + (*fov_mode)= cam->fov_mode; } else if(camera->type==OB_LAMP) { Lamp *la= camera->data; @@ -3035,9 +3041,10 @@ void object_camera_intrinsics(Object *camera, Camera **cam_r, short *is_ortho, f /* 'lens' may be set for envmap only */ void object_camera_matrix( RenderData *rd, Object *camera, int winx, int winy, short field_second, - float winmat[][4], rctf *viewplane, float *clipsta, float *clipend, float *lens, float *sensor_x, float *ycor, - float *viewdx, float *viewdy -) { + float winmat[][4], rctf *viewplane, float *clipsta, float *clipend, float *lens, + float *sensor_x, float *sensor_y, short *fov_mode, float *ycor, + float *viewdx, float *viewdy) +{ Camera *cam=NULL; float pixsize; float shiftx=0.0, shifty=0.0, winside, viewfac; @@ -3048,22 +3055,36 @@ void object_camera_matrix( if(rd->mode & R_FIELDS) (*ycor) *= 2.0f; - object_camera_intrinsics(camera, &cam, &is_ortho, &shiftx, &shifty, clipsta, clipend, lens, sensor_x); + object_camera_intrinsics(camera, &cam, &is_ortho, &shiftx, &shifty, clipsta, clipend, lens, sensor_x, sensor_y, fov_mode); /* ortho only with camera available */ if(cam && is_ortho) { - if(rd->xasp*winx >= rd->yasp*winy) { + if((*fov_mode)==CAMERA_FOV_AUTO) { + if(rd->xasp*winx >= rd->yasp*winy) viewfac= winx; + else viewfac= (*ycor) * winy; + } + else if((*fov_mode)==CAMERA_FOV_HOR) { viewfac= winx; } else { viewfac= (*ycor) * winy; } + /* ortho_scale == 1.0 means exact 1 to 1 mapping */ pixsize= cam->ortho_scale/viewfac; } else { - if(rd->xasp*winx >= rd->yasp*winy) viewfac= ((*lens) * winx) / (*sensor_x); - else viewfac= (*ycor) * ((*lens) * winy) / (*sensor_x); + if((*fov_mode)==CAMERA_FOV_AUTO) { + if(rd->xasp*winx >= rd->yasp*winy) viewfac= ((*lens) * winx) / (*sensor_x); + else viewfac= (*ycor) * ((*lens) * winy) / (*sensor_x); + } + else if((*fov_mode)==CAMERA_FOV_HOR) { + viewfac= ((*lens) * winx) / (*sensor_x); + } + else if((*fov_mode)==CAMERA_FOV_VERT) { + viewfac= ((*lens) * winy) / (*sensor_y); + } + pixsize= (*clipsta) / viewfac; } diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index b2ef021234f..fca7c3469a1 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -179,8 +179,8 @@ void dquat_to_mat4(float R[4][4], DualQuat *dq); void quat_apply_track(float quat[4], short axis, short upflag); void vec_apply_track(float vec[3], short axis); -float focallength_to_hfov(float focal_length, float sensor_x); -float hfov_to_focallength(float hfov, float sensor_x); +float focallength_to_fov(float focal_length, float sensor); +float fov_to_focallength(float fov, float sensor); float angle_wrap_rad(float angle); float angle_wrap_deg(float angle); diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 53cdb5327bc..82e93154b8f 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -1688,14 +1688,14 @@ void vec_apply_track(float vec[3], short axis) } /* lens/angle conversion (radians) */ -float focallength_to_hfov(float focal_length, float sensor_x) +float focallength_to_fov(float focal_length, float sensor) { - return 2.0f * atanf((sensor_x/2.0f) / focal_length); + return 2.0f * atanf((sensor/2.0f) / focal_length); } -float hfov_to_focallength(float hfov, float sensor_x) +float fov_to_focallength(float hfov, float sensor) { - return (sensor_x/2.0f) / tanf(hfov * 0.5f); + return (sensor/2.0f) / tanf(hfov * 0.5f); } /* 'mod_inline(-3,4)= 1', 'fmod(-3,4)= -3' */ diff --git a/source/blender/blenlib/intern/uvproject.c b/source/blender/blenlib/intern/uvproject.c index c11308e8510..8b00d8e48a6 100644 --- a/source/blender/blenlib/intern/uvproject.c +++ b/source/blender/blenlib/intern/uvproject.c @@ -141,7 +141,7 @@ UvCameraInfo *project_camera_info(Object *ob, float (*rotmat)[4], float winx, fl uci.do_pano = (camera->flag & CAM_PANORAMA); uci.do_persp = (camera->type==CAM_PERSP); - uci.camangle= focallength_to_hfov(camera->lens, camera->sensor_x) / 2.0f; + uci.camangle= focallength_to_fov(camera->lens, camera->sensor_x) / 2.0f; uci.camsize= uci.do_persp ? tanf(uci.camangle) : camera->ortho_scale; /* account for scaled cameras */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 875ab0ecf08..03e1ca25c07 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -12360,9 +12360,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } for(cam= main->camera.first; cam; cam= cam->id.next) { - if (cam->sensor_x < 0.01) { - cam->sensor_x = 32.f; - } + if (cam->sensor_x < 0.01) + cam->sensor_x = DEFAULT_SENSOR_WIDTH; + + if (cam->sensor_y < 0.01) + cam->sensor_y = DEFAULT_SENSOR_HEIGHT; } for (clip= main->movieclip.first; clip; clip= clip->id.next) { diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 9b165bb4977..292d998bf5c 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -57,6 +57,7 @@ #include "IMB_imbuf_types.h" #include "DNA_brush_types.h" +#include "DNA_camera_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" @@ -3000,7 +3001,8 @@ static void project_paint_begin(ProjPaintState *ps) Object *camera= ps->scene->camera; /* dont actually use these */ - float _viewdx, _viewdy, _ycor, _lens=0.0f, _sensor_x=0.0f; + float _viewdx, _viewdy, _ycor, _lens=0.0f, _sensor_x=DEFAULT_SENSOR_WIDTH, _sensor_y= DEFAULT_SENSOR_HEIGHT; + short _fov_mode= CAMERA_FOV_AUTO; rctf _viewplane; /* viewmat & viewinv */ @@ -3012,7 +3014,7 @@ static void project_paint_begin(ProjPaintState *ps) object_camera_mode(&ps->scene->r, camera); object_camera_matrix(&ps->scene->r, camera, ps->winx, ps->winy, 0, winmat, &_viewplane, &ps->clipsta, &ps->clipend, - &_lens, &_sensor_x, &_ycor, &_viewdx, &_viewdy); + &_lens, &_sensor_x, &_sensor_x, &_fov_mode, &_ycor, &_viewdx, &_viewdy); ps->is_ortho= (ps->scene->r.mode & R_ORTHO) ? 1 : 0; } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index 32177eee78a..83aadb66423 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -118,7 +118,7 @@ static void add_marker(SpaceClip *sc, float x, float y) MovieClip *clip= ED_space_clip(sc); MovieTrackingTrack *track; int width, height; - + ED_space_clip_size(sc, &width, &height); track= BKE_tracking_add_track(&clip->tracking, x, y, sc->user.framenr, width, height); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2db6286a600..af9ab7f1cf9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -921,17 +921,34 @@ static void draw_selected_name(Scene *scene, Object *ob) BLF_draw_default(offset, 10, 0.0f, info, sizeof(info)-1); } -void view3d_viewborder_size_get(Scene *scene, ARegion *ar, float size_r[2]) +void view3d_viewborder_size_get(Scene *scene, Object *camob, ARegion *ar, float size_r[2]) { - float winmax= MAX2(ar->winx, ar->winy); float aspect= (scene->r.xsch*scene->r.xasp) / (scene->r.ysch*scene->r.yasp); - - if(aspect > 1.0f) { - size_r[0]= winmax; - size_r[1]= winmax/aspect; - } else { - size_r[0]= winmax*aspect; - size_r[1]= winmax; + short fov_mode= CAMERA_FOV_AUTO; + + if(camob && camob->type==OB_CAMERA) { + Camera *cam= (Camera *)camob->data; + fov_mode= cam->fov_mode; + } + + if(fov_mode==CAMERA_FOV_AUTO) { + float winmax= MAX2(ar->winx, ar->winy); + + if(aspect > 1.0f) { + size_r[0]= winmax; + size_r[1]= winmax/aspect; + } else { + size_r[0]= winmax*aspect; + size_r[1]= winmax; + } + } + else if(fov_mode==CAMERA_FOV_HOR) { + size_r[0]= ar->winx; + size_r[1]= ar->winx/aspect; + } + else { + size_r[0]= ar->winy*aspect; + size_r[1]= ar->winy; } } @@ -941,7 +958,7 @@ void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, Region float size[2]; float dx= 0.0f, dy= 0.0f; - view3d_viewborder_size_get(scene, ar, size); + view3d_viewborder_size_get(scene, v3d->camera, ar, size); size[0]= size[0]*zoomfac; size[1]= size[1]*zoomfac; @@ -2444,10 +2461,12 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Scene *scene, View3D *v3d, ARegion *ar, in /* render 3d view */ if(rv3d->persp==RV3D_CAMOB && v3d->camera) { float winmat[4][4]; - float _clipsta, _clipend, _lens, _yco, _dx, _dy, _sensor_x=0; + float _clipsta, _clipend, _lens, _yco, _dx, _dy, _sensor_x= DEFAULT_SENSOR_WIDTH, _sensor_y= DEFAULT_SENSOR_HEIGHT; + short _fov_mode= CAMERA_FOV_AUTO; rctf _viewplane; - object_camera_matrix(&scene->r, v3d->camera, sizex, sizey, 0, winmat, &_viewplane, &_clipsta, &_clipend, &_lens, &_sensor_x, &_yco, &_dx, &_dy); + object_camera_matrix(&scene->r, v3d->camera, sizex, sizey, 0, winmat, &_viewplane, &_clipsta, &_clipend, &_lens, + &_sensor_x, &_sensor_y, &_fov_mode, &_yco, &_dx, &_dy); ED_view3d_draw_offscreen(scene, v3d, ar, sizex, sizey, NULL, winmat); } @@ -2502,9 +2521,10 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Scene *scene, Object *camera, int w invert_m4_m4(rv3d.viewmat, rv3d.viewinv); { - float _yco, _dx, _dy, _sensor_x=0; + float _yco, _dx, _dy, _sensor_x= DEFAULT_SENSOR_WIDTH, _sensor_y= DEFAULT_SENSOR_HEIGHT; + short _fov_mode= CAMERA_FOV_AUTO; rctf _viewplane; - object_camera_matrix(&scene->r, v3d.camera, width, height, 0, rv3d.winmat, &_viewplane, &v3d.near, &v3d.far, &v3d.lens, &_sensor_x, &_yco, &_dx, &_dy); + object_camera_matrix(&scene->r, v3d.camera, width, height, 0, rv3d.winmat, &_viewplane, &v3d.near, &v3d.far, &v3d.lens, &_sensor_x, &_sensor_y, &_fov_mode, &_yco, &_dx, &_dy); } mul_m4_m4m4(rv3d.persmat, rv3d.viewmat, rv3d.winmat); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 00c9bf55f56..d8936efce36 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2255,13 +2255,14 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was { ARegion *ar= CTX_wm_region(C); RegionView3D *rv3d= CTX_wm_region_view3d(C); + View3D *v3d= CTX_wm_view3d(C); Scene *scene= CTX_data_scene(C); float xfac, yfac; float size[2]; rv3d->camdx= rv3d->camdy= 0.0f; - view3d_viewborder_size_get(scene, ar, size); + view3d_viewborder_size_get(scene, v3d->camera, ar, size); /* 4px is just a little room from the edge of the area */ xfac= (float)ar->winx / (float)(size[0] + 4); @@ -2523,13 +2524,13 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) } /* sets the view to 1:1 camera/render-pixel */ -static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar) +static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d) { RegionView3D *rv3d= ar->regiondata; float size[2]; int im_width= (scene->r.size*scene->r.xsch)/100; - view3d_viewborder_size_get(scene, ar, size); + view3d_viewborder_size_get(scene, v3d->camera, ar, size); rv3d->camzoom= BKE_screen_view3d_zoom_from_fac((float)im_width/size[0]); CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); @@ -2540,7 +2541,7 @@ static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene= CTX_data_scene(C); ARegion *ar= CTX_wm_region(C); - view3d_set_1_to_1_viewborder(scene, ar); + view3d_set_1_to_1_viewborder(scene, ar, CTX_wm_view3d(C)); WM_event_add_notifier(C, NC_SPACE|ND_SPACE_VIEW3D, CTX_wm_view3d(C)); diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 4901957c0a2..1afbd57c6e6 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -136,7 +136,7 @@ void draw_depth_gpencil(Scene *scene, ARegion *ar, View3D *v3d); void view3d_clr_clipping(void); void view3d_set_clipping(RegionView3D *rv3d); void add_view3d_after(ListBase *lb, Base *base, int flag); -void view3d_viewborder_size_get(struct Scene *scene, struct ARegion *ar, float size_r[2]); +void view3d_viewborder_size_get(struct Scene *scene, struct Objecy *camob, struct ARegion *ar, float size_r[2]); void circf(float x, float y, float rad); void circ(float x, float y, float rad); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 8e0905d42d3..3122ef86a8c 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -966,9 +966,10 @@ int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, fl int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) { Camera *cam=NULL; - float lens, sensor=32.f, fac, x1, y1, x2, y2; + float lens, sensor_x =DEFAULT_SENSOR_WIDTH, sensor_y= DEFAULT_SENSOR_HEIGHT, fac, x1, y1, x2, y2; float winx= (float)winxi, winy= (float)winyi; int orth= 0; + short fov_mode= CAMERA_FOV_AUTO; lens= v3d->lens; @@ -992,9 +993,11 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winxi, int winy else if(v3d->camera->type==OB_CAMERA) { cam= v3d->camera->data; lens= cam->lens; - sensor= cam->sensor_x; + sensor_x= cam->sensor_x; + sensor_y= cam->sensor_y; *clipsta= cam->clipsta; *clipend= cam->clipend; + fov_mode= cam->fov_mode; } } } @@ -1025,21 +1028,44 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winxi, int winy if(cam && cam->type==CAM_ORTHO) { /* ortho_scale == 1 means exact 1 to 1 mapping */ float dfac= 2.0f*cam->ortho_scale/fac; - - if(winx>winy) x1= -dfac; - else x1= -winx*dfac/winy; + + if(fov_mode==CAMERA_FOV_AUTO) { + if(winx>winy) { + x1= -dfac; + y1= -winy*dfac/winx; + } + else { + x1= -winx*dfac/winy; + y1= -dfac; + } + } + else if(fov_mode==CAMERA_FOV_HOR) { + x1= -dfac; + y1= -winy*dfac/winx; + } + else { + x1= -winx*dfac/winy; + y1= -dfac; + } + x2= -x1; - - if(winx>winy) y1= -winy*dfac/winx; - else y1= -dfac; y2= -y1; + orth= 1; } else { float dfac; - if(winx>winy) dfac= (sensor * 2.0) / (fac*winx*lens); - else dfac= (sensor * 2.0) / (fac*winy*lens); + if(fov_mode==CAMERA_FOV_AUTO) { + if(winx>winy) dfac= (sensor_x * 2.0) / (fac*winx*lens); + else dfac= (sensor_x * 2.0) / (fac*winy*lens); + } + else if(fov_mode==CAMERA_FOV_HOR) { + dfac= (sensor_x * 2.0) / (fac*winx*lens); + } + else { + dfac= (sensor_y * 2.0) / (fac*winy*lens); + } x1= - *clipsta * winx*dfac; x2= -x1; @@ -1058,8 +1084,8 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winxi, int winy dy += cam->shifty * cam->ortho_scale; } else { - dx += cam->shiftx * (cam->clipsta / cam->lens) * sensor; - dy += cam->shifty * (cam->clipsta / cam->lens) * sensor; + dx += cam->shiftx * (cam->clipsta / cam->lens) * sensor_x; + dy += cam->shifty * (cam->clipsta / cam->lens) * sensor_x; } x1+= dx; diff --git a/source/blender/makesdna/DNA_camera_types.h b/source/blender/makesdna/DNA_camera_types.h index ed04ead36c2..08e8239641e 100644 --- a/source/blender/makesdna/DNA_camera_types.h +++ b/source/blender/makesdna/DNA_camera_types.h @@ -51,7 +51,7 @@ typedef struct Camera { float passepartalpha; float clipsta, clipend; float lens, ortho_scale, drawsize; - float sensor_x, pad; + float sensor_x, sensor_y; float shiftx, shifty; /* yafray: dof params */ @@ -62,6 +62,9 @@ typedef struct Camera { struct Ipo *ipo; // XXX depreceated... old animation system struct Object *dof_ob; + + char fov_mode; + char pad[7]; } Camera; /* **************** CAMERA ********************* */ @@ -94,6 +97,13 @@ typedef struct Camera { /* yafray: dof sampling switch */ /* #define CAM_YF_NO_QMC 512 */ /* depreceated */ +/* FOV mode */ +#define CAMERA_FOV_AUTO 0 +#define CAMERA_FOV_HOR 1 +#define CAMERA_FOV_VERT 2 + +#define DEFAULT_SENSOR_WIDTH 32.0f +#define DEFAULT_SENSOR_HEIGHT 18.0f #ifdef __cplusplus } diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 1c174c91347..69afd2dc427 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -43,16 +43,55 @@ #include "BKE_depsgraph.h" /* only for rad/deg conversion! can remove later */ +static float get_camera_sensor(Camera *cam) +{ + if(cam->fov_mode==CAMERA_FOV_AUTO) { + return cam->sensor_x; + } + else if(cam->fov_mode==CAMERA_FOV_HOR) { + return cam->sensor_x; + } + else { + return cam->sensor_y; + } +} + static float rna_Camera_angle_get(PointerRNA *ptr) { Camera *cam= ptr->id.data; - return focallength_to_hfov(cam->lens, cam->sensor_x); + float sensor= get_camera_sensor(cam); + return focallength_to_fov(cam->lens, sensor); } static void rna_Camera_angle_set(PointerRNA *ptr, float value) { Camera *cam= ptr->id.data; - cam->lens= hfov_to_focallength(value, cam->sensor_x); + float sensor= get_camera_sensor(cam); + cam->lens= fov_to_focallength(value, sensor); +} + +static float rna_Camera_angle_x_get(PointerRNA *ptr) +{ + Camera *cam= ptr->id.data; + return focallength_to_fov(cam->lens, cam->sensor_x); +} + +static void rna_Camera_angle_x_set(PointerRNA *ptr, float value) +{ + Camera *cam= ptr->id.data; + cam->lens= fov_to_focallength(value, cam->sensor_x); +} + +static float rna_Camera_angle_y_get(PointerRNA *ptr) +{ + Camera *cam= ptr->id.data; + return focallength_to_fov(cam->lens, cam->sensor_y); +} + +static void rna_Camera_angle_y_set(PointerRNA *ptr, float value) +{ + Camera *cam= ptr->id.data; + cam->lens= fov_to_focallength(value, cam->sensor_y); } static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) @@ -86,6 +125,11 @@ void RNA_def_camera(BlenderRNA *brna) {0, "MILLIMETERS", 0, "Millimeters", ""}, {CAM_ANGLETOGGLE, "DEGREES", 0, "Degrees", ""}, {0, NULL, 0, NULL, NULL}}; + static EnumPropertyItem fov_mode_items[] = { + {CAMERA_FOV_AUTO, "AUTO", 0, "Auto", "Calculate FOV using sensor size direction depending on image resolution"}, + {CAMERA_FOV_HOR, "HORIZONTAL", 0, "Hoizontal", "Calculate FOV using sensor width"}, + {CAMERA_FOV_VERT, "VERTICAL", 0, "Vertical", "Calculate FOV using sensor height"}, + {0, NULL, 0, NULL, NULL}}; srna= RNA_def_struct(brna, "Camera", "ID"); RNA_def_struct_ui_text(srna, "Camera", "Camera datablock for storing camera settings"); @@ -103,7 +147,13 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_property_ui_text(prop, "Composition Guides", "Draw overlay"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); - + + prop= RNA_def_property(srna, "fov_mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "fov_mode"); + RNA_def_property_enum_items(prop, fov_mode_items); + RNA_def_property_ui_text(prop, "FOV Mode", "Mode of calculating FOV from sensor imensions and focal length"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); + /* Number values */ prop= RNA_def_property(srna, "passepartout_alpha", PROP_FLOAT, PROP_FACTOR); @@ -111,10 +161,24 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Passepartout Alpha", "Opacity (alpha) of the darkened overlay in Camera view"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); + prop= RNA_def_property(srna, "angle_x", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_range(prop, M_PI * (0.367/180.0), M_PI * (172.847/180.0)); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Horizontal FOV", "Camera lens horizontal field of view in degrees"); + RNA_def_property_float_funcs(prop, "rna_Camera_angle_x_get", "rna_Camera_angle_x_set", NULL); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); + + prop= RNA_def_property(srna, "angle_y", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_range(prop, M_PI * (0.367/180.0), M_PI * (172.847/180.0)); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Vertical FOV", "Camera lens vertical field of view in degrees"); + RNA_def_property_float_funcs(prop, "rna_Camera_angle_y_get", "rna_Camera_angle_y_set", NULL); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); + prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_range(prop, M_PI * (0.367/180.0), M_PI * (172.847/180.0)); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_ui_text(prop, "Field of View", "Camera lens horizontal field of view in degrees"); + RNA_def_property_ui_text(prop, "Field of View", "Camera lens field of view in degrees"); RNA_def_property_float_funcs(prop, "rna_Camera_angle_get", "rna_Camera_angle_set", NULL); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); @@ -135,12 +199,19 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_range(prop, 1.0f, 5000.0f); RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); - + prop= RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sensor_x"); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); - RNA_def_property_ui_text(prop, "Sensor", "Horizontal size of the image sensor area in millimeters"); + RNA_def_property_ui_text(prop, "Sensor Width", "Horizontal size of the image sensor area in millimeters"); + RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); + + prop= RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "sensor_y"); + RNA_def_property_range(prop, 1.0f, FLT_MAX); + RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); + RNA_def_property_ui_text(prop, "Sensor Height", "Vertical size of the image sensor area in millimeters"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, "rna_Camera_update"); prop= RNA_def_property(srna, "ortho_scale", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 6cd59e59429..0515c08a4e1 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -195,16 +195,28 @@ static DerivedMesh *uvprojectModifier_do(UVProjectModifierData *umd, free_uci= 1; } else { - float scale= (cam->type == CAM_PERSP) ? cam->clipsta * cam->sensor_x / cam->lens : cam->ortho_scale; + float sensor= (cam->fov_mode == CAMERA_FOV_VERT) ? (cam->sensor_y) : cam->sensor_x; + float scale= (cam->type == CAM_PERSP) ? cam->clipsta * sensor / cam->lens : cam->ortho_scale; float xmax, xmin, ymax, ymin; - if(aspect > 1.0f) { + if(cam->fov_mode==CAMERA_FOV_AUTO) { + if(aspect > 1.0f) { + xmax = 0.5f * scale; + ymax = xmax / aspect; + } else { + ymax = 0.5f * scale; + xmax = ymax * aspect; + } + } + else if(cam->fov_mode==CAMERA_FOV_HOR) { xmax = 0.5f * scale; ymax = xmax / aspect; - } else { + } + else { ymax = 0.5f * scale; xmax = ymax * aspect; } + xmin = -xmax; ymin = -ymax; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 651608f83c3..cfc05533438 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -153,8 +153,9 @@ struct Render /* values for viewing */ float lens; - float sensor_x; /* image sensor size, same variable in camera */ + float sensor_x, sensor_y; /* image sensor size, same variable in camera */ float ycor; /* (scene->xasp / scene->yasp), multiplied with 'winy' */ + char fov_mode; float panophi, panosi, panoco, panodxp, panodxv; diff --git a/source/blender/render/intern/source/initrender.c b/source/blender/render/intern/source/initrender.c index b69dc6f85c3..77204365c0e 100644 --- a/source/blender/render/intern/source/initrender.c +++ b/source/blender/render/intern/source/initrender.c @@ -458,7 +458,7 @@ void RE_SetCamera(Render *re, Object *camera) object_camera_matrix(&re->r, camera, re->winx, re->winy, re->flag & R_SEC_FIELD, re->winmat, &re->viewplane, &re->clipsta, &re->clipend, - &re->lens, &re->sensor_x, &re->ycor, &re->viewdx, &re->viewdy); + &re->lens, &re->sensor_x, &re->sensor_y, &re->fov_mode, &re->ycor, &re->viewdx, &re->viewdy); } void RE_SetPixelSize(Render *re, float pixsize) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 779bc5b542c..80661fc29de 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1724,7 +1724,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) { Camera* ca = static_cast(ob->data); - RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist); + RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->fov_mode, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist); KX_Camera *gamecamera; gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index c3c3fc274ac..64bba6c87ca 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -208,6 +208,18 @@ float KX_Camera::GetSensorWidth() const return m_camdata.m_sensor_x; } +/* +* Gets the vertical size of the sensor - for camera matching. +*/ +float KX_Camera::GetSensorHeight() const +{ + return m_camdata.m_sensor_y; +} +/** Gets the mode FOV is calculating from sensor dimensions */ +short KX_Camera::GetFOVMode() const +{ + return m_camdata.m_fov_mode; +} float KX_Camera::GetCameraNear() const { diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 0638a7677bc..cc114deaef7 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -201,6 +201,10 @@ public: float GetScale() const; /** Gets the horizontal size of the sensor - for camera matching */ float GetSensorWidth() const; + /** Gets the vertical size of the sensor - for camera matching */ + float GetSensorHeight() const; + /** Gets the mode FOV is calculating from sensor dimensions */ + short GetFOVMode() const; /** Gets the near clip distance. */ float GetCameraNear() const; /** Gets the far clip distance. */ diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index ed03f68db14..371b3cdbb3c 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1251,6 +1251,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) cam->GetScale(), nearfrust, farfrust, + cam->GetFOVMode(), frustum ); if (!cam->GetViewport()) { @@ -1269,6 +1270,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) viewport, cam->GetLens(), cam->GetSensorWidth(), + cam->GetSensorHeight(), + cam->GetFOVMode(), nearfrust, farfrust, frustum diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 1e00be9c50f..7726aaafbca 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -37,6 +37,8 @@ struct RAS_CameraData float m_lens; float m_scale; float m_sensor_x; + float m_sensor_y; + short m_fov_mode; float m_clipstart; float m_clipend; bool m_perspective; @@ -47,12 +49,15 @@ struct RAS_CameraData int m_viewporttop; float m_focallength; - RAS_CameraData(float lens = 35.0, float scale = 6.0, float sensor_x = 32.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, + RAS_CameraData(float lens = 35.0, float scale = 6.0, float sensor_x = 32.0, float sensor_y = 18.0, short fov_mode = 0, + float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, float focallength = 3.0, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : m_lens(lens), m_scale(scale), m_sensor_x(sensor_x), + m_sensor_y(sensor_y), + m_fov_mode(fov_mode), m_clipstart(clipstart), m_clipend(clipend), m_perspective(perspective), diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp index d5d7b18cee5..7cd46acb085 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp +++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp @@ -39,27 +39,35 @@ ComputeDefaultFrustum( const float camnear, const float camfar, const float lens, - const float sensor_x, + const float sensor_x, const float sensor_y, + const short fov_mode, const float design_aspect_ratio, RAS_FrameFrustum & frustum -){ - - /* - * Magic Blender calculation. - * Blender does not give a Field of View as lens but a size - * at 16 units away from the lens. - * ^Deprecated Comment - */ - float halfSize = (sensor_x / 2.f) * camnear / lens; +){ + float halfSize; float sizeX; float sizeY; - if (design_aspect_ratio > 1.f) { - // halfsize defines the width + if(fov_mode==RAS_FOVMODE_AUTO) { + halfSize = (sensor_x / 2.f) * camnear / lens; + + if (design_aspect_ratio > 1.f) { + // halfsize defines the width + sizeX = halfSize; + sizeY = halfSize/design_aspect_ratio; + } else { + // halfsize defines the height + sizeX = halfSize * design_aspect_ratio; + sizeY = halfSize; + } + } + else if(fov_mode==RAS_FOVMODE_HOR) { + halfSize = (sensor_x / 2.f) * camnear / lens; sizeX = halfSize; sizeY = halfSize/design_aspect_ratio; - } else { - // halfsize defines the height + } + else { + halfSize = (sensor_y / 2.f) * camnear / lens; sizeX = halfSize * design_aspect_ratio; sizeY = halfSize; } @@ -79,6 +87,7 @@ ComputeDefaultOrtho( const float camfar, const float scale, const float design_aspect_ratio, + const short fov_mode, RAS_FrameFrustum & frustum ) { @@ -86,12 +95,22 @@ ComputeDefaultOrtho( float sizeX; float sizeY; - if (design_aspect_ratio > 1.f) { - // halfsize defines the width + if(fov_mode==RAS_FOVMODE_AUTO) { + if (design_aspect_ratio > 1.f) { + // halfsize defines the width + sizeX = halfSize; + sizeY = halfSize/design_aspect_ratio; + } else { + // halfsize defines the height + sizeX = halfSize * design_aspect_ratio; + sizeY = halfSize; + } + } + else if(fov_mode==RAS_FOVMODE_HOR) { sizeX = halfSize; sizeY = halfSize/design_aspect_ratio; - } else { - // halfsize defines the height + } + else { sizeX = halfSize * design_aspect_ratio; sizeY = halfSize; } @@ -201,7 +220,7 @@ ComputeFrustum( const RAS_Rect &availableViewport, const RAS_Rect &viewport, const float lens, - const float sensor_x, + const float sensor_x, const float sensor_y, const short fov_mode, const float camnear, const float camfar, RAS_FrameFrustum &frustum @@ -228,6 +247,8 @@ ComputeFrustum( camfar, lens, sensor_x, + sensor_y, + fov_mode, design_aspect_ratio, frustum ); @@ -273,6 +294,7 @@ RAS_FramingManager:: const float scale, const float camnear, const float camfar, + const short fov_mode, RAS_FrameFrustum &frustum ) { @@ -297,6 +319,7 @@ RAS_FramingManager:: camfar, scale, design_aspect_ratio, + fov_mode, frustum ); diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index ecac6ab0240..0ae7b6f18a6 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -184,6 +184,14 @@ enum RAS_CullingMode RAS_CULLING_NONE }; +/* Should match CAMERA_FOV... from DNA_camera_types.h */ +enum RAS_FovMode +{ + RAS_FOVMODE_AUTO = 0, + RAS_FOVMODE_HOR, + RAS_FOVMODE_VERT +}; + /** * @section RAS_FramingManager * This class helps to compute a view frustum @@ -229,6 +237,7 @@ public : const float scale, const float camnear, const float camfar, + const short fov_mode, RAS_FrameFrustum &frustum ); @@ -239,7 +248,7 @@ public : const RAS_Rect &availableViewport, const RAS_Rect &viewport, const float lens, - const float sensor_x, + const float sensor_x, const float sensor_y, const short fov_mode, const float camnear, const float camfar, RAS_FrameFrustum &frustum @@ -251,7 +260,8 @@ public : const float camnear, const float camfar, const float lens, - const float sensor_x, + const float sensor_x, const float sensor_y, + const short fov_mode, const float design_aspect_ratio, RAS_FrameFrustum & frustum ); @@ -263,6 +273,7 @@ public : const float camfar, const float scale, const float design_aspect_ratio, + const short fov_mode, RAS_FrameFrustum & frustum ); diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 0d8acc9c0c2..8bc8c67db6b 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -215,6 +215,7 @@ void ImageRender::Render() { float lens = m_camera->GetLens(); float sensor_x = m_camera->GetSensorWidth(); + float sensor_y = m_camera->GetSensorHeight(); bool orthographic = !m_camera->GetCameraData()->m_perspective; float nearfrust = m_camera->GetCameraNear(); float farfrust = m_camera->GetCameraFar(); @@ -234,6 +235,7 @@ void ImageRender::Render() farfrust, m_camera->GetScale(), aspect_ratio, + m_camera->GetFOVMode(), frustrum ); @@ -246,6 +248,8 @@ void ImageRender::Render() farfrust, lens, sensor_x, + sensor_y, + RAS_FOVMODE_AUTO, aspect_ratio, frustrum);