Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/gpencil_geom.cc')
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc183
1 files changed, 111 insertions, 72 deletions
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index 792474d30ea..4d0db4d5386 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -25,8 +25,6 @@
#include "BLI_polyfill_2d.h"
#include "BLI_span.hh"
-#include "BLT_translation.h"
-
#include "DNA_gpencil_modifier_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_material_types.h"
@@ -37,6 +35,7 @@
#include "BLT_translation.h"
+#include "BKE_attribute.hh"
#include "BKE_context.h"
#include "BKE_deform.h"
#include "BKE_gpencil.h"
@@ -2465,6 +2464,9 @@ static void gpencil_generate_edgeloops(Object *ob,
if (me->totedge == 0) {
return;
}
+ const Span<MVert> verts = me->verts();
+ const Span<MEdge> edges = me->edges();
+ const Span<MDeformVert> dverts = me->deform_verts();
const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(me);
/* Arrays for all edge vertices (forward and backward) that form a edge loop.
@@ -2477,15 +2479,15 @@ static void gpencil_generate_edgeloops(Object *ob,
GpEdge *gp_edges = (GpEdge *)MEM_callocN(sizeof(GpEdge) * me->totedge, __func__);
GpEdge *gped = nullptr;
for (int i = 0; i < me->totedge; i++) {
- MEdge *ed = &me->medge[i];
+ const MEdge *ed = &edges[i];
gped = &gp_edges[i];
- MVert *mv1 = &me->mvert[ed->v1];
+ const MVert *mv1 = &verts[ed->v1];
copy_v3_v3(gped->n1, vert_normals[ed->v1]);
gped->v1 = ed->v1;
copy_v3_v3(gped->v1_co, mv1->co);
- MVert *mv2 = &me->mvert[ed->v2];
+ const MVert *mv2 = &verts[ed->v2];
copy_v3_v3(gped->n2, vert_normals[ed->v2]);
gped->v2 = ed->v2;
copy_v3_v3(gped->v2_co, mv2->co);
@@ -2541,8 +2543,7 @@ static void gpencil_generate_edgeloops(Object *ob,
gpf_stroke, MAX2(stroke_mat_index, 0), array_len + 1, thickness * thickness, false);
/* Create dvert data. */
- MDeformVert *me_dvert = me->dvert;
- if (use_vgroups && me_dvert) {
+ if (use_vgroups && !dverts.is_empty()) {
gps_stroke->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * (array_len + 1),
"gp_stroke_dverts");
}
@@ -2551,7 +2552,7 @@ static void gpencil_generate_edgeloops(Object *ob,
float fpt[3];
for (int i = 0; i < array_len + 1; i++) {
int vertex_index = i == 0 ? gp_edges[stroke[0]].v1 : gp_edges[stroke[i - 1]].v2;
- MVert *mv = &me->mvert[vertex_index];
+ const MVert *mv = &verts[vertex_index];
/* Add segment. */
bGPDspoint *pt = &gps_stroke->points[i];
@@ -2564,9 +2565,9 @@ static void gpencil_generate_edgeloops(Object *ob,
pt->strength = 1.0f;
/* Copy vertex groups from mesh. Assuming they already exist in the same order. */
- if (use_vgroups && me_dvert) {
+ if (use_vgroups && !dverts.is_empty()) {
MDeformVert *dv = &gps_stroke->dvert[i];
- MDeformVert *src_dv = &me_dvert[vertex_index];
+ const MDeformVert *src_dv = &dverts[vertex_index];
dv->totweight = src_dv->totweight;
dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
"gp_stroke_dverts_dw");
@@ -2664,6 +2665,8 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
const bool use_faces,
const bool use_vgroups)
{
+ using namespace blender;
+ using namespace blender::bke;
if (ELEM(nullptr, ob_gp, ob_mesh) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == nullptr)) {
return false;
}
@@ -2673,8 +2676,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
/* Use evaluated data to get mesh with all modifiers on top. */
Object *ob_eval = (Object *)DEG_get_evaluated_object(depsgraph, ob_mesh);
const Mesh *me_eval = BKE_object_get_evaluated_mesh(ob_eval);
- const MPoly *mpoly = me_eval->mpoly;
- const MLoop *mloop = me_eval->mloop;
+ const Span<MVert> verts = me_eval->verts();
+ const Span<MPoly> polys = me_eval->polys();
+ const Span<MLoop> loops = me_eval->loops();
int mpoly_len = me_eval->totpoly;
char element_name[200];
@@ -2708,14 +2712,17 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gpl_fill = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
}
bGPDframe *gpf_fill = BKE_gpencil_layer_frame_get(
- gpl_fill, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
+ gpl_fill, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW);
int i;
+
+ const VArray<int> mesh_material_indices = me_eval->attributes().lookup_or_default<int>(
+ "material_index", ATTR_DOMAIN_FACE, 0);
for (i = 0; i < mpoly_len; i++) {
- const MPoly *mp = &mpoly[i];
+ const MPoly *mp = &polys[i];
/* Find material. */
int mat_idx = 0;
- Material *ma = BKE_object_material_get(ob_mesh, mp->mat_nr + 1);
+ Material *ma = BKE_object_material_get(ob_mesh, mesh_material_indices[i] + 1);
make_element_name(
ob_mesh->id.name + 2, (ma != nullptr) ? ma->id.name + 2 : "Fill", 64, element_name);
mat_idx = BKE_gpencil_material_find_index_by_name_prefix(ob_gp, element_name);
@@ -2735,16 +2742,16 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gps_fill->flag |= GP_STROKE_CYCLIC;
/* Create dvert data. */
- MDeformVert *me_dvert = me_eval->dvert;
- if (use_vgroups && me_dvert) {
+ const Span<MDeformVert> dverts = me_eval->deform_verts();
+ if (use_vgroups && !dverts.is_empty()) {
gps_fill->dvert = (MDeformVert *)MEM_callocN(sizeof(MDeformVert) * mp->totloop,
"gp_fill_dverts");
}
/* Add points to strokes. */
for (int j = 0; j < mp->totloop; j++) {
- const MLoop *ml = &mloop[mp->loopstart + j];
- const MVert *mv = &me_eval->mvert[ml->v];
+ const MLoop *ml = &loops[mp->loopstart + j];
+ const MVert *mv = &verts[ml->v];
bGPDspoint *pt = &gps_fill->points[j];
copy_v3_v3(&pt->x, mv->co);
@@ -2753,9 +2760,9 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
pt->strength = 1.0f;
/* Copy vertex groups from mesh. Assuming they already exist in the same order. */
- if (use_vgroups && me_dvert) {
+ if (use_vgroups && !dverts.is_empty()) {
MDeformVert *dv = &gps_fill->dvert[j];
- MDeformVert *src_dv = &me_dvert[ml->v];
+ const MDeformVert *src_dv = &dverts[ml->v];
dv->totweight = src_dv->totweight;
dv->dw = (MDeformWeight *)MEM_callocN(sizeof(MDeformWeight) * dv->totweight,
"gp_fill_dverts_dw");
@@ -2783,7 +2790,7 @@ bool BKE_gpencil_convert_mesh(Main *bmain,
gpl_stroke = BKE_gpencil_layer_addnew(gpd, element_name, true, false);
}
bGPDframe *gpf_stroke = BKE_gpencil_layer_frame_get(
- gpl_stroke, CFRA + frame_offset, GP_GETFRAME_ADD_NEW);
+ gpl_stroke, scene->r.cfra + frame_offset, GP_GETFRAME_ADD_NEW);
gpencil_generate_edgeloops(ob_eval,
gpd,
@@ -3411,7 +3418,8 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
bGPDstroke *gps_b,
const bool leave_gaps,
const bool fit_thickness,
- const bool smooth)
+ const bool smooth,
+ bool auto_flip)
{
bGPDspoint point;
bGPDspoint *pt;
@@ -3428,52 +3436,54 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
return;
}
- /* define start and end points of each stroke */
- float start_a[3], start_b[3], end_a[3], end_b[3];
- pt = &gps_a->points[0];
- copy_v3_v3(start_a, &pt->x);
+ if (auto_flip) {
+ /* define start and end points of each stroke */
+ float start_a[3], start_b[3], end_a[3], end_b[3];
+ pt = &gps_a->points[0];
+ copy_v3_v3(start_a, &pt->x);
- pt = &gps_a->points[gps_a->totpoints - 1];
- copy_v3_v3(end_a, &pt->x);
+ pt = &gps_a->points[gps_a->totpoints - 1];
+ copy_v3_v3(end_a, &pt->x);
- pt = &gps_b->points[0];
- copy_v3_v3(start_b, &pt->x);
+ pt = &gps_b->points[0];
+ copy_v3_v3(start_b, &pt->x);
- pt = &gps_b->points[gps_b->totpoints - 1];
- copy_v3_v3(end_b, &pt->x);
+ pt = &gps_b->points[gps_b->totpoints - 1];
+ copy_v3_v3(end_b, &pt->x);
- /* Check if need flip strokes. */
- float dist = len_squared_v3v3(end_a, start_b);
- bool flip_a = false;
- bool flip_b = false;
- float lowest = dist;
+ /* Check if need flip strokes. */
+ float dist = len_squared_v3v3(end_a, start_b);
+ bool flip_a = false;
+ bool flip_b = false;
+ float lowest = dist;
- dist = len_squared_v3v3(end_a, end_b);
- if (dist < lowest) {
- lowest = dist;
- flip_a = false;
- flip_b = true;
- }
+ dist = len_squared_v3v3(end_a, end_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = false;
+ flip_b = true;
+ }
- dist = len_squared_v3v3(start_a, start_b);
- if (dist < lowest) {
- lowest = dist;
- flip_a = true;
- flip_b = false;
- }
+ dist = len_squared_v3v3(start_a, start_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = true;
+ flip_b = false;
+ }
- dist = len_squared_v3v3(start_a, end_b);
- if (dist < lowest) {
- lowest = dist;
- flip_a = true;
- flip_b = true;
- }
+ dist = len_squared_v3v3(start_a, end_b);
+ if (dist < lowest) {
+ lowest = dist;
+ flip_a = true;
+ flip_b = true;
+ }
- if (flip_a) {
- BKE_gpencil_stroke_flip(gps_a);
- }
- if (flip_b) {
- BKE_gpencil_stroke_flip(gps_b);
+ if (flip_a) {
+ BKE_gpencil_stroke_flip(gps_a);
+ }
+ if (flip_b) {
+ BKE_gpencil_stroke_flip(gps_b);
+ }
}
/* don't visibly link the first and last points? */
@@ -3536,6 +3546,27 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
}
}
+void BKE_gpencil_stroke_start_set(bGPDstroke *gps, int start_idx)
+{
+ if ((start_idx < 1) || (start_idx >= gps->totpoints) || (gps->totpoints < 2)) {
+ return;
+ }
+
+ /* Only cyclic strokes. */
+ if ((gps->flag & GP_STROKE_CYCLIC) == 0) {
+ return;
+ }
+
+ bGPDstroke *gps_b = BKE_gpencil_stroke_duplicate(gps, true, false);
+ BKE_gpencil_stroke_trim_points(gps_b, 0, start_idx - 1);
+ BKE_gpencil_stroke_trim_points(gps, start_idx, gps->totpoints - 1);
+
+ /* Join both strokes. */
+ BKE_gpencil_stroke_join(gps, gps_b, false, false, false, false);
+
+ BKE_gpencil_free_stroke(gps_b);
+}
+
void BKE_gpencil_stroke_copy_to_keyframes(
bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, const bool tail)
{
@@ -3763,8 +3794,8 @@ void BKE_gpencil_stroke_uniform_subdivide(bGPdata *gpd,
BKE_gpencil_stroke_geometry_update(gpd, gps);
}
-void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
- bGPDstroke *gps,
+void BKE_gpencil_stroke_to_view_space(bGPDstroke *gps,
+ float viewmat[4][4],
const float diff_mat[4][4])
{
for (int i = 0; i < gps->totpoints; i++) {
@@ -3772,12 +3803,12 @@ void BKE_gpencil_stroke_to_view_space(RegionView3D *rv3d,
/* Point to parent space. */
mul_v3_m4v3(&pt->x, diff_mat, &pt->x);
/* point to view space */
- mul_m4_v3(rv3d->viewmat, &pt->x);
+ mul_m4_v3(viewmat, &pt->x);
}
}
-void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
- bGPDstroke *gps,
+void BKE_gpencil_stroke_from_view_space(bGPDstroke *gps,
+ float viewinv[4][4],
const float diff_mat[4][4])
{
float inverse_diff_mat[4][4];
@@ -3785,7 +3816,7 @@ void BKE_gpencil_stroke_from_view_space(RegionView3D *rv3d,
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- mul_v3_m4v3(&pt->x, rv3d->viewinv, &pt->x);
+ mul_v3_m4v3(&pt->x, viewinv, &pt->x);
mul_m4_v3(inverse_diff_mat, &pt->x);
}
}
@@ -3962,6 +3993,7 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
const bGPDlayer *gpl,
const bGPDstroke *gps,
int subdivisions,
+ const float thickness_chg,
int *r_num_perimeter_points)
{
/* sanity check */
@@ -3970,7 +4002,9 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
}
float defaultpixsize = 1000.0f / gpd->pixfactor;
+ float ovr_radius = thickness_chg / defaultpixsize / 2.0f;
float stroke_radius = ((gps->thickness + gpl->line_change) / defaultpixsize) / 2.0f;
+ stroke_radius = max_ff(stroke_radius - ovr_radius, 0.0f);
ListBase *perimeter_right_side = MEM_cnew<ListBase>(__func__);
ListBase *perimeter_left_side = MEM_cnew<ListBase>(__func__);
@@ -4199,16 +4233,21 @@ static ListBase *gpencil_stroke_perimeter_ex(const bGPdata *gpd,
return perimeter_list;
}
-bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
+bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(float viewmat[4][4],
bGPdata *gpd,
const bGPDlayer *gpl,
bGPDstroke *gps,
const int subdivisions,
- const float diff_mat[4][4])
+ const float diff_mat[4][4],
+ const float thickness_chg)
{
if (gps->totpoints == 0) {
return nullptr;
}
+
+ float viewinv[4][4];
+ invert_m4_m4(viewinv, viewmat);
+
/* Duplicate only points and fill data. Weight and Curve are not needed. */
bGPDstroke *gps_temp = (bGPDstroke *)MEM_dupallocN(gps);
gps_temp->prev = gps_temp->next = nullptr;
@@ -4233,10 +4272,10 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
pt_dst->uv_rot = 0;
}
- BKE_gpencil_stroke_to_view_space(rv3d, gps_temp, diff_mat);
+ BKE_gpencil_stroke_to_view_space(gps_temp, viewmat, diff_mat);
int num_perimeter_points = 0;
ListBase *perimeter_points = gpencil_stroke_perimeter_ex(
- gpd, gpl, gps_temp, subdivisions, &num_perimeter_points);
+ gpd, gpl, gps_temp, subdivisions, thickness_chg, &num_perimeter_points);
if (num_perimeter_points == 0) {
return nullptr;
@@ -4256,7 +4295,7 @@ bGPDstroke *BKE_gpencil_stroke_perimeter_from_view(struct RegionView3D *rv3d,
pt->flag |= GP_SPOINT_SELECT;
}
- BKE_gpencil_stroke_from_view_space(rv3d, perimeter_stroke, diff_mat);
+ BKE_gpencil_stroke_from_view_space(perimeter_stroke, viewinv, diff_mat);
/* Free temp data. */
BLI_freelistN(perimeter_points);