def loop_step(v1,loopVerts, step,outEdges, center, dVec): #Check both edges connected to this one for e in v1.link_edges: # We only go for the edge on the outside.... if e in outEdges: if v1 == e.verts[0]: v2 = e.verts[1] else: v2 = e.verts[0] v1co = v1.co - center v2co = v2.co - center if dVec is False: dVec = v2co - v1co relVec = v2co - v1co # If the dot is negative... we're moving back along the circle and we invert the step (move the vert toward the previous one in stead of away from it) dot = relVec.dot(dVec) #print(len(outEdges),'dot',dot) if dot < 0.0: v2co = misc.rotate_vector_to_vector(v1co, v2co, step) else: v2co = misc.rotate_vector_to_vector(v2co, v1co, step) # Put the vert in the right position v2.co = v2co + center # Remove the edge from the list of outer edges.... no lnoger needed outEdges.remove(e) loopVerts.append(v2) dVec = v2co - v1co outEdges, loopVerts = loop_step(v2, loopVerts, step, outEdges, center, dVec) break return outEdges, loopVerts
def cast(bme=None, corners=0, falloff_scale=1.0, falloff_shape='STR',corner_group=None,redraw=False): if not bme: bm = bmesh_extras.get_bmesh() else: bm = bme print(corners, falloff_scale, falloff_shape) # Get a heap of lists to work with later! selFaces = bmesh_extras.get_selected_faces(bm) selVerts = bmesh_extras.get_selected_verts(bm) outVerts = bmesh_extras.get_outer_verts(selFaces) outEdges = bmesh_extras.get_outer_edges(selFaces) cent = bmesh_extras.get_vert_center(selVerts ) normal = bmesh_extras.get_normal(selFaces) inVerts = [] if len(outVerts): # Let's quickly make a list of inner verts for v in selVerts: if not v in outVerts: inVerts.append(v) # make a quaternion and a matrix representing this "plane" quat = normal.to_track_quat('-Z', 'Y') mat = quat.to_matrix() # Put all the verts in the plane... # And.. find out for each vert how far it is along the normal # Ang get the average distance from the center point midDist = 0.0 for v in selVerts: relPos = (v.co - cent) relDot = normal.dot(relPos) v.co += (normal * (-relDot)) # If this is an outerVert... then we keep track of it's distance from the center if v in outVerts: midDist += relPos.length # The medium distance from the center point midDist /= len(outVerts) # now lets put them all the right distance from the center top = False topVert = False for i,v in enumerate(outVerts): relPos = v.co - cent relPos = relPos.normalized() * midDist v.co = relPos + cent # Find the top vert for nice alignment of the shape (start the steploop here) if top is False or v.co[2] > top: top = v.co[2] topVert = i # As a final step... we want them to be rotated neatly around the center... step = math.radians(360) / (len(outEdges)) # Now that we found the top vert we can start looping through to put them in the right position loopVerts = [outVerts[topVert]] outEdges, loopVerts = loop_step(outVerts[topVert],loopVerts,step,outEdges,cent,False) # Set corner group weight to 0.0 because the shape is a circle (will be reset to 1.0 later for the actual corners) if corner_group: bm, group_index = add_to_group(bme=bm,verts=outVerts, newGroup=False, groupName=corner_group, weight=0.0) if corners: # Initiate a list of all corner verts so we can set the weight accordingly later (best done in one move) cornerVerts = [] c = round((360.0 / corners),2) a = (180.0 - c) * 0.5 stepLen = math.ceil(len(outVerts) / corners) #print('stepLen', stepLen) aLine = False currentX = 0.0 vec = falloff_scale factor = 1.0 curve = falloff_curve.curve(falloff_shape, 'mult') loopCnt = len(loopVerts) cornerCnt = math.floor(loopCnt / corners) #print('\n',loopCnt,cornerCnt) for i, v in enumerate(loopVerts): #if(i>9): # return stepPos = i % stepLen #print(i,'stepPos',stepPos) # Get a normalized version of the current relative position line = mathutils.Vector(v.co - cent).normalized() # Get the starting line as a reference (is also a corner if not aLine: aLine = line currentX = 0.0 factor = 1.0 #if corner_group: corner_group.add([v.index], 1.0, 'REPLACE') if corner_group: cornerVerts.append(v) else: # Find the angle from the current starting line cAng = round(math.degrees(aLine.angle(line)),2) #print('ang',cAng,c,(cAng >= c)) # If the angle is bigger than a step, we make this the new start if cAng >= c: #print('found corner') #if corner_group: corner_group.add([v.index], 1.0, 'REPLACE') if corner_group: cornerVerts.append(v) # Make sure the angle is correct! line = misc.rotate_vector_to_vector(line, aLine, math.radians(c)) v.co = (line * midDist) + cent aLine = line currentX = 0.0 factor = 1.0 # These should all be midpoints along the line! # make sure we don't do the last one... because it's the first one! else: # Remove non corner items from the corner group #if corner_group: corner_group.remove([v.index]) # Only if we have to scale and the line isn't straight! if falloff_scale != 1.0 and falloff_shape != 'STR': # Find out how far we are from the start as a factor (fraction of one?) angFac = cAng / c newX = angFac # Create a nice curve object to represent the falloff curve.update(1.0, 0.0, vec, currentX, newX) fac = abs(curve.currentVal) factor *= fac currentX = newX # Find the corner of the new triangle b = 180 - (a+cAng) # find the distance from the midpoint A = math.sin(math.radians(a)) / (math.sin(math.radians(b))/midDist) bLine = line * A bLine *= factor v.co = bLine + cent if redraw: scene_update.go(False, 'RED') if len(cornerVerts): bm, group_index = add_to_group(bme=bm,verts=cornerVerts, newGroup=False, groupName=corner_group, weight=1.0) # I want to make sure these verts are inside the loop! # So we move all verts halfway towards the center before smoothing (neat results in entoforms) for v in inVerts: relPos = cent - v.co v.co += (relPos * 0.5) #for i in range(100): # SMOOTH THE VERTS MAN!!! bmesh_extras.smooth_verts(verts=inVerts,loops=10) #bmesh.ops.smooth_vert(bm, verts=inVerts,use_axis_x=True, use_axis_y=True, use_axis_z=True) if not bme: bmesh_extras.put_bmesh(bm) else: return bm
def cast_loop(bme=None, corners=0, falloff_scale=1.0, falloff_shape='STR',corner_group=None): if not bme: bm = get_bmesh() else: bm = bme # Get a heap of lists to work with later! selFaces = get_selected_faces(bm) selVerts = get_selected_verts(bm) outVerts = get_outer_verts(selFaces) outEdges = get_outer_edges(selFaces) cent = get_vert_center(selVerts ) normal = get_normal(selFaces) inVerts = [] if len(outVerts): # Let's quickly make a list of inner verts for v in selVerts: if not v in outVerts: inVerts.append(v) # make a quaternion and a matrix representing this "plane" quat = normal.to_track_quat('-Z', 'Y') mat = quat.to_matrix() # Put all the verts in the plane... # And.. find out for each vert how far it is along the normal # Ang get the average distance from the center point midDist = 0.0 for v in selVerts: relPos = (v.co - cent) relDot = normal.dot(relPos) v.co += (normal * (-relDot)) # If this is an outerVert... then we keep track of it's distance from the center if v in outVerts: midDist += relPos.length # The medium distance from the center point midDist /= len(outVerts) # now lets put them all the right distance from the center top = False topVert = False for i,v in enumerate(outVerts): relPos = v.co - cent relPos = relPos.normalized() * midDist v.co = relPos + cent # Find the top vert for nice alignment of the shape (start the steploop here) if top is False or v.co[2] > top: top = v.co[2] topVert = i # As a final step... we want them to be rotated neatly around the center... step = math.radians(360) / (len(outEdges)) # Now that we found the top vert we can start looping through to put them in the right position loopVerts = [outVerts[topVert]] outEdges, loopVerts = loop_step(outVerts[topVert],loopVerts,step,outEdges,cent,False) # Set corner group weight to 0.0 because the shape is a circle (will be reset to 1.0 later for the actual corners) if corner_group: bm, group_index = add_to_group(bme=bm,verts=outVerts, newGroup=False, groupName=corner_group, weight=0.0) if corners: # Initiate a list of all corner verts so we can set the weight accordingly later (best done in one move) cornerVerts = [] c = 360.0 / corners a = (180.0 - c) * 0.5 stepLen = math.ceil(len(outVerts) / corners) aLine = False currentX = 0.0 vec = falloff_scale factor = 1.0 curve = falloff_curve.curve(falloff_shape, 'mult') for i, v in enumerate(loopVerts): stepPos = i % stepLen # Get a normalized version of the current relative position line = mathutils.Vector(v.co - cent).normalized() # Get the starting line as a reference (is also a corner if not aLine: aLine = line currentX = 0.0 factor = 1.0 #if corner_group: corner_group.add([v.index], 1.0, 'REPLACE') if corner_group: cornerVerts.append(v) else: # Find the angle from the current starting line cAng = aLine.angle(line) # If the angle is bigger than a step, we make this the new start if cAng > math.radians(c): #if corner_group: corner_group.add([v.index], 1.0, 'REPLACE') if corner_group: cornerVerts.append(v) # Make sure the angle is correct! line = misc.rotate_vector_to_vector(line, aLine, math.radians(c)) v.co = (line * midDist) + cent aLine = line currentX = 0.0 factor = 1.0 # These should all be midpoints along the line! # make sure we don't do the last one... because it's the first one! else: # Remove non corner items from the corner group #if corner_group: corner_group.remove([v.index]) # Only if we have to scale and the line isn't straight! if falloff_scale != 1.0 and falloff_shape != 'STR': # Find out how far we are from the start as a factor (fraction of one?) angFac = cAng / math.radians(c) newX = angFac # Create a nice curve object to represent the falloff curve.update(1.0, 0.0, vec, currentX, newX) fac = abs(curve.currentVal) factor *= fac currentX = newX # Find the corner of the new triangle b = 180 - (a+math.degrees(cAng)) # find the distance from the midpoint A = math.sin(math.radians(a)) / (math.sin(math.radians(b))/midDist) bLine = line * A bLine *= factor v.co = bLine + cent if len(cornerVerts): bm, group_index = add_to_group(bme=bm,verts=cornerVerts, newGroup=False, groupName=corner_group, weight=1.0) # I want to make sure these verts are inside the loop! # So we move all verts halfway towards the center before smoothing (neat results in entoforms) for v in inVerts: relPos = cent - v.co v.co += (relPos * 0.5) #for i in range(100): # SMOOTH THE VERTS MAN!!! smooth_verts(verts=inVerts,loops=10) #bmesh.ops.smooth_vert(bm, verts=inVerts,use_axis_x=True, use_axis_y=True, use_axis_z=True) if not bme: put_bmesh(bm) else: return bm