def create_spline(self, curve_object, control_points, radiuses=None, tilts=None): curve_object.data.splines.clear() spline = curve_object.data.splines.new(type='BEZIER') spline.bezier_points.add(len(control_points)) first_point = start_point = spline.bezier_points[0] for idx, segment in enumerate(control_points): end_point = spline.bezier_points[idx+1] start_point.co = Vector(segment[0]) start_point.handle_right = Vector(segment[1]) end_point.handle_left = Vector(segment[2]) end_point.co = Vector(segment[3]) start_point = end_point first_point.handle_left = first_point.co end_point.handle_right = end_point.co if radiuses is not None: spline.bezier_points.foreach_set('radius', numpy_full_list(radiuses, len(spline.bezier_points))) if tilts is not None: spline.bezier_points.foreach_set('tilt', numpy_full_list(tilts, len(spline.bezier_points))) spline.use_smooth = self.use_smooth return spline
def unit_generator(self, idx, geometry): verts, _, _, radiix, radiiy = geometry ntimes = len(verts) radiix = numpy_full_list(radiix, ntimes) radiiy = numpy_full_list(radiiy, ntimes) radiuses = [radiix, radiiy] obj, data_layers = make_bmesh_geometry(self, bpy.context, geometry, idx, radiuses) if data_layers and self.distance_doubles > 0.0: # This sets the modified geometry with radius x and radius y. f_r = list(itertools.chain(*zip(data_layers[0], data_layers[1]))) f_r = [abs(f) for f in f_r] obj.data.skin_vertices[0].data.foreach_set('radius', f_r) all_yes = list(itertools.repeat(True, len(obj.data.vertices))) obj.data.skin_vertices[0].data.foreach_set('use_root', all_yes) elif len(radiix) == len(verts): f_r = list(itertools.chain(*zip(radiix, radiiy))) f_r = [abs(f) for f in f_r] obj.data.skin_vertices[0].data.foreach_set('radius', f_r) if self.use_root: # set all to root all_yes = list(itertools.repeat(True, ntimes)) obj.data.skin_vertices[0].data.foreach_set('use_root', all_yes) elif self.use_slow_root: process_mesh_into_features(obj.data.skin_vertices[0].data, obj.data.edge_keys)
def live_curve(obj_index, node, verts, radii, twist): obj, cu = node.get_obj_curve(obj_index) obj.show_wire = node.show_wire cu.bevel_depth = node.depth cu.bevel_resolution = node.resolution cu.dimensions = node.curve_dimensions cu.resolution_u = node.preview_resolution_u if cu.dimensions == '2D': cu.fill_mode = 'FRONT' else: cu.fill_mode = 'FULL' set_bevel_object(node, cu, obj_index) kind = ["POLY", "NURBS"][bool(node.bspline)] if node.selected_mode == 'Multi': verts = [verts] radii = [radii] twist = [twist] for idx, (VERTS, RADII, TWIST) in enumerate(zip(verts, radii, twist)): full_flat = [] for v in VERTS: full_flat.extend([v[0], v[1], v[2], 1.0]) polyline = cu.splines.new(kind) polyline.points.add(len(VERTS) - 1) polyline.points.foreach_set('co', full_flat) if len(RADII) > 0: rad = numpy_full_list(RADII, len(VERTS)) polyline.points.foreach_set('radius', rad) if len(TWIST) > 0: twist = numpy_full_list(TWIST, len(VERTS)) polyline.points.foreach_set('tilt', twist) if node.close: cu.splines[idx].use_cyclic_u = True if node.bspline: polyline.order_u = len(polyline.points) - 1 polyline.use_smooth = node.use_smooth return obj
def calc_full_mask(mask, index, filter_method, invert, length): if filter_method == 'INDEX': if invert: full_mask = np.zeros(length, dtype='bool') full_mask[np.array(index)] = True else: full_mask = np.ones(length, dtype='bool') full_mask[np.array(index)] = False else: if invert: full_mask = numpy_full_list( np.array(mask).astype(bool), length) else: full_mask = numpy_full_list( np.invert(np.array(mask).astype(bool)), length) return full_mask
def get_weights(edges_dir, input_weights, proportional): if proportional: edge_length = np.linalg.norm(edges_dir, axis=1) if len(input_weights) > 0: edges_weights = numpy_full_list(input_weights, len(edges_dir)) * edge_length weights = edges_weights / np.sum(edges_weights) else: weights = edge_length / np.sum(edge_length) else: if len(input_weights) > 0: edges_weights = numpy_full_list(input_weights, len(edges_dir)) weights = edges_weights / np.sum(edges_weights) else: weights = None return weights
def set_loops(loop_count, obj, index_socket, indices, input_colors, colors): if index_socket.is_linked: for idx, color in zip(indices, input_colors): colors[idx] = color else: if len(input_colors) < loop_count: colors[:] = numpy_full_list(input_colors, loop_count) elif len(input_colors) >= loop_count: colors[:] = input_colors[:loop_count]
def get_selected_edges(use_mask, masks, bm_edges): if use_mask: if isinstance(masks, ndarray): mask_matched = numpy_full_list(masks, len(bm_edges)).tolist() else: mask_matched = repeat_last_for_length(masks, len(bm_edges)) edge_id = bm_edges.layers.int.get("initial_index") return [edge for edge in bm_edges if mask_matched[edge[edge_id]]] return bm_edges
def _regenerate_spline(spline: bpy.types.Spline, vertices: np.ndarray, spline_type: str = 'POLY', vertices_radius: np.ndarray = None, tilt: np.ndarray = None, close_spline: bool = False, use_smooth: bool = True): spline.type = spline_type spline.use_cyclic_u = close_spline spline.use_smooth = use_smooth # flatten vertices array and add W component (X, Y, Z, W), W is responsible for drawing NURBS curves w_vertices = np.concatenate((vertices, np.ones((len(vertices), 1), dtype=np.float32)), axis=1) flatten_vertices = np.ravel(w_vertices) spline.points.foreach_set('co', flatten_vertices) if vertices_radius is not None: spline.points.foreach_set('radius', numpy_full_list(vertices_radius, len(vertices))) if tilt is not None: spline.points.foreach_set('tilt', numpy_full_list(tilt, len(vertices)))
def subdiv_mesh_to_quads_np(vertices, polygons, iterations, normal_displace, random_f, random_normal, random_seed, smooth_f, vert_data, face_data, output_edges=True, output_vert_map=True): np.random.seed(int(random_seed)) np_verts = vertices if isinstance(vertices, np.ndarray) else np.array(vertices) if output_vert_map: vert_map = np.zeros(np_verts.shape[0], dtype=int) else: vert_map = np.array([], dtype=int) matched_vert_data = dict() if vert_data: for key in vert_data: matched_vert_data[key] = numpy_full_list(vert_data[key], np_verts.shape[0]) matched_face_data = dict() if face_data: for key in face_data: data = face_data[key] if isinstance(data, np.ndarray): matched_face_data[key] = numpy_full_list(data, len(polygons)) else: matched_face_data[key] = repeat_last_for_length(data, len(polygons)) flat_pols, pol_len, pol_end = np_pols(polygons) edges, unique_edges, eds_inverse_idx = pols_to_edges(flat_pols, pol_len, pol_end) return subdiv_mesh_to_quads_inner( np_verts, polygons, pol_len, pol_end, edges, unique_edges, eds_inverse_idx, iterations, normal_displace, random_f, random_normal, smooth_f, vert_map, matched_vert_data, matched_face_data, output_edges=output_edges, max_iterations=iterations)
def set_vertices(loop_count, obj, index_socket, indices, input_colors, colors): vertex_index = np.zeros(loop_count, dtype=int) loops = obj.data.loops loops.foreach_get("vertex_index", vertex_index) if index_socket.is_linked: idx_lookup = collections.defaultdict(list) for idx, v_idx in enumerate(vertex_index): idx_lookup[v_idx].append(idx) for idx, col in zip(indices, input_colors): colors[idx_lookup[idx]] = col else: if len(obj.data.vertices) > len(input_colors): colors[:] = numpy_full_list(input_colors, len(obj.data.vertices))[vertex_index] else: if isinstance(input_colors, np.ndarray): colors[:] = input_colors[vertex_index] else: colors[:] = np.array(input_colors)[vertex_index]
def process(self): inputs, outputs = self.inputs, self.outputs if self.dont_process(): return result_vertices, result_edges, result_faces, result_face_data = [], [], [], [] r_inner_vertices, r_inner_edges, r_inner_faces = [], [], [] r_split_vertices, r_split_edges, r_split_faces = [], [], [] use_mask = inputs['EdgeMask'].is_linked show_new = self.show_new and any(s.is_linked for s in outputs[4:7]) show_old = self.show_old and any(s.is_linked for s in outputs[7:]) use_face_data = inputs['FaceData'].is_linked and outputs['FaceData'].is_linked output_numpy = any(self.out_np) meshes = self.get_data() for vertices, edges, faces, face_data, masks, cuts, smooth, fractal, along_normal, seed in zip(*meshes): if cuts < 1: result_vertices.append(vertices) result_edges.append(edges) result_faces.append(faces) result_face_data.append(face_data) r_inner_vertices.append(vertices) r_inner_edges.append(edges) r_inner_faces.append(faces) r_split_vertices.append(vertices) r_split_edges.append(edges) r_split_faces.append(faces) continue if use_face_data and len(face_data) > 0: if isinstance(face_data, ndarray): face_data_matched = numpy_full_list(face_data, len(faces)).tolist() else: face_data_matched = repeat_last_for_length(face_data, len(faces)) else: face_data_matched =[] bm = bmesh_from_pydata( vertices, edges, faces, markup_face_data=use_face_data, markup_edge_data=use_mask, normal_update=True) selected_edges = get_selected_edges(use_mask, masks, bm.edges) geom = subdivide_edges( bm, edges=selected_edges, smooth=smooth, smooth_falloff=self.falloff_type, fractal=fractal, along_normal=along_normal, cuts=cuts, seed=seed, quad_corner_type=self.corner_type, use_grid_fill=self.grid_fill, use_single_edge=self.single_edge, use_only_quads=self.only_quads, use_smooth_even=self.smooth_even) if output_numpy: new_verts, new_edges, new_faces, new_face_data = numpy_data_from_bmesh(bm, self.out_np, face_data_matched) else: if use_face_data and len(face_data) > 0: new_verts, new_edges, new_faces, new_face_data = pydata_from_bmesh(bm, face_data_matched) else: new_verts, new_edges, new_faces = pydata_from_bmesh(bm) new_face_data = [] result_vertices.append(new_verts) result_edges.append(new_edges) result_faces.append(new_faces) result_face_data.append(new_face_data) if show_new: inner_verts, inner_edges, inner_faces = get_partial_result_pydata(geom['geom_inner']) r_inner_vertices.append(inner_verts) r_inner_edges.append(inner_edges) r_inner_faces.append(inner_faces) if show_old: split_verts, split_edges, split_faces = get_partial_result_pydata(geom['geom_split']) r_split_vertices.append(split_verts) r_split_edges.append(split_edges) r_split_faces.append(split_faces) bm.free() outputs['Vertices'].sv_set(result_vertices) outputs['Edges'].sv_set(result_edges) outputs['Faces'].sv_set(result_faces) outputs['FaceData'].sv_set(result_face_data) outputs['NewVertices'].sv_set(r_inner_vertices) outputs['NewEdges'].sv_set(r_inner_edges) outputs['NewFaces'].sv_set(r_inner_faces) outputs['OldVertices'].sv_set(r_split_vertices) outputs['OldEdges'].sv_set(r_split_edges) outputs['OldFaces'].sv_set(r_split_faces)
def inset_special_np(vertices, faces, inset_rates, distances, ignores, make_inners, custom_normals, matrices, zero_mode="SKIP", offset_mode='CENTER', proportional=False, concave_support=True, output_old_face_id=False, output_old_v_id=False, output_pols_groups=False, output_new_verts_mask=False): if not has_element(faces): return new_faces, new_ignores, new_insets = [], [], [] original_face_ids, original_vertex_id, new_pols_groups, new_verts_mask = [], [], [], [] inset_faces_id, fan_faces_id, ignores_id, fan_faces = [], [], [], [] np_distances, np_matrices = [], [] np_verts = vertices if isinstance(vertices, np.ndarray) else np.array(vertices) invert_face_mask = numpy_full_list(np_array(ignores, dtype=bool), len(faces)) np_faces_mask = np.invert(invert_face_mask) if not any(np_faces_mask): return np_faces = np_array(faces) np_faces_id = np.arange(len(faces)) if output_old_face_id else [] np_inset_rate = numpy_full_list(inset_rates, len(faces)) if has_element(custom_normals): np_custom_normals = numpy_full_list(custom_normals, len(faces)) use_custom_normals = True else: np_custom_normals = [] use_custom_normals = False if offset_mode == 'CENTER': zero_inset = np_inset_rate == 0 if zero_mode == 'SKIP': np_faces_mask[zero_inset] = False invert_face_mask[zero_inset] = True inset_pols = np_faces[np_faces_mask] np_distances = numpy_full_list(distances, len(faces))[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] new_ignores = np_faces[invert_face_mask].tolist() if output_old_face_id: ignores_id = np_faces_id[invert_face_mask].tolist() inset_faces_id = np_faces_id[np_faces_mask] else: # FAN if output_old_face_id: ignores_maks = np.invert(np_faces_mask) ignores_id = np_faces_id[ignores_maks].tolist() new_ignores = np_faces[ignores_maks].tolist() else: new_ignores = np_faces[np.invert(np_faces_mask)].tolist() np_faces_mask[zero_inset] = False inset_pols = np_faces[np_faces_mask] np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] np_all_distances = numpy_full_list(distances, len(faces)) np_distances = np_all_distances[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] fan_faces = np_faces[zero_inset] fan_distances = np_all_distances[zero_inset] if output_old_face_id: inset_faces_id = np_faces_id[np_faces_mask] fan_faces_id = np_faces_id[zero_inset] else: #SIDES mode inset_pols = np_faces[np_faces_mask] if offset_mode == 'SIDES': np_distances = numpy_full_list(distances, len(faces))[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] else: #MATRIX if len(matrices) == len(faces): np_matrices = np.array(matrices)[np_faces_mask] else: np_matrices = numpy_full_list(matrices, len(inset_pols)) np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] new_ignores = np_faces[invert_face_mask].tolist() fan_faces = [] if output_old_face_id: ignores_id = np_faces_id[invert_face_mask].tolist() inset_faces_id = np_faces_id[np_faces_mask] common_args = { 'use_custom_normals': use_custom_normals, 'output_old_v_id': output_old_v_id, 'output_old_face_id': output_old_face_id, 'output_pols_groups': output_pols_groups } new_verts = np_verts.tolist() if output_old_v_id: original_vertex_id = list(range(len(vertices))) if output_new_verts_mask: new_verts_mask.extend([0] * len(new_verts)) variable_pols = inset_pols.dtype == 'object' np_len = np_vectorize(len) index_offset = 0 if len(inset_pols) > 0: if variable_pols: lens = np_len(inset_pols) pol_types = np.unique(lens) else: pol_types = [inset_pols.shape[1]] for pol_sides in pol_types: if variable_pols: mask = lens == pol_sides pols_group = np_array(inset_pols[mask].tolist(), dtype=int) res = inset_regular_pols( np_verts, pols_group, np_distances[mask] if offset_mode != 'MATRIX' else [], np_inset_rate[mask] if offset_mode != 'MATRIX' else [], np_make_inners[mask], inset_faces_id[mask] if output_old_face_id else [], np_custom_normals[mask] if use_custom_normals else [], np_matrices[mask] if offset_mode == 'MATRIX' else [], offset_mode=offset_mode, proportional=proportional, concave_support=concave_support, index_offset=index_offset, **common_args) else: res = inset_regular_pols( np_verts, inset_pols, np_distances, np_inset_rate, np_make_inners, inset_faces_id if output_old_face_id else [], np_custom_normals if use_custom_normals else [], np_matrices, offset_mode=offset_mode, proportional=proportional, concave_support=concave_support, index_offset=index_offset, **common_args) index_offset += len(res[0]) new_verts.extend(res[0]) new_faces.extend(res[1]) new_insets.extend(res[2]) original_vertex_id.extend(res[3]) original_face_ids.extend(res[4]) new_pols_groups.extend(res[5]) if output_new_verts_mask: new_verts_mask.extend([1] * len(res[0])) if zero_mode == 'FAN' and len(fan_faces) > 0: if variable_pols: lens = np_len(fan_faces) pol_types = np.unique(lens) else: pol_types = [inset_pols.shape[1]] for pol_sides in pol_types: if variable_pols: mask = lens == pol_sides pols_group = np_array(fan_faces[mask].tolist(), dtype=int) res = fan_regular_pols( np_verts, pols_group, fan_distances[mask], fan_faces_id[mask] if output_old_face_id else [], np_custom_normals[mask] if use_custom_normals else [], index_offset=index_offset, **common_args) else: res = fan_regular_pols( np_verts, fan_faces, fan_distances, fan_faces_id if output_old_face_id else [], np_custom_normals if use_custom_normals else [], index_offset=index_offset, **common_args) index_offset += len(res[0]) new_verts.extend(res[0]) new_faces.extend(res[1]) original_vertex_id.extend(res[2]) original_face_ids.extend(res[3]) new_pols_groups.extend(res[4]) if output_new_verts_mask: new_verts_mask.extend([1] * len(res[0])) return (new_verts, new_faces + new_ignores, new_ignores, new_insets, original_vertex_id, original_face_ids + ignores_id, new_pols_groups + [0] * len(new_ignores), new_verts_mask)
def triangle_mesh_poke(mesh, mask_in, offset_in, v_color, mat_id, relative_offset=False, deepcopy=True): if deepcopy: triangle_mesh = copy.deepcopy(mesh) else: triangle_mesh = mesh np_verts = np.asarray(triangle_mesh.vertices) mask = numpy_full_list(mask_in, len(triangle_mesh.triangles)).astype('bool') if len(offset_in) == np.sum(mask): offset = np.array(offset_in)[:, np.newaxis] elif len(offset_in) > 1: offset = numpy_full_list(offset_in, len(triangle_mesh.triangles))[mask, np.newaxis] else: offset = offset_in np_faces = np.asarray(triangle_mesh.triangles) faces_masked = np_faces[mask] v_pols = np_verts[np_faces[mask]] center = np.sum(v_pols, axis=1) / 3 normals = get_normals(triangle_mesh, np_verts, np_faces, mask) faces_num = np_faces[mask].shape[0] if relative_offset: areas = calc_tris_areas(v_pols) new_vecs = center + normals * (offset* areas[:, np.newaxis]) else: new_vecs = center + normals * offset all_vecs = np.concatenate([np_verts, new_vecs]) new_faces = np.zeros((faces_num, 3, 3), dtype='int') new_faces[:, :, 2] = (np.arange(faces_num) + len(np_verts))[:, np.newaxis] for i in range(3): new_faces[:, i, 0] = np_faces[mask, i] new_faces[:, i, 1] = np_faces[mask, (i + 1) % 3] new_faces_shaped = new_faces.reshape(-1, 3) all_faces = np.concatenate([np_faces[np.invert(mask)], new_faces_shaped]) if has_element(v_color): if triangle_mesh.has_vertex_colors(): v_col = numpy_full_list(v_color, len(new_vecs))[:,:3] triangle_mesh.vertex_colors = vec_3f(np.concatenate([np.asarray(triangle_mesh.vertex_colors), v_col])) else: spread_vertex_attrib(triangle_mesh, faces_masked, 'vertex_colors') spread_vertex_attrib(triangle_mesh, faces_masked, 'vertex_normals') spread_face_attrib(triangle_mesh, mask, 'triangle_normals', 3, vec_3f) if len(mat_id) > 0: if triangle_mesh.has_triangle_material_ids(): mat_id_shaped = numpy_full_list(mat_id, len(new_faces_shaped)) triangle_mesh.triangle_material_ids = vec_1i( np.concatenate( [np.asarray(triangle_mesh.triangle_material_ids)[np.invert(mask)], mat_id_shaped] )) else: mat_id_shaped = numpy_full_list(mat_id, len(all_faces)) triangle_mesh.triangle_material_ids = vec_1i(mat_id_shaped) else: spread_face_attrib(triangle_mesh, mask, 'triangle_material_ids', 1, vec_1i) poke_uvs(triangle_mesh, mask) triangle_mesh.vertices = vec_3f(all_vecs) triangle_mesh.triangles = vec_3i(all_faces) return (triangle_mesh, new_vecs, np.arange(len(np_verts), len(np_verts)+len(new_vecs)), np.arange(len(all_faces)-len(new_faces_shaped), len(all_faces)) )