Blender  V2.93
multires_bake.c
Go to the documentation of this file.
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) 2012 by Blender Foundation
17  * All rights reserved.
18  */
19 
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_mesh_types.h"
29 #include "DNA_object_types.h"
30 #include "DNA_scene_types.h"
31 
32 #include "BLI_listbase.h"
33 #include "BLI_math.h"
34 #include "BLI_threads.h"
35 
36 #include "BKE_ccg.h"
37 #include "BKE_global.h"
38 #include "BKE_image.h"
39 #include "BKE_material.h"
40 #include "BKE_mesh.h"
41 #include "BKE_modifier.h"
42 #include "BKE_multires.h"
43 #include "BKE_subsurf.h"
44 
45 #include "DEG_depsgraph.h"
46 
47 #include "RE_multires_bake.h"
48 #include "RE_pipeline.h"
49 #include "RE_texture.h"
50 
51 #include "IMB_imbuf.h"
52 #include "IMB_imbuf_types.h"
53 
54 typedef void (*MPassKnownData)(DerivedMesh *lores_dm,
55  DerivedMesh *hires_dm,
56  void *thread_data,
57  void *bake_data,
58  ImBuf *ibuf,
59  const int face_index,
60  const int lvl,
61  const float st[2],
62  float tangmat[3][3],
63  const int x,
64  const int y);
65 
66 typedef void *(*MInitBakeData)(MultiresBakeRender *bkr, Image *ima);
67 typedef void (*MFreeBakeData)(void *bake_data);
68 
69 typedef struct MultiresBakeResult {
72 
73 typedef struct {
79  float *pvtangent;
80  const float *precomputed_normals;
81  int w, h;
82  int tri_index;
83  DerivedMesh *lores_dm, *hires_dm;
84  int lvl;
85  void *thread_data;
86  void *bake_data;
89  /* material aligned UV array */
92 
93 typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y);
94 
95 typedef struct {
96  int w, h;
97  char *texels;
100  short *do_update;
101 } MBakeRast;
102 
103 typedef struct {
104  float *heights;
109 
110 typedef struct {
113 
114 typedef struct BakeImBufuserData {
116  char *mask_buffer;
118 
120  float norm[],
121  const int tri_num,
122  const int vert_index)
123 {
124  const int poly_index = data->mlooptri[tri_num].poly;
125  const MPoly *mp = &data->mpoly[poly_index];
126  const bool smoothnormal = (mp->flag & ME_SMOOTH) != 0;
127 
128  if (!smoothnormal) { /* flat */
129  if (data->precomputed_normals) {
130  copy_v3_v3(norm, &data->precomputed_normals[poly_index]);
131  }
132  else {
133  BKE_mesh_calc_poly_normal(mp, &data->mloop[mp->loopstart], data->mvert, norm);
134  }
135  }
136  else {
137  const int vi = data->mloop[data->mlooptri[tri_num].tri[vert_index]].v;
138  const short *no = data->mvert[vi].no;
139 
142  }
143 }
144 
145 static void init_bake_rast(MBakeRast *bake_rast,
146  const ImBuf *ibuf,
147  const MResolvePixelData *data,
149  short *do_update)
150 {
151  BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
152 
153  memset(bake_rast, 0, sizeof(MBakeRast));
154 
155  bake_rast->texels = userdata->mask_buffer;
156  bake_rast->w = ibuf->x;
157  bake_rast->h = ibuf->y;
158  bake_rast->data = data;
159  bake_rast->flush_pixel = flush_pixel;
160  bake_rast->do_update = do_update;
161 }
162 
163 static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
164 {
165  const float st[2] = {(x + 0.5f) / data->w, (y + 0.5f) / data->h};
166  const float *st0, *st1, *st2;
167  const float *tang0, *tang1, *tang2;
168  float no0[3], no1[3], no2[3];
169  float fUV[2], from_tang[3][3], to_tang[3][3];
170  float u, v, w, sign;
171  int r;
172 
173  st0 = data->mloopuv[data->mlooptri[data->tri_index].tri[0]].uv;
174  st1 = data->mloopuv[data->mlooptri[data->tri_index].tri[1]].uv;
175  st2 = data->mloopuv[data->mlooptri[data->tri_index].tri[2]].uv;
176 
177  multiresbake_get_normal(data, no0, data->tri_index, 0); /* can optimize these 3 into one call */
178  multiresbake_get_normal(data, no1, data->tri_index, 1);
179  multiresbake_get_normal(data, no2, data->tri_index, 2);
180 
181  resolve_tri_uv_v2(fUV, st, st0, st1, st2);
182 
183  u = fUV[0];
184  v = fUV[1];
185  w = 1 - u - v;
186 
187  if (data->pvtangent) {
188  tang0 = data->pvtangent + data->mlooptri[data->tri_index].tri[0] * 4;
189  tang1 = data->pvtangent + data->mlooptri[data->tri_index].tri[1] * 4;
190  tang2 = data->pvtangent + data->mlooptri[data->tri_index].tri[2] * 4;
191 
192  /* the sign is the same at all face vertices for any non degenerate face.
193  * Just in case we clamp the interpolated value though. */
194  sign = (tang0[3] * u + tang1[3] * v + tang2[3] * w) < 0 ? (-1.0f) : 1.0f;
195 
196  /* this sequence of math is designed specifically as is with great care
197  * to be compatible with our shader. Please don't change without good reason. */
198  for (r = 0; r < 3; r++) {
199  from_tang[0][r] = tang0[r] * u + tang1[r] * v + tang2[r] * w;
200  from_tang[2][r] = no0[r] * u + no1[r] * v + no2[r] * w;
201  }
202 
203  cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */
204  mul_v3_fl(from_tang[1], sign);
205  invert_m3_m3(to_tang, from_tang);
206  }
207  else {
208  zero_m3(to_tang);
209  }
210 
211  data->pass_data(data->lores_dm,
212  data->hires_dm,
213  data->thread_data,
214  data->bake_data,
215  data->ibuf,
216  data->tri_index,
217  data->lvl,
218  st,
219  to_tang,
220  x,
221  y);
222 }
223 
224 static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
225 {
226  const int w = bake_rast->w;
227  const int h = bake_rast->h;
228 
229  if (x >= 0 && x < w && y >= 0 && y < h) {
230  if ((bake_rast->texels[y * w + x]) == 0) {
231  bake_rast->texels[y * w + x] = FILTER_MASK_USED;
232  flush_pixel(bake_rast->data, x, y);
233  if (bake_rast->do_update) {
234  *bake_rast->do_update = true;
235  }
236  }
237  }
238 }
239 
240 static void rasterize_half(const MBakeRast *bake_rast,
241  const float s0_s,
242  const float t0_s,
243  const float s1_s,
244  const float t1_s,
245  const float s0_l,
246  const float t0_l,
247  const float s1_l,
248  const float t1_l,
249  const int y0_in,
250  const int y1_in,
251  const int is_mid_right)
252 {
253  const int s_stable = fabsf(t1_s - t0_s) > FLT_EPSILON ? 1 : 0;
254  const int l_stable = fabsf(t1_l - t0_l) > FLT_EPSILON ? 1 : 0;
255  const int w = bake_rast->w;
256  const int h = bake_rast->h;
257  int y, y0, y1;
258 
259  if (y1_in <= 0 || y0_in >= h) {
260  return;
261  }
262 
263  y0 = y0_in < 0 ? 0 : y0_in;
264  y1 = y1_in >= h ? h : y1_in;
265 
266  for (y = y0; y < y1; y++) {
267  /*-b(x-x0) + a(y-y0) = 0 */
268  int iXl, iXr, x;
269  float x_l = s_stable != 0 ? (s0_s + (((s1_s - s0_s) * (y - t0_s)) / (t1_s - t0_s))) : s0_s;
270  float x_r = l_stable != 0 ? (s0_l + (((s1_l - s0_l) * (y - t0_l)) / (t1_l - t0_l))) : s0_l;
271 
272  if (is_mid_right != 0) {
273  SWAP(float, x_l, x_r);
274  }
275 
276  iXl = (int)ceilf(x_l);
277  iXr = (int)ceilf(x_r);
278 
279  if (iXr > 0 && iXl < w) {
280  iXl = iXl < 0 ? 0 : iXl;
281  iXr = iXr >= w ? w : iXr;
282 
283  for (x = iXl; x < iXr; x++) {
284  set_rast_triangle(bake_rast, x, y);
285  }
286  }
287  }
288 }
289 
290 static void bake_rasterize(const MBakeRast *bake_rast,
291  const float st0_in[2],
292  const float st1_in[2],
293  const float st2_in[2])
294 {
295  const int w = bake_rast->w;
296  const int h = bake_rast->h;
297  float slo = st0_in[0] * w - 0.5f;
298  float tlo = st0_in[1] * h - 0.5f;
299  float smi = st1_in[0] * w - 0.5f;
300  float tmi = st1_in[1] * h - 0.5f;
301  float shi = st2_in[0] * w - 0.5f;
302  float thi = st2_in[1] * h - 0.5f;
303  int is_mid_right = 0, ylo, yhi, yhi_beg;
304 
305  /* skip degenerates */
306  if ((slo == smi && tlo == tmi) || (slo == shi && tlo == thi) || (smi == shi && tmi == thi)) {
307  return;
308  }
309 
310  /* sort by T */
311  if (tlo > tmi && tlo > thi) {
312  SWAP(float, shi, slo);
313  SWAP(float, thi, tlo);
314  }
315  else if (tmi > thi) {
316  SWAP(float, shi, smi);
317  SWAP(float, thi, tmi);
318  }
319 
320  if (tlo > tmi) {
321  SWAP(float, slo, smi);
322  SWAP(float, tlo, tmi);
323  }
324 
325  /* check if mid point is to the left or to the right of the lo-hi edge */
326  is_mid_right = (-(shi - slo) * (tmi - thi) + (thi - tlo) * (smi - shi)) > 0 ? 1 : 0;
327  ylo = (int)ceilf(tlo);
328  yhi_beg = (int)ceilf(tmi);
329  yhi = (int)ceilf(thi);
330 
331  /*if (fTmi>ceilf(fTlo))*/
332  rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right);
333  rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right);
334 }
335 
337 {
338  if (!bkr->stop) {
339  /* this means baker is executed outside from job system */
340  return 0;
341  }
342 
343  return *bkr->stop || G.is_break;
344 }
345 
346 /* **** Threading routines **** */
347 
348 typedef struct MultiresBakeQueue {
349  int cur_tri;
350  int tot_tri;
353 
354 typedef struct MultiresBakeThread {
355  /* this data is actually shared between all the threads */
359  void *bake_data;
360 
361  /* thread-specific data */
364 
365  /* displacement-specific data */
368 
370 {
371  int face = -1;
372 
373  /* TODO: it could worth making it so thread will handle neighbor faces
374  * for better memory cache utilization
375  */
376 
377  BLI_spin_lock(&queue->spin);
378  if (queue->cur_tri < queue->tot_tri) {
379  face = queue->cur_tri;
380  queue->cur_tri++;
381  }
382  BLI_spin_unlock(&queue->spin);
383 
384  return face;
385 }
386 
387 static void *do_multires_bake_thread(void *data_v)
388 {
389  MultiresBakeThread *handle = (MultiresBakeThread *)data_v;
390  MResolvePixelData *data = &handle->data;
391  MBakeRast *bake_rast = &handle->bake_rast;
392  MultiresBakeRender *bkr = handle->bkr;
393  int tri_index;
394 
395  while ((tri_index = multires_bake_queue_next_tri(handle->queue)) >= 0) {
396  const MLoopTri *lt = &data->mlooptri[tri_index];
397  const MPoly *mp = &data->mpoly[lt->poly];
398  const short mat_nr = mp->mat_nr;
399  const MLoopUV *mloopuv = data->mloopuv;
400 
401  if (multiresbake_test_break(bkr)) {
402  break;
403  }
404 
405  Image *tri_image = mat_nr < bkr->ob_image.len ? bkr->ob_image.array[mat_nr] : NULL;
406  if (tri_image != handle->image) {
407  continue;
408  }
409 
410  data->tri_index = tri_index;
411 
413  bake_rast, mloopuv[lt->tri[0]].uv, mloopuv[lt->tri[1]].uv, mloopuv[lt->tri[2]].uv);
414 
415  /* tag image buffer for refresh */
416  if (data->ibuf->rect_float) {
417  data->ibuf->userflags |= IB_RECT_INVALID;
418  }
419 
420  data->ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
421 
422  /* update progress */
423  BLI_spin_lock(&handle->queue->spin);
424  bkr->baked_faces++;
425 
426  if (bkr->do_update) {
427  *bkr->do_update = true;
428  }
429 
430  if (bkr->progress) {
431  *bkr->progress = ((float)bkr->baked_objects +
432  (float)bkr->baked_faces / handle->queue->tot_tri) /
433  bkr->tot_obj;
434  }
435  BLI_spin_unlock(&handle->queue->spin);
436  }
437 
438  return NULL;
439 }
440 
441 /* some of arrays inside ccgdm are lazy-initialized, which will generally
442  * require lock around accessing such data
443  * this function will ensure all arrays are allocated before threading started
444  */
446 {
447  CCGElem **grid_data;
448  CCGKey key;
449  int grid_size;
450  const int *grid_offset;
451 
452  grid_size = dm->getGridSize(dm);
453  grid_data = dm->getGridData(dm);
454  grid_offset = dm->getGridOffset(dm);
455  dm->getGridKey(dm, &key);
456 
457  (void)grid_size;
458  (void)grid_data;
459  (void)grid_offset;
460 }
461 
463  Image *ima,
464  bool require_tangent,
465  MPassKnownData passKnownData,
466  MInitBakeData initBakeData,
467  MFreeBakeData freeBakeData,
469 {
470  DerivedMesh *dm = bkr->lores_dm;
471  const MLoopTri *mlooptri = dm->getLoopTriArray(dm);
472  const int lvl = bkr->lvl;
473  int tot_tri = dm->getNumLoopTri(dm);
474 
475  if (tot_tri > 0) {
478 
479  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
480  MVert *mvert = dm->getVertArray(dm);
481  MPoly *mpoly = dm->getPolyArray(dm);
482  MLoop *mloop = dm->getLoopArray(dm);
483  MLoopUV *mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV);
484  const float *precomputed_normals = dm->getPolyDataArray(dm, CD_NORMAL);
485  float *pvtangent = NULL;
486 
488  int i, tot_thread = bkr->threads > 0 ? bkr->threads : BLI_system_thread_count();
489 
490  void *bake_data = NULL;
491 
492  if (require_tangent) {
494  DM_calc_loop_tangents(dm, true, NULL, 0);
495  }
496 
497  pvtangent = DM_get_loop_data_layer(dm, CD_TANGENT);
498  }
499 
500  /* all threads shares the same custom bake data */
501  if (initBakeData) {
502  bake_data = initBakeData(bkr, ima);
503  }
504 
505  if (tot_thread > 1) {
507  }
508 
509  handles = MEM_callocN(tot_thread * sizeof(MultiresBakeThread), "do_multires_bake handles");
510 
512 
513  /* faces queue */
514  queue.cur_tri = 0;
515  queue.tot_tri = tot_tri;
516  BLI_spin_init(&queue.spin);
517 
518  /* fill in threads handles */
519  for (i = 0; i < tot_thread; i++) {
520  MultiresBakeThread *handle = &handles[i];
521 
522  handle->bkr = bkr;
523  handle->image = ima;
524  handle->queue = &queue;
525 
526  handle->data.mpoly = mpoly;
527  handle->data.mvert = mvert;
528  handle->data.mloopuv = mloopuv;
529  handle->data.mlooptri = mlooptri;
530  handle->data.mloop = mloop;
531  handle->data.pvtangent = pvtangent;
532  handle->data.precomputed_normals = precomputed_normals; /* don't strictly need this */
533  handle->data.w = ibuf->x;
534  handle->data.h = ibuf->y;
535  handle->data.lores_dm = dm;
536  handle->data.hires_dm = bkr->hires_dm;
537  handle->data.lvl = lvl;
538  handle->data.pass_data = passKnownData;
539  handle->data.thread_data = handle;
540  handle->data.bake_data = bake_data;
541  handle->data.ibuf = ibuf;
542 
543  handle->height_min = FLT_MAX;
544  handle->height_max = -FLT_MAX;
545 
546  init_bake_rast(&handle->bake_rast, ibuf, &handle->data, flush_pixel, bkr->do_update);
547 
548  if (tot_thread > 1) {
549  BLI_threadpool_insert(&threads, handle);
550  }
551  }
552 
553  /* run threads */
554  if (tot_thread > 1) {
556  }
557  else {
559  }
560 
561  /* construct bake result */
562  result->height_min = handles[0].height_min;
563  result->height_max = handles[0].height_max;
564 
565  for (i = 1; i < tot_thread; i++) {
566  result->height_min = min_ff(result->height_min, handles[i].height_min);
567  result->height_max = max_ff(result->height_max, handles[i].height_max);
568  }
569 
570  BLI_spin_end(&queue.spin);
571 
572  /* finalize baking */
573  if (freeBakeData) {
574  freeBakeData(bake_data);
575  }
576 
578 
579  BKE_image_release_ibuf(ima, ibuf, NULL);
580  }
581 }
582 
583 /* mode = 0: interpolate normals,
584  * mode = 1: interpolate coord */
586  CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
587 {
588  int x0, x1, y0, y1;
589  float u, v;
590  float data[4][3];
591 
592  x0 = (int)crn_x;
593  x1 = x0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (x0 + 1);
594 
595  y0 = (int)crn_y;
596  y1 = y0 >= (key->grid_size - 1) ? (key->grid_size - 1) : (y0 + 1);
597 
598  u = crn_x - x0;
599  v = crn_y - y0;
600 
601  if (mode == 0) {
602  copy_v3_v3(data[0], CCG_grid_elem_no(key, grid, x0, y0));
603  copy_v3_v3(data[1], CCG_grid_elem_no(key, grid, x1, y0));
604  copy_v3_v3(data[2], CCG_grid_elem_no(key, grid, x1, y1));
605  copy_v3_v3(data[3], CCG_grid_elem_no(key, grid, x0, y1));
606  }
607  else {
608  copy_v3_v3(data[0], CCG_grid_elem_co(key, grid, x0, y0));
609  copy_v3_v3(data[1], CCG_grid_elem_co(key, grid, x1, y0));
610  copy_v3_v3(data[2], CCG_grid_elem_co(key, grid, x1, y1));
611  copy_v3_v3(data[3], CCG_grid_elem_co(key, grid, x0, y1));
612  }
613 
614  interp_bilinear_quad_v3(data, u, v, res);
615 }
616 
617 static void get_ccgdm_data(DerivedMesh *lodm,
618  DerivedMesh *hidm,
619  const int *index_mp_to_orig,
620  const int lvl,
621  const MLoopTri *lt,
622  const float u,
623  const float v,
624  float co[3],
625  float n[3])
626 {
627  CCGElem **grid_data;
628  CCGKey key;
629  float crn_x, crn_y;
630  int grid_size, S, face_side;
631  int *grid_offset, g_index;
632  int poly_index = lt->poly;
633 
634  grid_size = hidm->getGridSize(hidm);
635  grid_data = hidm->getGridData(hidm);
636  grid_offset = hidm->getGridOffset(hidm);
637  hidm->getGridKey(hidm, &key);
638 
639  if (lvl == 0) {
640  MPoly *mpoly;
641  face_side = (grid_size << 1) - 1;
642 
643  mpoly = lodm->getPolyArray(lodm) + poly_index;
644  g_index = grid_offset[poly_index];
645  S = mdisp_rot_face_to_crn(lodm->getVertArray(lodm),
646  mpoly,
647  lodm->getLoopArray(lodm),
648  lt,
649  face_side,
650  u * (face_side - 1),
651  v * (face_side - 1),
652  &crn_x,
653  &crn_y);
654  }
655  else {
656  /* number of faces per grid side */
657  int polys_per_grid_side = (1 << (lvl - 1));
658  /* get the original cage face index */
659  int cage_face_index = index_mp_to_orig ? index_mp_to_orig[poly_index] : poly_index;
660  /* local offset in total cage face grids
661  * `(1 << (2 * lvl))` is number of all polys for one cage face */
662  int loc_cage_poly_ofs = poly_index % (1 << (2 * lvl));
663  /* local offset in the vertex grid itself */
664  int cell_index = loc_cage_poly_ofs % (polys_per_grid_side * polys_per_grid_side);
665  int cell_side = (grid_size - 1) / polys_per_grid_side;
666  /* row and column based on grid side */
667  int row = cell_index / polys_per_grid_side;
668  int col = cell_index % polys_per_grid_side;
669 
670  /* S is the vertex whose grid we are examining */
671  S = poly_index / (1 << (2 * (lvl - 1))) - grid_offset[cage_face_index];
672  /* get offset of grid data for original cage face */
673  g_index = grid_offset[cage_face_index];
674 
675  crn_y = (row * cell_side) + u * cell_side;
676  crn_x = (col * cell_side) + v * cell_side;
677  }
678 
679  CLAMP(crn_x, 0.0f, grid_size);
680  CLAMP(crn_y, 0.0f, grid_size);
681 
682  if (n != NULL) {
683  interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 0, n);
684  }
685 
686  if (co != NULL) {
687  interp_bilinear_grid(&key, grid_data[g_index + S], crn_x, crn_y, 1, co);
688  }
689 }
690 
691 /* mode = 0: interpolate normals,
692  * mode = 1: interpolate coord */
693 
695  MLoop *mloop,
696  MPoly *mpoly,
697  const float u,
698  const float v,
699  const int mode,
700  float res[3])
701 {
702  float data[4][3];
703 
704  if (mode == 0) {
705  dm->getVertNo(dm, mloop[mpoly->loopstart].v, data[0]);
706  dm->getVertNo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
707  dm->getVertNo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
708  dm->getVertNo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
709  }
710  else {
711  dm->getVertCo(dm, mloop[mpoly->loopstart].v, data[0]);
712  dm->getVertCo(dm, mloop[mpoly->loopstart + 1].v, data[1]);
713  dm->getVertCo(dm, mloop[mpoly->loopstart + 2].v, data[2]);
714  dm->getVertCo(dm, mloop[mpoly->loopstart + 3].v, data[3]);
715  }
716 
717  interp_bilinear_quad_v3(data, u, v, res);
718 }
719 
721  MLoop *mloop,
722  const MLoopTri *lt,
723  const float u,
724  const float v,
725  const int mode,
726  float res[3])
727 {
728  float data[3][3];
729 
730  if (mode == 0) {
731  dm->getVertNo(dm, mloop[lt->tri[0]].v, data[0]);
732  dm->getVertNo(dm, mloop[lt->tri[1]].v, data[1]);
733  dm->getVertNo(dm, mloop[lt->tri[2]].v, data[2]);
734  }
735  else {
736  dm->getVertCo(dm, mloop[lt->tri[0]].v, data[0]);
737  dm->getVertCo(dm, mloop[lt->tri[1]].v, data[1]);
738  dm->getVertCo(dm, mloop[lt->tri[2]].v, data[2]);
739  }
740 
741  interp_barycentric_tri_v3(data, u, v, res);
742 }
743 
744 /* **************** Displacement Baker **************** */
745 
747 {
748  MHeightBakeData *height_data;
749  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
750  DerivedMesh *lodm = bkr->lores_dm;
751  BakeImBufuserData *userdata = ibuf->userdata;
752 
753  if (userdata->displacement_buffer == NULL) {
754  userdata->displacement_buffer = MEM_callocN(sizeof(float) * ibuf->x * ibuf->y,
755  "MultiresBake heights");
756  }
757 
758  height_data = MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData");
759 
760  height_data->ima = ima;
761  height_data->heights = userdata->displacement_buffer;
762 
763  if (!bkr->use_lores_mesh) {
764  SubsurfModifierData smd = {{NULL}};
765  int ss_lvl = bkr->tot_lvl - bkr->lvl;
766 
767  CLAMP(ss_lvl, 0, 6);
768 
769  if (ss_lvl > 0) {
770  smd.levels = smd.renderLevels = ss_lvl;
772  smd.quality = 3;
773 
775  bkr->lores_dm, &smd, bkr->scene, NULL, 0);
776  init_ccgdm_arrays(height_data->ssdm);
777  }
778  }
779 
780  height_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
781 
782  BKE_image_release_ibuf(ima, ibuf, NULL);
783 
784  return (void *)height_data;
785 }
786 
787 static void free_heights_data(void *bake_data)
788 {
789  MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
790 
791  if (height_data->ssdm) {
792  height_data->ssdm->release(height_data->ssdm);
793  }
794 
795  MEM_freeN(height_data);
796 }
797 
798 /* MultiresBake callback for heights baking
799  * general idea:
800  * - find coord of point with specified UV in hi-res mesh (let's call it p1)
801  * - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res
802  * mesh to make texture smoother) let's call this point p0 and n.
803  * - height wound be dot(n, p1-p0) */
804 static void apply_heights_callback(DerivedMesh *lores_dm,
805  DerivedMesh *hires_dm,
806  void *thread_data_v,
807  void *bake_data,
808  ImBuf *ibuf,
809  const int tri_index,
810  const int lvl,
811  const float st[2],
812  float UNUSED(tangmat[3][3]),
813  const int x,
814  const int y)
815 {
816  const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
817  MLoop *mloop = lores_dm->getLoopArray(lores_dm);
818  MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
819  MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
820  MHeightBakeData *height_data = (MHeightBakeData *)bake_data;
821  MultiresBakeThread *thread_data = (MultiresBakeThread *)thread_data_v;
822  float uv[2], *st0, *st1, *st2, *st3;
823  int pixel = ibuf->x * y + x;
824  float vec[3], p0[3], p1[3], n[3], len;
825 
826  /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
827  * coordinates for use in grid space (triangle barycentric is not orthogonal) */
828  if (mpoly->totloop == 4) {
829  st0 = mloopuv[mpoly->loopstart].uv;
830  st1 = mloopuv[mpoly->loopstart + 1].uv;
831  st2 = mloopuv[mpoly->loopstart + 2].uv;
832  st3 = mloopuv[mpoly->loopstart + 3].uv;
833  resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
834  }
835  else {
836  st0 = mloopuv[lt->tri[0]].uv;
837  st1 = mloopuv[lt->tri[1]].uv;
838  st2 = mloopuv[lt->tri[2]].uv;
839  resolve_tri_uv_v2(uv, st, st0, st1, st2);
840  }
841 
842  clamp_v2(uv, 0.0f, 1.0f);
843 
845  lores_dm, hires_dm, height_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], p1, NULL);
846 
847  if (height_data->ssdm) {
848  get_ccgdm_data(lores_dm,
849  height_data->ssdm,
850  height_data->orig_index_mp_to_orig,
851  0,
852  lt,
853  uv[0],
854  uv[1],
855  p0,
856  n);
857  }
858  else {
859  if (mpoly->totloop == 4) {
860  interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 1, p0);
861  interp_bilinear_mpoly(lores_dm, mloop, mpoly, uv[0], uv[1], 0, n);
862  }
863  else {
864  interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 1, p0);
865  interp_barycentric_mlooptri(lores_dm, mloop, lt, uv[0], uv[1], 0, n);
866  }
867  }
868 
869  sub_v3_v3v3(vec, p1, p0);
870  len = dot_v3v3(n, vec);
871 
872  height_data->heights[pixel] = len;
873 
874  thread_data->height_min = min_ff(thread_data->height_min, len);
875  thread_data->height_max = max_ff(thread_data->height_max, len);
876 
877  if (ibuf->rect_float) {
878  float *rrgbf = ibuf->rect_float + pixel * 4;
879  rrgbf[0] = rrgbf[1] = rrgbf[2] = len;
880  rrgbf[3] = 1.0f;
881  }
882  else {
883  char *rrgb = (char *)ibuf->rect + pixel * 4;
884  rrgb[0] = rrgb[1] = rrgb[2] = unit_float_to_uchar_clamp(len);
885  rrgb[3] = 255;
886  }
887 }
888 
889 /* **************** Normal Maps Baker **************** */
890 
892 {
893  MNormalBakeData *normal_data;
894  DerivedMesh *lodm = bkr->lores_dm;
895 
896  normal_data = MEM_callocN(sizeof(MNormalBakeData), "MultiresBake normalData");
897 
898  normal_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
899 
900  return (void *)normal_data;
901 }
902 
903 static void free_normal_data(void *bake_data)
904 {
905  MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
906 
907  MEM_freeN(normal_data);
908 }
909 
918 static void apply_tangmat_callback(DerivedMesh *lores_dm,
919  DerivedMesh *hires_dm,
920  void *UNUSED(thread_data),
921  void *bake_data,
922  ImBuf *ibuf,
923  const int tri_index,
924  const int lvl,
925  const float st[2],
926  float tangmat[3][3],
927  const int x,
928  const int y)
929 {
930  const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
931  MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
932  MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
933  MNormalBakeData *normal_data = (MNormalBakeData *)bake_data;
934  float uv[2], *st0, *st1, *st2, *st3;
935  int pixel = ibuf->x * y + x;
936  float n[3], vec[3], tmp[3] = {0.5, 0.5, 0.5};
937 
938  /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
939  * coordinates for use in grid space (triangle barycentric is not orthogonal) */
940  if (mpoly->totloop == 4) {
941  st0 = mloopuv[mpoly->loopstart].uv;
942  st1 = mloopuv[mpoly->loopstart + 1].uv;
943  st2 = mloopuv[mpoly->loopstart + 2].uv;
944  st3 = mloopuv[mpoly->loopstart + 3].uv;
945  resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
946  }
947  else {
948  st0 = mloopuv[lt->tri[0]].uv;
949  st1 = mloopuv[lt->tri[1]].uv;
950  st2 = mloopuv[lt->tri[2]].uv;
951  resolve_tri_uv_v2(uv, st, st0, st1, st2);
952  }
953 
954  clamp_v2(uv, 0.0f, 1.0f);
955 
957  lores_dm, hires_dm, normal_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], NULL, n);
958 
959  mul_v3_m3v3(vec, tangmat, n);
960  normalize_v3_length(vec, 0.5);
961  add_v3_v3(vec, tmp);
962 
963  if (ibuf->rect_float) {
964  float *rrgbf = ibuf->rect_float + pixel * 4;
965  rrgbf[0] = vec[0];
966  rrgbf[1] = vec[1];
967  rrgbf[2] = vec[2];
968  rrgbf[3] = 1.0f;
969  }
970  else {
971  unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
972  rgb_float_to_uchar(rrgb, vec);
973  rrgb[3] = 255;
974  }
975 }
976 
977 /* TODO: restore ambient occlusion baking support, using BLI BVH? */
978 #if 0
979 /* **************** Ambient Occlusion Baker **************** */
980 
981 // must be a power of two
982 # define MAX_NUMBER_OF_AO_RAYS 1024
983 
984 static unsigned short ao_random_table_1[MAX_NUMBER_OF_AO_RAYS];
985 static unsigned short ao_random_table_2[MAX_NUMBER_OF_AO_RAYS];
986 
987 static void init_ao_random(void)
988 {
989  int i;
990 
991  for (i = 0; i < MAX_NUMBER_OF_AO_RAYS; i++) {
992  ao_random_table_1[i] = rand() & 0xffff;
993  ao_random_table_2[i] = rand() & 0xffff;
994  }
995 }
996 
997 static unsigned short get_ao_random1(const int i)
998 {
999  return ao_random_table_1[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
1000 }
1001 
1002 static unsigned short get_ao_random2(const int i)
1003 {
1004  return ao_random_table_2[i & (MAX_NUMBER_OF_AO_RAYS - 1)];
1005 }
1006 
1007 static void build_permutation_table(unsigned short permutation[],
1008  unsigned short temp_permutation[],
1009  const int number_of_rays,
1010  const int is_first_perm_table)
1011 {
1012  int i, k;
1013 
1014  for (i = 0; i < number_of_rays; i++) {
1015  temp_permutation[i] = i;
1016  }
1017 
1018  for (i = 0; i < number_of_rays; i++) {
1019  const unsigned int nr_entries_left = number_of_rays - i;
1020  unsigned short rnd = is_first_perm_table != false ? get_ao_random1(i) : get_ao_random2(i);
1021  const unsigned short entry = rnd % nr_entries_left;
1022 
1023  /* pull entry */
1024  permutation[i] = temp_permutation[entry];
1025 
1026  /* delete entry */
1027  for (k = entry; k < nr_entries_left - 1; k++) {
1028  temp_permutation[k] = temp_permutation[k + 1];
1029  }
1030  }
1031 
1032  /* verify permutation table
1033  * every entry must appear exactly once
1034  */
1035 # if 0
1036  for (i = 0; i < number_of_rays; i++) temp_permutation[i] = 0;
1037  for (i = 0; i < number_of_rays; i++) ++temp_permutation[permutation[i]];
1038  for (i = 0; i < number_of_rays; i++) BLI_assert(temp_permutation[i] == 1);
1039 # endif
1040 }
1041 
1042 static void create_ao_raytree(MultiresBakeRender *bkr, MAOBakeData *ao_data)
1043 {
1044  DerivedMesh *hidm = bkr->hires_dm;
1045  RayObject *raytree;
1046  RayFace *face;
1047  CCGElem **grid_data;
1048  CCGKey key;
1049  int num_grids, grid_size /*, face_side */, num_faces;
1050  int i;
1051 
1052  num_grids = hidm->getNumGrids(hidm);
1053  grid_size = hidm->getGridSize(hidm);
1054  grid_data = hidm->getGridData(hidm);
1055  hidm->getGridKey(hidm, &key);
1056 
1057  /* face_side = (grid_size << 1) - 1; */ /* UNUSED */
1058  num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
1059 
1060  raytree = ao_data->raytree = RE_rayobject_create(
1061  bkr->raytrace_structure, num_faces, bkr->octree_resolution);
1062  face = ao_data->rayfaces = (RayFace *)MEM_callocN(num_faces * sizeof(RayFace),
1063  "ObjectRen faces");
1064 
1065  for (i = 0; i < num_grids; i++) {
1066  int x, y;
1067  for (x = 0; x < grid_size - 1; x++) {
1068  for (y = 0; y < grid_size - 1; y++) {
1069  float co[4][3];
1070 
1071  copy_v3_v3(co[0], CCG_grid_elem_co(&key, grid_data[i], x, y));
1072  copy_v3_v3(co[1], CCG_grid_elem_co(&key, grid_data[i], x, y + 1));
1073  copy_v3_v3(co[2], CCG_grid_elem_co(&key, grid_data[i], x + 1, y + 1));
1074  copy_v3_v3(co[3], CCG_grid_elem_co(&key, grid_data[i], x + 1, y));
1075 
1076  RE_rayface_from_coords(face, ao_data, face, co[0], co[1], co[2], co[3]);
1077  RE_rayobject_add(raytree, RE_rayobject_unalignRayFace(face));
1078 
1079  face++;
1080  }
1081  }
1082  }
1083 
1084  RE_rayobject_done(raytree);
1085 }
1086 
1087 static void *init_ao_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
1088 {
1089  MAOBakeData *ao_data;
1090  DerivedMesh *lodm = bkr->lores_dm;
1091  unsigned short *temp_permutation_table;
1092  size_t permutation_size;
1093 
1094  init_ao_random();
1095 
1096  ao_data = MEM_callocN(sizeof(MAOBakeData), "MultiresBake aoData");
1097 
1098  ao_data->number_of_rays = bkr->number_of_rays;
1099  ao_data->bias = bkr->bias;
1100 
1101  ao_data->orig_index_mp_to_orig = lodm->getPolyDataArray(lodm, CD_ORIGINDEX);
1102 
1103  create_ao_raytree(bkr, ao_data);
1104 
1105  /* initialize permutation tables */
1106  permutation_size = sizeof(unsigned short) * bkr->number_of_rays;
1107  ao_data->permutation_table_1 = MEM_callocN(permutation_size, "multires AO baker perm1");
1108  ao_data->permutation_table_2 = MEM_callocN(permutation_size, "multires AO baker perm2");
1109  temp_permutation_table = MEM_callocN(permutation_size, "multires AO baker temp perm");
1110 
1111  build_permutation_table(
1112  ao_data->permutation_table_1, temp_permutation_table, bkr->number_of_rays, 1);
1113  build_permutation_table(
1114  ao_data->permutation_table_2, temp_permutation_table, bkr->number_of_rays, 0);
1115 
1116  MEM_freeN(temp_permutation_table);
1117 
1118  return (void *)ao_data;
1119 }
1120 
1121 static void free_ao_data(void *bake_data)
1122 {
1123  MAOBakeData *ao_data = (MAOBakeData *)bake_data;
1124 
1125  RE_rayobject_free(ao_data->raytree);
1126  MEM_freeN(ao_data->rayfaces);
1127 
1128  MEM_freeN(ao_data->permutation_table_1);
1129  MEM_freeN(ao_data->permutation_table_2);
1130 
1131  MEM_freeN(ao_data);
1132 }
1133 
1134 /* builds an X and a Y axis from the given Z axis */
1135 static void build_coordinate_frame(float axisX[3], float axisY[3], const float axisZ[3])
1136 {
1137  const float faX = fabsf(axisZ[0]);
1138  const float faY = fabsf(axisZ[1]);
1139  const float faZ = fabsf(axisZ[2]);
1140 
1141  if (faX <= faY && faX <= faZ) {
1142  const float len = sqrtf(axisZ[1] * axisZ[1] + axisZ[2] * axisZ[2]);
1143  axisY[0] = 0;
1144  axisY[1] = axisZ[2] / len;
1145  axisY[2] = -axisZ[1] / len;
1146  cross_v3_v3v3(axisX, axisY, axisZ);
1147  }
1148  else if (faY <= faZ) {
1149  const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[2] * axisZ[2]);
1150  axisX[0] = axisZ[2] / len;
1151  axisX[1] = 0;
1152  axisX[2] = -axisZ[0] / len;
1153  cross_v3_v3v3(axisY, axisZ, axisX);
1154  }
1155  else {
1156  const float len = sqrtf(axisZ[0] * axisZ[0] + axisZ[1] * axisZ[1]);
1157  axisX[0] = axisZ[1] / len;
1158  axisX[1] = -axisZ[0] / len;
1159  axisX[2] = 0;
1160  cross_v3_v3v3(axisY, axisZ, axisX);
1161  }
1162 }
1163 
1164 /* return false if nothing was hit and true otherwise */
1165 static int trace_ao_ray(MAOBakeData *ao_data, float ray_start[3], float ray_direction[3])
1166 {
1167  Isect isect = {{0}};
1168 
1169  isect.dist = RE_RAYTRACE_MAXDIST;
1170  copy_v3_v3(isect.start, ray_start);
1171  copy_v3_v3(isect.dir, ray_direction);
1172  isect.lay = -1;
1173 
1174  normalize_v3(isect.dir);
1175 
1176  return RE_rayobject_raycast(ao_data->raytree, &isect);
1177 }
1178 
1179 static void apply_ao_callback(DerivedMesh *lores_dm,
1180  DerivedMesh *hires_dm,
1181  void *UNUSED(thread_data),
1182  void *bake_data,
1183  ImBuf *ibuf,
1184  const int tri_index,
1185  const int lvl,
1186  const float st[2],
1187  float UNUSED(tangmat[3][3]),
1188  const int x,
1189  const int y)
1190 {
1191  const MLoopTri *lt = lores_dm->getLoopTriArray(lores_dm) + tri_index;
1192  MPoly *mpoly = lores_dm->getPolyArray(lores_dm) + lt->poly;
1193  MLoopUV *mloopuv = lores_dm->getLoopDataArray(lores_dm, CD_MLOOPUV);
1194  MAOBakeData *ao_data = (MAOBakeData *)bake_data;
1195 
1196  int i, k, perm_ofs;
1197  float pos[3], nrm[3];
1198  float cen[3];
1199  float axisX[3], axisY[3], axisZ[3];
1200  float shadow = 0;
1201  float value;
1202  int pixel = ibuf->x * y + x;
1203  float uv[2], *st0, *st1, *st2, *st3;
1204 
1205  /* ideally we would work on triangles only, however, we rely on quads to get orthogonal
1206  * coordinates for use in grid space (triangle barycentric is not orthogonal) */
1207  if (mpoly->totloop == 4) {
1208  st0 = mloopuv[mpoly->loopstart].uv;
1209  st1 = mloopuv[mpoly->loopstart + 1].uv;
1210  st2 = mloopuv[mpoly->loopstart + 2].uv;
1211  st3 = mloopuv[mpoly->loopstart + 3].uv;
1212  resolve_quad_uv_v2(uv, st, st0, st1, st2, st3);
1213  }
1214  else {
1215  st0 = mloopuv[lt->tri[0]].uv;
1216  st1 = mloopuv[lt->tri[1]].uv;
1217  st2 = mloopuv[lt->tri[2]].uv;
1218  resolve_tri_uv_v2(uv, st, st0, st1, st2);
1219  }
1220 
1221  clamp_v2(uv, 0.0f, 1.0f);
1222 
1224  lores_dm, hires_dm, ao_data->orig_index_mp_to_orig, lvl, lt, uv[0], uv[1], pos, nrm);
1225 
1226  /* offset ray origin by user bias along normal */
1227  for (i = 0; i < 3; i++) {
1228  cen[i] = pos[i] + ao_data->bias * nrm[i];
1229  }
1230 
1231  /* build tangent frame */
1232  for (i = 0; i < 3; i++) {
1233  axisZ[i] = nrm[i];
1234  }
1235 
1236  build_coordinate_frame(axisX, axisY, axisZ);
1237 
1238  /* static noise */
1239  perm_ofs = (get_ao_random2(get_ao_random1(x) + y)) & (MAX_NUMBER_OF_AO_RAYS - 1);
1240 
1241  /* importance sample shadow rays (cosine weighted) */
1242  for (i = 0; i < ao_data->number_of_rays; i++) {
1243  int hit_something;
1244 
1245  /* use N-Rooks to distribute our N ray samples across
1246  * a multi-dimensional domain (2D)
1247  */
1248  const unsigned short I =
1249  ao_data->permutation_table_1[(i + perm_ofs) % ao_data->number_of_rays];
1250  const unsigned short J = ao_data->permutation_table_2[i];
1251 
1252  const float JitPh = (get_ao_random2(I + perm_ofs) & (MAX_NUMBER_OF_AO_RAYS - 1)) /
1253  ((float)MAX_NUMBER_OF_AO_RAYS);
1254  const float JitTh = (get_ao_random1(J + perm_ofs) & (MAX_NUMBER_OF_AO_RAYS - 1)) /
1255  ((float)MAX_NUMBER_OF_AO_RAYS);
1256  const float SiSqPhi = (I + JitPh) / ao_data->number_of_rays;
1257  const float Theta = (float)(2 * M_PI) * ((J + JitTh) / ao_data->number_of_rays);
1258 
1259  /* this gives results identical to the so-called cosine
1260  * weighted distribution relative to the north pole.
1261  */
1262  float SiPhi = sqrtf(SiSqPhi);
1263  float CoPhi = SiSqPhi < 1.0f ? sqrtf(1.0f - SiSqPhi) : 0;
1264  float CoThe = cosf(Theta);
1265  float SiThe = sinf(Theta);
1266 
1267  const float dx = CoThe * CoPhi;
1268  const float dy = SiThe * CoPhi;
1269  const float dz = SiPhi;
1270 
1271  /* transform ray direction out of tangent frame */
1272  float dv[3];
1273  for (k = 0; k < 3; k++) {
1274  dv[k] = axisX[k] * dx + axisY[k] * dy + axisZ[k] * dz;
1275  }
1276 
1277  hit_something = trace_ao_ray(ao_data, cen, dv);
1278 
1279  if (hit_something != 0) {
1280  shadow += 1;
1281  }
1282  }
1283 
1284  value = 1.0f - (shadow / ao_data->number_of_rays);
1285 
1286  if (ibuf->rect_float) {
1287  float *rrgbf = ibuf->rect_float + pixel * 4;
1288  rrgbf[0] = rrgbf[1] = rrgbf[2] = value;
1289  rrgbf[3] = 1.0f;
1290  }
1291  else {
1292  unsigned char *rrgb = (unsigned char *)ibuf->rect + pixel * 4;
1293  rrgb[0] = rrgb[1] = rrgb[2] = unit_float_to_uchar_clamp(value);
1294  rrgb[3] = 255;
1295  }
1296 }
1297 #endif
1298 
1299 /* ******$***************** Post processing ************************* */
1300 
1301 static void bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
1302 {
1303  /* must check before filtering */
1304  const bool is_new_alpha = (ibuf->planes != R_IMF_PLANES_RGBA) && BKE_imbuf_alpha_test(ibuf);
1305 
1306  /* Margin */
1307  if (filter) {
1308  IMB_filter_extend(ibuf, mask, filter);
1309  }
1310 
1311  /* if the bake results in new alpha then change the image setting */
1312  if (is_new_alpha) {
1313  ibuf->planes = R_IMF_PLANES_RGBA;
1314  }
1315  else {
1316  if (filter && ibuf->planes != R_IMF_PLANES_RGBA) {
1317  /* clear alpha added by filtering */
1318  IMB_rectfill_alpha(ibuf, 1.0f);
1319  }
1320  }
1321 }
1322 
1324  const float *displacement,
1325  const char *mask,
1326  float displacement_min,
1327  float displacement_max)
1328 {
1329  int i;
1330  const float *current_displacement = displacement;
1331  const char *current_mask = mask;
1332  float max_distance;
1333 
1334  max_distance = max_ff(fabsf(displacement_min), fabsf(displacement_max));
1335 
1336  for (i = 0; i < ibuf->x * ibuf->y; i++) {
1337  if (*current_mask == FILTER_MASK_USED) {
1338  float normalized_displacement;
1339 
1340  if (max_distance > 1e-5f) {
1341  normalized_displacement = (*current_displacement + max_distance) / (max_distance * 2);
1342  }
1343  else {
1344  normalized_displacement = 0.5f;
1345  }
1346 
1347  if (ibuf->rect_float) {
1348  /* currently baking happens to RGBA only */
1349  float *fp = ibuf->rect_float + i * 4;
1350  fp[0] = fp[1] = fp[2] = normalized_displacement;
1351  fp[3] = 1.0f;
1352  }
1353 
1354  if (ibuf->rect) {
1355  unsigned char *cp = (unsigned char *)(ibuf->rect + i);
1356  cp[0] = cp[1] = cp[2] = unit_float_to_uchar_clamp(normalized_displacement);
1357  cp[3] = 255;
1358  }
1359  }
1360 
1361  current_displacement++;
1362  current_mask++;
1363  }
1364 }
1365 
1366 /* **************** Common functions public API relates on **************** */
1367 
1369 {
1370  BLI_listbase_clear(&bkr->image);
1371  bkr->tot_image = 0;
1372 
1373  for (int i = 0; i < bkr->ob_image.len; i++) {
1374  Image *ima = bkr->ob_image.array[i];
1375  if (ima) {
1376  ima->id.tag &= ~LIB_TAG_DOIT;
1377  }
1378  }
1379 
1380  for (int i = 0; i < bkr->ob_image.len; i++) {
1381  Image *ima = bkr->ob_image.array[i];
1382  if (ima) {
1383  if ((ima->id.tag & LIB_TAG_DOIT) == 0) {
1384  LinkData *data = BLI_genericNodeN(ima);
1385  BLI_addtail(&bkr->image, data);
1386  bkr->tot_image++;
1387  ima->id.tag |= LIB_TAG_DOIT;
1388  }
1389  }
1390  }
1391 
1392  for (int i = 0; i < bkr->ob_image.len; i++) {
1393  Image *ima = bkr->ob_image.array[i];
1394  if (ima) {
1395  ima->id.tag &= ~LIB_TAG_DOIT;
1396  }
1397  }
1398 }
1399 
1401 {
1402  LinkData *link;
1403 
1404  for (link = bkr->image.first; link; link = link->next) {
1405  Image *ima = (Image *)link->data;
1406  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
1407 
1408  if (ibuf->x > 0 && ibuf->y > 0) {
1409  BakeImBufuserData *userdata = MEM_callocN(sizeof(BakeImBufuserData),
1410  "MultiresBake userdata");
1411  userdata->mask_buffer = MEM_callocN(ibuf->y * ibuf->x, "MultiresBake imbuf mask");
1412  ibuf->userdata = userdata;
1413 
1414  switch (bkr->mode) {
1415  case RE_BAKE_NORMALS:
1418  break;
1419  case RE_BAKE_DISPLACEMENT:
1420  do_multires_bake(bkr,
1421  ima,
1422  false,
1426  result);
1427  break;
1428 /* TODO: restore ambient occlusion baking support. */
1429 #if 0
1430  case RE_BAKE_AO:
1431  do_multires_bake(bkr, ima, false, apply_ao_callback, init_ao_data, free_ao_data, result);
1432  break;
1433 #endif
1434  }
1435  }
1436 
1437  BKE_image_release_ibuf(ima, ibuf, NULL);
1438 
1439  ima->id.tag |= LIB_TAG_DOIT;
1440  }
1441 }
1442 
1444 {
1445  LinkData *link;
1446  bool use_displacement_buffer = bkr->mode == RE_BAKE_DISPLACEMENT;
1447 
1448  for (link = bkr->image.first; link; link = link->next) {
1449  Image *ima = (Image *)link->data;
1450  ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
1451  BakeImBufuserData *userdata = (BakeImBufuserData *)ibuf->userdata;
1452 
1453  if (ibuf->x <= 0 || ibuf->y <= 0) {
1454  continue;
1455  }
1456 
1457  if (use_displacement_buffer) {
1459  userdata->displacement_buffer,
1460  userdata->mask_buffer,
1461  result->height_min,
1462  result->height_max);
1463  }
1464 
1465  bake_ibuf_filter(ibuf, userdata->mask_buffer, bkr->bake_filter);
1466 
1468  BKE_image_mark_dirty(ima, ibuf);
1469 
1470  if (ibuf->rect_float) {
1471  ibuf->userflags |= IB_RECT_INVALID;
1472  }
1473 
1474  if (ibuf->mipmap[0]) {
1475  ibuf->userflags |= IB_MIPMAP_INVALID;
1476  imb_freemipmapImBuf(ibuf);
1477  }
1478 
1479  if (ibuf->userdata) {
1480  if (userdata->displacement_buffer) {
1481  MEM_freeN(userdata->displacement_buffer);
1482  }
1483 
1484  MEM_freeN(userdata->mask_buffer);
1485  MEM_freeN(userdata);
1486  ibuf->userdata = NULL;
1487  }
1488 
1489  BKE_image_release_ibuf(ima, ibuf, NULL);
1490  DEG_id_tag_update(&ima->id, 0);
1491  }
1492 }
1493 
1495 {
1497 
1498  count_images(bkr);
1499  bake_images(bkr, &result);
1500  finish_images(bkr, &result);
1501 }
typedef float(TangentPoint)[2]
void DM_calc_loop_tangents(DerivedMesh *dm, bool calc_active_tangent, const char(*tangent_names)[MAX_NAME], int tangent_names_len)
void * DM_get_loop_data_layer(struct DerivedMesh *dm, int type)
Definition: DerivedMesh.cc:649
BLI_INLINE float * CCG_grid_elem_co(const CCGKey *key, CCGElem *elem, int x, int y)
Definition: BKE_ccg.h:130
BLI_INLINE float * CCG_grid_elem_no(const CCGKey *key, CCGElem *elem, int x, int y)
Definition: BKE_ccg.h:135
struct CCGElem CCGElem
Definition: BKE_ccg.h:46
int CustomData_get_layer_index(const struct CustomData *data, int type)
void BKE_image_release_ibuf(struct Image *ima, struct ImBuf *ibuf, void *lock)
Definition: image.c:5113
bool BKE_imbuf_alpha_test(struct ImBuf *ibuf)
Definition: image.c:2812
struct ImBuf * BKE_image_acquire_ibuf(struct Image *ima, struct ImageUser *iuser, void **r_lock)
Definition: image.c:5100
void BKE_image_mark_dirty(struct Image *image, struct ImBuf *ibuf)
General operations, lookup, etc. for materials.
void BKE_mesh_calc_poly_normal(const struct MPoly *mpoly, const struct MLoop *loopstart, const struct MVert *mvarray, float r_no[3])
int mdisp_rot_face_to_crn(struct MVert *mvert, struct MPoly *mpoly, struct MLoop *mloop, const struct MLoopTri *lt, const int face_side, const float u, const float v, float *x, float *y)
struct DerivedMesh * subsurf_make_derived_from_derived(struct DerivedMesh *dm, struct SubsurfModifierData *smd, const struct Scene *scene, float(*vertCos)[3], SubsurfFlags flags)
Definition: subsurf_ccg.c:2343
#define BLI_assert(a)
Definition: BLI_assert.h:58
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:128
struct LinkData * BLI_genericNodeN(void *data)
Definition: listbase.c:923
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:110
MINLINE float max_ff(float a, float b)
MINLINE float min_ff(float a, float b)
#define M_PI
Definition: BLI_math_base.h:38
void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
Definition: math_color.c:422
void resolve_tri_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
Definition: math_geom.c:4561
void resolve_quad_uv_v2(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
Definition: math_geom.c:4620
void interp_barycentric_tri_v3(float data[3][3], float u, float v, float res[3])
Definition: math_geom.c:4783
void interp_bilinear_quad_v3(float data[4][3], float u, float v, float res[3])
Definition: math_geom.c:4766
void zero_m3(float m[3][3])
Definition: math_matrix.c:41
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void normal_short_to_float_v3(float r[3], const short n[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void clamp_v2(float vec[2], const float min, const float max)
MINLINE float normalize_v3_length(float r[3], const float unit_scale)
MINLINE void add_v3_v3(float r[3], const float a[3])
pthread_spinlock_t SpinLock
Definition: BLI_threads.h:111
void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot)
Definition: threads.cc:159
int BLI_system_thread_count(void)
Definition: threads.cc:309
void BLI_threadpool_end(struct ListBase *threadbase)
Definition: threads.cc:289
void BLI_spin_init(SpinLock *spin)
Definition: threads.cc:447
void BLI_spin_unlock(SpinLock *spin)
Definition: threads.cc:480
void BLI_spin_lock(SpinLock *spin)
Definition: threads.cc:461
void BLI_threadpool_insert(struct ListBase *threadbase, void *callerdata)
Definition: threads.cc:239
void BLI_spin_end(SpinLock *spin)
Definition: threads.cc:495
#define SWAP(type, a, b)
#define UNUSED(x)
void DEG_id_tag_update(struct ID *id, int flag)
@ LIB_TAG_DOIT
Definition: DNA_ID.h:554
@ CD_ORIGINDEX
@ CD_MLOOPUV
@ CD_TANGENT
@ ME_SMOOTH
@ SUBSURF_UV_SMOOTH_PRESERVE_BOUNDARIES
Object is a sort of wrapper for general info.
#define R_IMF_PLANES_RGBA
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
#define FILTER_MASK_USED
Definition: IMB_imbuf.h:421
void imb_freemipmapImBuf(struct ImBuf *ibuf)
Definition: allocimbuf.c:80
void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
Definition: filter.c:429
void IMB_rectfill_alpha(struct ImBuf *ibuf, const float value)
Definition: rectop.c:1313
Contains defines and structs used throughout the imbuf module.
@ IB_RECT_INVALID
@ IB_MIPMAP_INVALID
@ IB_DISPLAY_BUFFER_INVALID
Read Guarded memory(de)allocation.
Group RGB to Bright Vector Camera CLAMP
#define RE_BAKE_AO
Definition: RE_pipeline.h:358
#define RE_BAKE_NORMALS
Definition: RE_pipeline.h:356
#define RE_BAKE_DISPLACEMENT
Definition: RE_pipeline.h:357
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
uint pos
uint col
DO_INLINE void filter(lfVector *V, fmatrix3x3 *S)
#define sinf(x)
#define cosf(x)
#define ceilf(x)
#define fabsf(x)
#define sqrtf(x)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
MINLINE unsigned char unit_float_to_uchar_clamp(float val)
static int multiresbake_test_break(MultiresBakeRender *bkr)
struct MultiresBakeQueue MultiresBakeQueue
struct BakeImBufuserData BakeImBufuserData
static void rasterize_half(const MBakeRast *bake_rast, const float s0_s, const float t0_s, const float s1_s, const float t1_s, const float s0_l, const float t0_l, const float s1_l, const float t1_l, const int y0_in, const int y1_in, const int is_mid_right)
static void bake_ibuf_normalize_displacement(ImBuf *ibuf, const float *displacement, const char *mask, float displacement_min, float displacement_max)
static void bake_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
static void count_images(MultiresBakeRender *bkr)
static void bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter)
void(* MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data, void *bake_data, ImBuf *ibuf, const int face_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y)
Definition: multires_bake.c:54
static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel, short *do_update)
static void finish_images(MultiresBakeRender *bkr, MultiresBakeResult *result)
struct MultiresBakeResult MultiresBakeResult
static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int tri_num, const int vert_index)
static void init_ccgdm_arrays(DerivedMesh *dm)
static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y)
static void do_multires_bake(MultiresBakeRender *bkr, Image *ima, bool require_tangent, MPassKnownData passKnownData, MInitBakeData initBakeData, MFreeBakeData freeBakeData, MultiresBakeResult *result)
static void interp_bilinear_mpoly(DerivedMesh *dm, MLoop *mloop, MPoly *mpoly, const float u, const float v, const int mode, float res[3])
static void interp_barycentric_mlooptri(DerivedMesh *dm, MLoop *mloop, const MLoopTri *lt, const float u, const float v, const int mode, float res[3])
static void free_normal_data(void *bake_data)
static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2])
static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *index_mp_to_orig, const int lvl, const MLoopTri *lt, const float u, const float v, float co[3], float n[3])
void RE_multires_bake_images(MultiresBakeRender *bkr)
static void * init_normal_data(MultiresBakeRender *bkr, Image *UNUSED(ima))
static void * init_heights_data(MultiresBakeRender *bkr, Image *ima)
static int multires_bake_queue_next_tri(MultiresBakeQueue *queue)
static void interp_bilinear_grid(CCGKey *key, CCGElem *grid, float crn_x, float crn_y, int mode, float res[3])
void(* MFreeBakeData)(void *bake_data)
Definition: multires_bake.c:67
void *(* MInitBakeData)(MultiresBakeRender *bkr, Image *ima)
Definition: multires_bake.c:66
static void flush_pixel(const MResolvePixelData *data, const int x, const int y)
static void free_heights_data(void *bake_data)
struct MultiresBakeThread MultiresBakeThread
static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *thread_data_v, void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl, const float st[2], float UNUSED(tangmat[3][3]), const int x, const int y)
static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, void *UNUSED(thread_data), void *bake_data, ImBuf *ibuf, const int tri_index, const int lvl, const float st[2], float tangmat[3][3], const int x, const int y)
void(* MFlushPixel)(const MResolvePixelData *data, const int x, const int y)
Definition: multires_bake.c:93
static void * do_multires_bake_thread(void *data_v)
double sign(double arg)
Definition: utility.h:250
ThreadQueue * queue
all scheduled work for the cpu
ListBase threads
list of all thread for every CPUDevice in cpudevices a thread exists.
#define I
float * displacement_buffer
Definition: BKE_ccg.h:48
int grid_size
Definition: BKE_ccg.h:56
int(* getGridSize)(DerivedMesh *dm)
struct MLoop *(* getLoopArray)(DerivedMesh *dm)
void(* getVertNo)(DerivedMesh *dm, int index, float r_no[3])
struct MVert *(* getVertArray)(DerivedMesh *dm)
const struct MLoopTri *(* getLoopTriArray)(DerivedMesh *dm)
int(* getNumLoopTri)(DerivedMesh *dm)
struct CCGElem **(* getGridData)(DerivedMesh *dm)
void *(* getLoopDataArray)(DerivedMesh *dm, int type)
int(* getNumGrids)(DerivedMesh *dm)
void *(* getPolyDataArray)(DerivedMesh *dm, int type)
void(* getGridKey)(DerivedMesh *dm, struct CCGKey *key)
struct MPoly *(* getPolyArray)(DerivedMesh *dm)
CustomData loopData
void(* release)(DerivedMesh *dm)
void(* getVertCo)(DerivedMesh *dm, int index, float r_co[3])
int *(* getGridOffset)(DerivedMesh *dm)
int tag
Definition: DNA_ID.h:292
void * userdata
struct ImBuf * mipmap[IMB_MIPMAP_LEVELS]
int userflags
unsigned char planes
unsigned int * rect
float * rect_float
void * data
Definition: DNA_listBase.h:42
struct LinkData * next
Definition: DNA_listBase.h:41
void * first
Definition: DNA_listBase.h:47
MFlushPixel flush_pixel
Definition: multires_bake.c:99
const MResolvePixelData * data
Definition: multires_bake.c:98
char * texels
Definition: multires_bake.c:97
short * do_update
DerivedMesh * ssdm
const int * orig_index_mp_to_orig
unsigned int poly
unsigned int tri[3]
unsigned int v
const int * orig_index_mp_to_orig
short mat_nr
Image ** image_array
Definition: multires_bake.c:90
const float * precomputed_normals
Definition: multires_bake.c:80
DerivedMesh * hires_dm
Definition: multires_bake.c:83
const MLoopTri * mlooptri
Definition: multires_bake.c:78
DerivedMesh * lores_dm
Definition: multires_bake.c:83
MPassKnownData pass_data
Definition: multires_bake.c:88
DerivedMesh * hires_dm
DerivedMesh * lores_dm
struct MultiresBakeRender::@1137 ob_image
MultiresBakeQueue * queue
MResolvePixelData data
MultiresBakeRender * bkr
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
#define G(x, y, z)
uint len
ParamHandle ** handles