Fix ShaderNodeCustomGroup.copy method being called too often
[blender.git] / source / blender / modifiers / intern / MOD_shrinkwrap.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software  Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2005 by the Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup modifiers
22  */
23
24 #include <string.h>
25
26 #include "BLI_utildefines.h"
27
28 #include "DNA_mesh_types.h"
29 #include "DNA_object_types.h"
30
31 #include "BKE_editmesh.h"
32 #include "BKE_library.h"
33 #include "BKE_library_query.h"
34 #include "BKE_mesh.h"
35 #include "BKE_modifier.h"
36 #include "BKE_shrinkwrap.h"
37
38 #include "DEG_depsgraph_query.h"
39
40 #include "MOD_util.h"
41
42 static bool dependsOnNormals(ModifierData *md);
43
44 static void initData(ModifierData *md)
45 {
46   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
47   smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
48   smd->shrinkOpts = MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR;
49   smd->keepDist = 0.0f;
50
51   smd->target = NULL;
52   smd->auxTarget = NULL;
53 }
54
55 static void requiredDataMask(Object *UNUSED(ob),
56                              ModifierData *md,
57                              CustomData_MeshMasks *r_cddata_masks)
58 {
59   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
60
61   /* ask for vertexgroups if we need them */
62   if (smd->vgroup_name[0] != '\0') {
63     r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT;
64   }
65
66   if ((smd->shrinkType == MOD_SHRINKWRAP_PROJECT) &&
67       (smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL)) {
68     /* XXX Really? These should always be present, always... */
69     r_cddata_masks->vmask |= CD_MASK_MVERT;
70   }
71 }
72
73 static bool isDisabled(const struct Scene *UNUSED(scene),
74                        ModifierData *md,
75                        bool UNUSED(useRenderParams))
76 {
77   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
78
79   /* The object type check is only needed here in case we have a placeholder
80    * object assigned (because the library containing the mesh is missing).
81    *
82    * In other cases it should be impossible to have a type mismatch.
83    */
84   if (!smd->target || smd->target->type != OB_MESH) {
85     return true;
86   }
87   else if (smd->auxTarget && smd->auxTarget->type != OB_MESH) {
88     return true;
89   }
90   return false;
91 }
92
93 static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
94 {
95   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
96
97   walk(userData, ob, &smd->target, IDWALK_CB_NOP);
98   walk(userData, ob, &smd->auxTarget, IDWALK_CB_NOP);
99 }
100
101 static void deformVerts(ModifierData *md,
102                         const ModifierEvalContext *ctx,
103                         Mesh *mesh,
104                         float (*vertexCos)[3],
105                         int numVerts)
106 {
107   ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md;
108   struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
109   Mesh *mesh_src = NULL;
110
111   if (ctx->object->type == OB_MESH) {
112     /* mesh_src is only needed for vgroups. */
113     mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh, NULL, numVerts, false, false);
114   }
115
116   struct MDeformVert *dvert = NULL;
117   int defgrp_index = -1;
118   MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index);
119
120   shrinkwrapModifier_deform(
121       swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts);
122
123   if (!ELEM(mesh_src, NULL, mesh)) {
124     BKE_id_free(NULL, mesh_src);
125   }
126 }
127
128 static void deformVertsEM(ModifierData *md,
129                           const ModifierEvalContext *ctx,
130                           struct BMEditMesh *editData,
131                           Mesh *mesh,
132                           float (*vertexCos)[3],
133                           int numVerts)
134 {
135   ShrinkwrapModifierData *swmd = (ShrinkwrapModifierData *)md;
136   struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
137   Mesh *mesh_src = MOD_deform_mesh_eval_get(
138       ctx->object, editData, mesh, NULL, numVerts, false, false);
139
140   struct MDeformVert *dvert = NULL;
141   int defgrp_index = -1;
142   MOD_get_vgroup(ctx->object, mesh_src, swmd->vgroup_name, &dvert, &defgrp_index);
143
144   shrinkwrapModifier_deform(
145       swmd, ctx, scene, ctx->object, mesh_src, dvert, defgrp_index, vertexCos, numVerts);
146
147   if (!ELEM(mesh_src, NULL, mesh)) {
148     BKE_id_free(NULL, mesh_src);
149   }
150 }
151
152 static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
153 {
154   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
155   CustomData_MeshMasks mask = {0};
156
157   if (BKE_shrinkwrap_needs_normals(smd->shrinkType, smd->shrinkMode)) {
158     mask.vmask |= CD_MASK_NORMAL;
159     mask.lmask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
160   }
161
162   if (smd->target != NULL) {
163     DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
164     DEG_add_object_relation(ctx->node, smd->target, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
165     DEG_add_customdata_mask(ctx->node, smd->target, &mask);
166     if (smd->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
167       DEG_add_special_eval_flag(ctx->node, &smd->target->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
168     }
169   }
170   if (smd->auxTarget != NULL) {
171     DEG_add_object_relation(
172         ctx->node, smd->auxTarget, DEG_OB_COMP_TRANSFORM, "Shrinkwrap Modifier");
173     DEG_add_object_relation(
174         ctx->node, smd->auxTarget, DEG_OB_COMP_GEOMETRY, "Shrinkwrap Modifier");
175     DEG_add_customdata_mask(ctx->node, smd->auxTarget, &mask);
176     if (smd->shrinkType == MOD_SHRINKWRAP_TARGET_PROJECT) {
177       DEG_add_special_eval_flag(ctx->node, &smd->auxTarget->id, DAG_EVAL_NEED_SHRINKWRAP_BOUNDARY);
178     }
179   }
180   DEG_add_modifier_to_transform_relation(ctx->node, "Shrinkwrap Modifier");
181 }
182
183 static bool dependsOnNormals(ModifierData *md)
184 {
185   ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
186
187   if (smd->target && smd->shrinkType == MOD_SHRINKWRAP_PROJECT) {
188     return (smd->projAxis == MOD_SHRINKWRAP_PROJECT_OVER_NORMAL);
189   }
190
191   return false;
192 }
193
194 ModifierTypeInfo modifierType_Shrinkwrap = {
195     /* name */ "Shrinkwrap",
196     /* structName */ "ShrinkwrapModifierData",
197     /* structSize */ sizeof(ShrinkwrapModifierData),
198     /* type */ eModifierTypeType_OnlyDeform,
199     /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs |
200         eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode |
201         eModifierTypeFlag_EnableInEditmode,
202
203     /* copyData */ modifier_copyData_generic,
204
205     /* deformVerts */ deformVerts,
206     /* deformMatrices */ NULL,
207     /* deformVertsEM */ deformVertsEM,
208     /* deformMatricesEM */ NULL,
209     /* applyModifier */ NULL,
210
211     /* initData */ initData,
212     /* requiredDataMask */ requiredDataMask,
213     /* freeData */ NULL,
214     /* isDisabled */ isDisabled,
215     /* updateDepsgraph */ updateDepsgraph,
216     /* dependsOnTime */ NULL,
217     /* dependsOnNormals */ dependsOnNormals,
218     /* foreachObjectLink */ foreachObjectLink,
219     /* foreachIDLink */ NULL,
220     /* foreachTexLink */ NULL,
221     /* freeRuntimeData */ NULL,
222 };