Blender  V3.3
texture_margin.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include "BLI_assert.h"
9 #include "BLI_math_geom.h"
10 #include "BLI_math_vec_types.hh"
11 #include "BLI_math_vector.hh"
12 #include "BLI_vector.hh"
13 
14 #include "BKE_DerivedMesh.h"
15 #include "BKE_customdata.h"
16 #include "BKE_mesh.h"
17 
18 #include "DNA_mesh_types.h"
19 #include "DNA_meshdata_types.h"
20 
21 #include "IMB_imbuf.h"
22 #include "IMB_imbuf_types.h"
23 
24 #include "MEM_guardedalloc.h"
25 
26 #include "zbuf.h" // for rasterizer
27 
28 #include "RE_texture_margin.h"
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <valarray>
33 
35 
41  static const int directions[8][2];
42  static const int distances[8];
43 
45  Vector<int> loop_adjacency_map_;
47  Vector<int> loop_to_poly_map_;
48 
49  int w_, h_;
50  float uv_offset_[2];
51  Vector<uint32_t> pixel_data_;
52  ZSpan zspan_;
53  uint32_t value_to_store_;
54  char *mask_;
55 
56  MPoly const *mpoly_;
57  MLoop const *mloop_;
58  MLoopUV const *mloopuv_;
59  int totpoly_;
60  int totloop_;
61  int totedge_;
62 
63  public:
65  size_t h,
66  const float uv_offset[2],
67  MPoly const *mpoly,
68  MLoop const *mloop,
69  MLoopUV const *mloopuv,
70  int totpoly,
71  int totloop,
72  int totedge)
73  : w_(w),
74  h_(h),
75  mpoly_(mpoly),
76  mloop_(mloop),
77  mloopuv_(mloopuv),
78  totpoly_(totpoly),
79  totloop_(totloop),
80  totedge_(totedge)
81  {
82  copy_v2_v2(uv_offset_, uv_offset);
83 
84  pixel_data_.resize(w_ * h_, 0xFFFFFFFF);
85 
86  zbuf_alloc_span(&zspan_, w_, h_);
87 
88  build_tables();
89  }
90 
92  {
93  zbuf_free_span(&zspan_);
94  }
95 
96  inline void set_pixel(int x, int y, uint32_t value)
97  {
98  BLI_assert(x < w_);
99  BLI_assert(x >= 0);
100  pixel_data_[y * w_ + x] = value;
101  }
102 
103  inline uint32_t get_pixel(int x, int y) const
104  {
105  if (x < 0 || y < 0 || x >= w_ || y >= h_) {
106  return 0xFFFFFFFF;
107  }
108 
109  return pixel_data_[y * w_ + x];
110  }
111 
112  void rasterize_tri(float *v1, float *v2, float *v3, uint32_t value, char *mask)
113  {
114  /* NOTE: This is not thread safe, because the value to be written by the rasterizer is
115  * a class member. If this is ever made multi-threaded each thread needs to get its own. */
116  value_to_store_ = value;
117  mask_ = mask;
119  &zspan_, this, &(v1[0]), &(v2[0]), &(v3[0]), TextureMarginMap::zscan_store_pixel);
120  }
121 
122  static void zscan_store_pixel(
123  void *map, int x, int y, [[maybe_unused]] float u, [[maybe_unused]] float v)
124  {
125  /* NOTE: Not thread safe, see comment above. */
126  TextureMarginMap *m = static_cast<TextureMarginMap *>(map);
127  m->set_pixel(x, y, m->value_to_store_);
128  if (m->mask_) {
129  m->mask_[y * m->w_ + x] = 1;
130  }
131  }
132 
133 /* The map contains 2 kinds of pixels: DijkstraPixels and polygon indices. The top bit determines
134  * what kind it is. With the top bit set, it is a 'dijkstra' pixel. The bottom 4 bits encode the
135  * direction of the shortest path and the remaining 27 bits are used to store the distance. If
136  * the top bit is not set, the rest of the bits is used to store the polygon index.
137  */
138 #define PackDijkstraPixel(dist, dir) (0x80000000 + ((dist) << 4) + (dir))
139 #define DijkstraPixelGetDistance(dp) (((dp) ^ 0x80000000) >> 4)
140 #define DijkstraPixelGetDirection(dp) ((dp)&0xF)
141 #define IsDijkstraPixel(dp) ((dp)&0x80000000)
142 #define DijkstraPixelIsUnset(dp) ((dp) == 0xFFFFFFFF)
143 
148  void grow_dijkstra(int margin)
149  {
150  class DijkstraActivePixel {
151  public:
152  DijkstraActivePixel(int dist, int _x, int _y) : distance(dist), x(_x), y(_y)
153  {
154  }
155  int distance;
156  int x, y;
157  };
158  auto cmp_dijkstrapixel_fun = [](DijkstraActivePixel const &a1, DijkstraActivePixel const &a2) {
159  return a1.distance > a2.distance;
160  };
161 
162  Vector<DijkstraActivePixel> active_pixels;
163  for (int y = 0; y < h_; y++) {
164  for (int x = 0; x < w_; x++) {
166  for (int i = 0; i < 8; i++) {
167  int xx = x - directions[i][0];
168  int yy = y - directions[i][1];
169 
170  if (xx >= 0 && xx < w_ && yy >= 0 && yy < w_ && !IsDijkstraPixel(get_pixel(xx, yy))) {
171  set_pixel(x, y, PackDijkstraPixel(distances[i], i));
172  active_pixels.append(DijkstraActivePixel(distances[i], x, y));
173  break;
174  }
175  }
176  }
177  }
178  }
179 
180  /* Not strictly needed because at this point it already is a heap. */
181 #if 0
182  std::make_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
183 #endif
184 
185  while (active_pixels.size()) {
186  std::pop_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
187  DijkstraActivePixel p = active_pixels.pop_last();
188 
189  int dist = p.distance;
190 
191  if (dist < 2 * (margin + 1)) {
192  for (int i = 0; i < 8; i++) {
193  int x = p.x + directions[i][0];
194  int y = p.y + directions[i][1];
195  if (x >= 0 && x < w_ && y >= 0 && y < h_) {
196  uint32_t dp = get_pixel(x, y);
197  if (IsDijkstraPixel(dp) && (DijkstraPixelGetDistance(dp) > dist + distances[i])) {
199  set_pixel(x, y, PackDijkstraPixel(dist + distances[i], i));
200  active_pixels.append(DijkstraActivePixel(dist + distances[i], x, y));
201  std::push_heap(active_pixels.begin(), active_pixels.end(), cmp_dijkstrapixel_fun);
202  }
203  }
204  }
205  }
206  }
207  }
208 
214  void lookup_pixels(ImBuf *ibuf, char *mask, int maxPolygonSteps)
215  {
216  for (int y = 0; y < h_; y++) {
217  for (int x = 0; x < w_; x++) {
218  uint32_t dp = get_pixel(x, y);
219  if (IsDijkstraPixel(dp) && !DijkstraPixelIsUnset(dp)) {
220  int dist = DijkstraPixelGetDistance(dp);
221  int direction = DijkstraPixelGetDirection(dp);
222 
223  int xx = x;
224  int yy = y;
225 
226  /* Follow the dijkstra directions to find the polygon this margin pixels belongs to. */
227  while (dist > 0) {
228  xx -= directions[direction][0];
229  yy -= directions[direction][1];
230  dp = get_pixel(xx, yy);
231  dist -= distances[direction];
232  BLI_assert(!dist || (dist == DijkstraPixelGetDistance(dp)));
233  direction = DijkstraPixelGetDirection(dp);
234  }
235 
236  uint32_t poly = get_pixel(xx, yy);
237 
238  BLI_assert(!IsDijkstraPixel(poly));
239 
240  float destX, destY;
241 
242  int other_poly;
243  bool found_pixel_in_polygon = false;
244  if (lookup_pixel_polygon_neighbourhood(x, y, &poly, &destX, &destY, &other_poly)) {
245 
246  for (int i = 0; i < maxPolygonSteps; i++) {
247  /* Force to pixel grid. */
248  int nx = (int)round(destX);
249  int ny = (int)round(destY);
250  uint32_t polygon_from_map = get_pixel(nx, ny);
251  if (other_poly == polygon_from_map) {
252  found_pixel_in_polygon = true;
253  break;
254  }
255 
256  float dist_to_edge;
257  /* Look up again, but starting from the polygon we were expected to land in. */
258  if (!lookup_pixel(nx, ny, other_poly, &destX, &destY, &other_poly, &dist_to_edge)) {
259  found_pixel_in_polygon = false;
260  break;
261  }
262  }
263 
264  if (found_pixel_in_polygon) {
265  bilinear_interpolation(ibuf, ibuf, destX, destY, x, y);
266  /* Add our new pixels to the assigned pixel map. */
267  mask[y * w_ + x] = 1;
268  }
269  }
270  }
271  else if (DijkstraPixelIsUnset(dp) || !IsDijkstraPixel(dp)) {
272  /* These are not margin pixels, make sure the extend filter which is run after this step
273  * leaves them alone.
274  */
275  mask[y * w_ + x] = 1;
276  }
277  }
278  }
279  }
280 
281  private:
282  float2 uv_to_xy(MLoopUV const &mloopuv) const
283  {
284  float2 ret;
285  ret.x = (((mloopuv.uv[0] - uv_offset_[0]) * w_) - (0.5f + 0.001f));
286  ret.y = (((mloopuv.uv[1] - uv_offset_[1]) * h_) - (0.5f + 0.001f));
287  return ret;
288  }
289 
290  void build_tables()
291  {
292  loop_to_poly_map_.resize(totloop_);
293  for (int i = 0; i < totpoly_; i++) {
294  for (int j = 0; j < mpoly_[i].totloop; j++) {
295  int l = j + mpoly_[i].loopstart;
296  loop_to_poly_map_[l] = i;
297  }
298  }
299 
300  loop_adjacency_map_.resize(totloop_, -1);
301 
302  Vector<int> tmpmap;
303  tmpmap.resize(totedge_, -1);
304 
305  for (size_t i = 0; i < totloop_; i++) {
306  int edge = mloop_[i].e;
307  if (tmpmap[edge] == -1) {
308  loop_adjacency_map_[i] = -1;
309  tmpmap[edge] = i;
310  }
311  else {
312  BLI_assert(tmpmap[edge] >= 0);
313  loop_adjacency_map_[i] = tmpmap[edge];
314  loop_adjacency_map_[tmpmap[edge]] = i;
315  }
316  }
317  }
318 
325  bool lookup_pixel_polygon_neighbourhood(
326  float x, float y, uint32_t *r_start_poly, float *r_destx, float *r_desty, int *r_other_poly)
327  {
328  float found_dist;
329  if (lookup_pixel(x, y, *r_start_poly, r_destx, r_desty, r_other_poly, &found_dist)) {
330  return true;
331  }
332 
333  int loopstart = mpoly_[*r_start_poly].loopstart;
334  int totloop = mpoly_[*r_start_poly].totloop;
335 
336  float destx, desty;
337  int foundpoly;
338 
339  float mindist = -1.0f;
340 
341  /* Loop over all adjacent polygons and determine which edge is closest.
342  * This could be optimized by only inspecting neighbors which are on the edge of an island.
343  * But it seems fast enough for now and that would add a lot of complexity. */
344  for (int i = 0; i < totloop; i++) {
345  int otherloop = loop_adjacency_map_[i + loopstart];
346 
347  if (otherloop < 0) {
348  continue;
349  }
350 
351  uint32_t poly = loop_to_poly_map_[otherloop];
352 
353  if (lookup_pixel(x, y, poly, &destx, &desty, &foundpoly, &found_dist)) {
354  if (mindist < 0.f || found_dist < mindist) {
355  mindist = found_dist;
356  *r_other_poly = foundpoly;
357  *r_destx = destx;
358  *r_desty = desty;
359  *r_start_poly = poly;
360  }
361  }
362  }
363 
364  return mindist >= 0.0f;
365  }
366 
373  bool lookup_pixel(float x,
374  float y,
375  int src_poly,
376  float *r_destx,
377  float *r_desty,
378  int *r_other_poly,
379  float *r_dist_to_edge)
380  {
381  float2 point(x, y);
382 
383  *r_destx = *r_desty = 0;
384 
385  int found_edge = -1;
386  float found_dist = -1;
387  float found_t = 0;
388 
389  /* Find the closest edge on which the point x,y can be projected.
390  */
391  for (size_t i = 0; i < mpoly_[src_poly].totloop; i++) {
392  int l1 = mpoly_[src_poly].loopstart + i;
393  int l2 = l1 + 1;
394  if (l2 >= mpoly_[src_poly].loopstart + mpoly_[src_poly].totloop) {
395  l2 = mpoly_[src_poly].loopstart;
396  }
397  /* edge points */
398  float2 edgepoint1 = uv_to_xy(mloopuv_[l1]);
399  float2 edgepoint2 = uv_to_xy(mloopuv_[l2]);
400  /* Vector AB is the vector from the first edge point to the second edge point.
401  * Vector AP is the vector from the first edge point to our point under investigation. */
402  float2 ab = edgepoint2 - edgepoint1;
403  float2 ap = point - edgepoint1;
404 
405  /* Project ap onto ab. */
406  float dotv = math::dot(ab, ap);
407 
408  float ablensq = math::length_squared(ab);
409 
410  float t = dotv / ablensq;
411 
412  if (t >= 0.0 && t <= 1.0) {
413 
414  /* Find the point on the edge closest to P */
415  float2 reflect_point = edgepoint1 + (t * ab);
416  /* This is the vector to P, so 90 degrees out from the edge. */
417  float2 reflect_vec = reflect_point - point;
418 
419  float reflectLen = sqrt(reflect_vec[0] * reflect_vec[0] + reflect_vec[1] * reflect_vec[1]);
420  float cross = ab[0] * reflect_vec[1] - ab[1] * reflect_vec[0];
421  /* Only if P is on the outside of the edge, which means the cross product is positive,
422  * we consider this edge.
423  */
424  bool valid = (cross > 0.0);
425 
426  if (valid && (found_dist < 0 || reflectLen < found_dist)) {
427  /* Stother_ab the info of the closest edge so far. */
428  found_dist = reflectLen;
429  found_t = t;
430  found_edge = i + mpoly_[src_poly].loopstart;
431  }
432  }
433  }
434 
435  if (found_edge < 0) {
436  return false;
437  }
438 
439  *r_dist_to_edge = found_dist;
440 
441  /* Get the 'other' edge. I.E. the UV edge from the neighbor polygon. */
442  int other_edge = loop_adjacency_map_[found_edge];
443 
444  if (other_edge < 0) {
445  return false;
446  }
447 
448  int dst_poly = loop_to_poly_map_[other_edge];
449 
450  if (r_other_poly) {
451  *r_other_poly = dst_poly;
452  }
453 
454  int other_edge2 = other_edge + 1;
455  if (other_edge2 >= mpoly_[dst_poly].loopstart + mpoly_[dst_poly].totloop) {
456  other_edge2 = mpoly_[dst_poly].loopstart;
457  }
458 
459  float2 other_edgepoint1 = uv_to_xy(mloopuv_[other_edge]);
460  float2 other_edgepoint2 = uv_to_xy(mloopuv_[other_edge2]);
461 
462  /* Calculate the vector from the order edges last point to its first point. */
463  float2 other_ab = other_edgepoint1 - other_edgepoint2;
464  float2 other_reflect_point = other_edgepoint2 + (found_t * other_ab);
465  float2 perpendicular_other_ab;
466  perpendicular_other_ab.x = other_ab.y;
467  perpendicular_other_ab.y = -other_ab.x;
468 
469  /* The new point is dound_dist distance from other_reflect_point at a 90 degree angle to
470  * other_ab */
471  float2 new_point = other_reflect_point + (found_dist / math::length(perpendicular_other_ab)) *
472  perpendicular_other_ab;
473 
474  *r_destx = new_point.x;
475  *r_desty = new_point.y;
476 
477  return true;
478  }
479 }; // class TextureMarginMap
480 
481 const int TextureMarginMap::directions[8][2] = {
482  {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
483 const int TextureMarginMap::distances[8] = {2, 3, 2, 3, 2, 3, 2, 3};
484 
485 static void generate_margin(ImBuf *ibuf,
486  char *mask,
487  const int margin,
488  const Mesh *me,
489  DerivedMesh *dm,
490  char const *uv_layer,
491  const float uv_offset[2])
492 {
493 
494  MPoly *mpoly;
495  MLoop *mloop;
496  const MLoopUV *mloopuv;
497  int totpoly, totloop, totedge;
498 
499  int tottri;
500  const MLoopTri *looptri;
501  MLoopTri *looptri_mem = nullptr;
502 
503  if (me) {
504  BLI_assert(dm == nullptr);
505  totpoly = me->totpoly;
506  totloop = me->totloop;
507  totedge = me->totedge;
508  mpoly = me->mpoly;
509  mloop = me->mloop;
510 
511  if ((uv_layer == nullptr) || (uv_layer[0] == '\0')) {
512  mloopuv = static_cast<const MLoopUV *>(CustomData_get_layer(&me->ldata, CD_MLOOPUV));
513  }
514  else {
515  int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
516  mloopuv = static_cast<const MLoopUV *>(
517  CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, uv_id));
518  }
519 
520  tottri = poly_to_tri_count(me->totpoly, me->totloop);
521  looptri_mem = static_cast<MLoopTri *>(MEM_mallocN(sizeof(*looptri) * tottri, __func__));
523  me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri_mem);
524  looptri = looptri_mem;
525  }
526  else {
527  BLI_assert(dm != nullptr);
528  BLI_assert(me == nullptr);
529  totpoly = dm->getNumPolys(dm);
530  totedge = dm->getNumEdges(dm);
531  totloop = dm->getNumLoops(dm);
532  mpoly = dm->getPolyArray(dm);
533  mloop = dm->getLoopArray(dm);
534  mloopuv = (MLoopUV const *)dm->getLoopDataArray(dm, CD_MLOOPUV);
535 
536  looptri = dm->getLoopTriArray(dm);
537  tottri = dm->getNumLoopTri(dm);
538  }
539 
541  ibuf->x, ibuf->y, uv_offset, mpoly, mloop, mloopuv, totpoly, totloop, totedge);
542 
543  bool draw_new_mask = false;
544  /* Now the map contains 3 sorts of values: 0xFFFFFFFF for empty pixels, `0x80000000 + polyindex`
545  * for margin pixels, just `polyindex` for poly pixels. */
546  if (mask) {
547  mask = (char *)MEM_dupallocN(mask);
548  }
549  else {
550  mask = (char *)MEM_callocN(sizeof(char) * ibuf->x * ibuf->y, __func__);
551  draw_new_mask = true;
552  }
553 
554  for (int i = 0; i < tottri; i++) {
555  const MLoopTri *lt = &looptri[i];
556  float vec[3][2];
557 
558  for (int a = 0; a < 3; a++) {
559  const float *uv = mloopuv[lt->tri[a]].uv;
560 
561  /* NOTE(campbell): workaround for pixel aligned UVs which are common and can screw up our
562  * intersection tests where a pixel gets in between 2 faces or the middle of a quad,
563  * camera aligned quads also have this problem but they are less common.
564  * Add a small offset to the UVs, fixes bug T18685. */
565  vec[a][0] = (uv[0] - uv_offset[0]) * (float)ibuf->x - (0.5f + 0.001f);
566  vec[a][1] = (uv[1] - uv_offset[1]) * (float)ibuf->y - (0.5f + 0.002f);
567  }
568 
569  /* NOTE: we need the top bit for the dijkstra distance map. */
570  BLI_assert(lt->poly < 0x80000000);
571 
572  map.rasterize_tri(vec[0], vec[1], vec[2], lt->poly, draw_new_mask ? mask : nullptr);
573  }
574 
575  char *tmpmask = (char *)MEM_dupallocN(mask);
576  /* Extend (with averaging) by 2 pixels. Those will be overwritten, but it
577  * helps linear interpolations on the edges of polygons. */
578  IMB_filter_extend(ibuf, tmpmask, 2);
579  MEM_freeN(tmpmask);
580 
581  map.grow_dijkstra(margin);
582 
583  /* Looking further than 3 polygons away leads to so much cumulative rounding
584  * that it isn't worth it. So hard-code it to 3. */
585  map.lookup_pixels(ibuf, mask, 3);
586 
587  /* Use the extend filter to fill in the missing pixels at the corners, not strictly correct, but
588  * the visual difference seems very minimal. This also catches pixels we missed because of very
589  * narrow polygons.
590  */
591  IMB_filter_extend(ibuf, mask, margin);
592 
593  MEM_freeN(mask);
594 
595  if (looptri_mem) {
596  MEM_freeN(looptri_mem);
597  }
598 }
599 
600 } // namespace blender::render::texturemargin
601 
603  char *mask,
604  const int margin,
605  const Mesh *me,
606  char const *uv_layer,
607  const float uv_offset[2])
608 {
610  ibuf, mask, margin, me, nullptr, uv_layer, uv_offset);
611 }
612 
614  ImBuf *ibuf, char *mask, const int margin, DerivedMesh *dm, const float uv_offset[2])
615 {
617  ibuf, mask, margin, nullptr, dm, nullptr, uv_offset);
618 }
CustomData interface, see also DNA_customdata_types.h.
void * CustomData_get_layer_n(const struct CustomData *data, int type, int n)
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_get_named_layer(const struct CustomData *data, int type, const char *name)
void BKE_mesh_recalc_looptri(const struct MLoop *mloop, const struct MPoly *mpoly, const struct MVert *mvert, int totloop, int totpoly, struct MLoopTri *mlooptri)
#define BLI_assert(a)
Definition: BLI_assert.h:46
sqrt(x)+1/max(0
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
MINLINE void copy_v2_v2(float r[2], const float a[2])
@ CD_MLOOPUV
_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 ny
_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
_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 t
_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 v1
void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter)
Definition: filter.c:406
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
void resize(const int64_t new_size)
Definition: BLI_vector.hh:353
void set_pixel(int x, int y, uint32_t value)
static void zscan_store_pixel(void *map, int x, int y, [[maybe_unused]] float u, [[maybe_unused]] float v)
void lookup_pixels(ImBuf *ibuf, char *mask, int maxPolygonSteps)
void rasterize_tri(float *v1, float *v2, float *v3, uint32_t value, char *mask)
TextureMarginMap(size_t w, size_t h, const float uv_offset[2], MPoly const *mpoly, MLoop const *mloop, MLoopUV const *mloopuv, int totpoly, int totloop, int totedge)
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)
Definition: math_float4.h:513
BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, unsigned char *byte_output, float *float_output, int width, int height, int components, float u, float v, bool wrap_x, bool wrap_y)
Definition: math_interp.c:248
static unsigned a[3]
Definition: RandGen.cpp:78
void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty, float clipcrop)
void zbuf_free_span(ZSpan *zspan)
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, 3 > cross(const vec_base< T, 3 > &a, const vec_base< T, 3 > &b)
T length(const vec_base< T, Size > &a)
T distance(const T &a, const T &b)
T length_squared(const vec_base< T, Size > &a)
static void generate_margin(ImBuf *ibuf, char *mask, const int margin, const Mesh *me, DerivedMesh *dm, char const *uv_layer, const float uv_offset[2])
SocketIndexByIdentifierMap * map
return ret
unsigned int uint32_t
Definition: stdint.h:80
struct MLoop *(* getLoopArray)(DerivedMesh *dm)
const struct MLoopTri *(* getLoopTriArray)(DerivedMesh *dm)
int(* getNumLoopTri)(DerivedMesh *dm)
int(* getNumPolys)(DerivedMesh *dm)
int(* getNumEdges)(DerivedMesh *dm)
void *(* getLoopDataArray)(DerivedMesh *dm, int type)
struct MPoly *(* getPolyArray)(DerivedMesh *dm)
int(* getNumLoops)(DerivedMesh *dm)
unsigned int poly
unsigned int tri[3]
unsigned int e
struct MVert * mvert
int totedge
struct MLoop * mloop
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
Definition: zbuf.h:14
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
#define PackDijkstraPixel(dist, dir)
void RE_generate_texturemargin_adjacentfaces_dm(ImBuf *ibuf, char *mask, const int margin, DerivedMesh *dm, const float uv_offset[2])
#define DijkstraPixelIsUnset(dp)
#define DijkstraPixelGetDistance(dp)
void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf, char *mask, const int margin, const Mesh *me, char const *uv_layer, const float uv_offset[2])
#define DijkstraPixelGetDirection(dp)
#define IsDijkstraPixel(dp)
void zspan_scanconvert(ZSpan *zspan, void *handle, float *v1, float *v2, float *v3, void(*func)(void *, int, int, float, float))
Definition: zbuf.c:159