41 static const int directions[8][2];
42 static const int distances[8];
65 const float uv_offset[2],
73 corner_edges_(corner_edges),
79 pixel_data_.
resize(w_ * h_, 0xFFFFFFFF);
95 pixel_data_[y * w_ +
x] = value;
104 return pixel_data_[y * w_ +
x];
111 value_to_store_ = value;
113 write_mask_ = writemask;
119 void *map,
int x,
int y, [[maybe_unused]]
float u, [[maybe_unused]]
float v)
124 if (m->write_mask_) {
126 m->mask_[y * m->w_ +
x] = 1;
133 if (m->mask_[y * m->w_ + x] != 0) {
148#define PackDijkstraPixel(dist, dir) (0x80000000 + ((dist) << 4) + (dir))
149#define DijkstraPixelGetDistance(dp) (((dp) ^ 0x80000000) >> 4)
150#define DijkstraPixelGetDirection(dp) ((dp) & 0xF)
151#define IsDijkstraPixel(dp) ((dp) & 0x80000000)
152#define DijkstraPixelIsUnset(dp) ((dp) == 0xFFFFFFFF)
160 class DijkstraActivePixel {
162 DijkstraActivePixel(
int dist,
int _x,
int _y) :
distance(dist),
x(_x),
y(_y) {}
166 auto cmp_dijkstrapixel_fun = [](DijkstraActivePixel
const &a1, DijkstraActivePixel
const &a2) {
167 return a1.distance > a2.distance;
171 for (
int y = 0; y < h_; y++) {
172 for (
int x = 0; x < w_; x++) {
174 for (
int i = 0; i < 8; i++) {
175 int xx = x - directions[i][0];
176 int yy = y - directions[i][1];
180 active_pixels.
append(DijkstraActivePixel(distances[i], x, y));
190 std::make_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
193 while (active_pixels.
size()) {
194 std::pop_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
195 DijkstraActivePixel p = active_pixels.
pop_last();
197 int dist = p.distance;
199 if (dist < 2 * (margin + 1)) {
200 for (
int i = 0; i < 8; i++) {
201 int x = p.x + directions[i][0];
202 int y = p.y + directions[i][1];
208 active_pixels.
append(DijkstraActivePixel(dist + distances[i], x, y));
209 std::push_heap(active_pixels.
begin(), active_pixels.
end(), cmp_dijkstrapixel_fun);
226 size_t pixel_index = 0;
227 for (
int y = 0; y < h_; y++) {
228 for (
int x = 0; x < w_; x++) {
229 uint32_t dp = pixel_data_[pixel_index];
239 xx -= directions[direction][0];
240 yy -= directions[direction][1];
242 dist -= distances[direction];
254 bool found_pixel_in_polygon =
false;
255 if (lookup_pixel_polygon_neighborhood(x, y, &face, &destX, &destY, &other_poly)) {
257 for (
int i = 0; i < maxPolygonSteps; i++) {
259 int nx =
int(round(destX));
260 int ny =
int(round(destY));
262 if (other_poly == polygon_from_map) {
263 found_pixel_in_polygon =
true;
269 if (!lookup_pixel(nx, ny, other_poly, &destX, &destY, &other_poly, &dist_to_edge)) {
270 found_pixel_in_polygon =
false;
275 if (found_pixel_in_polygon) {
285 mask[pixel_index] = 1;
293 mask[pixel_index] = 1;
304 ret.x = (((mloopuv[0] - uv_offset_[0]) * w_) - (0.5f + 0.001f));
305 ret.y = (((mloopuv[1] - uv_offset_[1]) * h_) - (0.5f + 0.001f));
313 loop_adjacency_map_.
resize(corner_edges_.
size(), -1);
316 tmpmap.
resize(totedge_, -1);
318 for (
const int64_t i : corner_edges_.index_range()) {
319 int edge = corner_edges_[i];
320 if (tmpmap[edge] == -1) {
321 loop_adjacency_map_[i] = -1;
326 loop_adjacency_map_[i] = tmpmap[edge];
327 loop_adjacency_map_[tmpmap[edge]] = i;
338 bool lookup_pixel_polygon_neighborhood(
339 float x,
float y,
uint32_t *r_start_poly,
float *r_destx,
float *r_desty,
int *r_other_poly)
342 if (lookup_pixel(x, y, *r_start_poly, r_destx, r_desty, r_other_poly, &found_dist)) {
346 int loopstart = faces_[*r_start_poly].start();
347 int totloop = faces_[*r_start_poly].
size();
352 float mindist = -1.0f;
357 for (
int i = 0; i < totloop; i++) {
358 int otherloop = loop_adjacency_map_[i + loopstart];
364 uint32_t face = loop_to_face_map_[otherloop];
366 if (lookup_pixel(x, y, face, &destx, &desty, &foundpoly, &found_dist)) {
367 if (mindist < 0.0f || found_dist < mindist) {
368 mindist = found_dist;
369 *r_other_poly = foundpoly;
372 *r_start_poly = face;
377 return mindist >= 0.0f;
386 bool lookup_pixel(
float x,
392 float *r_dist_to_edge)
396 *r_destx = *r_desty = 0;
399 float found_dist = -1;
404 for (
size_t i = 0; i < faces_[src_poly].
size(); i++) {
405 int l1 = faces_[src_poly].start() + i;
407 if (l2 >= faces_[src_poly].start() + faces_[src_poly].
size()) {
408 l2 = faces_[src_poly].start();
411 float2 edgepoint1 = uv_to_xy(mloopuv_[l1]);
412 float2 edgepoint2 = uv_to_xy(mloopuv_[l2]);
415 float2 ab = edgepoint2 - edgepoint1;
416 float2 ap = point - edgepoint1;
423 float t = dotv / ablensq;
425 if (t >= 0.0 && t <= 1.0) {
428 float2 reflect_point = edgepoint1 + (t * ab);
432 float reflectLen =
sqrt(reflect_vec[0] * reflect_vec[0] + reflect_vec[1] * reflect_vec[1]);
433 float cross = ab[0] * reflect_vec[1] - ab[1] * reflect_vec[0];
437 bool valid = (
cross > 0.0);
439 if (valid && (found_dist < 0 || reflectLen < found_dist)) {
441 found_dist = reflectLen;
443 found_edge = i + faces_[src_poly].start();
448 if (found_edge < 0) {
452 *r_dist_to_edge = found_dist;
455 int other_edge = loop_adjacency_map_[found_edge];
457 if (other_edge < 0) {
461 int dst_poly = loop_to_face_map_[other_edge];
464 *r_other_poly = dst_poly;
467 int other_edge2 = other_edge + 1;
468 if (other_edge2 >= faces_[dst_poly].start() + faces_[dst_poly].
size()) {
469 other_edge2 = faces_[dst_poly].start();
472 float2 other_edgepoint1 = uv_to_xy(mloopuv_[other_edge]);
473 float2 other_edgepoint2 = uv_to_xy(mloopuv_[other_edge2]);
476 float2 other_ab = other_edgepoint1 - other_edgepoint2;
477 float2 other_reflect_point = other_edgepoint2 + (found_t * other_ab);
478 float2 perpendicular_other_ab;
479 perpendicular_other_ab.
x = other_ab.
y;
480 perpendicular_other_ab.y = -other_ab.
x;
484 float2 new_point = other_reflect_point + (found_dist /
math::length(perpendicular_other_ab)) *
485 perpendicular_other_ab;
487 *r_destx = new_point.
x;
488 *r_desty = new_point.
y;
494const int TextureMarginMap::directions[8][2] = {
495 {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
496const int TextureMarginMap::distances[8] = {2, 3, 2, 3, 2, 3, 2, 3};
507 const float uv_offset[2])
515 TextureMarginMap map(ibuf->
x, ibuf->
y, uv_offset, edges_num, faces, corner_edges, mloopuv);
517 bool draw_new_mask =
false;
524 mask = (
char *)
MEM_callocN(
sizeof(
char) * ibuf->
x * ibuf->
y, __func__);
525 draw_new_mask =
true;
529 const int3 tri = corner_tris[i];
532 for (
int a = 0; a < 3; a++) {
533 const float *uv = mloopuv[tri[a]];
539 vec[a][0] = (uv[0] - uv_offset[0]) *
float(ibuf->
x) - (0.5f + 0.001f);
540 vec[a][1] = (uv[1] - uv_offset[1]) *
float(ibuf->
y) - (0.5f + 0.002f);
546 map.rasterize_tri(vec[0], vec[1], vec[2], tri_faces[i], mask, draw_new_mask);
555 map.grow_dijkstra(margin);
559 map.lookup_pixels(ibuf, mask, 3);
576 char const *uv_layer,
577 const float uv_offset[2])
586 bke::AttrDomain::Corner);
591 mesh->vert_positions(),
594 mesh->corner_edges(),
595 mesh->corner_verts(),
601 ImBuf *ibuf,
char *mask,
const int margin,
DerivedMesh *dm,
const float uv_offset[2])
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.
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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 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
void append(const T &value)
void resize(const int64_t new_size)
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
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
void *(* MEM_dupallocN)(const void *vmemh)
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_inline float4 mask(const int4 mask, const float4 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])
float distance(float a, float b)
int *(* getPolyArray)(DerivedMesh *dm)
int(* getNumVerts)(DerivedMesh *dm)
int *(* getCornerVertArray)(DerivedMesh *dm)
int(* getNumPolys)(DerivedMesh *dm)
int(* getNumEdges)(DerivedMesh *dm)
float *(* getVertArray)(DerivedMesh *dm)
void *(* getLoopDataArray)(DerivedMesh *dm, eCustomDataType type)
int *(* getCornerEdgeArray)(DerivedMesh *dm)
int(* getNumLoops)(DerivedMesh *dm)
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)