GPv3: Basic vertex group operators #117476
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset Browser
Interest
Asset Browser Project Overview
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
EEVEE & Viewport
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
EEVEE & Viewport
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Priority
High
Priority
Low
Priority
Normal
Priority
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
5 Participants
Notifications
Due Date
No due date set.
Blocks
#117689 GPv3: Vertex Group Operators
blender/blender
Reference: blender/blender#117476
Loading…
Reference in New Issue
No description provided.
Delete Branch "LukasTonne/blender:gp3-vertex-group-operators"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Adds vertex groups and basic operator support to the
GreasePencil
data block.Vertex groups in the
GreasePencil
ID are used as the source of truth for vertex groups names and ordering in the UI. Individual drawings also have vertex group lists, but they should not be modified directly by users or the API. The main purpose of storing vertex group names in in a drawing'sCurveGeometry
is to make it self-contained, so that vertex weights can be associated with names without requiring theGreasePencil
parent data.Vertex group operators are implemented generically for some ID types. Grease Pencil needs its own handling in these operators. After manipulating
vertex_group_names
thevalidate_drawing_vertex_groups
utility function should be called to ensure that drawings only contain a true subset of theGreasePencil
data block.Operators for assigning/removing/selecting/deselecting vertices are also implemented here. To avoid putting grease pencil logic into the generic
object_deform.cc
file a number of utility functions have been added inBKE_grease_pencil_vgroup.hh
.Fixes #117337
The design choice here also affects how to deal with attributes across layers more generally. Since I imagine when you are doing vertex color painting, you also want to select from a single list that aggregates attributes from all layers.
I can't immediately think of a better alternative to this mechanism, it seems ok.
I would expect this to be purely a runtime cache, not saved to the .blend file. And rather than syncing after modifying drawings, it would clear the cache and generate it when needed?
Reason for storing the list in DNA is that it also encodes the global order of vertex groups. Otherwise adding or removing vertices from groups can change the order of vertex groups:
In addition to the stable order it's also useful to have a single consistent
lock_weight
flag for vertex groups (this maintains relative weights in a group during edits).Sorry, we were typing at the same moment. Didn't see your post until I posted mine...
Perhaps premature questions, since this is a first WIP, but:
Drawing
s are created. I don't see anything for that yet in the PR, but I expect some mechanism for that will be added toGreasePencil::add_empty_drawings
,add_duplicate_drawings
etc., right?It's not entirely clear to me if there can be an 'unsynced' state. Is it possible that at any moment a
Drawing
can have a different list of vertex groups than the otherDrawing
s in the scene? When thevertex_group_names
are always in sync, you could skip the iteration over all drawings insync_vertex_groups_from_layers
.@SietseB We want to move away from the idea that "every drawing always has the same vertex groups" which is similar to the idea that "all drawings are one geometry in grease pencil".
We want to treat vertex groups as attributes. And yes, different drawings can have different attributes. This might seem like an issue, because "what happens if I want to access a vertex group on a drawing that doesn't have it?!" and the awnser is simple: it returns a virtual array with a default value for all the elements (e.g. see
VArray::ForSingle
). When writing to a vertex group of a drawing, then it will actually create it.So we can think of this global list on the grease pencil as the list that tells us:
Yes in those cases the groups list also needs to be synced. Although new drawings probably don't have vertex groups by default and adding groups is separate operation. Vertex groups in drawings don't have to match the groups list in
GreasePencil
, they can be a subset and don't even have to follow the same order.By writing to blend files, and by keeping the order unchanged, unless users actively change it using vertex group operators.
By "sync" i will mean copying the combined set of vertex groups from drawings to the vertex groups in
GreasePencil
. The individual drawings can have different subsets of vertex groups of theGreasePencil
list, they can have all of the groups or none or just a few. TheGreasePencil
list functions like a registry for theDrawing
groups.I want to mention a behavior that can be hard to notice about vertex group , to be aware of it , when we duplicate / copy / interpolate points that are in a vertex group , all those generated point will be automatically assigned to this vertex group, hope i'm to be helpful here.
This should work just fine. When points are copied or interpolated within a drawing the vertex groups already exist there. The process is already covered by
CurvesGeometry
functions and does not need to involve theGreasePencil
data block.This is confusing to me. In the first paragraph you say that drawings do not share vertex groups,. But in the second you seem to say that it works as if they are shared by all drawings, at least from a user point of view.
Can it be clarified how this will work on a user level? Ignoring for a moment the implementation.
@brecht Right, we want vertex groups to be stored per drawing, but expose them to the user at the object-data level. Let me explain the reasoning first:
Now to awnser your questions:
Thanks for all the answers.
So, for my own understanding: there are two sources of truth. The vertex groups in
Drawing
s are the source of truth for the existence of the groups. And theGreasePencil
list is the source of truth for the (UI) order of the groups.What about this edge case: I have one keyframe (
Drawing
), I create a vertex group, I create a second keyframe (which doesn't get the vertex group added by default, as I understand it) and I delete the first keyframe. Now my vertex group is gone. From a UX perspective I would say this is undesirable, but is this the price we have to pay for this design?@SietseB We don't need to remove the vertex group name from the list. We could keep it if we wanted to. Wouldn't hurt and I guess would be consistent with the other object types.
No, we don't need to, but as soon as
sync_vertex_groups_from_layers()
is called somewhere, the vertex group will be gone. So that's pretty tricky...A few things I noticed when scanning the code.
@ -2420,0 +2509,4 @@
const bDeformGroup &defgroup,
blender::StringRef name)
{
for (const GreasePencilDrawingBase *base : grease_pencil.drawings()) {
You could iterate over
grease_pencil.vertex_group_names
here? That's less data than all the drawings in a scene.@ -2420,0 +2567,4 @@
BLI_addtail(&this->vertex_group_names, defgroup);
for (GreasePencilDrawingBase *base : this->drawings()) {
It seems a bit random to me that all existing drawings get the vertex group added here, but newly inserted keyframes/drawings after this don't (as I understood from the conversation). There is no real reasoning behind it then, which
Drawing
contains the vertex group and which not.@ -2420,0 +2581,4 @@
BLI_addtail(&curves.vertex_group_names, drawing_defgroup);
}
this->sync_vertex_groups_from_layers();
I would say this call is redundant.
@SietseB What I meant was that
sync_vertex_groups_from_layers
doesn't need to remove vertex groups that are unused.I think users managing vertex groups and attributes per drawing is something we should not add even if we had the time. I don't think the UI and conceptual complexity is worth it. So I would avoid complicating the design for a use case that is not going to happen.
Still in practical terms, the implementation might end up similar anyway. If you want to avoid memory usage for attributes that only have default values on some drawings, then with current data structures indeed you would need to not have the custom data layer at all on them.
For vertex groups there is not as much reason since it doesn't save memory to have it per drawing. My guess would be that storing the list of vertex group names only on the datablock would give the simplest implementation, but I might be wrong about that.
@filedescriptor Ah, right. So when the
GreasePencil
list can contain unused vertex groups, then that list is basically the only source of truth.You can omit the whole
sync_vertex_groups_from_layers
mechanism then. And only adding a vertex group as an attribute to theDrawing
when there are actually stroke points part of that group (e.g. by weight painting or through a node in GN).Thanks for all the comments, i think we've arrived at a feasible plan:
GreasePencil
is the main source of truth for which vertex groups exist and what their order is.GreasePencil
list.Drawings have their own vertex groups to be self-contained: we can relate vertex groups to e.g. armatures without having to refer to the
GreasePencil
data block.GreasePencil
data block.Changing vertex groups applies to the
GreasePencil
list first, then drawings are updated to match (remove invalid groups).GreasePencil
data.If necessary we can add a "sync" function to update
GreasePencil
from its drawings, but i consider that not recommended.Note: Using the
attributes
API of drawings does not allow adding new vertex groups, only changing existing groups. This is "safe" wrt. the proposed design.WIP: GPv3: Support for vertex group operators in GreasePencil data blocksto WIP: GPv3: Basic vertex group operators066ebd70af
to0bff7079f2
WIP: GPv3: Basic vertex group operatorsto GPv3: Basic vertex group operatorsDid a first pass on this.
@ -0,0 +20,4 @@
#include "BLT_translation.h"
#include <iostream>
This header should probably be removed.
@ -0,0 +30,4 @@
void validate_drawing_vertex_groups(GreasePencil &grease_pencil)
{
Set<const char *> valid_names;
Will this not just compare the pointers to check for equality? I feel like this should be a
Set<std::string>
Yes, should be
Set<std::string>
. I think the idea was to avoid string copies, but that's not very important for operators.@ -0,0 +70,4 @@
/* Look for existing group, otherwise lazy-initialize if any vertex is selected. */
int def_nr = BLI_findstringindex(
&vertex_group_names, name.data(), offsetof(bDeformGroup, name));
auto ensure_group_in_drawing = [&]() {
I think this lambda is not too helpful. Seems better to just put the code in the loop.
@ -0,0 +85,4 @@
};
const bke::AttributeAccessor attributes = curves.attributes();
const VArray<bool> select_vert = *attributes.lookup_or_default<bool>(
select_vert
->selection
@ -0,0 +103,4 @@
}
/** Remove selected vertices from the vertex group. */
bool remove_from_vertex_group(GreasePencil &grease_pencil, StringRef name, bool use_selection)
const StringRef name
andconst bool use_selection
@blender-bot build
@blender-bot build
The code looks good to me.
Personally, I would name the files
grease_pencil_vertex_groups
even if it's not consistent with the other ones.@blender-bot build
@blender-bot build