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