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(&params);
203   BKE_camera_params_from_object(&params, cam_ob);
204   re_camera_params_stereo3d(re, &params, cam_ob);
205 
206   /* compute matrix, viewplane, .. */
207   BKE_camera_params_compute_viewplane(&params, re->winx, re->winy, re->r.xasp, re->r.yasp);
208   BKE_camera_params_compute_matrix(&params);
209 
210   /* extract results */
211   re_camera_params_get(re, &params);
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(&params.viewplane), BLI_rctf_size_y(&params.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(&params);
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