add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[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 "device.h"
23
24 #include "util_vector.h"
25
26 CCL_NAMESPACE_BEGIN
27
28 Camera::Camera()
29 {
30         shuttertime = 1.0f;
31
32         aperturesize = 0.0f;
33         focaldistance = 10.0f;
34         blades = 0;
35         bladesrotation = 0.0f;
36
37         matrix = transform_identity();
38
39         motion.pre = transform_identity();
40         motion.post = transform_identity();
41         use_motion = false;
42
43         type = CAMERA_PERSPECTIVE;
44         panorama_type = PANORAMA_EQUIRECTANGULAR;
45         fisheye_fov = M_PI_F;
46         fisheye_lens = 10.5f;
47         fov = M_PI_4_F;
48
49         sensorwidth = 0.036;
50         sensorheight = 0.024;
51
52         nearclip = 1e-5f;
53         farclip = 1e5f;
54
55         width = 1024;
56         height = 512;
57
58         viewplane.left = -((float)width/(float)height);
59         viewplane.right = (float)width/(float)height;
60         viewplane.bottom = -1.0f;
61         viewplane.top = 1.0f;
62
63         screentoworld = transform_identity();
64         rastertoworld = transform_identity();
65         ndctoworld = transform_identity();
66         rastertocamera = transform_identity();
67         cameratoworld = transform_identity();
68         worldtoraster = transform_identity();
69
70         dx = make_float3(0.0f, 0.0f, 0.0f);
71         dy = make_float3(0.0f, 0.0f, 0.0f);
72
73         need_update = true;
74         need_device_update = true;
75         previous_need_motion = -1;
76 }
77
78 Camera::~Camera()
79 {
80 }
81
82 void Camera::update()
83 {
84         if(!need_update)
85                 return;
86         
87         /* ndc to raster */
88         Transform screentocamera;
89         Transform ndctoraster = transform_scale(width, height, 1.0f);
90
91         /* raster to screen */
92         Transform screentondc = 
93                 transform_scale(1.0f/(viewplane.right - viewplane.left),
94                                 1.0f/(viewplane.top - viewplane.bottom), 1.0f) *
95                 transform_translate(-viewplane.left, -viewplane.bottom, 0.0f);
96
97         Transform screentoraster = ndctoraster * screentondc;
98         Transform rastertoscreen = transform_inverse(screentoraster);
99
100         /* screen to camera */
101         if(type == CAMERA_PERSPECTIVE)
102                 screentocamera = transform_inverse(transform_perspective(fov, nearclip, farclip));
103         else if(type == CAMERA_ORTHOGRAPHIC)
104                 screentocamera = transform_inverse(transform_orthographic(nearclip, farclip));
105         else
106                 screentocamera = transform_identity();
107         
108         Transform cameratoscreen = transform_inverse(screentocamera);
109
110         rastertocamera = screentocamera * rastertoscreen;
111         cameratoraster = screentoraster * cameratoscreen;
112
113         cameratoworld = matrix;
114         screentoworld = cameratoworld * screentocamera;
115         rastertoworld = cameratoworld * rastertocamera;
116         ndctoworld = rastertoworld * ndctoraster;
117
118         /* note we recompose matrices instead of taking inverses of the above, this
119          * is needed to avoid inverting near degenerate matrices that happen due to
120          * precision issues with large scenes */
121         worldtocamera = transform_inverse(matrix);
122         worldtoscreen = cameratoscreen * worldtocamera;
123         worldtondc = screentondc * worldtoscreen;
124         worldtoraster = ndctoraster * worldtondc;
125
126         /* differentials */
127         if(type == CAMERA_ORTHOGRAPHIC) {
128                 dx = transform_direction(&rastertocamera, make_float3(1, 0, 0));
129                 dy = transform_direction(&rastertocamera, make_float3(0, 1, 0));
130         }
131         else if(type == CAMERA_PERSPECTIVE) {
132                 dx = transform_perspective(&rastertocamera, make_float3(1, 0, 0)) -
133                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
134                 dy = transform_perspective(&rastertocamera, make_float3(0, 1, 0)) -
135                      transform_perspective(&rastertocamera, make_float3(0, 0, 0));
136         }
137         else {
138                 dx = make_float3(0, 0, 0);
139                 dy = make_float3(0, 0, 0);
140         }
141
142         dx = transform_direction(&cameratoworld, dx);
143         dy = transform_direction(&cameratoworld, dy);
144
145         need_update = false;
146         need_device_update = true;
147 }
148
149 void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
150 {
151         Scene::MotionType need_motion = scene->need_motion(device->info.advanced_shading);
152
153         update();
154
155         if (previous_need_motion != need_motion) {
156                 /* scene's motion model could have been changed since previous device
157                  * camera update this could happen for example in case when one render
158                  * layer has got motion pass and another not */
159                 need_device_update = true;
160         }
161
162         if(!need_device_update)
163                 return;
164         
165         KernelCamera *kcam = &dscene->data.cam;
166
167         /* store matrices */
168         kcam->screentoworld = screentoworld;
169         kcam->rastertoworld = rastertoworld;
170         kcam->rastertocamera = rastertocamera;
171         kcam->cameratoworld = cameratoworld;
172         kcam->worldtocamera = worldtocamera;
173         kcam->worldtoscreen = worldtoscreen;
174         kcam->worldtoraster = worldtoraster;
175         kcam->worldtondc = worldtondc;
176
177         /* camera motion */
178         kcam->have_motion = 0;
179
180         if(need_motion == Scene::MOTION_PASS) {
181                 if(type == CAMERA_PANORAMA) {
182                         if(use_motion) {
183                                 kcam->motion.pre = transform_inverse(motion.pre);
184                                 kcam->motion.post = transform_inverse(motion.post);
185                         }
186                         else {
187                                 kcam->motion.pre = kcam->worldtocamera;
188                                 kcam->motion.post = kcam->worldtocamera;
189                         }
190                 }
191                 else {
192                         if(use_motion) {
193                                 kcam->motion.pre = cameratoraster * transform_inverse(motion.pre);
194                                 kcam->motion.post = cameratoraster * transform_inverse(motion.post);
195                         }
196                         else {
197                                 kcam->motion.pre = worldtoraster;
198                                 kcam->motion.post = worldtoraster;
199                         }
200                 }
201         }
202 #ifdef __CAMERA_MOTION__
203         else if(need_motion == Scene::MOTION_BLUR) {
204                 if(use_motion) {
205                         transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix);
206                         kcam->have_motion = 1;
207                 }
208         }
209 #endif
210
211         /* depth of field */
212         kcam->aperturesize = aperturesize;
213         kcam->focaldistance = focaldistance;
214         kcam->blades = (blades < 3)? 0.0f: blades;
215         kcam->bladesrotation = bladesrotation;
216
217         /* motion blur */
218 #ifdef __CAMERA_MOTION__
219         kcam->shuttertime = (need_motion == Scene::MOTION_BLUR) ? shuttertime: -1.0f;
220 #else
221         kcam->shuttertime = -1.0f;
222 #endif
223
224         /* type */
225         kcam->type = type;
226
227         /* panorama */
228         kcam->panorama_type = panorama_type;
229         kcam->fisheye_fov = fisheye_fov;
230         kcam->fisheye_lens = fisheye_lens;
231
232         /* sensor size */
233         kcam->sensorwidth = sensorwidth;
234         kcam->sensorheight = sensorheight;
235
236         /* render size */
237         kcam->width = width;
238         kcam->height = height;
239         kcam->resolution = resolution;
240
241         /* store differentials */
242         kcam->dx = float3_to_float4(dx);
243         kcam->dy = float3_to_float4(dy);
244
245         /* clipping */
246         kcam->nearclip = nearclip;
247         kcam->cliplength = (farclip == FLT_MAX)? FLT_MAX: farclip - nearclip;
248
249         need_device_update = false;
250         previous_need_motion = need_motion;
251 }
252
253 void Camera::device_free(Device *device, DeviceScene *dscene)
254 {
255         /* nothing to free, only writing to constant memory */
256 }
257
258 bool Camera::modified(const Camera& cam)
259 {
260         return !((shuttertime == cam.shuttertime) &&
261                 (aperturesize == cam.aperturesize) &&
262                 (blades == cam.blades) &&
263                 (bladesrotation == cam.bladesrotation) &&
264                 (focaldistance == cam.focaldistance) &&
265                 (type == cam.type) &&
266                 (fov == cam.fov) &&
267                 (nearclip == cam.nearclip) &&
268                 (farclip == cam.farclip) &&
269                 (sensorwidth == cam.sensorwidth) &&
270                 (sensorheight == cam.sensorheight) &&
271                 // modified for progressive render
272                 // (width == cam.width) &&
273                 // (height == cam.height) &&
274                 (viewplane == cam.viewplane) &&
275                 (border == cam.border) &&
276                 (matrix == cam.matrix) &&
277                 (panorama_type == cam.panorama_type) &&
278                 (fisheye_fov == cam.fisheye_fov) &&
279                 (fisheye_lens == cam.fisheye_lens));
280 }
281
282 bool Camera::motion_modified(const Camera& cam)
283 {
284         return !((motion == cam.motion) &&
285                 (use_motion == cam.use_motion));
286 }
287
288 void Camera::tag_update()
289 {
290         need_update = true;
291 }
292
293 CCL_NAMESPACE_END
294