Is there a way to make a low poly mesh automatically reshape to follow the shape of a high poly mesh being animated with a shape key?
My idea is to create a low poly version of a high poly poser character in blender, then be able to bring in various different character morph shapes from poser and apply them to the high poly character and have the low poly one follow the changes automatically. (I like the poser characters - i.e. victoria 3 and michael 3 - and all their gazillion different morph shapes, but they’re just too high poly to be of any use on any computer that doesn’t need a time flux capacitor to run).
edit One very painful way of doing it would be to put a hook on every single vertex of the low poly character to the high poly character… Hopefully there’s an easier way of doing it than that with python…
all excited edit How hard is it to create hooks between two meshes in python? Can anyone point me at any existing python code that does anything like this?
Ok, so really wanted to get this going, so I did battle with python and seem to have emerged with a reasonable measure of victory. What I’ve got going at the moment is a system with two scripts :
L2H_read.py
Reads through all the vertices of the object called “low_poly” and for each one finds the closest vertex in the object called “high_poly”. Then it records which vertex in high_poly was the closest and the distance between the low_poly and high_poly vertices and stores it in low_poly in properties (for each vertex).
L2H_write.py
After you’ve changed the shape (but not structure) of the object called “high_poly” (either manually or with shape keys), you run this script and it goes through all of the vertices in the object called “low_poly”, and for each one recalls which vertex from “high_poly” was (originally) the closest and what it’s offset was from the current vertex in “low_poly” (originally). Then it uses this information to reposition all of the vertices in “low_poly” so that they are positioned the same distance from their matching vertices in “high_poly” as they were before high_polys shape was changed.
(sorry I couldn’t explain that better, it’s late here - it’ll be interesting to see how many people get it…)
Anyways, here are the scripts:
L2H_read.py
##################################################
## ##
## L2H_read.py - read diff between two meshes ##
## ##
##################################################
import Blender
from Blender import Object
### setup object references
low_poly = Object.Get('low_poly')
low_poly_mesh = low_poly.getData()
lpox = low_poly.loc[0]
lpoy = low_poly.loc[1]
lpoz = low_poly.loc[2]
high_poly = Object.Get('high_poly')
high_poly_mesh = high_poly.getData()
hpox = high_poly.loc[0]
hpoy = high_poly.loc[1]
hpoz = high_poly.loc[2]
### loop through each vert in low_poly_mesh
for lp_vert in low_poly_mesh.verts:
l2h_closest_index = 0
l2h_closest_dist = 100000
l2h_offset_x = 0
l2h_offset_y = 0
l2h_offset_z = 0
lpvx = lp_vert.co[0] + lpox
lpvy = lp_vert.co[1] + lpoy
lpvz = lp_vert.co[2] + lpoz
### loop through each vert in high_poly_mesh
for hp_vert in high_poly_mesh.verts:
hpvx = hp_vert.co[0] + hpox
hpvy = hp_vert.co[1] + hpoy
hpvz = hp_vert.co[2] + hpoz
# figure out additive distance between lp_vert and hp_vert
distance_x = abs(hpvx - lpvx)
distance_y = abs(hpvy - lpvy)
distance_z = abs(hpvz - lpvz)
distance = distance_x + distance_y + distance_z
if(distance < l2h_closest_dist):
l2h_closest_dist = distance
l2h_closest_index = hp_vert.index
l2h_offset_x = hpvx - lpvx
l2h_offset_y = hpvy - lpvy
l2h_offset_z = hpvz - lpvz
### write distance analysis results to low_poly properties
low_poly.properties[str(lp_vert.index)+"_index"] = l2h_closest_index
low_poly.properties[str(lp_vert.index)+"_ox"] = l2h_offset_x
low_poly.properties[str(lp_vert.index)+"_oy"] = l2h_offset_y
low_poly.properties[str(lp_vert.index)+"_oz"] = l2h_offset_z
low_poly_mesh.update()
#and than maybe redraw the scene
Blender.Redraw()
############################################################################
## ##
## L2H_write.py - update low poly mesh to match reshaped high poly mesh ##
## ##
############################################################################
import Blender
from Blender import Object
### setup object references
low_poly = Object.Get('low_poly')
low_poly_mesh = low_poly.getData()
lpox = low_poly.loc[0]
lpoy = low_poly.loc[1]
lpoz = low_poly.loc[2]
high_poly = Object.Get('high_poly')
high_poly_mesh = high_poly.getData()
hpox = high_poly.loc[0]
hpoy = high_poly.loc[1]
hpoz = high_poly.loc[2]
### loop through each vert in low_poly_mesh
for lp_vert in low_poly_mesh.verts:
# read offsets from properties
l2h_closest_index = low_poly.properties[str(lp_vert.index) + "_index"]
l2h_offset_x = low_poly.properties[str(lp_vert.index) + "_ox"]
l2h_offset_y = low_poly.properties[str(lp_vert.index) + "_oy"]
l2h_offset_z = low_poly.properties[str(lp_vert.index) + "_oz"]
# get absolutes from matching high_poly vert
hp_vert = high_poly_mesh.verts[int(l2h_closest_index)]
hpvx = hp_vert.loc[0] + hpox
hpvy = hp_vert.loc[1] + hpoy
hpvz = hp_vert.loc[2] + hpoz
# move low poly verts to matching high poly verts + offsets
lp_vert.loc[0] = (hpvx - l2h_offset_x) - lpox
lp_vert.loc[1] = (hpvy - l2h_offset_y) - lpoy
lp_vert.loc[2] = (hpvz - l2h_offset_z) - lpoz
# update mesh and redraw the scene
low_poly_mesh.update()
Blender.Redraw()
Hmmm, interesting. At the moment though, for my purposes, I don’t need the effect animated over time. For now, I just want to be able to bring in a high poly morph shape and have the script auto adjust a low poly morph shape to match it. After that, any animating can just be done with bones on a pre prepared low poly blender character.
One interesting thing that did occur to me though is that a slightly better version of the script could be used to create a sticky mesh effect - more specifically clothes - but I think that would be a lot more complicated when there are already cool solutions out there that work a lot better (I’m thinking of that cool tute for using softbodies to do animated clothing with wrinkles).