Files
test/source/blender/blenkernel/intern/paint_canvas.cc
Jeroen Bakker 4ed649352f 3D Texturing: Fix seam bleeding.
{F13294314}
# Process

In the pixel extraction process a larger domain will be extracted then the input mesh.
The borders of uv islands are extended with connected geometry of the input mesh.
The extended mesh is then fed into the pixel extraction process.
A mask is used to limit the extraction so UV islands will not overlap.

Input UV islands.
{F13206401}

Extended UV Island (only one showing).
{F13288764}

This patch doesn't include fixing uv seams at non-manifold edges (like suzannes eyes) as that
would require a different approach (edge extending or pixel copy-ing). The later has already been
implemented in D14702, but should be revisited to only use do the non-manifold edge fixing.

This patch supports fixing UV seams across UDIM textures.
There might be an issue when using a single texture on multiple uv maps.

Reviewed By: brecht, joeedh, JulienKaspar

Maniphest Tasks: T97352

Differential Revision: https://developer.blender.org/D14970
2022-11-28 08:32:06 +01:00

133 lines
3.4 KiB
C++

/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_compiler_compat.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BKE_customdata.h"
#include "BKE_image.h"
#include "BKE_material.h"
#include "BKE_paint.h"
#include "IMB_imbuf_types.h"
namespace blender::bke::paint::canvas {
static TexPaintSlot *get_active_slot(Object *ob)
{
Material *mat = BKE_object_material_get(ob, ob->actcol);
if (mat == nullptr) {
return nullptr;
}
if (mat->texpaintslot == nullptr) {
return nullptr;
}
if (mat->paint_active_slot >= mat->tot_slots) {
return nullptr;
}
TexPaintSlot *slot = &mat->texpaintslot[mat->paint_active_slot];
return slot;
}
} // namespace blender::bke::paint::canvas
extern "C" {
using namespace blender::bke::paint::canvas;
bool BKE_paint_canvas_image_get(PaintModeSettings *settings,
Object *ob,
Image **r_image,
ImageUser **r_image_user)
{
*r_image = nullptr;
*r_image_user = nullptr;
switch (settings->canvas_source) {
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
break;
case PAINT_CANVAS_SOURCE_IMAGE:
*r_image = settings->canvas_image;
*r_image_user = &settings->image_user;
break;
case PAINT_CANVAS_SOURCE_MATERIAL: {
TexPaintSlot *slot = get_active_slot(ob);
if (slot == nullptr) {
break;
}
*r_image = slot->ima;
*r_image_user = slot->image_user;
break;
}
}
return *r_image != nullptr;
}
int BKE_paint_canvas_uvmap_layer_index_get(const struct PaintModeSettings *settings,
struct Object *ob)
{
switch (settings->canvas_source) {
case PAINT_CANVAS_SOURCE_COLOR_ATTRIBUTE:
return -1;
case PAINT_CANVAS_SOURCE_IMAGE: {
/* Use active uv map of the object. */
if (ob->type != OB_MESH) {
return -1;
}
const Mesh *mesh = static_cast<Mesh *>(ob->data);
return CustomData_get_active_layer_index(&mesh->ldata, CD_MLOOPUV);
}
case PAINT_CANVAS_SOURCE_MATERIAL: {
/* Use uv map of the canvas. */
TexPaintSlot *slot = get_active_slot(ob);
if (slot == nullptr) {
break;
}
if (ob->type != OB_MESH) {
return -1;
}
if (slot->uvname == nullptr) {
return -1;
}
const Mesh *mesh = static_cast<Mesh *>(ob->data);
return CustomData_get_named_layer_index(&mesh->ldata, CD_MLOOPUV, slot->uvname);
}
}
return -1;
}
char *BKE_paint_canvas_key_get(struct PaintModeSettings *settings, struct Object *ob)
{
std::stringstream ss;
int active_uv_map_layer_index = BKE_paint_canvas_uvmap_layer_index_get(settings, ob);
ss << "UV_MAP:" << active_uv_map_layer_index;
Image *image;
ImageUser *image_user;
if (BKE_paint_canvas_image_get(settings, ob, &image, &image_user)) {
ss << ",SEAM_MARGIN:" << image->seam_margin;
ImageUser tile_user = *image_user;
LISTBASE_FOREACH (ImageTile *, image_tile, &image->tiles) {
tile_user.tile = image_tile->tile_number;
ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &tile_user, nullptr);
if (!image_buffer) {
continue;
}
ss << ",TILE_" << image_tile->tile_number;
ss << "(" << image_buffer->x << "," << image_buffer->y << ")";
BKE_image_release_ibuf(image, image_buffer, nullptr);
}
}
return BLI_strdup(ss.str().c_str());
}
}