From 5429a701c4f2674e6fa4c0eef8c285c13e16af0c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 18 Nov 2011 21:19:03 +0000 Subject: Camera: more code refactoring, adding a function to create CameraParams from 3d view, deduplicating the complex code for setting up the viewplane. --- source/blender/blenkernel/BKE_camera.h | 12 +- source/blender/blenkernel/intern/camera.c | 116 ++++++++++----- source/blender/editors/include/ED_view3d.h | 2 +- source/blender/editors/render/render_opengl.c | 2 +- source/blender/editors/sculpt_paint/paint_image.c | 2 +- source/blender/editors/space_view3d/view3d_view.c | 170 ++-------------------- source/blender/makesrna/intern/rna_camera.c | 19 +-- 7 files changed, 107 insertions(+), 216 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 4a0f38d926c..8aec576b963 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -40,21 +40,27 @@ extern "C" { struct Camera; struct Object; +struct RegionView3D; struct RenderData; struct Scene; struct rctf; struct View3D; +/* Camera Datablock */ + void *add_camera(const char *name); struct Camera *copy_camera(struct Camera *cam); void make_local_camera(struct Camera *cam); void free_camera(struct Camera *ca); -/* Camera Object */ +/* Camera Usage */ float object_camera_dof_distance(struct Object *ob); void object_camera_mode(struct RenderData *rd, struct Object *ob); +int camera_sensor_fit(int sensor_fit, float sizex, float sizey); +float camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y); + /* Camera Parameters: * * Intermediate struct for storing camera parameters from various sources, @@ -65,9 +71,12 @@ typedef struct CameraParams { int is_ortho; float lens; float ortho_scale; + float zoom; float shiftx; float shifty; + float offsetx; + float offsety; /* sensor */ float sensor_x; @@ -95,6 +104,7 @@ typedef struct CameraParams { void camera_params_init(CameraParams *params); void camera_params_from_object(CameraParams *params, struct Object *camera); +void camera_params_from_view3d(CameraParams *params, struct View3D *v3d, struct RegionView3D *rv3d); void camera_params_compute(CameraParams *params, int winx, int winy, float aspx, float aspy); /* Camera View Frame */ diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 858351ebbf3..29770e37ea1 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -35,6 +35,7 @@ #include "DNA_lamp_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_view3d_types.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -45,6 +46,7 @@ #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_screen.h" /****************************** Camera Datablock *****************************/ @@ -161,9 +163,16 @@ float object_camera_dof_distance(Object *ob) return cam->YF_dofdist; } -/******************************** Camera Params *******************************/ +float camera_sensor_size(int sensor_fit, float sensor_x, float sensor_y) +{ + /* sensor size used to fit to. for auto, sensor_x is both x and y. */ + if(sensor_fit == CAMERA_SENSOR_FIT_VERT) + return sensor_y; -static int camera_sensor_fit(int sensor_fit, float sizex, float sizey) + return sensor_x; +} + +int camera_sensor_fit(int sensor_fit, float sizex, float sizey) { if(sensor_fit == CAMERA_SENSOR_FIT_AUTO) { if(sizex >= sizey) @@ -175,6 +184,8 @@ static int camera_sensor_fit(int sensor_fit, float sizex, float sizey) return sensor_fit; } +/******************************** Camera Params *******************************/ + void camera_params_init(CameraParams *params) { memset(params, 0, sizeof(CameraParams)); @@ -183,6 +194,8 @@ void camera_params_init(CameraParams *params) params->sensor_x= DEFAULT_SENSOR_WIDTH; params->sensor_y= DEFAULT_SENSOR_HEIGHT; params->sensor_fit= CAMERA_SENSOR_FIT_AUTO; + + params->zoom= 1.0f; } void camera_params_from_object(CameraParams *params, Object *ob) @@ -224,10 +237,42 @@ void camera_params_from_object(CameraParams *params, Object *ob) } } +void camera_params_from_view3d(CameraParams *params, View3D *v3d, RegionView3D *rv3d) +{ + /* perspective view */ + params->lens= v3d->lens; + params->clipsta= v3d->near; + params->clipend= v3d->far; + + if(rv3d->persp==RV3D_CAMOB) { + /* camera view */ + camera_params_from_object(params, v3d->camera); + + params->zoom= BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom) * 2.0f; + params->zoom= 1.0f/params->zoom; + + params->offsetx= rv3d->camdx; + params->offsety= rv3d->camdy; + + params->shiftx *= 0.5f; + params->shifty *= 0.5f; + } + else if(rv3d->persp==RV3D_ORTHO) { + /* orthographic view */ + params->clipend *= 0.5f; // otherwise too extreme low zbuffer quality + params->clipsta= - params->clipend; + + params->is_ortho= 1; + params->ortho_scale = rv3d->dist; + } + + params->zoom *= 2.0f; +} + void camera_params_compute(CameraParams *params, int winx, int winy, float xasp, float yasp) { rctf viewplane; - float pixsize, winside, viewfac; + float pixsize, viewfac, sensor_size, dx, dy; int sensor_fit; /* fields rendering */ @@ -235,48 +280,47 @@ void camera_params_compute(CameraParams *params, int winx, int winy, float xasp, if(params->use_fields) params->ycor *= 2.0f; - /* determine sensor fit */ - sensor_fit = camera_sensor_fit(params->sensor_fit, xasp*winx, yasp*winy); - if(params->is_ortho) { - /* orthographic camera, scale == 1.0 means exact 1 to 1 mapping */ - if(sensor_fit==CAMERA_SENSOR_FIT_HOR) - viewfac= winx; - else - viewfac= params->ycor * winy; - - pixsize= params->ortho_scale/viewfac; + /* orthographic camera */ + /* scale == 1.0 means exact 1 to 1 mapping */ + pixsize= params->ortho_scale; } else { /* perspective camera */ - float sensor_size; + sensor_size= camera_sensor_size(params->sensor_fit, params->sensor_x, params->sensor_y); + pixsize= (sensor_size * params->clipsta)/params->lens; + } - /* note for auto fit sensor_x is both width and height */ - if(params->sensor_fit == CAMERA_SENSOR_FIT_VERT) - sensor_size= params->sensor_y; - else - sensor_size= params->sensor_x; - - if(sensor_fit == CAMERA_SENSOR_FIT_HOR) - viewfac= (params->lens * winx) / sensor_size; - else - viewfac= params->ycor * (params->lens * winy) / sensor_size; + /* determine sensor fit */ + sensor_fit = camera_sensor_fit(params->sensor_fit, xasp*winx, yasp*winy); - pixsize= params->clipsta/viewfac; - } + if(sensor_fit==CAMERA_SENSOR_FIT_HOR) + viewfac= winx; + else + viewfac= params->ycor * winy; + + pixsize /= viewfac; + + /* extra zoom factor */ + pixsize *= params->zoom; /* compute view plane: * fully centered, zbuffer fills in jittered between -.5 and +.5 */ - if(sensor_fit == CAMERA_SENSOR_FIT_HOR) - winside= winx; - else - winside= winy; + viewplane.xmin= -0.5f*(float)winx; + viewplane.ymin= -0.5f*params->ycor*(float)winy; + viewplane.xmax= 0.5f*(float)winx; + viewplane.ymax= 0.5f*params->ycor*(float)winy; - viewplane.xmin= -0.5f*(float)winx + params->shiftx*winside; - viewplane.ymin= -0.5f*params->ycor*(float)winy + params->shifty*winside; - viewplane.xmax= 0.5f*(float)winx + params->shiftx*winside; - viewplane.ymax= 0.5f*params->ycor*(float)winy + params->shifty*winside; + /* lens shift and offset */ + dx= params->shiftx*viewfac + winx*params->offsetx; + dy= params->shifty*viewfac + winy*params->offsety; + viewplane.xmin += dx; + viewplane.ymin += dy; + viewplane.xmax += dx; + viewplane.ymax += dy; + + /* fields offset */ if(params->field_second) { if(params->field_odd) { viewplane.ymin-= 0.5f * params->ycor; @@ -297,15 +341,15 @@ void camera_params_compute(CameraParams *params, int winx, int winy, float xasp, params->viewdx= pixsize; params->viewdy= params->ycor * pixsize; + params->viewplane= viewplane; + /* compute projection matrix */ if(params->is_ortho) orthographic_m4(params->winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend); else perspective_m4(params->winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, params->clipsta, params->clipend); - - params->viewplane= viewplane; } /***************************** Camera View Frame *****************************/ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 6536741af00..e2405425891 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -208,7 +208,7 @@ void project_float_noclip(struct ARegion *ar, const float vec[3], float adr[2]); void ED_view3d_ob_clip_range_get(struct Object *ob, float *lens, float *clipsta, float *clipend); int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend); -int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend, float *pixsize); +int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend); void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); void ED_view3d_project_float(struct ARegion *a, const float vec[3], float adr[2], float mat[4][4]); void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short do_shift); diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index fa764e6eefc..843918e9173 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -147,7 +147,7 @@ static void screen_opengl_render_apply(OGLRender *oglrender) rctf viewplane; float clipsta, clipend; - int is_ortho= ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL); + int is_ortho= ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend); if(is_ortho) orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend); else perspective_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, clipsta, clipend); } diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index 97a0c92d197..a856f959b49 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -3068,7 +3068,7 @@ static void project_paint_begin(ProjPaintState *ps) /* window matrix, clipping and ortho */ camera_params_init(¶ms); camera_params_from_object(¶ms, cam_ob); - camera_params_compute(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); /* XXX aspect? */ + camera_params_compute(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); copy_m4_m4(winmat, params.winmat); ps->clipsta= params.clipsta; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index d2d6d6b0959..cf838cb94ce 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1018,169 +1018,19 @@ int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, fl } /* also exposed in previewrender.c */ -int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) +int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, rctf *viewplane, float *clipsta, float *clipend) { - Camera *cam=NULL; - 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 sensor_fit= CAMERA_SENSOR_FIT_AUTO; - - /* currnetly using sensor size (depends on fov calculating method) */ - float sensor= DEFAULT_SENSOR_WIDTH; - - lens= v3d->lens; - - *clipsta= v3d->near; - *clipend= v3d->far; - - if(rv3d->persp==RV3D_CAMOB) { - if(v3d->camera) { - if(v3d->camera->type==OB_LAMP ) { - Lamp *la; - - la= v3d->camera->data; - fac= cosf(((float)M_PI)*la->spotsize/360.0f); - - x1= saacos(fac); - lens= 16.0f*fac/sinf(x1); - - *clipsta= la->clipsta; - *clipend= la->clipend; - } - else if(v3d->camera->type==OB_CAMERA) { - cam= v3d->camera->data; - lens= cam->lens; - sensor_x= cam->sensor_x; - sensor_y= cam->sensor_y; - *clipsta= cam->clipsta; - *clipend= cam->clipend; - sensor_fit= cam->sensor_fit; - - sensor= (cam->sensor_fit==CAMERA_SENSOR_FIT_VERT) ? (cam->sensor_y) : (cam->sensor_x); - } - } - } - - if(rv3d->persp==RV3D_ORTHO) { - if(winx>winy) x1= -rv3d->dist; - else x1= -winx*rv3d->dist/winy; - x2= -x1; - - if(winx>winy) y1= -winy*rv3d->dist/winx; - else y1= -rv3d->dist; - y2= -y1; - - *clipend *= 0.5f; // otherwise too extreme low zbuffer quality - *clipsta= - *clipend; - orth= 1; - } - else { - /* fac for zoom, also used for camdx */ - if(rv3d->persp==RV3D_CAMOB) { - fac= BKE_screen_view3d_zoom_to_fac((float)rv3d->camzoom) * 4.0f; - } - else { - fac= 2.0; - } - - /* viewplane size depends... */ - if(cam && cam->type==CAM_ORTHO) { - /* ortho_scale == 1 means exact 1 to 1 mapping */ - float dfac= 2.0f*cam->ortho_scale/fac; - - if(sensor_fit==CAMERA_SENSOR_FIT_AUTO) { - if(winx>winy) { - x1= -dfac; - y1= -winy*dfac/winx; - } - else { - x1= -winx*dfac/winy; - y1= -dfac; - } - } - else if(sensor_fit==CAMERA_SENSOR_FIT_HOR) { - x1= -dfac; - y1= -winy*dfac/winx; - } - else { - x1= -winx*dfac/winy; - y1= -dfac; - } - - x2= -x1; - y2= -y1; - - orth= 1; - } - else { - float dfac; - - if(sensor_fit==CAMERA_SENSOR_FIT_AUTO) { - if(winx>winy) dfac= (sensor_x * 2.0f) / (fac*winx*lens); - else dfac= (sensor_x * 2.0f) / (fac*winy*lens); - } - else if(sensor_fit==CAMERA_SENSOR_FIT_HOR) { - dfac= (sensor_x * 2.0f) / (fac*winx*lens); - } - else { - dfac= (sensor_y * 2.0f) / (fac*winy*lens); - } - - x1= - *clipsta * winx*dfac; - x2= -x1; - y1= - *clipsta * winy*dfac; - y2= -y1; - orth= 0; - } - /* cam view offset */ - if(cam) { - float dx= 0.5f*fac*rv3d->camdx*(x2-x1); - float dy= 0.5f*fac*rv3d->camdy*(y2-y1); - - /* shift offset */ - if(cam->type==CAM_ORTHO) { - dx += cam->shiftx * cam->ortho_scale; - dy += cam->shifty * cam->ortho_scale; - } - else { - dx += cam->shiftx * (cam->clipsta / cam->lens) * sensor; - dy += cam->shifty * (cam->clipsta / cam->lens) * sensor; - } + CameraParams params; - x1+= dx; - x2+= dx; - y1+= dy; - y2+= dy; - } - } - - if(pixsize) { - float viewfac; - - if(orth) { - viewfac= (winx >= winy)? winx: winy; - *pixsize= 1.0f/viewfac; - } - else { - float size= ((winx >= winy)? winx: winy); - - if(sensor_fit==CAMERA_SENSOR_FIT_HOR) - size= winx; - else if(sensor_fit==CAMERA_SENSOR_FIT_VERT) - size= winy; + camera_params_init(¶ms); + camera_params_from_view3d(¶ms, v3d, rv3d); + camera_params_compute(¶ms, winx, winy, 1.0f, 1.0f); - viewfac= (size*lens)/sensor; - *pixsize= *clipsta/viewfac; - } - } + *viewplane= params.viewplane; + *clipsta= params.clipsta; + *clipend= params.clipend; - viewplane->xmin= x1; - viewplane->ymin= y1; - viewplane->xmax= x2; - viewplane->ymax= y2; - - return orth; + return params.is_ortho; } void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) /* rect: for picking */ @@ -1190,7 +1040,7 @@ void setwinmatrixview3d(ARegion *ar, View3D *v3d, rctf *rect) /* rect: for pick float clipsta, clipend, x1, y1, x2, y2; int orth; - orth= ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL); + orth= ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend); rv3d->is_persp= !orth; // printf("%d %d %f %f %f %f %f %f\n", winx, winy, viewplane.xmin, viewplane.ymin, viewplane.xmax, viewplane.ymax, clipsta, clipend); diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 1e7a969caaa..77b41b507c6 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -39,34 +39,21 @@ #ifdef RNA_RUNTIME +#include "BKE_camera.h" #include "BKE_object.h" #include "BKE_depsgraph.h" -/* only for rad/deg conversion! can remove later */ -static float get_camera_sensor(Camera *cam) -{ - if(cam->sensor_fit==CAMERA_SENSOR_FIT_AUTO) { - return cam->sensor_x; - } - else if(cam->sensor_fit==CAMERA_SENSOR_FIT_HOR) { - return cam->sensor_x; - } - else { - return cam->sensor_y; - } -} - static float rna_Camera_angle_get(PointerRNA *ptr) { Camera *cam= ptr->id.data; - float sensor= get_camera_sensor(cam); + float sensor= camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); return focallength_to_fov(cam->lens, sensor); } static void rna_Camera_angle_set(PointerRNA *ptr, float value) { Camera *cam= ptr->id.data; - float sensor= get_camera_sensor(cam); + float sensor= camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y); cam->lens= fov_to_focallength(value, sensor); } -- cgit v1.2.3