3
$\begingroup$

Is it possible -- without using a previously defined vertex group -- to select those vertice, which are affected by a shape key? How?

$\endgroup$
1
  • $\begingroup$ perhaps to make the question clearer, do you mean is it possible to know exactly what vertices are affected by a shape key? I haven't heard of that $\endgroup$
    – moonboots
    Commented Aug 24, 2018 at 7:50

2 Answers 2

4
$\begingroup$

I think a shape key stores the coordinates of any vertex of the mesh, regardless of whether the position has been changed or not. So it seems as if the only way to select vertices affected by the shape key is to individually compare whether the position of the vertices is the same for different shape keys.

import bpy
tolerance = 1e-5
obj = bpy.context.active_object
shape_keys = obj.data.shape_keys.key_blocks
sk1_data = shape_keys['Key 1'].data
skb_data = shape_keys['Basis'].data

bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="DESELECT")
bpy.ops.mesh.select_mode(type="VERT")
bpy.ops.object.mode_set(mode="OBJECT")

for i, (x, y) in enumerate(zip(sk1_data, skb_data)):
    if (x.co - y.co).length > tolerance:
        obj.data.vertices[i].select = True

bpy.ops.object.mode_set(mode="EDIT")

EDIT: As per batFINGER's suggestion, replaced comparison based on equality with a tolerance based approach.

$\endgroup$
3
$\begingroup$

BMesh version

Using the same principle as @binweg's answer with an edit bmesh

  • Shapekey vertex coordinate needs to be further than TOL (local) from vertex coordinate. Always suggest using a tolerance approach when looking at floats, rather than relying on 10.0000000001 == 10 for example.
  • The two points of interest are vector coords. Test the length of the vector calcuated from their difference.
  • Uses the active shapekey.
  • Selected result is those verts further than tolerance from base mesh, IF the shapekey is the solo shape at full value
  • For the script to "poll" needs to be run in edit mesh mode. The object must have an active shapekey.

script

import bpy
import bmesh

context = bpy.context
TOL = 1e-5 # tolerance
ob = context.edit_object
me = ob.data
bm = bmesh.from_edit_mesh(me)
ask = ob.active_shape_key

for v in bm.verts:
    bv = me.vertices[v.index]
    v.select = (ask.data[v.index].co - bv.co).length > TOL

bmesh.update_edit_mesh(me)
$\endgroup$
2
  • $\begingroup$ I might have used this script wrong, but for me this script doesn't work. In edit mode bm's values always seem to be identical to the active shape key's values, so for me there is no selection. Only by replacing v.co with me.vertices[v.index].co or ask.relative_key.data[v.index].co I manage to run it. I appreciate your suggestion of using tolerances. I initially decided against it as I was under the assumption that, even if some coordinates are not exactly integers, when you create a new shape key the value gets copied just like it is. But I guess it's better to be safe than sorry. $\endgroup$
    – binweg
    Commented Aug 25, 2018 at 6:24
  • $\begingroup$ @binweg cheers... Have used the mesh coord as suggested. Forgot the nuances of different bmesh modes. from_edit_mesh vs from_mesh vs from_object. A second non live edit bmesh could be another way to go, but ultimately the mesh vert coord is the go. $\endgroup$
    – batFINGER
    Commented Aug 25, 2018 at 6:54

You must log in to answer this question.