#!BPY """ Name: 'Cookie Cut from View' Blender: 234 Group: 'Object' Tooltip: 'Cut from the view axis, (Sel 3d Curves and Meshes (only edges) into other meshes with faces)' """ __author__= "Campbell Barton" __url__= ["blender", "blenderartist"] __version__= "1.0" __bpydoc__= """\ This script takes the selected mesh objects, devides them into 2 groups Cutters and The objects to be cut. Cutters are meshes with no faces, just edge loops. and any meshes with faces will be cut. Usage: Select 2 or more meshes, one with no faces (a closed polyline) and one with faces to cut. Align the view on the axis you want to cut. For shapes that have overlapping faces (from the view), hide any backfacing faces so they will be ignored during the cut. Run the script. You can choose to make the cut verts lie on the face that they were cut from or on the edge that cut them. This script supports UV coordinates and images. """ # ***** BEGIN GPL LICENSE BLOCK ***** # # Script copyright (C) Campbell Barton # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- import Blender from math import sqrt import BPyMesh Vector= Blender.Mathutils.Vector LineIntersect2D= Blender.Geometry.LineIntersect2D # Auto class def auto_class(slots): exec('class container_class(object): __slots__=%s' % slots) return container_class bignum= 1<<30 def bounds_xy(iter_item): ''' Works with types MMesh.verts MFace MEdge ''' xmin= ymin= bignum xmax= ymax= -bignum for v in iter_item: x= v.co.x y= v.co.y if xxmax: xmax= x if y>ymax: ymax= y return xmin, ymin, xmax, ymax def bounds_intersect(a,b): ''' each tuple is xmin, ymin, xmax, ymax ''' if\ a[0]>b[2] or\ a[1]>b[3] or\ a[2]i2: i1,i2= i2,i1 return i1, i2 def sorted_indicies(i1, i2): if i1>i2: i1,i2= i2,i1 return i1, i2 def fake_length2d(pt1, pt2): ''' Only used for comparison so dont sqrt ''' #return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2))) return pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2) def length2d(pt1, pt2): ''' Only used for comparison so dont sqrt ''' #return math.sqrt(abs(pow(x1-x2, 2)+ pow(y1-y2, 2))) return sqrt(pow(pt1[0]-pt2[0], 2) + pow(pt1[1]- pt2[1], 2)) def tri_area_2d(v1, v2, v3): e1 = length2d(v1, v2) e2 = length2d(v2, v3) e3 = length2d(v3, v1) p = e1+e2+e3 return 0.25 * sqrt(abs(p*(p-2*e1)*(p-2*e2)*(p-2*e3))) def tri_pt_find_z_2d(pt, tri): """ Takes a face and 3d vector and assigns teh vectors Z to its on the face""" l1= tri_area_2d(tri[1], tri[2], pt) l2= tri_area_2d(tri[0], tri[2], pt) l3= tri_area_2d(tri[0], tri[1], pt) tot= l1+l2+l3 # Normalize l1=l1/tot l2=l2/tot l3=l3/tot z1= tri[0].z*l1 z2= tri[1].z*l2 z3= tri[2].z*l3 return z1+z2+z3 def tri_pt_find_uv_2d(pt, tri, uvs): """ Takes a face and 3d vector and assigns teh vectors Z to its on the face""" l1= tri_area_2d(tri[1], tri[2], pt) l2= tri_area_2d(tri[0], tri[2], pt) l3= tri_area_2d(tri[0], tri[1], pt) tot= l1+l2+l3 if not tot: # No area, just return the first uv return Vector(uvs[0]) # Normalize l1=l1/tot l2=l2/tot l3=l3/tot uv1= uvs[0]*l1 uv2= uvs[1]*l2 uv3= uvs[2]*l3 return uv1+uv2+uv3 def mesh_edge_dict(me): ed_dict= {} for f in me.faces: if not f.hide: for edkey in f.edge_keys: ed_dict.setdefault(edkey, []).append(f) return ed_dict def terrain_cut_2d(t, c, PREF_Z_LOC): ''' t is the terrain c is the cutter PREF_Z_LOC: 0 - from terrain face 1 - from cutter edge returns nothing ''' # do we have a 2d intersection if not bounds_intersect(t.bounds, c.bounds): return # Local vars me_t= t.mesh me_c= c.mesh has_uv= me_t.faceUV Blender.Mesh.Mode(Blender.Mesh.SelectModes['VERTEX']) ''' first assign a face terrain face for each cutter verticie ''' cut_verts_temp= list(me_c.verts) cut_vert_terrain_faces= [None] * len(me_c.verts) vert_z_level= [-10.0] * len(me_c.verts) for v in me_c.verts: v_index= v.index v_co= v.co for fidx, f in enumerate(me_t.faces): if not f.hide: if point_in_bounds(v_co, t.face_bounds[fidx]): f_v= [vv.co for vv in f] if point_in_poly2d(v_co, f_v): if PREF_Z_LOC==0: ''' Get the z location from the face. ''' if len(f_v)==3: vert_z_level[v_index]= tri_pt_find_z_2d(v_co, (f_v[0], f_v[1], f_v[2]) ) else: # Quad, which side are we on? a1= tri_area_2d(f_v[0], f_v[1], v_co) a2= tri_area_2d(f_v[1], f_v[2], v_co) a3= tri_area_2d(f_v[0], f_v[1], f_v[2]) if a1+a2