40 static const int directions[8][2];
41 static const int distances[8];
52 uint32_t value_to_store_;
64 const float uv_offset[2],
72 corner_edges_(corner_edges),
78 pixel_data_.resize(w_ * h_, 0xFFFFFFFF);
94 pixel_data_[
y * w_ +
x] = value;
103 return pixel_data_[
y * w_ +
x];
110 value_to_store_ = value;
112 write_mask_ = writemask;
118 void *map,
int x,
int y, [[maybe_unused]]
float u, [[maybe_unused]]
float v)
123 if (m->write_mask_) {
125 m->mask_[
y * m->w_ +
x] = 1;
132 if (m->mask_[
y * m->w_ +
x] != 0) {
147#define PackDijkstraPixel(dist, dir) (0x80000000 + ((dist) << 4) + (dir))
148#define DijkstraPixelGetDistance(dp) (((dp) ^ 0x80000000) >> 4)
149#define DijkstraPixelGetDirection(dp) ((dp) & 0xF)
150#define IsDijkstraPixel(dp) ((dp) & 0x80000000)
151#define DijkstraPixelIsUnset(dp) ((dp) == 0xFFFFFFFF)
159 class DijkstraActivePixel {
161 DijkstraActivePixel(
int dist,
int _x,
int _y) :
distance(dist),
x(_x),
y(_y) {}
165 auto cmp_dijkstrapixel_fun = [](DijkstraActivePixel
const &a1, DijkstraActivePixel
const &a2) {
166 return a1.distance > a2.distance;
170 for (
int y = 0;
y < h_;
y++) {
171 for (
int x = 0;
x < w_;
x++) {
173 for (
int i = 0;
i < 8;
i++) {
174 int xx =
x - directions[
i][0];
175 int yy =
y - directions[
i][1];
179 active_pixels.
append(DijkstraActivePixel(distances[
i],
x,
y));
189 std::make_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
192 while (active_pixels.
size()) {
193 std::pop_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
194 DijkstraActivePixel p = active_pixels.
pop_last();
196 int dist = p.distance;
198 if (dist < 2 * (margin + 1)) {
199 for (
int i = 0;
i < 8;
i++) {
200 int x = p.x + directions[
i][0];
201 int y = p.y + directions[
i][1];
207 active_pixels.
append(DijkstraActivePixel(dist + distances[
i],
x,
y));
208 std::push_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
225 size_t pixel_index = 0;
226 for (
int y = 0;
y < h_;
y++) {
227 for (
int x = 0;
x < w_;
x++) {
228 uint32_t dp = pixel_data_[pixel_index];
238 xx -= directions[direction][0];
239 yy -= directions[direction][1];
241 dist -= distances[direction];
253 bool found_pixel_in_polygon =
false;
254 if (lookup_pixel_polygon_neighborhood(
x,
y, &face, &destX, &destY, &other_poly)) {
256 for (
int i = 0;
i < maxPolygonSteps;
i++) {
258 int nx = int(
round(destX));
259 int ny = int(
round(destY));
260 uint32_t polygon_from_map =
get_pixel(nx, ny);
261 if (other_poly == polygon_from_map) {
262 found_pixel_in_polygon =
true;
268 if (!lookup_pixel(nx, ny, other_poly, &destX, &destY, &other_poly, &dist_to_edge)) {
269 found_pixel_in_polygon =
false;
274 if (found_pixel_in_polygon) {
284 mask[pixel_index] = 1;
292 mask[pixel_index] = 1;
303 ret.x = (((mloopuv[0] - uv_offset_[0]) * w_) - (0.5f + 0.001f));
304 ret.y = (((mloopuv[1] - uv_offset_[1]) * h_) - (0.5f + 0.001f));
312 loop_adjacency_map_.
resize(corner_edges_.
size(), -1);
315 tmpmap.
resize(totedge_, -1);
318 int edge = corner_edges_[
i];
319 if (tmpmap[edge] == -1) {
320 loop_adjacency_map_[
i] = -1;
325 loop_adjacency_map_[
i] = tmpmap[edge];
326 loop_adjacency_map_[tmpmap[edge]] =
i;
337 bool lookup_pixel_polygon_neighborhood(
338 float x,
float y, uint32_t *r_start_poly,
float *r_destx,
float *r_desty,
int *r_other_poly)
341 if (lookup_pixel(
x,
y, *r_start_poly, r_destx, r_desty, r_other_poly, &found_dist)) {
345 int loopstart = faces_[*r_start_poly].start();
346 int totloop = faces_[*r_start_poly].size();
351 float mindist = -1.0f;
356 for (
int i = 0;
i < totloop;
i++) {
357 int otherloop = loop_adjacency_map_[
i + loopstart];
363 uint32_t face = loop_to_face_map_[otherloop];
365 if (lookup_pixel(
x,
y, face, &destx, &desty, &foundpoly, &found_dist)) {
366 if (mindist < 0.0f || found_dist < mindist) {
367 mindist = found_dist;
368 *r_other_poly = foundpoly;
371 *r_start_poly = face;
376 return mindist >= 0.0f;
385 bool lookup_pixel(
float x,
391 float *r_dist_to_edge)
395 *r_destx = *r_desty = 0;
398 float found_dist = -1;
403 for (
size_t i = 0;
i < faces_[src_poly].size();
i++) {
404 int l1 = faces_[src_poly].start() +
i;
406 if (l2 >= faces_[src_poly].start() + faces_[src_poly].
size()) {
407 l2 = faces_[src_poly].start();
410 float2 edgepoint1 = uv_to_xy(mloopuv_[l1]);
411 float2 edgepoint2 = uv_to_xy(mloopuv_[l2]);
414 float2 ab = edgepoint2 - edgepoint1;
415 float2 ap = point - edgepoint1;
422 float t = dotv / ablensq;
424 if (t >= 0.0 && t <= 1.0) {
427 float2 reflect_point = edgepoint1 + (t * ab);
429 float2 reflect_vec = reflect_point - point;
431 float reflectLen =
sqrt(reflect_vec[0] * reflect_vec[0] + reflect_vec[1] * reflect_vec[1]);
432 float cross = ab[0] * reflect_vec[1] - ab[1] * reflect_vec[0];
436 bool valid = (
cross > 0.0);
438 if (valid && (found_dist < 0 || reflectLen < found_dist)) {
440 found_dist = reflectLen;
442 found_edge =
i + faces_[src_poly].start();
447 if (found_edge < 0) {
451 *r_dist_to_edge = found_dist;
454 int other_edge = loop_adjacency_map_[found_edge];
456 if (other_edge < 0) {
460 int dst_poly = loop_to_face_map_[other_edge];
463 *r_other_poly = dst_poly;
466 int other_edge2 = other_edge + 1;
467 if (other_edge2 >= faces_[dst_poly].start() + faces_[dst_poly].
size()) {
468 other_edge2 = faces_[dst_poly].start();
471 float2 other_edgepoint1 = uv_to_xy(mloopuv_[other_edge]);
472 float2 other_edgepoint2 = uv_to_xy(mloopuv_[other_edge2]);
475 float2 other_ab = other_edgepoint1 - other_edgepoint2;
476 float2 other_reflect_point = other_edgepoint2 + (found_t * other_ab);
477 float2 perpendicular_other_ab;
478 perpendicular_other_ab.x = other_ab.
y;
479 perpendicular_other_ab.y = -other_ab.
x;
483 float2 new_point = other_reflect_point + (found_dist /
math::length(perpendicular_other_ab)) *
484 perpendicular_other_ab;
486 *r_destx = new_point.
x;
487 *r_desty = new_point.
y;
493const int TextureMarginMap::directions[8][2] = {
494 {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
495const int TextureMarginMap::distances[8] = {2, 3, 2, 3, 2, 3, 2, 3};
506 const float uv_offset[2])
516 bool draw_new_mask =
false;
524 draw_new_mask =
true;
528 const int3 tri = corner_tris[
i];
531 for (
int a = 0; a < 3; a++) {
532 const float *uv = mloopuv[tri[a]];
538 vec[a][0] = (uv[0] - uv_offset[0]) *
float(ibuf->
x) - (0.5f + 0.001f);
539 vec[a][1] = (uv[1] - uv_offset[1]) *
float(ibuf->
y) - (0.5f + 0.002f);
575 char const *uv_layer,
576 const float uv_offset[2])
590 mesh->vert_positions(),
593 mesh->corner_edges(),
594 mesh->corner_verts(),
612 {dm->getCornerEdgeArray(dm), dm->getNumLoops(dm)},
613 {dm->getCornerVertArray(dm), dm->getNumLoops(dm)},
614 {mloopuv, dm->getNumLoops(dm)},
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_active_layer_name(const CustomData *data, eCustomDataType type)
MINLINE int poly_to_tri_count(int poly_count, int corner_count)
MINLINE void copy_v2_v2(float r[2], const float a[2])
void IMB_filter_extend(ImBuf *ibuf, char *mask, int filter)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
IndexRange index_range() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
void append(const T &value)
void resize(const int64_t new_size)
GAttributeReader lookup(const StringRef attribute_id) const
void rasterize_tri(float *v1, float *v2, float *v3, uint32_t value, char *mask, bool writemask)
void set_pixel(int x, int y, uint32_t value)
TextureMarginMap(size_t w, size_t h, const float uv_offset[2], const int totedge, const OffsetIndices< int > faces, const Span< int > corner_edges, const Span< float2 > mloopuv)
void grow_dijkstra(int margin)
void lookup_pixels(ImBuf *ibuf, char *mask, int maxPolygonSteps)
static void zscan_store_pixel(void *map, int x, int y, float u, float v)
uint32_t get_pixel(int x, int y) const
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
float distance(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void corner_tris_calc(Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, MutableSpan< int3 > corner_tris)
Array< int > build_corner_to_face_map(OffsetIndices< int > faces)
void corner_tris_calc_face_indices(OffsetIndices< int > faces, MutableSpan< int > tri_faces)
uchar4 interpolate_bilinear_border_byte(const ImBuf *in, float u, float v)
float4 interpolate_bilinear_border_fl(const ImBuf *in, float u, float v)
T length_squared(const VecBase< T, Size > &a)
T length(const VecBase< T, Size > &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
static void generate_margin(ImBuf *ibuf, char *mask, const int margin, const Span< float3 > vert_positions, const int edges_num, const OffsetIndices< int > faces, const Span< int > corner_edges, const Span< int > corner_verts, const Span< float2 > mloopuv, const float uv_offset[2])
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
VecBase< float, 3 > float3
int *(* getPolyArray)(DerivedMesh *dm)
int(* getNumVerts)(DerivedMesh *dm)
int(* getNumPolys)(DerivedMesh *dm)
int(* getNumEdges)(DerivedMesh *dm)
float *(* getVertArray)(DerivedMesh *dm)
void *(* getLoopDataArray)(DerivedMesh *dm, eCustomDataType type)
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer
#define PackDijkstraPixel(dist, dir)
void RE_generate_texturemargin_adjacentfaces(ImBuf *ibuf, char *mask, const int margin, const Mesh *mesh, char const *uv_layer, const float uv_offset[2])
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)
#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))
void zbuf_alloc_span(ZSpan *zspan, int rectx, int recty)
void zbuf_free_span(ZSpan *zspan)