Cycles: merge of changes from tomato branch.
[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         previous_need_motion = -1;
79 }
80
81 Camera::~Camera()
82 {
83 }
84
85 void Camera::update()
86 {
87         if(!need_update)
88                 return;
89         
90         /* ndc to raster */
91         Transform screentocamera;
92         Transform ndctoraster = transform_scale(width, height, 1.0f);
93
94         /* raster to screen */
95         Transform screentoraster = ndctoraster;
96         
97         screentoraster = ndctoraster *
98                 transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) *
99                 transform_translate(-left, -bottom, 0.0f);
100
101         Transform rastertoscreen = transform_inverse(screentoraster);
102
103         /* screen to camera */
104         if(type == CAMERA_PERSPECTIVE)
105                 screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip));
106         else if(type == CAMERA_ORTHOGRAPHIC)
107                 screentocamera = transform_inverse(transform_orthographic(nearclip, farclip));
108         else
109                 screentocamera = transform_identity();
110
111         rastertocamera = screentocamera * rastertoscreen;
112
113         cameratoworld = matrix;
114         screentoworld = cameratoworld * screentocamera;
115         rastertoworld = cameratoworld * rastertocamera;
116         ndctoworld = rastertoworld * ndctoraster;
117         worldtoraster = transform_inverse(rastertoworld);
118
119         /* differentials */
120         if(type == CAMERA_ORTHOGRAPHIC) {
121                 dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
122                 dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
123         }
124         else if(type == CAMERA_PERSPECTIVE) {
125                 dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
126                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
127                 dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
128                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
129         }
130         else {
131                 dx = make_float3(0, 0, 0);
132                 dy = make_float3(0, 0, 0);
133         }
134
135         dx = transform_direction(&cameratoworld, dx);
136         dy = transform_direction(&cameratoworld, dy);
137
138         need_update = false;
139         need_device_update = true;
140 }
141
142 void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
143 {
144         Scene::MotionType need_motion = scene->need_motion();
145
146         update();
147
148         if (previous_need_motion != need_motion) {
149                 /* scene's motion model could have been changed since previous device
150                  * camera update this could happen for example in case when one render
151                  * layer has got motion pass and another not */
152                 need_device_update = true;
153         }
154
155         if(!need_device_update)
156                 return;
157         
158         KernelCamera *kcam = &dscene->data.cam;
159
160         /* store matrices */
161         kcam->screentoworld = screentoworld;
162         kcam->rastertoworld = rastertoworld;
163         kcam->ndctoworld = ndctoworld;
164         kcam->rastertocamera = rastertocamera;
165         kcam->cameratoworld = cameratoworld;
166         kcam->worldtoscreen = transform_inverse(screentoworld);
167         kcam->worldtoraster = worldtoraster;
168         kcam->worldtondc = transform_inverse(ndctoworld);
169         kcam->worldtocamera = transform_inverse(cameratoworld);
170
171         /* camera motion */
172         kcam->have_motion = 0;
173
174         if(need_motion == Scene::MOTION_PASS) {
175                 if(type == CAMERA_PANORAMA) {
176                         if(use_motion) {
177                                 kcam->motion.pre = transform_inverse(motion.pre);
178                                 kcam->motion.post = transform_inverse(motion.post);
179                         }
180                         else {
181                                 kcam->motion.pre = kcam->worldtocamera;
182                                 kcam->motion.post = kcam->worldtocamera;
183                         }
184                 }
185                 else {
186                         if(use_motion) {
187                                 kcam->motion.pre = transform_inverse(motion.pre * rastertocamera);
188                                 kcam->motion.post = transform_inverse(motion.post * rastertocamera);
189                         }
190                         else {
191                                 kcam->motion.pre = worldtoraster;
192                                 kcam->motion.post = worldtoraster;
193                         }
194                 }
195         }
196         else if(need_motion == Scene::MOTION_BLUR) {
197                 /* todo: exact camera position will not be hit this way */
198                 if(use_motion) {
199                         transform_motion_decompose(&kcam->motion, &motion);
200                         kcam->have_motion = 1;
201                 }
202         }
203
204         /* depth of field */
205         kcam->aperturesize = aperturesize;
206         kcam->focaldistance = focaldistance;
207         kcam->blades = (blades < 3)? 0.0f: blades;
208         kcam->bladesrotation = bladesrotation;
209
210         /* motion blur */
211         kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: 0.0f;
212
213         /* type */
214         kcam->type = type;
215
216         /* panorama */
217         kcam->panorama_type = panorama_type;
218         kcam->fisheye_fov = fisheye_fov;
219         kcam->fisheye_lens = fisheye_lens;
220
221         /* sensor size */
222         kcam->sensorwidth = sensorwidth;
223         kcam->sensorheight = sensorheight;
224
225         /* render size */
226         kcam->width = width;
227         kcam->height = height;
228
229         /* store differentials */
230         kcam->dx = float3_to_float4(dx);
231         kcam->dy = float3_to_float4(dy);
232
233         /* clipping */
234         kcam->nearclip = nearclip;
235         kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
236
237         need_device_update = false;
238         previous_need_motion = need_motion;
239 }
240
241 void Camera::device_free(Device *device, DeviceScene *dscene)
242 {
243         /* nothing to free, only writing to constant memory */
244 }
245
246 bool Camera::modified(const Camera& cam)
247 {
248         return !((shuttertime== cam.shuttertime) &&
249                 (aperturesize == cam.aperturesize) &&
250                 (blades == cam.blades) &&
251                 (bladesrotation == cam.bladesrotation) &&
252                 (focaldistance == cam.focaldistance) &&
253                 (type == cam.type) &&
254                 (fov == cam.fov) &&
255                 (nearclip == cam.nearclip) &&
256                 (farclip == cam.farclip) &&
257                 (sensorwidth == cam.sensorwidth) &&
258                 (sensorheight == cam.sensorheight) &&
259                 // modified for progressive render
260                 // (width == cam.width) &&
261                 // (height == cam.height) &&
262                 (left == cam.left) &&
263                 (right == cam.right) &&
264                 (bottom == cam.bottom) &&
265                 (top == cam.top) &&
266                 (border_left == cam.border_left) &&
267                 (border_right == cam.border_right) &&
268                 (border_bottom == cam.border_bottom) &&
269                 (border_top == cam.border_top) &&
270                 (matrix == cam.matrix) &&
271                 (motion == cam.motion) &&
272                 (use_motion == cam.use_motion) &&
273                 (panorama_type == cam.panorama_type) &&
274                 (fisheye_fov == cam.fisheye_fov) &&
275                 (fisheye_lens == cam.fisheye_lens));
276 }
277
278 void Camera::tag_update()
279 {
280         need_update = true;
281 }
282
283 CCL_NAMESPACE_END
284