mirror of
https://projects.blender.org/blender/blender.git
synced 2025-01-22 07:22:12 -05:00
Fix #133035: Grease Pencil: Convert mesh materials to fill materials
When converting mesh to grease pencil, different face materials should also be converted to grease pencil ones. This now works by converting viewport display color diffuse_color from the mesh material to grease pencil material fill color. Notes: - If there are empty material slots in the mesh, faces assgined to these material slots will be assgined to a new fallback white material in the converted grease pencil fills. - If original mesh does not have any material slots, a white material will be created in the grease pencil object for the fills. - If original mesh has multiple material slots of the same material, they would be reduced to one material slot in the converted fills. Pull Request: https://projects.blender.org/blender/blender/pulls/133087
This commit is contained in:
parent
f105366d73
commit
43492a8278
1 changed files with 86 additions and 12 deletions
|
@ -3114,12 +3114,62 @@ static int mesh_to_grease_pencil_add_material(Main &bmain,
|
|||
return index;
|
||||
}
|
||||
|
||||
class FillColorRecord {
|
||||
public:
|
||||
float4 color;
|
||||
StringRefNull name;
|
||||
bool operator==(const FillColorRecord &other) const
|
||||
{
|
||||
return other.color == color && other.name == name;
|
||||
}
|
||||
uint64_t hash() const
|
||||
{
|
||||
return hash_string(name);
|
||||
}
|
||||
};
|
||||
|
||||
static VectorSet<FillColorRecord> mesh_to_grease_pencil_get_material_list(
|
||||
Object &ob_mesh, const Mesh &mesh, Array<int> &material_remap)
|
||||
{
|
||||
const short num_materials = mesh.totcol;
|
||||
const FillColorRecord empty_fill = {float4(1.0f), DATA_("Empty Fill")};
|
||||
|
||||
/* This function will only be called when we want to create fills out of mesh faces, so always
|
||||
* ensure that fills would have at least one material to be assigned to. */
|
||||
if (num_materials == 0) {
|
||||
VectorSet<FillColorRecord> fill_colors;
|
||||
fill_colors.add(empty_fill);
|
||||
material_remap.reinitialize(1);
|
||||
material_remap[0] = 0;
|
||||
return fill_colors;
|
||||
}
|
||||
|
||||
VectorSet<FillColorRecord> fill_colors;
|
||||
|
||||
material_remap.reinitialize(num_materials);
|
||||
|
||||
for (const int material_i : IndexRange(num_materials)) {
|
||||
const Material *mesh_material = BKE_object_material_get(&ob_mesh, material_i + 1);
|
||||
if (!mesh_material) {
|
||||
material_remap[material_i] = fill_colors.index_of_or_add(empty_fill);
|
||||
continue;
|
||||
}
|
||||
const float4 fill_color = float4(
|
||||
mesh_material->r, mesh_material->g, mesh_material->b, mesh_material->a);
|
||||
const StringRefNull material_name = BKE_id_name(mesh_material->id);
|
||||
const FillColorRecord record = {fill_color, material_name};
|
||||
material_remap[material_i] = fill_colors.index_of_or_add(record);
|
||||
}
|
||||
|
||||
return fill_colors;
|
||||
}
|
||||
static void mesh_data_to_grease_pencil(const Mesh &mesh_eval,
|
||||
GreasePencil &grease_pencil,
|
||||
const int current_frame,
|
||||
const bool generate_faces,
|
||||
const float stroke_radius,
|
||||
const float offset)
|
||||
const float offset,
|
||||
const Array<int> &material_remap)
|
||||
{
|
||||
grease_pencil.flag |= GREASE_PENCIL_STROKE_ORDER_3D;
|
||||
|
||||
|
@ -3130,7 +3180,6 @@ static void mesh_data_to_grease_pencil(const Mesh &mesh_eval,
|
|||
bke::greasepencil::Layer &layer_line = grease_pencil.add_layer(DATA_("Lines"));
|
||||
bke::greasepencil::Drawing *drawing_line = grease_pencil.insert_frame(layer_line, current_frame);
|
||||
|
||||
constexpr int face_mat_index = 1;
|
||||
const Span<float3> mesh_positions = mesh_eval.vert_positions();
|
||||
const Span<float3> vert_normals = mesh_eval.vert_normals();
|
||||
const Span<int2> edges = mesh_eval.edges();
|
||||
|
@ -3153,12 +3202,20 @@ static void mesh_data_to_grease_pencil(const Mesh &mesh_eval,
|
|||
bke::SpanAttributeWriter<int> stroke_materials_fill =
|
||||
curves_fill.attributes_for_write().lookup_or_add_for_write_span<int>(
|
||||
"material_index", bke::AttrDomain::Curve);
|
||||
curves_fill.fill_curve_types(CURVE_TYPE_POLY);
|
||||
bke::AttributeAccessor mesh_attributes = mesh_eval.attributes();
|
||||
VArray<int> mesh_materials = *mesh_attributes.lookup_or_default(
|
||||
"material_index", bke::AttrDomain::Face, 0);
|
||||
|
||||
curves_fill.fill_curve_types(CURVE_TYPE_POLY);
|
||||
array_utils::gather(mesh_positions, corner_verts, positions_fill);
|
||||
array_utils::copy(faces_span, offsets_fill);
|
||||
cyclic_fill.fill(true);
|
||||
stroke_materials_fill.span.fill(face_mat_index);
|
||||
|
||||
MutableSpan<int> material_span = stroke_materials_fill.span;
|
||||
for (const int face_i : material_span.index_range()) {
|
||||
/* Increase material index by 1 to accommodate the stroke material. */
|
||||
material_span[face_i] = material_remap[mesh_materials[face_i]] + 1;
|
||||
}
|
||||
stroke_materials_fill.finish();
|
||||
}
|
||||
|
||||
|
@ -3197,11 +3254,20 @@ static Object *convert_mesh_to_grease_pencil(Base &base,
|
|||
const float offset = RNA_float_get(info.op_props, "offset");
|
||||
|
||||
/* To be compatible with the thickness value prior to Grease Pencil v3. */
|
||||
const float stroke_radius = float(thickness) / 1000.0f;
|
||||
const float stroke_radius = float(thickness) / 2 *
|
||||
bke::greasepencil::LEGACY_RADIUS_CONVERSION_FACTOR;
|
||||
|
||||
const Object *ob_eval = DEG_get_evaluated_object(info.depsgraph, ob);
|
||||
Object *ob_eval = DEG_get_evaluated_object(info.depsgraph, ob);
|
||||
const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob_eval);
|
||||
|
||||
VectorSet<FillColorRecord> fill_colors;
|
||||
Array<int> material_remap;
|
||||
if (generate_faces) {
|
||||
fill_colors = mesh_to_grease_pencil_get_material_list(*ob_eval, *mesh_eval, material_remap);
|
||||
}
|
||||
|
||||
Mesh *newob_mesh = static_cast<Mesh *>(newob->data);
|
||||
BKE_id_material_clear(info.bmain, &newob_mesh->id);
|
||||
BKE_object_free_derived_caches(newob);
|
||||
BKE_object_free_modifiers(newob, 0);
|
||||
|
||||
|
@ -3213,18 +3279,26 @@ static Object *convert_mesh_to_grease_pencil(Base &base,
|
|||
* functions still depend on this value being coherent (The same value as
|
||||
* `GreasePencil::material_array_num`).
|
||||
*/
|
||||
short *totcol = BKE_object_material_len_p(newob);
|
||||
newob->totcol = *totcol;
|
||||
newob->actcol = *totcol;
|
||||
newob->totcol = 0;
|
||||
newob->actcol = 0;
|
||||
|
||||
mesh_to_grease_pencil_add_material(
|
||||
*info.bmain, *newob, DATA_("Stroke"), float4(0.0f, 0.0f, 0.0f, 1.0f), {});
|
||||
|
||||
if (generate_faces) {
|
||||
mesh_to_grease_pencil_add_material(*info.bmain, *newob, DATA_("Fill"), {}, float4(1.0f));
|
||||
for (const int fill_i : fill_colors.index_range()) {
|
||||
const FillColorRecord &record = fill_colors[fill_i];
|
||||
mesh_to_grease_pencil_add_material(*info.bmain, *newob, record.name, {}, record.color);
|
||||
}
|
||||
}
|
||||
|
||||
mesh_data_to_grease_pencil(
|
||||
*mesh_eval, *grease_pencil, info.scene->r.cfra, generate_faces, stroke_radius, offset);
|
||||
mesh_data_to_grease_pencil(*mesh_eval,
|
||||
*grease_pencil,
|
||||
info.scene->r.cfra,
|
||||
generate_faces,
|
||||
stroke_radius,
|
||||
offset,
|
||||
material_remap);
|
||||
|
||||
return newob;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue