Exemplo n.º 1
0
static int mask_flood_fill_exec(bContext *C, wmOperator *op)
{
	ARegion *ar = CTX_wm_region(C);
	struct Scene *scene = CTX_data_scene(C);
	Object *ob = CTX_data_active_object(C);
	PaintMaskFloodMode mode;
	float value;
	PBVH *pbvh;
	PBVHNode **nodes;
	int totnode, i;
	bool multires;
	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;

	mode = RNA_enum_get(op->ptr, "mode");
	value = RNA_float_get(op->ptr, "value");

	BKE_sculpt_update_mesh_elements(scene, sd, ob, false, true);
	pbvh = ob->sculpt->pbvh;
	multires = (BKE_pbvh_type(pbvh) == PBVH_GRIDS);

	BKE_pbvh_search_gather(pbvh, NULL, NULL, &nodes, &totnode);

	sculpt_undo_push_begin("Mask flood fill");

#pragma omp parallel for schedule(guided) if ((sd->flags & SCULPT_USE_OPENMP) && totnode > SCULPT_OMP_LIMIT)
	for (i = 0; i < totnode; i++) {
		PBVHVertexIter vi;

		sculpt_undo_push_node(ob, nodes[i], SCULPT_UNDO_MASK);

		BKE_pbvh_vertex_iter_begin(pbvh, nodes[i], vi, PBVH_ITER_UNIQUE) {
			mask_flood_fill_set_elem(vi.mask, mode, value);
		} BKE_pbvh_vertex_iter_end;
		
		BKE_pbvh_node_mark_redraw(nodes[i]);
		if (multires)
			BKE_pbvh_node_mark_normals_update(nodes[i]);
	}
Exemplo n.º 2
0
static bool sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNode *unode)
{
	Scene *scene = CTX_data_scene(C);
	Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
	Object *ob = CTX_data_active_object(C);
	SculptSession *ss = ob->sculpt;
	MVert *mvert;
	int *index;

	if (unode->maxvert) {
		/* regular mesh restore */

		if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) {
			/* shape key has been changed before calling undo operator */

			Key *key = BKE_key_from_object(ob);
			KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL;

			if (kb) {
				ob->shapenr = BLI_findindex(&key->block, kb) + 1;

				BKE_sculpt_update_mesh_elements(scene, sd, ob, false, false);
				WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob);
			}
			else {
				/* key has been removed -- skip this undo node */
				return 0;
			}
		}

		/* no need for float comparison here (memory is exactly equal or not) */
		index = unode->index;
		mvert = ss->mvert;

		if (ss->kb) {
			float (*vertCos)[3];
			vertCos = BKE_keyblock_convert_to_vertcos(ob, ss->kb);

			if (unode->orig_co) {
				if (ss->modifiers_active) {
					for (int i = 0; i < unode->totvert; i++) {
						sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]);
					}
				}
				else {
					for (int i = 0; i < unode->totvert; i++) {
						swap_v3_v3(vertCos[index[i]], unode->orig_co[i]);
					}
				}
			}
			else {
				for (int i = 0; i < unode->totvert; i++) {
					swap_v3_v3(vertCos[index[i]], unode->co[i]);
				}
			}

			/* propagate new coords to keyblock */
			sculpt_vertcos_to_key(ob, ss->kb, vertCos);

			/* pbvh uses it's own mvert array, so coords should be */
			/* propagated to pbvh here */
			BKE_pbvh_apply_vertCos(ss->pbvh, vertCos);

			MEM_freeN(vertCos);
		}
		else {
			if (unode->orig_co) {
				if (ss->modifiers_active) {
					for (int i = 0; i < unode->totvert; i++) {
						if (sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co)) {
							mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
						}
					}
				}
				else {
					for (int i = 0; i < unode->totvert; i++) {
						if (test_swap_v3_v3(mvert[index[i]].co, unode->orig_co[i])) {
							mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
						}
					}
				}
			}
			else {
				for (int i = 0; i < unode->totvert; i++) {
					if (test_swap_v3_v3(mvert[index[i]].co, unode->co[i])) {
						mvert[index[i]].flag |= ME_VERT_PBVH_UPDATE;
					}
				}
			}
		}
	}
	else if (unode->maxgrid && dm->getGridData) {
		/* multires restore */
		CCGElem **grids, *grid;
		CCGKey key;
		float (*co)[3];
		int gridsize;

		grids = dm->getGridData(dm);
		gridsize = dm->getGridSize(dm);
		dm->getGridKey(dm, &key);

		co = unode->co;
		for (int j = 0; j < unode->totgrid; j++) {
			grid = grids[unode->grids[j]];

			for (int i = 0; i < gridsize * gridsize; i++, co++) {
				swap_v3_v3(CCG_elem_offset_co(&key, grid, i), co[0]);
			}
		}
	}

	return 1;
}