1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software Foundation,
14 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17 * All rights reserved.
18 */
19
20 /** \file
21 * \ingroup render
22 */
23
24 /* Global includes */
25
26 #include <math.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_ghash.h"
35 #include "BLI_math.h"
36 #include "BLI_utildefines.h"
37
38 #include "DNA_camera_types.h"
39
40 #include "BKE_camera.h"
41
42 /* this module */
43 #include "render_types.h"
44 #include "renderpipeline.h"
45
46 /* Own includes */
47 #include "initrender.h"
48
49 /* ****************** MASKS and LUTS **************** */
50
filt_quadratic(float x)51 static float filt_quadratic(float x)
52 {
53 if (x < 0.0f) {
54 x = -x;
55 }
56 if (x < 0.5f) {
57 return 0.75f - (x * x);
58 }
59 if (x < 1.5f) {
60 return 0.50f * (x - 1.5f) * (x - 1.5f);
61 }
62 return 0.0f;
63 }
64
filt_cubic(float x)65 static float filt_cubic(float x)
66 {
67 float x2 = x * x;
68
69 if (x < 0.0f) {
70 x = -x;
71 }
72
73 if (x < 1.0f) {
74 return 0.5f * x * x2 - x2 + 2.0f / 3.0f;
75 }
76 if (x < 2.0f) {
77 return (2.0f - x) * (2.0f - x) * (2.0f - x) / 6.0f;
78 }
79 return 0.0f;
80 }
81
filt_catrom(float x)82 static float filt_catrom(float x)
83 {
84 float x2 = x * x;
85
86 if (x < 0.0f) {
87 x = -x;
88 }
89 if (x < 1.0f) {
90 return 1.5f * x2 * x - 2.5f * x2 + 1.0f;
91 }
92 if (x < 2.0f) {
93 return -0.5f * x2 * x + 2.5f * x2 - 4.0f * x + 2.0f;
94 }
95 return 0.0f;
96 }
97
filt_mitchell(float x)98 static float filt_mitchell(float x) /* Mitchell & Netravali's two-param cubic */
99 {
100 float b = 1.0f / 3.0f, c = 1.0f / 3.0f;
101 float p0 = (6.0f - 2.0f * b) / 6.0f;
102 float p2 = (-18.0f + 12.0f * b + 6.0f * c) / 6.0f;
103 float p3 = (12.0f - 9.0f * b - 6.0f * c) / 6.0f;
104 float q0 = (8.0f * b + 24.0f * c) / 6.0f;
105 float q1 = (-12.0f * b - 48.0f * c) / 6.0f;
106 float q2 = (6.0f * b + 30.0f * c) / 6.0f;
107 float q3 = (-b - 6.0f * c) / 6.0f;
108
109 if (x < -2.0f) {
110 return 0.0f;
111 }
112 if (x < -1.0f) {
113 return (q0 - x * (q1 - x * (q2 - x * q3)));
114 }
115 if (x < 0.0f) {
116 return (p0 + x * x * (p2 - x * p3));
117 }
118 if (x < 1.0f) {
119 return (p0 + x * x * (p2 + x * p3));
120 }
121 if (x < 2.0f) {
122 return (q0 + x * (q1 + x * (q2 + x * q3)));
123 }
124 return 0.0f;
125 }
126
127 /* x ranges from -1 to 1 */
RE_filter_value(int type,float x)128 float RE_filter_value(int type, float x)
129 {
130 float gaussfac = 1.6f;
131
132 x = fabsf(x);
133
134 switch (type) {
135 case R_FILTER_BOX:
136 if (x > 1.0f) {
137 return 0.0f;
138 }
139 return 1.0f;
140
141 case R_FILTER_TENT:
142 if (x > 1.0f) {
143 return 0.0f;
144 }
145 return 1.0f - x;
146
147 case R_FILTER_GAUSS: {
148 const float two_gaussfac2 = 2.0f * gaussfac * gaussfac;
149 x *= 3.0f * gaussfac;
150 return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x * x / two_gaussfac2);
151 }
152
153 case R_FILTER_MITCH:
154 return filt_mitchell(x * gaussfac);
155
156 case R_FILTER_QUAD:
157 return filt_quadratic(x * gaussfac);
158
159 case R_FILTER_CUBIC:
160 return filt_cubic(x * gaussfac);
161
162 case R_FILTER_CATROM:
163 return filt_catrom(x * gaussfac);
164 }
165 return 0.0f;
166 }
167
168 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
RE_GetCamera(Render * re)169 struct Object *RE_GetCamera(Render *re)
170 {
171 Object *camera = re->camera_override ? re->camera_override : re->scene->camera;
172 return BKE_camera_multiview_render(re->scene, camera, re->viewname);
173 }
174
re_camera_params_get(Render * re,CameraParams * params)175 static void re_camera_params_get(Render *re, CameraParams *params)
176 {
177 copy_m4_m4(re->winmat, params->winmat);
178
179 re->clip_start = params->clip_start;
180 re->clip_end = params->clip_end;
181
182 re->viewplane = params->viewplane;
183 }
184
RE_SetOverrideCamera(Render * re,Object * cam_ob)185 void RE_SetOverrideCamera(Render *re, Object *cam_ob)
186 {
187 re->camera_override = cam_ob;
188 }
189
re_camera_params_stereo3d(Render * re,CameraParams * params,Object * cam_ob)190 static void re_camera_params_stereo3d(Render *re, CameraParams *params, Object *cam_ob)
191 {
192 BKE_camera_multiview_params(&re->r, params, cam_ob, re->viewname);
193 }
194
195 /* call this after InitState() */
196 /* per render, there's one persistent viewplane. Parts will set their own viewplanes */
RE_SetCamera(Render * re,Object * cam_ob)197 void RE_SetCamera(Render *re, Object *cam_ob)
198 {
199 CameraParams params;
200
201 /* setup parameters */
202 BKE_camera_params_init(¶ms);
203 BKE_camera_params_from_object(¶ms, cam_ob);
204 re_camera_params_stereo3d(re, ¶ms, cam_ob);
205
206 /* compute matrix, viewplane, .. */
207 BKE_camera_params_compute_viewplane(¶ms, re->winx, re->winy, re->r.xasp, re->r.yasp);
208 BKE_camera_params_compute_matrix(¶ms);
209
210 /* extract results */
211 re_camera_params_get(re, ¶ms);
212 }
213
RE_GetCameraWindow(struct Render * re,struct Object * camera,float r_winmat[4][4])214 void RE_GetCameraWindow(struct Render *re, struct Object *camera, float r_winmat[4][4])
215 {
216 RE_SetCamera(re, camera);
217 copy_m4_m4(r_winmat, re->winmat);
218 }
219
220 /* Must be called after RE_GetCameraWindow(), does not change re->winmat. */
RE_GetCameraWindowWithOverscan(struct Render * re,float overscan,float r_winmat[4][4])221 void RE_GetCameraWindowWithOverscan(struct Render *re, float overscan, float r_winmat[4][4])
222 {
223 CameraParams params;
224 params.is_ortho = re->winmat[3][3] != 0.0f;
225 params.clip_start = re->clip_start;
226 params.clip_end = re->clip_end;
227 params.viewplane = re->viewplane;
228
229 overscan *= max_ff(BLI_rctf_size_x(¶ms.viewplane), BLI_rctf_size_y(¶ms.viewplane));
230
231 params.viewplane.xmin -= overscan;
232 params.viewplane.xmax += overscan;
233 params.viewplane.ymin -= overscan;
234 params.viewplane.ymax += overscan;
235 BKE_camera_params_compute_matrix(¶ms);
236 copy_m4_m4(r_winmat, params.winmat);
237 }
238
RE_GetCameraModelMatrix(Render * re,struct Object * camera,float r_modelmat[4][4])239 void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_modelmat[4][4])
240 {
241 BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_modelmat);
242 }
243
244 /* ~~~~~~~~~~~~~~~~ part (tile) calculus ~~~~~~~~~~~~~~~~~~~~~~ */
245
RE_parts_free(Render * re)246 void RE_parts_free(Render *re)
247 {
248 if (re->parts) {
249 BLI_ghash_free(re->parts, NULL, MEM_freeN);
250 re->parts = NULL;
251 }
252 }
253
RE_parts_clamp(Render * re)254 void RE_parts_clamp(Render *re)
255 {
256 /* part size */
257 re->partx = max_ii(1, min_ii(re->r.tilex, re->rectx));
258 re->party = max_ii(1, min_ii(re->r.tiley, re->recty));
259 }
260
RE_parts_init(Render * re)261 void RE_parts_init(Render *re)
262 {
263 int nr, xd, yd, partx, party, xparts, yparts;
264 int xminb, xmaxb, yminb, ymaxb;
265
266 RE_parts_free(re);
267
268 re->parts = BLI_ghash_new(
269 BLI_ghashutil_inthash_v4_p, BLI_ghashutil_inthash_v4_cmp, "render parts");
270
271 /* this is render info for caller, is not reset when parts are freed! */
272 re->i.totpart = 0;
273
274 /* just for readable code.. */
275 xminb = re->disprect.xmin;
276 yminb = re->disprect.ymin;
277 xmaxb = re->disprect.xmax;
278 ymaxb = re->disprect.ymax;
279
280 RE_parts_clamp(re);
281
282 partx = re->partx;
283 party = re->party;
284 /* part count */
285 xparts = (re->rectx + partx - 1) / partx;
286 yparts = (re->recty + party - 1) / party;
287
288 for (nr = 0; nr < xparts * yparts; nr++) {
289 rcti disprect;
290 int rectx, recty;
291
292 xd = (nr % xparts);
293 yd = (nr - xd) / xparts;
294
295 disprect.xmin = xminb + xd * partx;
296 disprect.ymin = yminb + yd * party;
297
298 /* ensure we cover the entire picture, so last parts go to end */
299 if (xd < xparts - 1) {
300 disprect.xmax = disprect.xmin + partx;
301 if (disprect.xmax > xmaxb) {
302 disprect.xmax = xmaxb;
303 }
304 }
305 else {
306 disprect.xmax = xmaxb;
307 }
308
309 if (yd < yparts - 1) {
310 disprect.ymax = disprect.ymin + party;
311 if (disprect.ymax > ymaxb) {
312 disprect.ymax = ymaxb;
313 }
314 }
315 else {
316 disprect.ymax = ymaxb;
317 }
318
319 rectx = BLI_rcti_size_x(&disprect);
320 recty = BLI_rcti_size_y(&disprect);
321
322 /* so, now can we add this part? */
323 if (rectx > 0 && recty > 0) {
324 RenderPart *pa = MEM_callocN(sizeof(RenderPart), "new part");
325
326 pa->disprect = disprect;
327 pa->rectx = rectx;
328 pa->recty = recty;
329
330 BLI_ghash_insert(re->parts, &pa->disprect, pa);
331 re->i.totpart++;
332 }
333 }
334 }
335