0
$\begingroup$

I'm trying to fit the mesh of a human model with the MPFB Plugin until it has the same dimensions as a real world human (data read out of biplanar X-ray images and imported from matlab).

The program should check at every iteration if there is a difference between Blender model and real model and adapt the meshes step by step until it's of the same size. However, the meshes data (or coordinates of vertices) is not updated, even though the model visibly changes size, because the function "distance" gives the same output at every iteration. A while loop is too much for Blender here, therefore I'm using for loops. In this case it just loops through 20 times instead of stopping when equality is reached.

How can I make it update at every iteration?

mat = loadmat(r'P:\userspace\...\00_ToUse\mesh_sizes_mat.mat') 

#define distance between two vertices function
def distance(point1, point2) -> float: 
    return math.sqrt((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2 + (point2[2] - point1[2]) ** 2)

#define how to find coordinates
obj = context.active_object
v = obj.data.vertices[0]

coords = [(obj.matrix_world @ v.co) for v in obj.data.vertices]


# To change the measure targets the model has to be in "Object mode"
bpy.ops.object.mode_set(mode='OBJECT')

thigh1 = coords[11071] #front
thigh2 = coords[11073] #back
thigh_front_back = distance(thigh1 , thigh2)


#loop until mesh of model equals data from mat
for i in range(1,20):        
    if thigh_front_back < mat.get('size_thigh_front_back') and abs(thigh_front_back-mat.get('size_thigh_front_back')) > 0.02:
         bpy.data.scenes["Scene"].legs_l_upperleg_scale_depth_decr_incr += 0.02
         obj.data.update()
         thigh_front_back = distance(thigh1 , thigh2) 
    elif thigh_front_back > mat.get('size_thigh_front_back') and abs(thigh_front_back-mat.get('size_thigh_front_back')) > 0.02:
         bpy.data.scenes["Scene"].legs_l_upperleg_scale_depth_decr_incr -= 0.02
         obj.data.update()
         thigh_front_back = distance(thigh1 , thigh2) 
    else:
        print('Outline has been fitted')
        break 
$\endgroup$
3
  • 1
    $\begingroup$ Should the coords = [(obj.matrix_world @ v.co) for v in obj.data.vertices] and thigh1 = coords[11071] etc. not be within the for loop? Now the coordinates are only collected once and the distance between two vertices will always be the same. $\endgroup$ Dec 2, 2022 at 11:24
  • $\begingroup$ Yes this makes sense! However, the vertices coordinates are not updated as the mesh increases, even if I redefine them every loop :/ $\endgroup$
    – Ortho12
    Dec 2, 2022 at 14:04
  • 1
    $\begingroup$ It would be easier to help if the problem was minimized by stripping it from details unimportant to the problem: for example do you really need all those thighs objects? Wouldn't one pair of them be enough to show the problem? If vert coords don't update, can you print them twice to show their positions remain constant even though you expect them to change? Can you upload a simple .blend file to blend-exchange.com/ or produce testing geometry from within the script, so there's not too many verts to keep track of? Cheers. $\endgroup$ Dec 2, 2022 at 16:52

1 Answer 1

0
$\begingroup$

I think you are confusing a few different things here. You are comparing the raw object data vertex positions but you are changing shape key vertex positions implicitly by modifying a scene property which mirrors a shape key with the same name.

What you want to do is compare vertex positions as they look after taking all shape keys into account.

The easiest way to get access to all vertex positions after shape keys is to create a new temporary shape key "from mix" and read the data from that instead of using object.data. If "basemesh" is the human object you want to work with:

key_name = "temporary_fitting_key." + str(random.randrange(1000, 9999))
basemesh.shape_key_add(name=key_name, from_mix=True)
shape_key = basemesh.data.shape_keys.key_blocks[key_name]
human_vertices = shape_key.data

Here "human_vertices" contains the desired vertex positions.

Once you are done with the shape key you can then remove it:

basemesh.shape_key_remove(shape_key)
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .