static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int quad_method, const int ngon_method)
{
	DerivedMesh *result;
	BMesh *bm;
	int total_edges, i;
	MEdge *me;

	bm = DM_to_bmesh(dm, true);

	BM_mesh_triangulate(bm, quad_method, ngon_method, false, NULL, NULL);

	result = CDDM_from_bmesh(bm, false);
	BM_mesh_free(bm);

	total_edges = result->getNumEdges(result);
	me = CDDM_get_edges(result);

	/* force drawing of all edges (seems to be omitted in CDDM_from_bmesh) */
	for (i = 0; i < total_edges; i++, me++)
		me->flag |= ME_EDGEDRAW | ME_EDGERENDER;

	result->dirty |= DM_DIRTY_NORMALS;

	return result;
}
Example #2
0
static DerivedMesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, DerivedMesh *dm)
{
	DerivedMesh *result;
	BMesh *bm;

	const int defgrp_index = defgroup_name_index(ob, wmd->defgrp_name);

	bm = DM_to_bmesh(dm, true);

	BM_mesh_wireframe(
	       bm,
	       wmd->offset, wmd->offset_fac, wmd->offset_fac_vg,
	       (wmd->flag & MOD_WIREFRAME_REPLACE) != 0,
	       (wmd->flag & MOD_WIREFRAME_BOUNDARY) != 0,
	       (wmd->flag & MOD_WIREFRAME_OFS_EVEN) != 0,
	       (wmd->flag & MOD_WIREFRAME_OFS_RELATIVE) != 0,
	       (wmd->flag & MOD_WIREFRAME_CREASE) != 0,
	       wmd->crease_weight,
	       defgrp_index,
	       (wmd->flag & MOD_WIREFRAME_INVERT_VGROUP) != 0,
	       wmd->mat_ofs,
	       MAX2(ob->totcol - 1, 0),
	       false);

	result = CDDM_from_bmesh(bm, true);
	BM_mesh_free(bm);

	result->dirty |= DM_DIRTY_NORMALS;

	return result;

}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
                                  DerivedMesh *derivedData,
                                  ModifierApplyFlag UNUSED(flag))
{
	DecimateModifierData *dmd = (DecimateModifierData *) md;
	DerivedMesh *dm = derivedData, *result = NULL;
	BMesh *bm;
	bool calc_face_normal;

	float *vweights = NULL;

#ifdef USE_TIMEIT
	TIMEIT_START(decim);
#endif

	/* set up front so we dont show invalid info in the UI */
	dmd->face_count = dm->getNumPolys(dm);

	switch (dmd->mode) {
		case MOD_DECIM_MODE_COLLAPSE:
			if (dmd->percent == 1.0f) {
				return dm;
			}
			calc_face_normal = true;
			break;
		case MOD_DECIM_MODE_UNSUBDIV:
			if (dmd->iter == 0) {
				return dm;
			}
			calc_face_normal = false;
			break;
		case MOD_DECIM_MODE_DISSOLVE:
			if (dmd->angle == 0.0f) {
				return dm;
			}
			calc_face_normal = true;
			break;
		default:
			return dm;
	}

	if (dmd->face_count <= 3) {
		modifier_setError(md, "Modifier requires more than 3 input faces");
		return dm;
	}

	if (dmd->mode == MOD_DECIM_MODE_COLLAPSE) {
		if (dmd->defgrp_name[0]) {
			MDeformVert *dvert;
			int defgrp_index;

			modifier_get_vgroup(ob, dm, dmd->defgrp_name, &dvert, &defgrp_index);

			if (dvert) {
				const unsigned int vert_tot = dm->getNumVerts(dm);
				unsigned int i;

				vweights = MEM_mallocN(vert_tot * sizeof(float), __func__);

				if (dmd->flag & MOD_DECIM_FLAG_INVERT_VGROUP) {
					for (i = 0; i < vert_tot; i++) {
						const float f = 1.0f - defvert_find_weight(&dvert[i], defgrp_index);
						vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX;
					}
				}
				else {
					for (i = 0; i < vert_tot; i++) {
						const float f = defvert_find_weight(&dvert[i], defgrp_index);
						vweights[i] = f > BM_MESH_DECIM_WEIGHT_EPS ? (1.0f / f) : BM_MESH_DECIM_WEIGHT_MAX;
					}
				}
			}
		}
	}

	bm = DM_to_bmesh(dm, calc_face_normal);

	switch (dmd->mode) {
		case MOD_DECIM_MODE_COLLAPSE:
		{
			const int do_triangulate = (dmd->flag & MOD_DECIM_FLAG_TRIANGULATE) != 0;
			BM_mesh_decimate_collapse(bm, dmd->percent, vweights, do_triangulate);
			break;
		}
		case MOD_DECIM_MODE_UNSUBDIV:
		{
			BM_mesh_decimate_unsubdivide(bm, dmd->iter);
			break;
		}
		case MOD_DECIM_MODE_DISSOLVE:
		{
			const int do_dissolve_boundaries = (dmd->flag & MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS) != 0;
			BM_mesh_decimate_dissolve(bm, dmd->angle, do_dissolve_boundaries, (BMO_Delimit)dmd->delimit);
			break;
		}
	}

	if (vweights) {
		MEM_freeN(vweights);
	}

	/* update for display only */
	dmd->face_count = bm->totface;
	result = CDDM_from_bmesh(bm, false);
	BLI_assert(bm->vtoolflagpool == NULL &&
	           bm->etoolflagpool == NULL &&
	           bm->ftoolflagpool == NULL);  /* make sure we never alloc'd these */
	BLI_assert(bm->vtable == NULL &&
	           bm->etable == NULL &&
	           bm->ftable == NULL);

	BM_mesh_free(bm);

#ifdef USE_TIMEIT
	TIMEIT_END(decim);
#endif

	result->dirty = DM_DIRTY_NORMALS;

	return result;
}