From f90b7a69065b14cb1d5bb896a52a0d0c5783b8de Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 Jan 2006 23:47:45 +0000 Subject: moving to bpydata because it cant be accessed from the menus --- release/scripts/mesh_bbrush.py | 898 ----------------------------------------- 1 file changed, 898 deletions(-) delete mode 100644 release/scripts/mesh_bbrush.py (limited to 'release') diff --git a/release/scripts/mesh_bbrush.py b/release/scripts/mesh_bbrush.py deleted file mode 100644 index e174a52d515..00000000000 --- a/release/scripts/mesh_bbrush.py +++ /dev/null @@ -1,898 +0,0 @@ -# SPACEHANDLER.VIEW3D.EVENT -# Dont run, event handelers are accessed in the from the 3d View menu. - -import Blender -from Blender import Mathutils, Window, Scene, Draw, Mesh, NMesh -from Blender.Mathutils import CrossVecs, Matrix, Vector, Intersect, LineIntersect - - -# DESCRIPTION: -# screen_x, screen_y the origin point of the pick ray -# it is either the mouse location -# localMatrix is used if you want to have the returned values in an objects localspace. -# this is usefull when dealing with an objects data such as verts. -# or if useMid is true, the midpoint of the current 3dview -# returns -# Origin - the origin point of the pick ray -# Direction - the direction vector of the pick ray -# in global coordinates -epsilon = 1e-3 # just a small value to account for floating point errors - -def getPickRay(screen_x, screen_y, localMatrix=None, useMid = False): - - # Constant function variables - p = getPickRay.p - d = getPickRay.d - - for win3d in Window.GetScreenInfo(Window.Types.VIEW3D): # we search all 3dwins for the one containing the point (screen_x, screen_y) (could be the mousecoords for example) - win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices'] - # calculate a few geometric extents for this window - - win_mid_x = (win_max_x + win_min_x + 1.0) * 0.5 - win_mid_y = (win_max_y + win_min_y + 1.0) * 0.5 - win_size_x = (win_max_x - win_min_x + 1.0) * 0.5 - win_size_y = (win_max_y - win_min_y + 1.0) * 0.5 - - #useMid is for projecting the coordinates when we subdivide the screen into bins - if useMid: # == True - screen_x = win_mid_x - screen_y = win_mid_y - - # if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one... - if (win_max_x > screen_x > win_min_x) and ( win_max_y > screen_y > win_min_y): - # first we handle all pending events for this window (otherwise the matrices might come out wrong) - Window.QHandle(win3d['id']) - - # now we get a few matrices for our window... - # sorry - i cannot explain here what they all do - # - if you're not familiar with all those matrices take a look at an introduction to OpenGL... - pm = Window.GetPerspMatrix() # the prespective matrix - pmi = Matrix(pm); pmi.invert() # the inverted perspective matrix - - if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon): - # pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5) - hms = getPickRay.hms - ortho_d = getPickRay.ortho_d - - # ortho mode: is a bit strange - actually there's no definite location of the camera ... - # but the camera could be displaced anywhere along the viewing direction. - - ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector() - ortho_d.w = 0 - - # all rays are parallel in ortho mode - so the direction vector is simply the viewing direction - hms.x, hms.y, hms.z, hms.w = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0 - - # these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1 - p=(hms*pmi) + (1000*ortho_d) - p.resize3D() - d.x, d.y, d.z = ortho_d.x, ortho_d.y, ortho_d.z - - - # Finally we shift the position infinitely far away in - # the viewing direction to make sure the camera if outside the scene - # (this is actually a hack because this function - # is used in sculpt_mesh to initialize backface culling...) - else: - # PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location - vmi = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix - fp = getPickRay.fp - - dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0] - dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1] - - fp.x, fp.y, fp.z = \ - pmi[0][0]*dx+pmi[1][0]*dy,\ - pmi[0][1]*dx+pmi[1][1]*dy,\ - pmi[0][2]*dx+pmi[1][2]*dy - - # fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y) - #- figuring out how to calculate this took me quite some time. - # The calculation of dxy and fp are simplified versions of my original code - #- so it's almost impossible to explain what's going on geometrically... sorry - - p.x, p.y, p.z = vmi[3][:3] - - # the camera's location in global 3dcoords can be read directly from the inverted viewmatrix - #d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp)) - d.x, d.y, d.z = p.x-fp.x, p.y-fp.y, p.z-fp.z - - #print 'd', d, 'p', p, 'fp', fp - - - # the direction vector is simply the difference vector from the virtual camera's position - #to the unprojected (screenspace) point fp - - # Do we want to return a direction in object's localspace? - - if localMatrix: - localInvMatrix = Matrix(localMatrix) - localInvMatrix.invert() - p = p*localInvMatrix - d = d*localInvMatrix # normalize_v3 - p.x += localInvMatrix[3][0] - p.y += localInvMatrix[3][1] - p.z += localInvMatrix[3][2] - - #else: # Worldspace, do nothing - - d.normalize() - return True, p, d # Origin, Direction - - # Mouse is not in any view, return None. - return False, None, None - -# Constant function variables -getPickRay.d = Vector(0,0,0) # Perspective, 3d -getPickRay.p = Vector(0,0,0) -getPickRay.fp = Vector(0,0,0) - -getPickRay.hms = Vector(0,0,0,0) # ortho only 4d -getPickRay.ortho_d = Vector(0,0,0,0) # ortho only 4d - - - -def ui_set_preferences(user_interface=1): - - # Create data and set defaults. - ADAPTIVE_GEOMETRY_but = Draw.Create(1) - BRUSH_MODE_but = Draw.Create(1) - BRUSH_PRESSURE_but = Draw.Create(0.05) - BRUSH_RADIUS_but = Draw.Create(0.25) - RESOLUTION_MIN_but = Draw.Create(0.1) - DISPLACE_NORMAL_MODE_but = Draw.Create(2) - STATIC_NORMAL_but = Draw.Create(1) - XPLANE_CLIP_but = Draw.Create(0) - STATIC_MESH_but = Draw.Create(1) - FIX_TOPOLOGY_but = Draw.Create(0) - - # Remember old variables if alredy set. - try: - ADAPTIVE_GEOMETRY_but.val = Blender.bbrush['ADAPTIVE_GEOMETRY'] - BRUSH_MODE_but.val = Blender.bbrush['BRUSH_MODE'] - BRUSH_PRESSURE_but.val = Blender.bbrush['BRUSH_PRESSURE'] - BRUSH_RADIUS_but.val = Blender.bbrush['BRUSH_RADIUS'] - RESOLUTION_MIN_but.val = Blender.bbrush['RESOLUTION_MIN'] - DISPLACE_NORMAL_MODE_but.val = Blender.bbrush['DISPLACE_NORMAL_MODE'] - STATIC_NORMAL_but.val = Blender.bbrush['STATIC_NORMAL'] - XPLANE_CLIP_but.val = Blender.bbrush['XPLANE_CLIP'] - STATIC_MESH_but.val = Blender.bbrush['STATIC_MESH'] - FIX_TOPOLOGY_but.val = Blender.bbrush['FIX_TOPOLOGY'] - except: - Blender.bbrush = {} - - if user_interface: - pup_block = [\ - 'Brush Options',\ - ('Adaptive Geometry', ADAPTIVE_GEOMETRY_but, 'Add and remove detail as needed. Uses min/max resolution.'),\ - ('Brush Type: ', BRUSH_MODE_but, 1, 5, 'Push/Pull:1, Grow/Shrink:2, Spin:3, Relax:4, Goo:5'),\ - ('Pressure: ', BRUSH_PRESSURE_but, 0.0, 1.0, 'Pressure of the brush.'),\ - ('Size: ', BRUSH_RADIUS_but, 0.0, 2.0, 'Size of the brush.'),\ - ('Geometry Res: ', RESOLUTION_MIN_but, 0.01, 0.5, 'Size of the brush & Adaptive Subdivision.'),\ - ('Displace Vector: ', DISPLACE_NORMAL_MODE_but, 1, 4, 'Vertex Normal:1, Median Normal:2, Face Normal:3, View Normal:4'),\ - ('Static Normal', STATIC_NORMAL_but, 'Use the initial normal only.'),\ - ('No X Crossing', XPLANE_CLIP_but, 'Dont allow verts to have a negative X axis (use for x-mirror).'),\ - ('Static Mesh', STATIC_MESH_but, 'During mouse interaction, dont update the mesh.'),\ - #('Fix Topology', FIX_TOPOLOGY_but, 'Fix the mesh structure by rotating edges '),\ - ] - - Draw.PupBlock('BlenBrush Prefs (RMB)', pup_block) - - Blender.bbrush['ADAPTIVE_GEOMETRY'] = ADAPTIVE_GEOMETRY_but.val - Blender.bbrush['BRUSH_MODE'] = BRUSH_MODE_but.val - Blender.bbrush['BRUSH_PRESSURE'] = BRUSH_PRESSURE_but.val - Blender.bbrush['BRUSH_RADIUS'] = BRUSH_RADIUS_but.val - Blender.bbrush['RESOLUTION_MIN'] = RESOLUTION_MIN_but.val - Blender.bbrush['DISPLACE_NORMAL_MODE'] = DISPLACE_NORMAL_MODE_but.val - Blender.bbrush['STATIC_NORMAL'] = STATIC_NORMAL_but.val - Blender.bbrush['XPLANE_CLIP'] = XPLANE_CLIP_but.val - Blender.bbrush['STATIC_MESH'] = STATIC_MESH_but.val - Blender.bbrush['FIX_TOPOLOGY'] = FIX_TOPOLOGY_but.val - - -def triangulateNMesh(nm): - ''' - Converts the meshes faces to tris, modifies the mesh in place. - ''' - - #============================================================================# - # Returns a new face that has the same properties as the origional face # - # but with no verts # - #============================================================================# - def copyFace(face): - newFace = NMesh.Face() - # Copy some generic properties - newFace.mode = face.mode - if face.image != None: - newFace.image = face.image - newFace.flag = face.flag - newFace.mat = face.mat - newFace.smooth = face.smooth - return newFace - - # 2 List comprehensions are a lot faster then 1 for loop. - tris = [f for f in nm.faces if len(f) == 3] - quads = [f for f in nm.faces if len(f) == 4] - - - if quads: # Mesh may have no quads. - has_uv = quads[0].uv - has_vcol = quads[0].col - for quadFace in quads: - # Triangulate along the shortest edge - #if (quadFace.v[0].co - quadFace.v[2].co).length < (quadFace.v[1].co - quadFace.v[3].co).length: - a1 = Mathutils.TriangleArea(quadFace.v[0].co, quadFace.v[1].co, quadFace.v[2].co) - a2 = Mathutils.TriangleArea(quadFace.v[0].co, quadFace.v[2].co, quadFace.v[3].co) - b1 = Mathutils.TriangleArea(quadFace.v[1].co, quadFace.v[2].co, quadFace.v[3].co) - b2 = Mathutils.TriangleArea(quadFace.v[1].co, quadFace.v[3].co, quadFace.v[0].co) - a1,a2 = min(a1, a2), max(a1, a2) - b1,b2 = min(b1, b2), max(b1, b2) - if a1/a2 < b1/b2: - - # Method 1 - triA = 0,1,2 - triB = 0,2,3 - else: - # Method 2 - triA = 0,1,3 - triB = 1,2,3 - - for tri1, tri2, tri3 in (triA, triB): - newFace = copyFace(quadFace) - newFace.v = [quadFace.v[tri1], quadFace.v[tri2], quadFace.v[tri3]] - if has_uv: newFace.uv = [quadFace.uv[tri1], quadFace.uv[tri2], quadFace.uv[tri3]] - if has_vcol: newFace.col = [quadFace.col[tri1], quadFace.col[tri2], quadFace.col[tri3]] - - nm.addEdge(quadFace.v[tri1], quadFace.v[tri3]) # Add an edge where the 2 tris are devided. - tris.append(newFace) - - nm.faces = tris - -import mesh_tri2quad -def fix_topolagy(mesh): - ob = Scene.GetCurrent().getActiveObject() - - for f in mesh.faces: - f.sel = 1 - mesh.quadToTriangle(0) - nmesh = ob.getData() - - mesh_tri2quad.tri2quad(nmesh, 100, 0) - triangulateNMesh(nmesh) - nmesh.update() - - mesh = Mesh.Get(mesh.name) - for f in mesh.faces: - f.sel=1 - mesh.quadToTriangle() - Mesh.Mode(Mesh.SelectModes['EDGE']) - - - - - - -def event_main(): - #print Blender.event - #mod =[Window.Qual.CTRL, Window.Qual.ALT, Window.Qual.SHIFT] - mod =[Window.Qual.CTRL, Window.Qual.ALT] - - qual = Window.GetKeyQualifiers() - SHIFT_FLAG = Window.Qual.SHIFT - CTRL_FLAG = Window.Qual.CTRL - - - # UNDO - """ - is_editmode = Window.EditMode() # Exit Editmode. - if is_editmode: Window.EditMode(0) - if Blender.event == Draw.UKEY: - if is_editmode: - Blender.event = Draw.UKEY - return - else: - winId = [win3d for win3d in Window.GetScreenInfo(Window.Types.VIEW3D)][0] - Blender.event = None - Window.QHandle(winId['id']) - Window.EditMode(1) - Window.QHandle(winId['id']) - Window.QAdd(winId['id'],Draw.UKEY,1) # Change KeyPress Here for EditMode - Window.QAdd(winId['id'],Draw.UKEY,0) - Window.QHandle(winId['id']) - Window.EditMode(0) - Blender.event = None - return - """ - - ob = Scene.GetCurrent().getActiveObject() - if not ob or ob.getType() != 'Mesh': - return - - # Mouse button down with no modifiers. - if Blender.event == Draw.LEFTMOUSE and not [True for m in mod if m & qual]: - # Do not exit (draw) - pass - elif Blender.event == Draw.RIGHTMOUSE and not [True for m in mod if m & qual]: - ui_set_preferences() - return - else: - return - - del qual - - - try: - Blender.bbrush - except: - # First time run - ui_set_preferences() # No ui - return - - ADAPTIVE_GEOMETRY = Blender.bbrush['ADAPTIVE_GEOMETRY'] # 1 - BRUSH_MODE = Blender.bbrush['BRUSH_MODE'] # 1 - BRUSH_PRESSURE_ORIG = Blender.bbrush['BRUSH_PRESSURE'] # 0.1 - BRUSH_RADIUS = Blender.bbrush['BRUSH_RADIUS'] # 0.5 - RESOLUTION_MIN = Blender.bbrush['RESOLUTION_MIN'] # 0.08 - STATIC_NORMAL = Blender.bbrush['STATIC_NORMAL'] # 0 - XPLANE_CLIP = Blender.bbrush['XPLANE_CLIP'] # 0 - DISPLACE_NORMAL_MODE = Blender.bbrush['DISPLACE_NORMAL_MODE'] # 'Vertex Normal%x1|Median Normal%x2|Face Normal%x3|View Normal%x4' - STATIC_MESH = Blender.bbrush['STATIC_MESH'] - FIX_TOPOLOGY = Blender.bbrush['FIX_TOPOLOGY'] - - - # Angle between Vecs wrapper. - AngleBetweenVecs = Mathutils.AngleBetweenVecs - def ang(v1,v2): - try: - return AngleBetweenVecs(v1,v2) - except: - return 180 - """ - def Angle2D(x1, y1, x2, y2): - import math - RAD2DEG = 57.295779513082323 - ''' - Return the angle between two vectors on a plane - The angle is from vector 1 to vector 2, positive anticlockwise - The result is between -pi -> pi - ''' - dtheta = math.atan2(y2,x2) - math.atan2(y1,x1) # theta1 - theta2 - while dtheta > math.pi: - dtheta -= (math.pi*2) - while dtheta < -math.pi: - dtheta += (math.pi*2) - return dtheta * RAD2DEG #(180.0 / math.pi) - """ - - def faceIntersect(f): - isect = Intersect(f.v[0].co, f.v[1].co, f.v[2].co, Direction, Origin, 1) # Clipped. - if isect: - return isect - elif len(f.v) == 4: - isect = Intersect(f.v[0].co, f.v[2].co, f.v[3].co, Direction, Origin, 1) # Clipped. - return isect - """ - # Unused so farm, too slow. - def removeDouble(v1,v2, me): - v1List = [f for f in me.faces if v1 in f.v] - v2List = [f for f in me.faces if v2 in f.v] - #print v1List - #print v2List - remFaces = [] - newFaces = [] - for f2 in v2List: - f2ls = list(f2.v) - i = f2ls.index(v2) - f2ls[i] = v1 - #remFaces.append(f2) - if f2ls.count(v1) == 1: - newFaces.append(tuple(f2ls)) - if remFaces: - me.faces.delete(1, remFaces) - #me.verts.delete(v2) - if newFaces: - me.faces.extend(newFaces) - """ - - - me = ob.getData(mesh=1) - - is_editmode = Window.EditMode() # Exit Editmode. - if is_editmode: Window.EditMode(0) - - Mesh.Mode(Mesh.SelectModes['EDGE']) - - # At the moment ADAPTIVE_GEOMETRY is the only thing that uses selection. - if ADAPTIVE_GEOMETRY: - # Deslect all - SEL_FLAG = Mesh.EdgeFlags['SELECT'] - ''' - for ed in me.edges: - #ed.flag &= ~SEL_FLAG # deselect. 34 - ed.flag = 32 - ''' - filter(lambda ed: setattr(ed, 'flag', 32), me.edges) - - '''for v in me.verts: - v.sel = 0''' - filter(lambda v: setattr(v, 'sel', 0), me.verts) - - i = 0 - time = Blender.sys.time() - last_best_isect = None # used for goo only - old_screen_x, old_screen_y = 1<<30, 1<<30 - goo_dir_vec = last_goo_dir_vec = gooRotMatrix = None # goo mode only. - - # Normal stuff - iFaceNormal = medainNormal = None - - # Store all vert normals for now. - if BRUSH_MODE == 1 and STATIC_NORMAL: # Push pull - vert_orig_normals = dict([(v, v.no) for v in me.verts]) - - elif BRUSH_MODE == 4: # RELAX, BUILD EDGE CONNECTIVITE DATA. - # we need edge connectivity - #vertEdgeUsers = [list() for i in xrange(len(me.verts))] - verts_connected_by_edge = [list() for i in xrange(len(me.verts))] - - for ed in me.edges: - i1, i2 = ed.v1.index, ed.v2.index - #vertEdgeUsers[i1].append(ed) - #vertEdgeUsers[i2].append(ed) - - verts_connected_by_edge[i1].append(ed.v2) - verts_connected_by_edge[i2].append(ed.v1) - - if STATIC_MESH: - - # Try and find a static mesh to reuse. - # this is because we dont want to make a new mesh for each stroke. - mesh_static = None - for _me_name_ in Blender.NMesh.GetNames(): - _me_ = Mesh.Get(_me_name_) - #print _me_.users , len(me.verts) - if _me_.users == 0 and len(_me_.verts) == 0: - mesh_static = _me_ - #print 'using', _me_.name - break - del _me_name_ - del _me_ - - if not mesh_static: - mesh_static = Mesh.New() - print 'Making new mesh', mesh_static.name - - mesh_static.verts.extend([v.co for v in me.verts]) - mesh_static.faces.extend([tuple([mesh_static.verts[v.index] for v in f.v]) for f in me.faces]) - - - best_isect = gooPlane = None - - while Window.GetMouseButtons() == 1: - i+=1 - screen_x, screen_y = Window.GetMouseCoords() - - # Skip when no mouse movement, Only for Goo! - if screen_x == old_screen_x and screen_y == old_screen_y: - if BRUSH_MODE == 5: # Dont modify while mouse is not moved for goo. - continue - else: # mouse has moved get the new mouse ray. - old_screen_x, old_screen_y = screen_x, screen_y - mouseInView, Origin, Direction = getPickRay(screen_x, screen_y, ob.matrixWorld) - if not mouseInView or not Origin: - return - Origin_SCALE = Origin * 100 - - # Find an intersecting face! - bestLen = 1<<30 # start with an assumed realy bad match. - best_isect = None # last intersect is used for goo. - best_face = None - - if not last_best_isect: - last_best_isect = best_isect - - if not mouseInView: - last_best_isect = None - - else: - # Find Face intersection closest to the view. - #for f in [f for f in me.faces if ang(f.no, Direction) < 90]: - - # Goo brush only intersects faces once, after that the brush follows teh view plain. - if BRUSH_MODE == 5 and gooPlane != None and gooPlane: - best_isect = Intersect( gooPlane[0], gooPlane[1], gooPlane[2], Direction, Origin, 0) # Non clipped - else: - if STATIC_MESH: - intersectingFaces = [(f, ix) for f in mesh_static.faces for ix in (faceIntersect(f),) if ix] - else: - intersectingFaces = [(f, ix) for f in me.faces for ix in (faceIntersect(f),) if ix] - - for f, isect in intersectingFaces: - l = (Origin_SCALE-isect).length - if l < bestLen: - best_face = f - best_isect = isect - bestLen = l - - if not best_isect: - # Dont interpolate once the mouse moves off the mesh. - lastGooVec = last_best_isect = None - - else: # mouseInView must be true also - - # Use the shift key to modify the pressure. - if SHIFT_FLAG & Window.GetKeyQualifiers(): - BRUSH_PRESSURE = -BRUSH_PRESSURE_ORIG - else: - BRUSH_PRESSURE = BRUSH_PRESSURE_ORIG - - brush_verts = [(v,le) for v in me.verts for le in ((v.co-best_isect).length,) if le < BRUSH_RADIUS] - - # SETUP ONCE ONLY VARIABLES - if STATIC_NORMAL: # Only set the normal once. - if not iFaceNormal: - iFaceNormal = best_face.no - else: - if best_face: - iFaceNormal = best_face.no - - - if DISPLACE_NORMAL_MODE == 2: # MEDIAN NORMAL - if (STATIC_NORMAL and medainNormal == None) or not STATIC_NORMAL: - medainNormal = Vector(0,0,0) - for v, l in brush_verts: - medainNormal += v.no*(BRUSH_RADIUS-l) - medainNormal.normalize() - - - # ================================================================# - # == Tool code, loop on the verts and operate on them ============# - # ================================================================# - if BRUSH_MODE == 1: # NORMAL PAINT - for v,l in brush_verts: - if XPLANE_CLIP: - origx = False - if abs(v.co.x) < 0.001: origx = True - - - v.sel = 1 # MARK THE VERT AS DIRTY. - falloff = (BRUSH_RADIUS-l) / BRUSH_RADIUS # falloff between 0 and 1 - - if DISPLACE_NORMAL_MODE == 1: # VERTEX NORMAL - if STATIC_NORMAL: - try: - no = vert_orig_normals[v] - except: - no = vert_orig_normals[v] = v.no - v.co += (no * BRUSH_PRESSURE) * falloff - else: - v.co += (v.no * BRUSH_PRESSURE) * falloff - elif DISPLACE_NORMAL_MODE == 2: # MEDIAN NORMAL # FIXME - v.co += (medainNormal * BRUSH_PRESSURE) * falloff - elif DISPLACE_NORMAL_MODE == 3: # FACE NORMAL - v.co += (iFaceNormal * BRUSH_PRESSURE) * falloff - elif DISPLACE_NORMAL_MODE == 4: # VIEW NORMAL - v.co += (Direction * BRUSH_PRESSURE) * falloff - - # Clamp back to original x if needs be. - if XPLANE_CLIP and origx: - v.co.x = 0 - - elif BRUSH_MODE == 2: # SCALE - for v,l in brush_verts: - - if XPLANE_CLIP: - origx = False - if abs(v.co.x) < 0.001: origx = True - - v.sel = 1 # MARK THE VERT AS DIRTY. - falloff = (BRUSH_RADIUS-l) / BRUSH_RADIUS # falloff between 0 and 1 - - vert_scale_vec = v.co - best_isect - vert_scale_vec.normalize() - # falloff needs to be scaled for this tool - falloff = falloff / 10 - v.co += (vert_scale_vec * BRUSH_PRESSURE) * falloff # FLAT BRUSH - - # Clamp back to original x if needs be. - if XPLANE_CLIP and origx: - v.co.x = 0 - - if BRUSH_MODE == 3: # ROTATE. - - if DISPLACE_NORMAL_MODE == 1: # VERTEX NORMAL - ROTATE_MATRIX = Mathutils.RotationMatrix(BRUSH_PRESSURE*10, 4, 'r', iFaceNormal) # Cant use vertex normal, use face normal - elif DISPLACE_NORMAL_MODE == 2: # MEDIAN NORMAL - ROTATE_MATRIX = Mathutils.RotationMatrix(BRUSH_PRESSURE*10, 4, 'r', medainNormal) # Cant use vertex normal, use face normal - elif DISPLACE_NORMAL_MODE == 3: # FACE NORMAL - ROTATE_MATRIX = Mathutils.RotationMatrix(BRUSH_PRESSURE*10, 4, 'r', iFaceNormal) # Cant use vertex normal, use face normal - elif DISPLACE_NORMAL_MODE == 4: # VIEW NORMAL - ROTATE_MATRIX = Mathutils.RotationMatrix(BRUSH_PRESSURE*10, 4, 'r', Direction) # Cant use vertex normal, use face normal - # Brush code - - for v,l in brush_verts: - - if XPLANE_CLIP: - origx = False - if abs(v.co.x) < 0.001: origx = True - - # MARK THE VERT AS DIRTY. - v.sel = 1 - falloff = (BRUSH_RADIUS-l) / BRUSH_RADIUS # falloff between 0 and 1 - - # Vectors handeled with rotation matrix creation. - rot_vert_loc = (ROTATE_MATRIX * (v.co-best_isect)) + best_isect - v.co = (v.co*(1-falloff)) + (rot_vert_loc*(falloff)) - - # Clamp back to original x if needs be. - if XPLANE_CLIP and origx: - v.co.x = 0 - - elif BRUSH_MODE == 4: # RELAX - vert_orig_loc = [Vector(v.co) for v in me.verts ] # save orig vert location. - #vertOrigNor = [Vector(v.no) for v in me.verts ] # save orig vert location. - - # Brush code - for v,l in brush_verts: - - if XPLANE_CLIP: - origx = False - if abs(v.co.x) < 0.001: origx = True - - v.sel = 1 # Mark the vert as dirty. - falloff = (BRUSH_RADIUS-l) / BRUSH_RADIUS # falloff between 0 and 1 - connected_verts = verts_connected_by_edge[v.index] - relax_point = reduce(lambda a,b: a + vert_orig_loc[b.index], connected_verts, Mathutils.Vector(0,0,0)) * (1.0/len(connected_verts)) - falloff = falloff * BRUSH_PRESSURE - # Old relax. - #v.co = (v.co*(1-falloff)) + (relax_point*(falloff)) - - ll = (v.co-relax_point).length - newpoint = (v.co*(1-falloff)) + (relax_point*(falloff)) - v.co - newpoint = newpoint * (1/(1+ll)) - v.co = v.co + newpoint - - ''' - # New relax - relax_normal = vertOrigNor[v.index] - v1,v2,v3,v4 = v.co, v.co+relax_normal, relax_point-(relax_normal*10), relax_point+(relax_normal*10) - print v1,v2,v3,v4 - try: - a,b = LineIntersect(v1,v2,v3,v4) # Scale the normal to make a line. we know we will intersect with. - v.co = (v.co*(1-falloff)) + (a*(falloff)) - except: - pass - ''' - - # Clamp back to original x if needs be. - if XPLANE_CLIP and origx: - v.co.x = 0 - - elif BRUSH_MODE == 5: # GOO - #print last_best_isect, best_isect, 'AA' - if not last_best_isect: - last_best_isect = best_isect - - # Set up a triangle orthographic to the view plane - gooPlane = [best_isect, CrossVecs(best_isect, Direction), None] - - - if DISPLACE_NORMAL_MODE == 4: # View Normal - tempRotMatrix = Mathutils.RotationMatrix(90, 3, 'r', Direction) - else: - tempRotMatrix = Mathutils.RotationMatrix(90, 3, 'r', CrossVecs(best_face.no, Direction)) - - gooPlane[2] = best_isect + (tempRotMatrix * gooPlane[1]) - gooPlane[1] = gooPlane[1] + best_isect - - continue # we need another point of reference. - - elif last_best_isect == best_isect: - # Mouse has not moved, no point in trying to goo. - continue - else: - if goo_dir_vec: - last_goo_dir_vec = goo_dir_vec - # The direction the mouse moved in 3d space. use for gooing - - # Modify best_isect so its not moving allong the view z axis. - # Assume Origin hasnt changed since the view wont change while the mouse is drawing. ATM. - best_isect = Intersect( gooPlane[0], gooPlane[1], gooPlane[2], Direction, Origin, 0) # Non clipped - goo_dir_vec = (best_isect - last_best_isect) * 2 - - - # make a goo rotation matrix so the head of the goo rotates with the mouse. - """ - if last_goo_dir_vec and goo_dir_vec != last_goo_dir_vec: - ''' - vmi = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix - a = last_goo_dir_vec * vmi - b = goo_dir_vec * vmi - c = Angle2D(a.x, a.y, b.x, b.y) - gooRotMatrix = Mathutils.RotationMatrix((c * goo_dir_vec.length)*-20, 3, 'r', Direction) - ''' - pass - else: - gooRotMatrix = None - """ - - if goo_dir_vec.x == 0 and goo_dir_vec.y == 0 and goo_dir_vec.z == 0: - continue - - # Brush code - for v,l in brush_verts: - - if XPLANE_CLIP: - origx = False - if abs(v.co.x) < 0.001: origx = True - - # MARK THE VERT AS DIRTY. - v.sel = 1 - - ''' # ICICLES!!! - a = AngleBetweenVecs(goo_dir_vec, v.no) - if a > 66: - continue - - l = l * ((1+a)/67.0) - l = max(0.00000001, l) - ''' - - falloff = (BRUSH_RADIUS-l) / BRUSH_RADIUS # falloff between 0 and 1 - goo_loc = (v.co*(1-falloff)) + ((v.co+goo_dir_vec) *falloff) - - v.co = (goo_loc*BRUSH_PRESSURE) + (v.co*(1-BRUSH_PRESSURE)) - - ''' - if gooRotMatrix: - rotatedVertLocation = (gooRotMatrix * (v.co-best_isect)) + best_isect - v.co = (v.co*(1-falloff)) + (rotatedVertLocation*(falloff)) - # USe for goo only. - ''' - - # Clamp back to original x if needs be. - if XPLANE_CLIP and origx: - v.co.x = 0 - - - # Remember for the next sample - last_best_isect = best_isect - last_goo_dir_vec = goo_dir_vec - - # Post processing after the verts have moved - # Subdivide any large edges, all but relax. - - MAX_SUBDIV = 10 # Maximum number of subdivisions per redraw. makes things useable. - SUBDIV_COUNT = 0 - if ADAPTIVE_GEOMETRY and (BRUSH_MODE == 1 or BRUSH_MODE == 2 or BRUSH_MODE == 3 or BRUSH_MODE == 5): - orig_len_edges = 0 - #print 'ADAPTIVE_GEOMETRY' - while len(me.edges) != orig_len_edges and SUBDIV_COUNT < MAX_SUBDIV: - #print 'orig_len_edges', len(me.edges) - #me = ob.getData(mesh=1) - orig_len_edges = len(me.edges) - EDGE_COUNT = 0 - for ed in me.edges: - if ed.v1.sel or ed.v2.sel: - l = (ed.v1.co - ed.v2.co).length - #if l > RESOLUTION_MAX: - if l > BRUSH_RADIUS: - #print 'adding edge' - ed.flag |= SEL_FLAG - #ed.flag = 35 - SUBDIV_COUNT += 1 - EDGE_COUNT +=1 - """ - elif l < RESOLUTION_MIN: - ''' - print 'removing edge' - v1 =e.v1 - v2 =e.v2 - v1.co = v2.co = (v1.co + v2.co) * 0.5 - v1.sel = v2.sel = 1 - me.remDoubles(0.001) - me = ob.getData(mesh=1) - break - ''' - # Remove edge in python - print 'removing edge' - v1 =ed.v1 - v2 =ed.v2 - v1.co = v2.co = (v1.co + v2.co) * 0.5 - - removeDouble(v1, v2, me) - me = ob.getData(mesh=1) - break - """ - - if EDGE_COUNT: - me.subdivide(1) - - - # Deselect all, we know theres only 2 selected - ''' - for ee in me.edges: - if ee.flag & SEL_FLAG: - #ee.flag &= ~SEL_FLAG - ee.flag = 32 - elif l < RESOLUTION_MIN: - print 'removing edge' - e.v1.co = e.v2.co = (e.v1.co + e.v2.co) * 0.5 - me.remDoubles(0.001) - break - ''' - # Done subdividing - # Now remove doubles - #print Mesh.SelectModes['VERT'] - #Mesh.Mode(Mesh.SelectModes['VERTEX']) - - filter(lambda v: setattr(v, 'sel', 1), me.verts) - filter(lambda v: setattr(v[0], 'sel', 0), brush_verts) - - # Cycling editmode is too slow. - - remdoubles = False - for ed in me.edges: - - if (not ed.v1.sel) and (not ed.v1.sel): - l = (ed.v1.co - ed.v2.co).length - if l < RESOLUTION_MIN: - ed.v1.sel = ed.v2.sel = 1 - newco = (ed.v1.co + ed.v2.co)*0.5 - ed.v1.co.x = ed.v2.co.x = newco.x - ed.v1.co.y = ed.v2.co.y = newco.y - ed.v1.co.z = ed.v2.co.z = newco.z - remdoubles = True - - #if remdoubles: - - - filter(lambda v: setattr(v, 'sel', 0), me.verts) - #Mesh.Mode(Mesh.SelectModes['EDGE']) - # WHILE OVER - # Clean up selection. - #for v in me.verts: - # v.sel = 0 - ''' - for ee in me.edges: - if ee.flag & SEL_FLAG: - ee.flag &= ~SEL_FLAG - #ee.flag = 32 - ''' - filter(lambda ed: setattr(ed, 'flag', 32), me.edges) - - - if XPLANE_CLIP: - filter(lambda v: setattr(v.co, 'x', max(0, v.co.x)), me.verts) - - - me.update() - #Window.SetCursorPos(best_isect.x, best_isect.y, best_isect.z) - Window.Redraw(Window.Types.VIEW3D) - #Window.DrawProgressBar(1.0, '') - if STATIC_MESH: - #try: - mesh_static.verts = None - print len(mesh_static.verts) - mesh_static.update() - #except: - # pass - if FIX_TOPOLOGY: - fix_topolagy(me) - - Mesh.Mode(Mesh.SelectModes['VERTEX']) - filter(lambda v: setattr(v, 'sel', 1), me.verts) - me.remDoubles(0.001) - print 'removing doubles' - me = ob.getData(mesh=1) # Get new vert data - - Blender.event = Draw.LEFTMOUSE - - if i: - Window.EditMode(1) - if not is_editmode: # User was in edit mode, so stay there. - Window.EditMode(0) - print '100 draws in %.6f' % (((Blender.sys.time()-time) / float(i))*100) - -if __name__ == '__main__': - event_main() \ No newline at end of file -- cgit v1.2.3