# RBF Deformer with python issue

## Recommended Posts

Posted (edited)

Hey guys,

I started writing a deformer using rbf (Radial Basis Function) with python, my aim is to reproduce the one made by Artem Smirnov in his reel : https://vimeo.com/338885866

Currently I try to get it working on geometry and then I'll implement it for volumes

I'm experiencing an issue and I don't really know from where it's coming : the deformation is kind of inverted on the other side of the geometry, where the geometry should not move and stay where it is, and I don't know what causes this.

Input 1 is the mesh, Input 2 is the rest lattice and Input 3 is the deformed lattice

Here's the code :

```import numpy as np

node = hou.pwd()
inputs = node.inputs()

geo1 = node.geometry()
geo2 = inputs[1].geometry()
geo3 = inputs[2].geometry()

kernel_parm = node.evalParm("kernels")
kernel_names = "gaussian,thinPlateSpline,linear".split(",")
kernel = kernel_names[kernel_parm]

#####################################################
#distance calculation
def ext_arrs(A,B, precision="float64"):
nA,dim = A.shape
A_ext = np.ones((nA,dim*3),dtype=precision)
A_ext[:,dim:2*dim] = A
A_ext[:,2*dim:] = A**2

nB = B.shape[0]
B_ext = np.ones((dim*3,nB),dtype=precision)
B_ext[:dim] = (B**2).T
B_ext[dim:2*dim] = -2.0*B.T
return A_ext, B_ext

def pdist_squareformed(a, b):
A_ext, B_ext = ext_arrs(a, b)
dist = A_ext.dot(B_ext)
np.fill_diagonal(dist,0)
return dist

def thinPlateSpline(x, r):
arg = x / r
result = arg * arg
result = np.where(arg > 0, result * np.log(arg), result)
return result

def gaussianSpline(x, r):
result = np.exp(-(x * x) / (r * r))
return result

def linear(x, r):
result = x / r
return result

if kernel == "gaussian":

if kernel == "thinPlateSpline":

if kernel == "linear":

return result

#####################################################
#SETUP GEO POSITIONS MATRICES

numpt1 = len(geo1.iterPoints())
matrixQ1 = np.zeros((numpt1, 3))

numpt2 = len(geo2.iterPoints())
matrixQ2 = np.zeros((numpt2, 3))

numpt3 = len(geo3.iterPoints())
matrixQ3 = np.zeros((numpt3, 3))

#geo
i = 0;
for p1 in geo1.points():
matrixQ1[i, 0] = p1.position()[0]
matrixQ1[i, 1] = p1.position()[1]
matrixQ1[i, 2] = p1.position()[2]
i += 1

#lattice
j = 0;
for p2 in geo2.points():
matrixQ2[j, 0] = p2.position()[0]
matrixQ2[j, 1] = p2.position()[1]
matrixQ2[j, 2] = p2.position()[2]
j += 1

#deformed lattice
k = 0;
for p3 in geo3.points():
matrixQ3[k, 0] = p3.position()[0]
matrixQ3[k, 1] = p3.position()[1]
matrixQ3[k, 2] = p3.position()[2]
k += 1

#####################################################
#CALCULATE WEIGHTS

npts, dim = matrixQ2.shape

H = np.zeros((npts + 3 + 1, npts + 3 + 1))

H[:npts, :npts] = rbf(np.sqrt(pdist_squareformed(matrixQ2, matrixQ2)), kernel, radius_parm)

H[npts, :npts] = 1.0
H[:npts, npts] = 1.0
H[:npts, -3:] = matrixQ2
H[-3:, :npts] = matrixQ2.T

RH = np.zeros((npts + 3 + 1, dim))
RH[:npts, :] = matrixQ3

weights = np.linalg.solve(H, RH)

#####################################################
#DEFORMATION

npts2, dim2 = matrixQ1.shape

G = np.zeros((npts2, npts + 3 + 1))
G[:, :npts] = rbf(np.sqrt(pdist_squareformed(matrixQ1, matrixQ2)), kernel, radius_parm)

G[:, :npts] = 1.0
G[:, -3:] = matrixQ1

new_pos = np.asarray(np.dot(G, weights))

#####################################################
#SET POS

s = 0;
for p in geo1.points():
newX = new_pos[s, 0]
newY = new_pos[s, 1]
newZ = new_pos[s, 2]

p.setPosition((newX, newY, newZ))

s += 1

```

Edited by DonRomano

## Create an account

Register a new account