Blender V2.61 - r43446

blender_camera.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "camera.h"
00020 #include "scene.h"
00021 
00022 #include "blender_sync.h"
00023 #include "blender_util.h"
00024 
00025 CCL_NAMESPACE_BEGIN
00026 
00027 /* Blender Camera Intermediate: we first convert both the offline and 3d view
00028  * render camera to this, and from there convert to our native camera format. */
00029 
00030 struct BlenderCamera {
00031     float nearclip;
00032     float farclip;
00033 
00034     bool ortho;
00035     float ortho_scale;
00036 
00037     float lens;
00038 
00039     float aperturesize;
00040     uint apertureblades;
00041     float aperturerotation;
00042     float focaldistance;
00043 
00044     float2 shift;
00045     float2 offset;
00046     float zoom;
00047 
00048     float2 pixelaspect;
00049 
00050     enum { AUTO, HORIZONTAL, VERTICAL } sensor_fit;
00051     float sensor_width;
00052     float sensor_height;
00053 
00054     Transform matrix;
00055 };
00056 
00057 static void blender_camera_init(BlenderCamera *bcam)
00058 {
00059     memset(bcam, 0, sizeof(BlenderCamera));
00060 
00061     bcam->zoom = 1.0f;
00062     bcam->pixelaspect = make_float2(1.0f, 1.0f);
00063     bcam->sensor_width = 32.0f;
00064     bcam->sensor_height = 18.0f;
00065     bcam->sensor_fit = BlenderCamera::AUTO;
00066 }
00067 
00068 static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera)
00069 {
00070     BL::Object b_dof_object = b_camera.dof_object();
00071 
00072     if(!b_dof_object)
00073         return b_camera.dof_distance();
00074     
00075     /* for dof object, return distance along camera Z direction */
00076     Transform obmat = transform_clear_scale(get_transform(b_ob.matrix_world()));
00077     Transform dofmat = get_transform(b_dof_object.matrix_world());
00078     Transform mat = transform_inverse(obmat) * dofmat;
00079 
00080     return fabsf(transform_get_column(&mat, 3).z);
00081 }
00082 
00083 static void blender_camera_from_object(BlenderCamera *bcam, BL::Object b_ob)
00084 {
00085     BL::ID b_ob_data = b_ob.data();
00086 
00087     if(b_ob_data.is_a(&RNA_Camera)) {
00088         BL::Camera b_camera(b_ob_data);
00089         PointerRNA ccamera = RNA_pointer_get(&b_camera.ptr, "cycles");
00090 
00091         bcam->nearclip = b_camera.clip_start();
00092         bcam->farclip = b_camera.clip_end();
00093 
00094         bcam->ortho = (b_camera.type() == BL::Camera::type_ORTHO);
00095         bcam->ortho_scale = b_camera.ortho_scale();
00096 
00097         bcam->lens = b_camera.lens();
00098         bcam->aperturesize = RNA_float_get(&ccamera, "aperture_size");
00099         bcam->apertureblades = RNA_int_get(&ccamera, "aperture_blades");
00100         bcam->aperturerotation = RNA_float_get(&ccamera, "aperture_rotation");
00101         bcam->focaldistance = blender_camera_focal_distance(b_ob, b_camera);
00102 
00103         bcam->shift.x = b_camera.shift_x();
00104         bcam->shift.y = b_camera.shift_y();
00105 
00106         bcam->sensor_width = b_camera.sensor_width();
00107         bcam->sensor_height = b_camera.sensor_height();
00108 
00109         if(b_camera.sensor_fit() == BL::Camera::sensor_fit_AUTO)
00110             bcam->sensor_fit = BlenderCamera::AUTO;
00111         else if(b_camera.sensor_fit() == BL::Camera::sensor_fit_HORIZONTAL)
00112             bcam->sensor_fit = BlenderCamera::HORIZONTAL;
00113         else
00114             bcam->sensor_fit = BlenderCamera::VERTICAL;
00115     }
00116     else {
00117         /* from lamp not implemented yet */
00118     }
00119 }
00120 
00121 static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int height)
00122 {
00123     /* copy camera to compare later */
00124     Camera prevcam = *cam;
00125 
00126     /* dimensions */
00127     float xratio = width*bcam->pixelaspect.x;
00128     float yratio = height*bcam->pixelaspect.y;
00129 
00130     /* compute x/y aspect and ratio */
00131     float aspectratio, xaspect, yaspect;
00132 
00133     /* sensor fitting */
00134     bool horizontal_fit;
00135     float sensor_size;
00136 
00137     if(bcam->sensor_fit == BlenderCamera::AUTO) {
00138         horizontal_fit = (xratio > yratio);
00139         sensor_size = bcam->sensor_width;
00140     }
00141     else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
00142         horizontal_fit = true;
00143         sensor_size = bcam->sensor_width;
00144     }
00145     else {
00146         horizontal_fit = false;
00147         sensor_size = bcam->sensor_height;
00148     }
00149 
00150     if(horizontal_fit) {
00151         aspectratio= xratio/yratio;
00152         xaspect= aspectratio;
00153         yaspect= 1.0f;
00154     }
00155     else {
00156         aspectratio= yratio/xratio;
00157         xaspect= 1.0f;
00158         yaspect= aspectratio;
00159     }
00160 
00161     /* modify aspect for orthographic scale */
00162     if(bcam->ortho) {
00163         xaspect = xaspect*bcam->ortho_scale/(aspectratio*2.0f);
00164         yaspect = yaspect*bcam->ortho_scale/(aspectratio*2.0f);
00165         aspectratio = bcam->ortho_scale/2.0f;
00166     }
00167 
00168     /* set viewplane */
00169     cam->left = -xaspect;
00170     cam->right = xaspect;
00171     cam->bottom = -yaspect;
00172     cam->top = yaspect;
00173 
00174     /* zoom for 3d camera view */
00175     cam->left *= bcam->zoom;
00176     cam->right *= bcam->zoom;
00177     cam->bottom *= bcam->zoom;
00178     cam->top *= bcam->zoom;
00179 
00180     /* modify viewplane with camera shift and 3d camera view offset */
00181     float dx = 2.0f*(aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f);
00182     float dy = 2.0f*(aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f);
00183 
00184     cam->left += dx;
00185     cam->right += dx;
00186     cam->bottom += dy;
00187     cam->top += dy;
00188 
00189     /* clipping distances */
00190     cam->nearclip = bcam->nearclip;
00191     cam->farclip = bcam->farclip;
00192 
00193     /* orthographic */
00194     cam->ortho = bcam->ortho;
00195 
00196     /* perspective */
00197     cam->fov = 2.0f*atan((0.5f*sensor_size)/bcam->lens/aspectratio);
00198     cam->focaldistance = bcam->focaldistance;
00199     cam->aperturesize = bcam->aperturesize;
00200     cam->blades = bcam->apertureblades;
00201     cam->bladesrotation = bcam->aperturerotation;
00202 
00203     /* transform, note the blender camera points along the negative z-axis */
00204     cam->matrix = bcam->matrix * transform_scale(1.0f, 1.0f, -1.0f);
00205     cam->matrix = transform_clear_scale(cam->matrix);
00206 
00207     /* set update flag */
00208     if(cam->modified(prevcam))
00209         cam->tag_update();
00210 }
00211 
00212 /* Sync Render Camera */
00213 
00214 void BlenderSync::sync_camera(int width, int height)
00215 {
00216     BlenderCamera bcam;
00217     blender_camera_init(&bcam);
00218 
00219     /* pixel aspect */
00220     BL::RenderSettings r = b_scene.render();
00221 
00222     bcam.pixelaspect.x = r.pixel_aspect_x();
00223     bcam.pixelaspect.y = r.pixel_aspect_y();
00224 
00225     /* camera object */
00226     BL::Object b_ob = b_scene.camera();
00227 
00228     if(b_ob) {
00229         blender_camera_from_object(&bcam, b_ob);
00230         bcam.matrix = get_transform(b_ob.matrix_world());
00231     }
00232 
00233     /* sync */
00234     Camera *cam = scene->camera;
00235     blender_camera_sync(cam, &bcam, width, height);
00236 }
00237 
00238 /* Sync 3D View Camera */
00239 
00240 void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height)
00241 {
00242     BlenderCamera bcam;
00243     blender_camera_init(&bcam);
00244 
00245     /* 3d view parameters */
00246     bcam.nearclip = b_v3d.clip_start();
00247     bcam.farclip = b_v3d.clip_end();
00248     bcam.lens = b_v3d.lens();
00249 
00250     if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_CAMERA) {
00251         /* camera view */
00252         BL::Object b_ob = b_scene.camera();
00253 
00254         if(b_ob) {
00255             blender_camera_from_object(&bcam, b_ob);
00256 
00257             /* magic zoom formula */
00258             bcam.zoom = (float)b_rv3d.view_camera_zoom();
00259             bcam.zoom = (1.41421f + bcam.zoom/50.0f);
00260             bcam.zoom *= bcam.zoom;
00261             bcam.zoom = 2.0f/bcam.zoom;
00262 
00263             /* offset */
00264             bcam.offset = get_float2(b_rv3d.view_camera_offset());
00265         }
00266     }
00267     else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) {
00268         /* orthographic view */
00269         bcam.farclip *= 0.5;
00270         bcam.nearclip = -bcam.farclip;
00271 
00272         bcam.ortho = true;
00273         bcam.ortho_scale = b_rv3d.view_distance();
00274     }
00275 
00276     bcam.zoom *= 2.0f;
00277 
00278     /* 3d view transform */
00279     bcam.matrix = transform_inverse(get_transform(b_rv3d.view_matrix()));
00280 
00281     /* sync */
00282     blender_camera_sync(scene->camera, &bcam, width, height);
00283 }
00284 
00285 BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::RegionView3D b_rv3d, int width, int height)
00286 {
00287     BufferParams params;
00288 
00289     params.full_width = width;
00290     params.full_height = height;
00291 
00292     /* border render */
00293     BL::RenderSettings r = b_scene.render();
00294 
00295     if(!b_rv3d && r.use_border()) {
00296         params.full_x = r.border_min_x()*width;
00297         params.full_y = r.border_min_y()*height;
00298         params.width = (int)(r.border_max_x()*width) - params.full_x;
00299         params.height = (int)(r.border_max_y()*height) - params.full_y;
00300     }
00301     else {
00302         params.width = width;
00303         params.height = height;
00304     }
00305 
00306     return params;
00307 }
00308 
00309 CCL_NAMESPACE_END
00310