I am sure that there’s an easier way to do this - but I have created a script that creates a copy of a mesh such that the faces of the mesh are indented a small amount from the origional. eg. if applied to a sphere it creates a smaller concentric sphere. I want it to also work with much more complex shapes.
it works by walking through the list of faces and creating new vertices, offset a small distance from each origional vertex in a direction normal to the origional face.
If I create faces from these vertices, the new faces overlap at the edges making a very jagged shape, so I consolodate all vertices within a culling radius into a single value, forcing the faces to meet at the edges (well it’s supposed to) In practice it only works for very small offsets that can usefully use a small culling radius otherwise innocent bystanding points get culled too and the shape is whittled awat to a nub.
The vertex culling and consolidation algorithm stinks so I’m open to any better suggestions.
What I really would like is for someone to take the time to run the script (if anyone can follow a word of this explanation) and suggest ways in which I might improve the algorithms (improvement in my coding style is probably a dead loss)
The defaults in the gui are suitable to create a reasonabl
e shrunken monkey head from the one in the list of standard meshes in Blender Publisher.
you’ll need to cut the monkey’s head open or move the origional aside to see the very slighly smaller copy.
Many thanks to
csDraco_ and S68 via neil.
Here’s the script…
from Blender import *
from math import *
from Blender.Draw import *
false = 0
true = 1
offset = Create(0.01)
cullradius = Create(0.01)
indent = offset.val
newfaces=[]
faces=[]
facerefs = []
points = []
me = Mesh.New()
ob = Object.New('Mesh', 'nested')
sc = Scene.getCurrent()
def Warn():
BGL.glRasterPos2d(115, 23)
Blender.Window.Redraw(Blender.Window.Const.TEXT)
def draw():
global offset, cullradius
BGL.glClearColor(0.5, 0.7, 0.5, 1)
BGL.glColor3f(1,1,1)
BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
BGL.glColor3f(1, 1, 0)
BGL.glRasterPos2d(10, 170)
sc = Scene.getCurrent()
objects = Object.GetSelected()
if len(objects) > 0 : Text("Set the indent value and press Go - small indents work best")
else: Text("Select a mesh object to work with")
BGL.glRasterPos2d(10, 150)
Text("Blender Nested object maker - (L) Dec. 2002 Daddy")
offset=Slider("Offset ",2,10, 100, 250, 20, offset.val, 0, 0.1)
cullradius=Slider("Cull radius ",2,10, 120, 250, 20, cullradius.val, 0.001, 1.0)
Button("Break", 1 ,40 , 70, 40, 20)
Button("Go", 3, 120, 70, 40, 20)
def event(evt, val):
if (evt== QKEY and not val):
Exit()
def bevent(evt):
global faces, data, indent, mindistance
if (evt== 1):
Exit()
elif (evt== 2):
Draw()
elif (evt== 3):
objects = Object.GetSelected()
print len(objects)
if len(objects) < 1: Draw()
else:
object = objects[0]
data = object.data
faces = data.faces
indent = offset.val
mindistance = cullradius.val
make_shell()
Exit()
def crossprod (u, v):
return (((u[1]*v[2])-(u[2]*v[1])),-1.0*((u[0]*v[2])-(u[2]*v[0])), ((u[0]*v[1])-(u[1]*v[0])))
def dotprod (u,v):
return (u[0]*v[0])+(u[1]*v[1])+(u[2]*v[2])
def distance (p1, p2):
return sqrt(((p1[0]-p2[0])**2)+((p1[1]-p2[1])**2)+((p1[2]-p2[2])**2))
def normalise(vector):
factor = sqrt((vector[0]**2)+(vector[1]**2)+(vector[2]**2))/indent
if factor <= 0.000001:
print "warning - zero normal"
return (0.0, 0.0, 0.0)
else:
return (vector[0]/factor, vector[1]/factor, vector[2]/factor)
def normal (plane):
vector_1 = (plane[1].co[0] - plane[0].co[0], plane[1].co[1] - plane[0].co[1], plane[1].co[2] - plane[0].co[2])
vector_2 = (plane[2].co[0] - plane[0].co[0], plane[2].co[1] - plane[0].co[1], plane[2].co[2] - plane[0].co[2])
return normalise(crossprod(vector_1, vector_2))
def consolidate (point):
for counter in range (0, len(points)):
if distance(point,points[counter][0]) <= mindistance:
points[counter].append(point)
return counter
points.append([point])
return (len(points)-1)
def make_shell():
global offset, indent, points, objects, object, data, faces, newfaces, facerefs, ob, sc, me
for face in faces:
mugs=[]
if len(face) == 3:
mugs=[[face[0], face[1], face[2]]]
elif len(face) == 4:
mugs=[[face[0],face[1],face[3]]]
mugs.append([face[1],face[2],face[3]])
for mug in mugs:
newface=[]
norm = normal(mug)
for vertex in mug:
newface.append(consolidate((vertex.co[0]-norm[0],vertex.co[1] - norm[1],vertex.co[2]-norm[2])))
facerefs.append(newface)
for i in range (0,len(points)):
newx = 0.0
newy = 0.0
newz = 0.0
n = len(points[i])
m = 0.0+n
for j in range (0,n):
newx += points[i][j][0]
newy += points[i][j][1]
newz += points[i][j][2]
points[i]=(me.addVert((newx/m, newy/m, newz/m)))
for face in facerefs:
newface=[]
for vertex in face:
newface.append(points[vertex])
newfaces.append(newface)
me.addFace(newface)
points = []
facerefs=[]
ob.link(me)
sc.link(ob)
Register (draw, event, bevent)