Changeset View
Changeset View
Standalone View
Standalone View
source/blender/modifiers/intern/MOD_boolean.c
| Show All 27 Lines | |||||
| * | * | ||||
| */ | */ | ||||
| /** \file blender/modifiers/intern/MOD_boolean.c | /** \file blender/modifiers/intern/MOD_boolean.c | ||||
| * \ingroup modifiers | * \ingroup modifiers | ||||
| */ | */ | ||||
| // #ifdef DEBUG_TIME | // #ifdef DEBUG_TIME | ||||
| #define USE_BMESH | |||||
| #ifdef WITH_MOD_BOOLEAN | |||||
| # define USE_CARVE WITH_MOD_BOOLEAN | |||||
| #endif | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_math_matrix.h" | #include "BLI_math_matrix.h" | ||||
| #include "BKE_cdderivedmesh.h" | #include "BKE_cdderivedmesh.h" | ||||
| #include "BKE_library_query.h" | #include "BKE_library_query.h" | ||||
| #include "BKE_modifier.h" | #include "BKE_modifier.h" | ||||
| #include "depsgraph_private.h" | #include "depsgraph_private.h" | ||||
| #include "MOD_boolean_util.h" | |||||
| #include "MOD_util.h" | #include "MOD_util.h" | ||||
| #ifdef USE_BMESH | |||||
| #include "BLI_alloca.h" | #include "BLI_alloca.h" | ||||
| #include "BLI_math_geom.h" | #include "BLI_math_geom.h" | ||||
| #include "BKE_material.h" | #include "BKE_material.h" | ||||
| #include "BKE_global.h" /* only to check G.debug */ | #include "BKE_global.h" /* only to check G.debug */ | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "bmesh.h" | #include "bmesh.h" | ||||
| #include "bmesh_tools.h" | #include "bmesh_tools.h" | ||||
| #include "tools/bmesh_intersect.h" | #include "tools/bmesh_intersect.h" | ||||
| #endif | |||||
| #ifdef DEBUG_TIME | #ifdef DEBUG_TIME | ||||
| #include "PIL_time.h" | # include "PIL_time.h" | ||||
| #include "PIL_time_utildefines.h" | # include "PIL_time_utildefines.h" | ||||
| #endif | #endif | ||||
| static void initData(ModifierData *md) | static void initData(ModifierData *md) | ||||
| { | { | ||||
| BooleanModifierData *bmd = (BooleanModifierData *)md; | BooleanModifierData *bmd = (BooleanModifierData *)md; | ||||
| bmd->solver = eBooleanModifierSolver_BMesh; | |||||
| bmd->double_threshold = 1e-6f; | bmd->double_threshold = 1e-6f; | ||||
| } | } | ||||
| static void copyData(ModifierData *md, ModifierData *target) | static void copyData(ModifierData *md, ModifierData *target) | ||||
| { | { | ||||
| #if 0 | #if 0 | ||||
| BooleanModifierData *bmd = (BooleanModifierData *) md; | BooleanModifierData *bmd = (BooleanModifierData *) md; | ||||
| BooleanModifierData *tbmd = (BooleanModifierData *) target; | BooleanModifierData *tbmd = (BooleanModifierData *) target; | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | static void updateDepsgraph(ModifierData *md, | ||||
| if (bmd->object != NULL) { | if (bmd->object != NULL) { | ||||
| DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); | DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); | ||||
| DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); | DEG_add_object_relation(node, bmd->object, DEG_OB_COMP_GEOMETRY, "Boolean Modifier"); | ||||
| } | } | ||||
| /* We need own transformation as well. */ | /* We need own transformation as well. */ | ||||
| DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); | DEG_add_object_relation(node, ob, DEG_OB_COMP_TRANSFORM, "Boolean Modifier"); | ||||
| } | } | ||||
| #if defined(USE_CARVE) || defined(USE_BMESH) | |||||
| static DerivedMesh *get_quick_derivedMesh( | static DerivedMesh *get_quick_derivedMesh( | ||||
| Object *ob_self, DerivedMesh *dm_self, | Object *ob_self, DerivedMesh *dm_self, | ||||
| Object *ob_other, DerivedMesh *dm_other, | Object *ob_other, DerivedMesh *dm_other, | ||||
| int operation) | int operation) | ||||
| { | { | ||||
| DerivedMesh *result = NULL; | DerivedMesh *result = NULL; | ||||
| if (dm_self->getNumPolys(dm_self) == 0 || dm_other->getNumPolys(dm_other) == 0) { | if (dm_self->getNumPolys(dm_self) == 0 || dm_other->getNumPolys(dm_other) == 0) { | ||||
| Show All 30 Lines | switch (operation) { | ||||
| case eBooleanModifierOp_Difference: | case eBooleanModifierOp_Difference: | ||||
| result = dm_self; | result = dm_self; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| #endif /* defined(USE_CARVE) || defined(USE_BMESH) */ | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /* BMESH */ | |||||
| #ifdef USE_BMESH | |||||
| /* has no meaning for faces, do this so we can tell which face is which */ | /* has no meaning for faces, do this so we can tell which face is which */ | ||||
| #define BM_FACE_TAG BM_ELEM_DRAW | #define BM_FACE_TAG BM_ELEM_DRAW | ||||
| /** | /** | ||||
| * Compare selected/unselected. | * Compare selected/unselected. | ||||
| */ | */ | ||||
| static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) | static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) | ||||
| { | { | ||||
| return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; | return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; | ||||
| } | } | ||||
| static DerivedMesh *applyModifier_bmesh( | static DerivedMesh *applyModifier( | ||||
| ModifierData *md, Object *ob, | ModifierData *md, Object *ob, | ||||
| DerivedMesh *dm, | DerivedMesh *dm, | ||||
| ModifierApplyFlag flag) | ModifierApplyFlag flag) | ||||
| { | { | ||||
| BooleanModifierData *bmd = (BooleanModifierData *) md; | BooleanModifierData *bmd = (BooleanModifierData *) md; | ||||
| DerivedMesh *dm_other; | DerivedMesh *dm_other; | ||||
| if (!bmd->object) | if (!bmd->object) | ||||
| ▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | #endif | ||||
| if (result) | if (result) | ||||
| return result; | return result; | ||||
| else | else | ||||
| modifier_setError(md, "Cannot execute boolean operation"); | modifier_setError(md, "Cannot execute boolean operation"); | ||||
| } | } | ||||
| return dm; | return dm; | ||||
| } | } | ||||
| #endif /* USE_BMESH */ | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /* CARVE */ | |||||
| #ifdef USE_CARVE | |||||
| static DerivedMesh *applyModifier_carve( | |||||
| ModifierData *md, Object *ob, | |||||
| DerivedMesh *derivedData, | |||||
| ModifierApplyFlag flag) | |||||
| { | |||||
| BooleanModifierData *bmd = (BooleanModifierData *) md; | |||||
| DerivedMesh *dm; | |||||
| if (!bmd->object) | |||||
| return derivedData; | |||||
| dm = get_dm_for_modifier(bmd->object, flag); | |||||
| if (dm) { | |||||
| DerivedMesh *result; | |||||
| /* when one of objects is empty (has got no faces) we could speed up | |||||
| * calculation a bit returning one of objects' derived meshes (or empty one) | |||||
| * Returning mesh is depended on modifiers operation (sergey) */ | |||||
| result = get_quick_derivedMesh(ob, derivedData, bmd->object, dm, bmd->operation); | |||||
| if (result == NULL) { | |||||
| #ifdef DEBUG_TIME | |||||
| TIMEIT_START(boolean_carve); | |||||
| #endif | |||||
| result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob, | |||||
| 1 + bmd->operation); | |||||
| #ifdef DEBUG_TIME | |||||
| TIMEIT_END(boolean_carve); | |||||
| #endif | |||||
| } | |||||
| /* if new mesh returned, return it; otherwise there was | |||||
| * an error, so delete the modifier object */ | |||||
| if (result) | |||||
| return result; | |||||
| else | |||||
| modifier_setError(md, "Cannot execute boolean operation"); | |||||
| } | |||||
| return derivedData; | |||||
| } | |||||
| #endif /* USE_CARVE */ | |||||
| static DerivedMesh *applyModifier_nop( | |||||
| ModifierData *UNUSED(md), Object *UNUSED(ob), | |||||
| DerivedMesh *derivedData, | |||||
| ModifierApplyFlag UNUSED(flag)) | |||||
| { | |||||
| return derivedData; | |||||
| } | |||||
| static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) | static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) | ||||
| { | { | ||||
| CustomDataMask dataMask = CD_MASK_MTFACE | CD_MASK_MEDGE; | CustomDataMask dataMask = CD_MASK_MTFACE | CD_MASK_MEDGE; | ||||
| dataMask |= CD_MASK_MDEFORMVERT; | dataMask |= CD_MASK_MDEFORMVERT; | ||||
| return dataMask; | return dataMask; | ||||
| } | } | ||||
| static DerivedMesh *applyModifier( | |||||
| ModifierData *md, Object *ob, | |||||
| DerivedMesh *derivedData, | |||||
| ModifierApplyFlag flag) | |||||
| { | |||||
| BooleanModifierData *bmd = (BooleanModifierData *)md; | |||||
| switch (bmd->solver) { | |||||
| #ifdef USE_CARVE | |||||
| case eBooleanModifierSolver_Carve: | |||||
| return applyModifier_carve(md, ob, derivedData, flag); | |||||
| #endif | |||||
| #ifdef USE_BMESH | |||||
| case eBooleanModifierSolver_BMesh: | |||||
| return applyModifier_bmesh(md, ob, derivedData, flag); | |||||
| #endif | |||||
| default: | |||||
| return applyModifier_nop(md, ob, derivedData, flag); | |||||
| } | |||||
| } | |||||
| ModifierTypeInfo modifierType_Boolean = { | ModifierTypeInfo modifierType_Boolean = { | ||||
| /* name */ "Boolean", | /* name */ "Boolean", | ||||
| /* structName */ "BooleanModifierData", | /* structName */ "BooleanModifierData", | ||||
| /* structSize */ sizeof(BooleanModifierData), | /* structSize */ sizeof(BooleanModifierData), | ||||
| /* type */ eModifierTypeType_Nonconstructive, | /* type */ eModifierTypeType_Nonconstructive, | ||||
| /* flags */ eModifierTypeFlag_AcceptsMesh | | /* flags */ eModifierTypeFlag_AcceptsMesh | | ||||
| eModifierTypeFlag_UsesPointCache, | eModifierTypeFlag_UsesPointCache, | ||||
| Show All 19 Lines | |||||