2
$\begingroup$

I have a 3D surface with N vetrices and M faces. I also have independent numpy arrays for face normals, n, vertices coordinates, V, and the triangulation of the vertices in F.

For each vertex, I also have a function, f(iVertex) = h_i that defines how much the vertex should move along the local normal, which can be outward (positive h_i values) or inward (negative h_i values). In other words, displacing the vertices along the local normal are not uniform and is different from vertex to vertex according to the function f(iVertex).

The closest solution I found was posted here. However, I don't want my surface to get disintegrated and I want the faces to remain connected even after displacing the vertices. How can I move the vertices based on f efficiently in Blender using Python without disassembling the faces?

$\endgroup$
2
$\begingroup$

I used an existing base mesh to test this, which is why the code I'm using might need some changes for you to be able to implement it.

enter image description here

The most important thing here is lines 22-23:

d    = normal * h_i[i] # Current vertex's displacement value
v.co = V[i] + d        # Displace current vertex along normal

You calculate each vertex's new location by adding to it the displacement value, which is the h_i for that vertex X the face normal (which is a direction vector).

Here's the complete code:

import bpy, bmesh
import numpy as np

bm = bmesh.new()
bm.from_mesh( bpy.context.object.data )

worldMatrix = bpy.context.object.matrix_world

F   = bm.faces                                 # Face objects
V   = [ worldMatrix * v.co for v in bm.verts ] # Vert coordinates

# Generate a random number between -1 and 1 as a displacement value for each vertex
h_i = 2 * np.random.random( len( V ) ) - 1

# Perform displacement
# Iterate over faces (You might want to zip the face normals and triangulations here)
for f in F:
    normal = f.normal # get Face normal (your n value for this face)
    fVerts = f.verts  # List of face vertices (your "F" variable for this face)
    # Iterate over this face's vertices (F[face_index])
    for v in fVerts:
        i = v.index

        d    = normal * h_i[i] # Current vertex's displacement value
        v.co = V[i] + d        # Displace current vertex along normal


update_existing_mesh = True
if update_existing_mesh:
    bm.to_mesh( bpy.context.object.data )
else: # Generate a new mesh
    m = bpy.data.meshes.new( "Displaced" )
    bm.to_mesh( m )

    o = bpy.data.objects.new( "Displaced", m )
    bpy.context.scene.objects.link( o )
$\endgroup$
  • $\begingroup$ Thank you for your quick answer. As a side note, may I know how you recorded your screen for this answer? $\endgroup$ – AFP Apr 19 '16 at 6:28
  • 1
    $\begingroup$ No problem :) Recorded with: screentogif.codeplex.com $\endgroup$ – TLousky Apr 19 '16 at 6:38
  • $\begingroup$ I noticed that the mesh is not modified and instead a new object is created. Is there any way that instead of creating a new one the current object is displaced and gets modified? $\endgroup$ – AFP Apr 19 '16 at 22:44
  • 1
    $\begingroup$ @Ahmad, I updated the code to present both options $\endgroup$ – TLousky Apr 20 '16 at 5:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.