55a0f23f8d0d866883fccedef09c884eaf5c9be7
[blender-staging.git] / intern / cycles / render / camera.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "camera.h"
20 #include "scene.h"
21
22 #include "util_vector.h"
23
24 CCL_NAMESPACE_BEGIN
25
26 Camera::Camera()
27 {
28         shuttertime = 1.0f;
29
30         aperturesize = 0.0f;
31         focaldistance = 10.0f;
32         blades = 0;
33         bladesrotation = 0.0f;
34
35         matrix = transform_identity();
36
37         motion.pre = transform_identity();
38         motion.post = transform_identity();
39         use_motion = false;
40
41         type = CAMERA_PERSPECTIVE;
42         panorama_type = PANORAMA_EQUIRECTANGULAR;
43         fisheye_fov = M_PI_F;
44         fisheye_lens = 10.5f;
45         fov = M_PI_F/4.0f;
46
47         sensorwidth = 0.036;
48         sensorheight = 0.024;
49
50         nearclip = 1e-5f;
51         farclip = 1e5f;
52
53         width = 1024;
54         height = 512;
55
56         left = -((float)width/(float)height);
57         right = (float)width/(float)height;
58         bottom = -1.0f;
59         top = 1.0f;
60
61         border_left = 0.0f;
62         border_right = 1.0f;
63         border_bottom = 0.0f;
64         border_top = 1.0f;
65
66         screentoworld = transform_identity();
67         rastertoworld = transform_identity();
68         ndctoworld = transform_identity();
69         rastertocamera = transform_identity();
70         cameratoworld = transform_identity();
71         worldtoraster = transform_identity();
72
73         dx = make_float3(0.0f, 0.0f, 0.0f);
74         dy = make_float3(0.0f, 0.0f, 0.0f);
75
76         need_update = true;
77         need_device_update = true;
78 }
79
80 Camera::~Camera()
81 {
82 }
83
84 void Camera::update()
85 {
86         if(!need_update)
87                 return;
88         
89         /* ndc to raster */
90         Transform screentocamera;
91         Transform ndctoraster = transform_scale(width, height, 1.0f);
92
93         /* raster to screen */
94         Transform screentoraster = ndctoraster;
95         
96         screentoraster = ndctoraster *
97                 transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) *
98                 transform_translate(-left, -bottom, 0.0f);
99
100         Transform rastertoscreen = transform_inverse(screentoraster);
101
102         /* screen to camera */
103         if(type == CAMERA_PERSPECTIVE)
104                 screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip));
105         else if(type == CAMERA_ORTHOGRAPHIC)
106                 screentocamera = transform_inverse(transform_orthographic(nearclip, farclip));
107         else
108                 screentocamera = transform_identity();
109
110         rastertocamera = screentocamera * rastertoscreen;
111
112         cameratoworld = matrix;
113         screentoworld = cameratoworld * screentocamera;
114         rastertoworld = cameratoworld * rastertocamera;
115         ndctoworld = rastertoworld * ndctoraster;
116         worldtoraster = transform_inverse(rastertoworld);
117
118         /* differentials */
119         if(type == CAMERA_ORTHOGRAPHIC) {
120                 dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
121                 dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
122         }
123         else if(type == CAMERA_PERSPECTIVE) {
124                 dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
125                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
126                 dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
127                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
128         }
129         else {
130                 dx = make_float3(0, 0, 0);
131                 dy = make_float3(0, 0, 0);
132         }
133
134         dx = transform_direction(&cameratoworld, dx);
135         dy = transform_direction(&cameratoworld, dy);
136
137         need_update = false;
138         need_device_update = true;
139 }
140
141 void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
142 {
143         update();
144
145         if(!need_device_update)
146                 return;
147         
148         KernelCamera *kcam = &dscene->data.cam;
149
150         /* store matrices */
151         kcam->screentoworld = screentoworld;
152         kcam->rastertoworld = rastertoworld;
153         kcam->ndctoworld = ndctoworld;
154         kcam->rastertocamera = rastertocamera;
155         kcam->cameratoworld = cameratoworld;
156         kcam->worldtoscreen = transform_inverse(screentoworld);
157         kcam->worldtoraster = worldtoraster;
158         kcam->worldtondc = transform_inverse(ndctoworld);
159         kcam->worldtocamera = transform_inverse(cameratoworld);
160
161         /* camera motion */
162         Scene::MotionType need_motion = scene->need_motion();
163         kcam->have_motion = 0;
164
165         if(need_motion == Scene::MOTION_PASS) {
166                 if(type == CAMERA_PANORAMA) {
167                         if(use_motion) {
168                                 kcam->motion.pre = transform_inverse(motion.pre);
169                                 kcam->motion.post = transform_inverse(motion.post);
170                         }
171                         else {
172                                 kcam->motion.pre = kcam->worldtocamera;
173                                 kcam->motion.post = kcam->worldtocamera;
174                         }
175                 }
176                 else {
177                         if(use_motion) {
178                                 kcam->motion.pre = transform_inverse(motion.pre * rastertocamera);
179                                 kcam->motion.post = transform_inverse(motion.post * rastertocamera);
180                         }
181                         else {
182                                 kcam->motion.pre = worldtoraster;
183                                 kcam->motion.post = worldtoraster;
184                         }
185                 }
186         }
187         else if(need_motion == Scene::MOTION_BLUR) {
188                 /* todo: exact camera position will not be hit this way */
189                 if(use_motion) {
190                         transform_motion_decompose(&kcam->motion, &motion);
191                         kcam->have_motion = 1;
192                 }
193         }
194
195         /* depth of field */
196         kcam->aperturesize = aperturesize;
197         kcam->focaldistance = focaldistance;
198         kcam->blades = (blades < 3)? 0.0f: blades;
199         kcam->bladesrotation = bladesrotation;
200
201         /* motion blur */
202         kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f;
203
204         /* type */
205         kcam->type = type;
206
207         /* panorama */
208         kcam->panorama_type = panorama_type;
209         kcam->fisheye_fov = fisheye_fov;
210         kcam->fisheye_lens = fisheye_lens;
211
212         /* sensor size */
213         kcam->sensorwidth = sensorwidth;
214         kcam->sensorheight = sensorheight;
215
216         /* render size */
217         kcam->width = width;
218         kcam->height = height;
219
220         /* store differentials */
221         kcam->dx = float3_to_float4(dx);
222         kcam->dy = float3_to_float4(dy);
223
224         /* clipping */
225         kcam->nearclip = nearclip;
226         kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
227
228         need_device_update = false;
229 }
230
231 void Camera::device_free(Device *device, DeviceScene *dscene)
232 {
233         /* nothing to free, only writing to constant memory */
234 }
235
236 bool Camera::modified(const Camera& cam)
237 {
238         return !((shuttertime== cam.shuttertime) &&
239                 (aperturesize == cam.aperturesize) &&
240                 (blades == cam.blades) &&
241                 (bladesrotation == cam.bladesrotation) &&
242                 (focaldistance == cam.focaldistance) &&
243                 (type == cam.type) &&
244                 (fov == cam.fov) &&
245                 (nearclip == cam.nearclip) &&
246                 (farclip == cam.farclip) &&
247                 (sensorwidth == cam.sensorwidth) &&
248                 (sensorheight == cam.sensorheight) &&
249                 // modified for progressive render
250                 // (width == cam.width) &&
251                 // (height == cam.height) &&
252                 (left == cam.left) &&
253                 (right == cam.right) &&
254                 (bottom == cam.bottom) &&
255                 (top == cam.top) &&
256                 (border_left == cam.border_left) &&
257                 (border_right == cam.border_right) &&
258                 (border_bottom == cam.border_bottom) &&
259                 (border_top == cam.border_top) &&
260                 (matrix == cam.matrix) &&
261                 (motion == cam.motion) &&
262                 (use_motion == cam.use_motion) &&
263                 (panorama_type == cam.panorama_type) &&
264                 (fisheye_fov == cam.fisheye_fov) &&
265                 (fisheye_lens == cam.fisheye_lens));
266 }
267
268 void Camera::tag_update()
269 {
270         need_update = true;
271 }
272
273 CCL_NAMESPACE_END
274