def check_collision( object1, object2): #Renvois les faces qui sont en colisions avec l'objet 2 bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.select_mode(type="FACE") #bpy.ops.mesh.select_all(action = 'DESELECT') bpy.ops.object.mode_set(mode='OBJECT') # Get objects world matrix mat1 = object1.matrix_world mat2 = object2.matrix_world # Get the geometry in world coordinates vert1 = [mat1 @ v.co for v in object1.data.vertices] poly1 = [p.vertices for p in object1.data.polygons] vert2 = [mat2 @ v.co for v in object2.data.vertices] poly2 = [p.vertices for p in object2.data.polygons] # Create the BVH trees bvh1 = BVHTree.FromPolygons(vert1, poly1) bvh2 = BVHTree.FromPolygons(vert2, poly2) # Test if overlap overlaping = bvh1.overlap(bvh2) if (overlaping): facesToSelect = set(map(lambda x: x[1], overlaping)) for face in facesToSelect: object2.data.polygons[face].select = True bpy.ops.object.mode_set(mode='EDIT') return overlaping
def check_collision(object1, object2): # Get objects world matrix mat1 = object1.matrix_world mat2 = object2.matrix_world # Get the geometry in world coordinates vert1 = [mat1 @ v.co for v in object1.data.vertices] poly1 = [p.vertices for p in object1.data.polygons] vert2 = [mat2 @ v.co for v in object2.data.vertices] poly2 = [p.vertices for p in object2.data.polygons] # Create the BVH trees bvh1 = BVHTree.FromPolygons(vert1, poly1) bvh2 = BVHTree.FromPolygons(vert2, poly2) # Test if overlap overlaping = bvh1.overlap(bvh2) """ if overlaping: print("Overlap") else: print("NO") """ return overlaping
def fromMeshData(self, vectorList, polygonsIndices, epsilon): maxPolygonIndex = max(itertools.chain([-1], *polygonsIndices)) minPolygonIndex = min(itertools.chain([0], *polygonsIndices)) if 0 <= minPolygonIndex and maxPolygonIndex < len(vectorList): return BVHTree.FromPolygons(vectorList, polygonsIndices, epsilon = epsilon) return BVHTree.FromPolygons([], [], epsilon = epsilon)
def physIntersection(name1, name2): # Get the objects obj1 = bpy.data.objects[name1] obj2 = bpy.data.objects[name2] # Get their world matrix mat1 = obj1.matrix_world mat2 = obj2.matrix_world # Get the geometry in world coordinates vert1 = [mat1 @ v.co for v in obj1.data.vertices] poly1 = [p.vertices for p in obj1.data.polygons] vert2 = [mat2 @ v.co for v in obj2.data.vertices] poly2 = [p.vertices for p in obj2.data.polygons] # Create the BVH trees bvh1 = BVHTree.FromPolygons(vert1, poly1) bvh2 = BVHTree.FromPolygons(vert2, poly2) # Test if overlap if bvh1.overlap(bvh2): return True else: return False
def get_obj_mesh_bvht(obj, depsgraph, applyModifiers=True, world_space=True): if applyModifiers: if world_space: depsgraph.objects[obj.name].data.transform(obj.matrix_world) bvh = BVHTree.FromObject(obj, depsgraph) depsgraph.objects[obj.name].data.transform(obj.matrix_world.inverted()) return bvh else: return BVHTree.FromObject(obj, depsgraph) else: if world_space: return BVHTree.FromPolygons([obj.matrix_world @ v.co for v in obj.data.vertices], [p.vertices for p in obj.data.polygons]) else: return BVHTree.FromPolygons([v.co for v in obj.data.vertices], [p.vertices for p in obj.data.polygons])
def BVHTreeAndVerticesInWorldFromObj( obj ): mWorld = obj.matrix_world vertsInWorld = [mWorld @ v.co for v in obj.data.vertices] bvh = BVHTree.FromPolygons( vertsInWorld, [p.vertices for p in obj.data.polygons] ) return bvh, vertsInWorld
def compute_bbox(self): self.bbox_verts = np.array([(self.location[0] - self.size / 2, self.location[1] - self.size / 2, self.location[2] - self.size / 2), (self.location[0] - self.size / 2, self.location[1] - self.size / 2, self.location[2] + self.size / 2), (self.location[0] - self.size / 2, self.location[1] + self.size / 2, self.location[2] - self.size / 2), (self.location[0] - self.size / 2, self.location[1] + self.size / 2, self.location[2] + self.size / 2), (self.location[0] + self.size / 2, self.location[1] - self.size / 2, self.location[2] - self.size / 2), (self.location[0] + self.size / 2, self.location[1] - self.size / 2, self.location[2] + self.size / 2), (self.location[0] + self.size / 2, self.location[1] + self.size / 2, self.location[2] - self.size / 2), (self.location[0] + self.size / 2, self.location[1] + self.size / 2, self.location[2] + self.size / 2)]) self.bbox_faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 4, 5], [2, 3, 6, 7], [0, 2, 4, 6], [1, 3, 5, 7]] self.bvh_tree = BVHTree.FromPolygons(self.bbox_verts, self.bbox_faces, epsilon=1.0)
def process(self): Object, PointsUV = self.inputs Pom, uvV, uvP = self.outputs obj = Object.sv_get()[0] # triangulate faces UVMAPV, UVMAPP = UV(self, obj) if Pom.is_linked: pointuv = PointsUV.sv_get()[0] bvh = BVHTree.FromPolygons(UVMAPV, UVMAPP, all_triangles=False, epsilon=0.0) ran = range(3) out = [] uvMap = obj.data.uv_layers[0].data for Puv in pointuv: loc, norm, ind, dist = bvh.find_nearest(Puv) found_poly = obj.data.polygons[ind] verticesIndices = found_poly.vertices p1, p2, p3 = [ obj.data.vertices[verticesIndices[i]].co for i in ran ] uvMapIndices = found_poly.loop_indices uv1, uv2, uv3 = [ uvMap[uvMapIndices[i]].uv.to_3d() for i in ran ] V = barycentric_transform(Puv, uv1, uv2, uv3, p1, p2, p3) out.append(V[:]) Pom.sv_set([out]) if uvV.is_linked: uvV.sv_set([UVMAPV]) uvP.sv_set([UVMAPP])
def get_points_in_mesh_2D_clip(verts, faces, points, normal, clip_distance, eps=0.0, matchig_method='REPEAT'): mask_totals = [] bvh = BVHTree.FromPolygons(verts, faces, all_triangles=False, epsilon=eps) normal, clip_distance = list_match_func[matchig_method]( [normal, clip_distance]) for point in points: inside = False for direction, dist in zip(normal, clip_distance): hit = bvh.ray_cast(point, Vector(direction)) if hit[0] and hit[3] < dist: inside = True break else: hit = bvh.ray_cast(point, -Vector(direction)) if hit[0] and hit[3] < dist: inside = True break mask_totals.append(inside) return mask_totals
def init_guess(surface, src_points, directions, samples=50): u_min = surface.get_u_min() u_max = surface.get_u_max() v_min = surface.get_v_min() v_max = surface.get_v_max() us = np.linspace(u_min, u_max, num=samples) vs = np.linspace(v_min, v_max, num=samples) us, vs = np.meshgrid(us, vs) us = us.flatten() vs = vs.flatten() points = surface.evaluate_array(us, vs).tolist() faces = make_faces(samples) bvh = BVHTree.FromPolygons(points, faces) us_out = [] vs_out = [] t_out = [] nearest_out = [] h2 = (u_max - u_min) / (2 * samples) for src_point, direction in zip(src_points, directions): nearest, normal, index, distance = bvh.ray_cast( src_point, direction) us_out.append(us[index] + h2) vs_out.append(vs[index] + h2) t_out.append(distance) nearest_out.append(tuple(nearest)) return us_out, vs_out, t_out, nearest_out
def lloyd_on_mesh(verts, faces, sites, thickness, n_iterations, weight_field=None): bvh = BVHTree.FromPolygons(verts, faces) def iteration(points): n = len(points) normals = calc_bvh_normals(bvh, points) k = 0.5 * thickness points = np.array(points) plus_points = points + k * normals minus_points = points - k * normals all_points = points.tolist() + plus_points.tolist( ) + minus_points.tolist() diagram = Voronoi(all_points) centers = [] for site_idx in range(n): region_idx = diagram.point_region[site_idx] region = diagram.regions[region_idx] region_verts = np.array([diagram.vertices[i] for i in region]) center = weighted_center(region_verts, weight_field) centers.append(tuple(center)) return centers points = calc_bvh_projections(bvh, sites) for i in range(n_iterations): points = iteration(points) points = calc_bvh_projections(bvh, points) return points.tolist()
def execute_Mesh(self, mesh, epsilon): if len(mesh.polygons) == 0: return self.getFallbackBVHTree() return BVHTree.FromPolygons(mesh.vertices, mesh.polygons, epsilon=max(epsilon, 0))
def find_nearest_idxs(verts, faces, add_verts): bvh = BVHTree.FromPolygons(verts, faces) idxs = [] for vert in add_verts: loc, normal, idx, distance = bvh.find_nearest(vert) idxs.append(idx) return idxs
def execute_MeshSurfaceFalloff(self, mesh, size, falloffWidth, useVolume, invert, bvhMaxDistance, epsilon): vectorList, polygonsIndices = self.validMesh(mesh) bvhTree = BVHTree.FromPolygons(vectorList, polygonsIndices, epsilon=max(epsilon, 0)) return calculateMeshSurfaceFalloff(bvhTree, bvhMaxDistance, size, falloffWidth, useVolume, invert)
def __init__(self, obj): self.matrix_local = obj.matrix_local # mesh_settings = (bpy.context.scene, True, 'RENDER') data = obj.to_mesh() #*mesh_settings) vertices = [vert.co[:] for vert in data.vertices] polygons = [poly.vertices[:] for poly in data.polygons] self.BVH = BVHTree.FromPolygons(vertices, polygons) obj.to_mesh_clear()
def __init__(self, OB): self.matrix_local = OB.matrix_local mesh_settings = (bpy.context.scene, True, 'RENDER') data = OB.to_mesh(*mesh_settings) vertices = [vert.co[:] for vert in data.vertices] polygons = [poly.vertices[:] for poly in data.polygons] self.BVH = BVHTree.FromPolygons(vertices, polygons) bpy.data.meshes.remove(data)
def execute_Mesh(self, vectorList, polygonsIndices, epsilon): if len(polygonsIndices) == 0: return self.getFallbackBVHTree() if 0 <= polygonsIndices.getMinIndex() <= polygonsIndices.getMaxIndex( ) < len(vectorList): return BVHTree.FromPolygons(vectorList, polygonsIndices, epsilon=max(epsilon, 0))
def BVHTreeAndVerticesInWorldFromObj(obj): """ Input: Object of Blender type Object Output: BVH Tree necessary for ray tracing and vertsInWorld = verts in global coordinate system. """ mWorld = obj.matrix_world vertsInWorld = [mWorld @ v.co for v in obj.data.vertices] bvh = BVHTree.FromPolygons(vertsInWorld, [p.vertices for p in obj.data.polygons]) return bvh, vertsInWorld
def lloyd_in_mesh(verts, faces, sites, n_iterations, thickness=None, weight_field=None): bvh = BVHTree.FromPolygons(verts, faces) if thickness is None: x_min, x_max, y_min, y_max, z_min, z_max = calc_bounds(verts) thickness = max(x_max - x_min, y_max - y_min, z_max - z_min) / 4.0 epsilon = 1e-8 def iteration(points): n = len(points) all_points = points[:] k = 0.5 * thickness for p in points: p = Vector(p) loc, normal, index, distance = bvh.find_nearest(p) if distance <= epsilon: p1 = p + k * normal all_points.append(tuple(p1)) diagram = Voronoi(all_points) centers = [] for site_idx in range(n): region_idx = diagram.point_region[site_idx] region = diagram.regions[region_idx] region_verts = np.array([diagram.vertices[i] for i in region]) center = weighted_center(region_verts, weight_field) centers.append(tuple(center)) return centers def restrict(points): result = [] for p in points: if point_inside_mesh(bvh, p): result.append(p) else: loc, normal, index, distance = bvh.find_nearest(p) if loc is not None: result.append(tuple(loc)) return result points = restrict(sites) for i in range(n_iterations): points = iteration(points) points = restrict(points) return points
def voronoi_on_mesh(verts, faces, sites, thickness, spacing=0.0, clip_inner=True, clip_outer=True, do_clip=True, clipping=1.0, mode='REGIONS', precision=1e-8): bvh = BVHTree.FromPolygons(verts, faces) npoints = len(sites) if clipping is None: x_min, x_max, y_min, y_max, z_min, z_max = calc_bounds(verts) clipping = max(x_max - x_min, y_max - y_min, z_max - z_min) / 2.0 if mode in {'REGIONS', 'RIDGES'}: if clip_inner or clip_outer: normals = calc_bvh_normals(bvh, sites) k = 0.5 * thickness sites = np.array(sites) all_points = sites.tolist() if clip_outer: plus_points = sites + k * normals all_points.extend(plus_points.tolist()) if clip_inner: minus_points = sites - k * normals all_points.extend(minus_points.tolist()) return voronoi3d_layer(npoints, all_points, make_regions=(mode == 'REGIONS'), do_clip=do_clip, clipping=clipping) else: # VOLUME, SURFACE all_points = sites[:] if do_clip: for site in sites: loc, normal, index, distance = bvh.find_nearest(site) if loc is not None: p1 = loc + clipping * normal all_points.append(p1) verts, edges, faces = voronoi_on_mesh_bmesh(verts, faces, len(sites), all_points, spacing=spacing, fill=(mode == 'VOLUME'), precision=precision) return verts, edges, faces, all_points
def __init__(self, obj): self.matrix_local = obj.matrix_local # mesh_settings = (..., True, 'RENDER') # data = OB.to_mesh(*mesh_settings) data = obj.to_mesh() # bpy.context.depsgraph, apply_modifiers=True, calc_undeformed=False) vertices = [vert.co[:] for vert in data.vertices] polygons = [poly.vertices[:] for poly in data.polygons] self.BVH = BVHTree.FromPolygons(vertices, polygons) obj.to_mesh_clear()
def lloyd_relax(vertices, faces, iterations, mask=None, method=NORMAL, skip_boundary=True, use_axes={0,1,2}): """ supported shape preservation methods: NONE, NORMAL, LINEAR, BVH """ def do_iteration(bvh, bm): verts_out = [] face_centers = np.array([face.calc_center_median() for face in bm.faces]) for bm_vert in bm.verts: co = bm_vert.co if (skip_boundary and bm_vert.is_boundary) or (mask is not None and not mask[bm_vert.index]): new_vert = tuple(co) else: normal = bm_vert.normal cs = np.array([face_centers[face.index] for face in bm_vert.link_faces]) if method == NONE: new_vert = cs.mean(axis=0) elif method == NORMAL: median = mathutils.Vector(cs.mean(axis=0)) dv = median - co dv = dv - dv.project(normal) new_vert = co + dv elif method == LINEAR: approx = linear_approximation(cs) median = mathutils.Vector(approx.center) plane = approx.most_similar_plane() dist = plane.distance_to_point(bm_vert.co) new_vert = median + plane.normal.normalized() * dist elif method == BVH: median = mathutils.Vector(cs.mean(axis=0)) new_vert, normal, idx, dist = bvh.find_nearest(median) else: raise Exception("Unsupported volume preservation method") new_vert = tuple(new_vert) new_vert = mask_axes(tuple(co), new_vert, use_axes) verts_out.append(new_vert) return verts_out if mask is not None: mask = repeat_last_for_length(mask, len(vertices)) bvh = BVHTree.FromPolygons(vertices, faces) for i in range(iterations): bm = bmesh_from_pydata(vertices, [], faces, normal_update=True) vertices = do_iteration(bvh, bm) bm.free() return vertices
def construct_pattern_BVHTree(self, obj): # give world space points ( multiplied by obj.mat_world) resampled_curve_segments = self.patter_segments_cache[obj.name] segments_points_flat = [] for segment in resampled_curve_segments: # add cloth sillayette segments_points_flat.extend(segment[:-1]) # cast the ray sourceTri_BVHT = BVHTree.FromPolygons( segments_points_flat, [tuple(i for i in range(len(segments_points_flat)))], all_triangles=False) # [0,1,2] - polygon == vert indices list return sourceTri_BVHT
def _get_bvh(obj): """Get the BVH for an object Args: obj (variant): object to get the BVH for Returns: BVH for obj """ mat = obj.matrix_world vs = [mat @ v.co for v in obj.data.vertices] ps = [p.vertices for p in obj.data.polygons] return BVHTree.FromPolygons(vs, ps)
def getValue(self): if getattr(self.object, "type", "") != "MESH": return self.getDefaultValue() evaluatedObject = getEvaluatedID(self.object) mesh = evaluatedObject.data polygons = mesh.an.getPolygonIndices() if len(polygons) == 0: return self.getDefaultValue() vertices = mesh.an.getVertices() if self.useWorldSpace: vertices.transform(evaluatedObject.matrix_world) return BVHTree.FromPolygons(vertices, polygons)
def bvh_tree_from_polygons(vertices, polygons, all_triangles=False, epsilon=0.0, safe_check=True): if safe_check: bvh_safe_check(vertices, polygons) if isinstance(vertices, np.ndarray): vertices = vertices.tolist() if isinstance(polygons, np.ndarray): polygons = polygons.tolist() return BVHTree.FromPolygons(vertices, polygons, all_triangles=all_triangles, epsilon=epsilon)
def curve_ray_cast(self, obj, ray_origin, ray_target): """Wrapper for ray casting that moves the ray into object space""" # get the ray relative to the object ray_direction = ray_target - ray_origin resampled_curve_segments = self.patter_segments_cache[obj.name] segments_points_flat = [] for segment in resampled_curve_segments: # add cloth sillayette segments_points_flat.extend(segment[:-1]) # cast the ray sourceTri_BVHT = BVHTree.FromPolygons( segments_points_flat, [tuple(i for i in range(len(segments_points_flat)))], all_triangles=False) # [0,1,2] - polygon == vert indices list # location, normal, index, dist = return sourceTri_BVHT.ray_cast(ray_origin, ray_direction, 600)
def mesh_insert_verts(verts, faces, add_verts_by_face, epsilon=1e-6, exclude_boundary=True, recalc_normals=True, preserve_shape=False): if preserve_shape: bvh = BVHTree.FromPolygons(verts, faces) bm = bmesh_from_pydata(verts, [], []) for face_idx, face in enumerate(faces): n = len(face) add_verts = add_verts_by_face.get(face_idx) if not add_verts: bm_verts = [bm.verts[idx] for idx in face] bm.faces.new(bm_verts) bm.faces.index_update() continue done_verts = dict((i, bm.verts[face[i]]) for i in range(n)) face_verts = [verts[i] for i in face] new_face_verts, edges, new_faces = single_face_delaunay( face_verts, add_verts, epsilon, exclude_boundary) if preserve_shape: new_face_verts = find_nearest_points(bvh, new_face_verts) for new_face in new_faces: bm_verts = [] for i in new_face: bm_vert = done_verts.get(i) if not bm_vert: bm_vert = bm.verts.new(new_face_verts[i]) bm.verts.index_update() bm.verts.ensure_lookup_table() done_verts[i] = bm_vert bm_verts.append(bm_vert) bm.faces.new(bm_verts) bm.faces.index_update() if recalc_normals: bmesh.ops.recalc_face_normals(bm, faces=bm.faces) verts, edges, faces = pydata_from_bmesh(bm) bm.free() return verts, edges, faces
def execute_Object(self, object, epsilon): if object is None: return self.getFallbackBVHTree() if object.type != "MESH": return self.getFallbackBVHTree() evaluatedObject = getEvaluatedID(object) mesh = evaluatedObject.data polygons = mesh.an.getPolygonIndices() if len(polygons) == 0: return self.getFallbackBVHTree() vertices = mesh.an.getVertices() vertices.transform(evaluatedObject.matrix_world) return BVHTree.FromPolygons(vertices, polygons, epsilon=max(epsilon, 0))
def get_points_in_mesh_2D(verts, faces, points, normal, eps=0.0): mask_totals = [] bvh = BVHTree.FromPolygons(verts, faces, all_triangles=False, epsilon=eps) for point in points: inside = False for direction in normal: hit = bvh.ray_cast(point, Vector(direction)) if hit[0]: inside = True break else: hit = bvh.ray_cast(point, -Vector(direction)) if hit[0]: inside = True break mask_totals.append(inside) return mask_totals