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