Blender  V2.59
MOD_boolean.c
Go to the documentation of this file.
00001 /*
00002 * $Id: MOD_boolean.c 37005 2011-05-29 15:53:38Z nazgul $
00003 *
00004 * ***** BEGIN GPL LICENSE BLOCK *****
00005 *
00006 * This program is free software; you can redistribute it and/or
00007 * modify it under the terms of the GNU General Public License
00008 * as published by the Free Software Foundation; either version 2
00009 * of the License, or (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software  Foundation,
00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *
00020 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00021 * All rights reserved.
00022 *
00023 * Contributor(s): Daniel Dunbar
00024 *                 Ton Roosendaal,
00025 *                 Ben Batt,
00026 *                 Brecht Van Lommel,
00027 *                 Campbell Barton
00028 *
00029 * ***** END GPL LICENSE BLOCK *****
00030 *
00031 */
00032 
00037 #include <stdio.h>
00038 
00039 #include "DNA_object_types.h"
00040 
00041 #include "BLI_utildefines.h"
00042 
00043 
00044 #include "BKE_cdderivedmesh.h"
00045 #include "BKE_modifier.h"
00046 
00047 #include "depsgraph_private.h"
00048 
00049 #include "MOD_boolean_util.h"
00050 #include "MOD_util.h"
00051 
00052 
00053 static void copyData(ModifierData *md, ModifierData *target)
00054 {
00055         BooleanModifierData *bmd = (BooleanModifierData*) md;
00056         BooleanModifierData *tbmd = (BooleanModifierData*) target;
00057 
00058         tbmd->object = bmd->object;
00059         tbmd->operation = bmd->operation;
00060 }
00061 
00062 static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
00063 {
00064         BooleanModifierData *bmd = (BooleanModifierData*) md;
00065 
00066         return !bmd->object;
00067 }
00068 
00069 static void foreachObjectLink(
00070                                                   ModifierData *md, Object *ob,
00071            void (*walk)(void *userData, Object *ob, Object **obpoin),
00072                   void *userData)
00073 {
00074         BooleanModifierData *bmd = (BooleanModifierData*) md;
00075 
00076         walk(userData, ob, &bmd->object);
00077 }
00078 
00079 static void updateDepgraph(ModifierData *md, DagForest *forest,
00080                                                 struct Scene *UNUSED(scene),
00081                                                 Object *UNUSED(ob),
00082                                                 DagNode *obNode)
00083 {
00084         BooleanModifierData *bmd = (BooleanModifierData*) md;
00085 
00086         if(bmd->object) {
00087                 DagNode *curNode = dag_get_node(forest, bmd->object);
00088 
00089                 dag_add_relation(forest, curNode, obNode,
00090                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Boolean Modifier");
00091         }
00092 }
00093 
00094 #ifdef WITH_MOD_BOOLEAN
00095 static DerivedMesh *get_quick_derivedMesh(DerivedMesh *derivedData, DerivedMesh *dm, int operation)
00096 {
00097         DerivedMesh *result = NULL;
00098 
00099         if(derivedData->getNumFaces(derivedData) == 0 || dm->getNumFaces(dm) == 0) {
00100                 switch(operation) {
00101                         case eBooleanModifierOp_Intersect:
00102                                 result = CDDM_new(0, 0, 0);
00103                                 break;
00104 
00105                         case eBooleanModifierOp_Union:
00106                                 if(derivedData->getNumFaces(derivedData)) result = derivedData;
00107                                 else result = CDDM_copy(dm);
00108 
00109                                 break;
00110 
00111                         case eBooleanModifierOp_Difference:
00112                                 result = derivedData;
00113                                 break;
00114                 }
00115         }
00116 
00117         return result;
00118 }
00119 
00120 static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
00121                                                 DerivedMesh *derivedData,
00122                                                 int UNUSED(useRenderParams),
00123                                                 int UNUSED(isFinalCalc))
00124 {
00125         BooleanModifierData *bmd = (BooleanModifierData*) md;
00126         DerivedMesh *dm;
00127 
00128         if(!bmd->object)
00129                 return derivedData;
00130 
00131         dm = bmd->object->derivedFinal;
00132 
00133         if(dm) {
00134                 DerivedMesh *result;
00135 
00136                 /* when one of objects is empty (has got no faces) we could speed up
00137                    calculation a bit returning one of objects' derived meshes (or empty one)
00138                    Returning mesh is depended on modifieier's operation (sergey) */
00139                 result = get_quick_derivedMesh(derivedData, dm, bmd->operation);
00140 
00141                 if(result == NULL) {
00142                         result = NewBooleanDerivedMesh(dm, bmd->object, derivedData, ob,
00143                                         1 + bmd->operation);
00144                 }
00145 
00146                 /* if new mesh returned, return it; otherwise there was
00147                 * an error, so delete the modifier object */
00148                 if(result)
00149                         return result;
00150                 else
00151                         modifier_setError(md, "Can't execute boolean operation.");
00152         }
00153         
00154         return derivedData;
00155 }
00156 #else // WITH_MOD_BOOLEAN
00157 static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
00158                                                 DerivedMesh *derivedData,
00159                                                 int UNUSED(useRenderParams),
00160                                                 int UNUSED(isFinalCalc))
00161 {
00162         return derivedData;
00163 }
00164 #endif // WITH_MOD_BOOLEAN
00165 
00166 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md))
00167 {
00168         CustomDataMask dataMask = CD_MASK_MTFACE | CD_MASK_MEDGE;
00169 
00170         dataMask |= CD_MASK_MDEFORMVERT;
00171         
00172         return dataMask;
00173 }
00174 
00175 
00176 ModifierTypeInfo modifierType_Boolean = {
00177         /* name */              "Boolean",
00178         /* structName */        "BooleanModifierData",
00179         /* structSize */        sizeof(BooleanModifierData),
00180         /* type */              eModifierTypeType_Nonconstructive,
00181         /* flags */             eModifierTypeFlag_AcceptsMesh
00182                                                         | eModifierTypeFlag_UsesPointCache,
00183 
00184         /* copyData */          copyData,
00185         /* deformVerts */       NULL,
00186         /* deformMatrices */    NULL,
00187         /* deformVertsEM */     NULL,
00188         /* deformMatricesEM */  NULL,
00189         /* applyModifier */     applyModifier,
00190         /* applyModifierEM */   NULL,
00191         /* initData */          NULL,
00192         /* requiredDataMask */  requiredDataMask,
00193         /* freeData */          NULL,
00194         /* isDisabled */        isDisabled,
00195         /* updateDepgraph */    updateDepgraph,
00196         /* dependsOnTime */     NULL,
00197         /* dependsOnNormals */  NULL,
00198         /* foreachObjectLink */ foreachObjectLink,
00199         /* foreachIDLink */     NULL,
00200 };