Fix T97164: Voxel remesh only supports vertex float
color attributes. Voxel remesher now supports all color attribute types.
This commit is contained in:
parent
e0c8d0913b
commit
4a70561bbd
Notes:
blender-bot
2023-02-14 04:31:04 +01:00
Referenced by issue #97164, Voxel Remesher: Only "Vertex -> Color" color attributes are preserved Referenced by issue #96916, Crash if same object is dragged from asset browser as link and append (reuse data) sequentially.
|
@ -65,7 +65,7 @@ struct CustomDataLayer *BKE_id_attribute_find(const struct ID *id,
|
|||
int type,
|
||||
AttributeDomain domain);
|
||||
|
||||
AttributeDomain BKE_id_attribute_domain(struct ID *id, const struct CustomDataLayer *layer);
|
||||
AttributeDomain BKE_id_attribute_domain(const struct ID *id, const struct CustomDataLayer *layer);
|
||||
int BKE_id_attribute_data_length(struct ID *id, struct CustomDataLayer *layer);
|
||||
bool BKE_id_attribute_required(struct ID *id, struct CustomDataLayer *layer);
|
||||
bool BKE_id_attribute_rename(struct ID *id,
|
||||
|
|
|
@ -292,7 +292,7 @@ int BKE_id_attributes_length(const ID *id, AttributeDomainMask domain_mask, Cust
|
|||
return length;
|
||||
}
|
||||
|
||||
AttributeDomain BKE_id_attribute_domain(ID *id, const CustomDataLayer *layer)
|
||||
AttributeDomain BKE_id_attribute_domain(const ID *id, const CustomDataLayer *layer)
|
||||
{
|
||||
DomainInfo info[ATTR_DOMAIN_NUM];
|
||||
get_domains(id, info);
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_meshdata_types.h"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_bvhutils.h"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_mesh_mapping.h"
|
||||
#include "BKE_mesh_remesh_voxel.h" /* own include */
|
||||
#include "BKE_mesh_runtime.h"
|
||||
|
||||
|
@ -365,30 +367,139 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source)
|
|||
BVHTreeFromMesh bvhtree = {nullptr};
|
||||
BKE_bvhtree_from_mesh_get(&bvhtree, source, BVHTREE_FROM_VERTS, 2);
|
||||
|
||||
int tot_color_layer = CustomData_number_of_layers(&source->vdata, CD_PROP_COLOR);
|
||||
int i = 0;
|
||||
const CustomDataLayer *layer;
|
||||
|
||||
for (int layer_n = 0; layer_n < tot_color_layer; layer_n++) {
|
||||
const char *layer_name = CustomData_get_layer_name(&source->vdata, CD_PROP_COLOR, layer_n);
|
||||
CustomData_add_layer_named(
|
||||
&target->vdata, CD_PROP_COLOR, CD_CALLOC, nullptr, target->totvert, layer_name);
|
||||
MeshElemMap *source_lmap = nullptr;
|
||||
int *source_lmap_mem = nullptr;
|
||||
MeshElemMap *target_lmap = nullptr;
|
||||
int *target_lmap_mem = nullptr;
|
||||
|
||||
MPropCol *target_color = (MPropCol *)CustomData_get_layer_n(
|
||||
&target->vdata, CD_PROP_COLOR, layer_n);
|
||||
while (layer = BKE_id_attribute_from_index(
|
||||
const_cast<ID *>(&source->id), i++, ATTR_DOMAIN_MASK_COLOR, CD_MASK_COLOR_ALL)) {
|
||||
AttributeDomain domain = BKE_id_attribute_domain(&source->id, layer);
|
||||
|
||||
CustomData *target_cdata = domain == ATTR_DOMAIN_POINT ? &target->vdata : &target->ldata;
|
||||
const CustomData *source_cdata = domain == ATTR_DOMAIN_POINT ? &source->vdata : &source->ldata;
|
||||
|
||||
/* Check attribute exists in target. */
|
||||
int layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
|
||||
if (layer_i == -1) {
|
||||
int elem_num = domain == ATTR_DOMAIN_POINT ? target->totvert : target->totloop;
|
||||
|
||||
CustomData_add_layer_named(
|
||||
target_cdata, layer->type, CD_CALLOC, nullptr, elem_num, layer->name);
|
||||
layer_i = CustomData_get_named_layer_index(target_cdata, layer->type, layer->name);
|
||||
}
|
||||
|
||||
size_t data_size = CustomData_sizeof(layer->type);
|
||||
void *target_data = target_cdata->layers[layer_i].data;
|
||||
void *source_data = layer->data;
|
||||
MVert *target_verts = (MVert *)CustomData_get_layer(&target->vdata, CD_MVERT);
|
||||
const MPropCol *source_color = (const MPropCol *)CustomData_get_layer_n(
|
||||
&source->vdata, CD_PROP_COLOR, layer_n);
|
||||
for (int i = 0; i < target->totvert; i++) {
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
if (nearest.index != -1) {
|
||||
copy_v4_v4(target_color[i].color, source_color[nearest.index].color);
|
||||
|
||||
if (domain == ATTR_DOMAIN_POINT) {
|
||||
for (int i = 0; i < target->totvert; i++) {
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
|
||||
if (nearest.index != -1) {
|
||||
memcpy(POINTER_OFFSET(target_data, (size_t)i * data_size),
|
||||
POINTER_OFFSET(source_data, (size_t)nearest.index * data_size),
|
||||
data_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Lazily init vertex -> loop maps. */
|
||||
if (!source_lmap) {
|
||||
const MPoly *source_polys = (MPoly *)CustomData_get_layer(&source->pdata, CD_MPOLY);
|
||||
const MLoop *source_loops = (MLoop *)CustomData_get_layer(&source->ldata, CD_MLOOP);
|
||||
const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY);
|
||||
const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP);
|
||||
|
||||
BKE_mesh_vert_loop_map_create(&source_lmap,
|
||||
&source_lmap_mem,
|
||||
source_polys,
|
||||
source_loops,
|
||||
source->totvert,
|
||||
source->totpoly,
|
||||
source->totloop);
|
||||
|
||||
BKE_mesh_vert_loop_map_create(&target_lmap,
|
||||
&target_lmap_mem,
|
||||
target_polys,
|
||||
target_loops,
|
||||
target->totvert,
|
||||
target->totpoly,
|
||||
target->totloop);
|
||||
}
|
||||
|
||||
for (int i = 0; i < target->totvert; i++) {
|
||||
BVHTreeNearest nearest;
|
||||
nearest.index = -1;
|
||||
nearest.dist_sq = FLT_MAX;
|
||||
BLI_bvhtree_find_nearest(
|
||||
bvhtree.tree, target_verts[i].co, &nearest, bvhtree.nearest_callback, &bvhtree);
|
||||
|
||||
if (nearest.index == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MeshElemMap *source_loops = source_lmap + nearest.index;
|
||||
MeshElemMap *target_loops = target_lmap + i;
|
||||
|
||||
if (target_loops->count == 0 || source_loops->count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Average color data for loops around the source vertex into
|
||||
* the first target loop around the target vertex
|
||||
*/
|
||||
|
||||
CustomData_interp(source_cdata,
|
||||
target_cdata,
|
||||
source_loops->indices,
|
||||
nullptr,
|
||||
nullptr,
|
||||
source_loops->count,
|
||||
target_loops->indices[0]);
|
||||
|
||||
void *elem = POINTER_OFFSET(target_data, (size_t)target_loops->indices[0] * data_size);
|
||||
|
||||
/* Copy to rest of target loops. */
|
||||
for (int j = 1; j < target_loops->count; j++) {
|
||||
memcpy(POINTER_OFFSET(target_data, (size_t)target_loops->indices[j] * data_size),
|
||||
elem,
|
||||
data_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(source_lmap);
|
||||
MEM_SAFE_FREE(source_lmap_mem);
|
||||
MEM_SAFE_FREE(target_lmap);
|
||||
MEM_SAFE_FREE(target_lmap_mem);
|
||||
free_bvhtree_from_mesh(&bvhtree);
|
||||
|
||||
/* Transfer active/render color attributes */
|
||||
|
||||
CustomDataLayer *active_layer = BKE_id_attributes_active_color_get(&source->id);
|
||||
CustomDataLayer *render_layer = BKE_id_attributes_render_color_get(&source->id);
|
||||
|
||||
if (active_layer) {
|
||||
BKE_id_attributes_active_color_set(
|
||||
&target->id, BKE_id_attributes_color_find(&target->id, active_layer->name));
|
||||
}
|
||||
|
||||
if (render_layer) {
|
||||
BKE_id_attributes_render_color_set(
|
||||
&target->id, BKE_id_attributes_color_find(&target->id, render_layer->name));
|
||||
}
|
||||
}
|
||||
|
||||
struct Mesh *BKE_mesh_remesh_voxel_fix_poles(const Mesh *mesh)
|
||||
|
|
Loading…
Reference in New Issue