Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // struct added to DNA_modifier_types.h
- typedef struct VertexSnapModifierData {
- ModifierData modifier;
- struct Object *target; /* bind target object */
- char vertex_group[64];
- int *bindings; /* This is not unsigned so that -1 can be skipped */
- int total_bindings;
- int binding_type;
- float binding_distance;
- float blend;
- int deform_space;
- int flags;
- } VertexSnapModifierData;
- enum {
- MOD_VSNAP_NEEDS_BIND = (1 << 1),
- MOD_VSNAP_NEEDS_UNBIND = (1 << 2)
- };
- enum {
- MOD_VSNAP_LOCAL = 0,
- MOD_VSNAP_WORLD = 1
- };
- enum {
- MOD_VSNAP_BIND_INDEX = 0,
- MOD_VSNAP_BIND_CLOSEST = 1,
- MOD_VSNAP_BIND_NORMAL = 2
- };
- // MOD_vertexsnap.c
- /*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 by the Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): Your name
- *
- * ***** END GPL LICENSE BLOCK *****
- *
- */
- /** \file blender/modifiers/intern/MOD_Snap.c
- * \ingroup modifiers
- */
- #include "DNA_mesh_types.h"
- #include "DNA_meshdata_types.h"
- #include "DNA_object_types.h"
- #include "BLI_math.h"
- #include "BLI_task.h"
- #include "BLI_string.h"
- #include "BLI_utildefines.h"
- #include "MEM_guardedalloc.h"
- #include "BKE_action.h"
- #include "BKE_bvhutils.h"
- #include "BKE_cdderivedmesh.h"
- #include "BKE_deform.h"
- #include "BKE_library.h"
- #include "BKE_library_query.h"
- #include "BKE_mesh.h"
- #include "BKE_particle.h"
- #include "MOD_util.h"
- #include "DEG_depsgraph_query.h"
- // #define DEBUG_TIME 1
- #include "PIL_time.h"
- #ifdef DEBUG_TIME
- #include "PIL_time_utildefines.h"
- #endif
- static void initData(ModifierData *md)
- {
- VertexSnapModifierData* vmd = (VertexSnapModifierData*) md;
- vmd->blend = 1.0f;
- vmd->target = NULL;
- vmd->vertex_group[0] = 0;
- vmd->deform_space = MOD_VSNAP_LOCAL;
- vmd->bindings = NULL;
- vmd->total_bindings = 0;
- vmd->binding_type = MOD_VSNAP_BIND_INDEX;
- vmd->binding_distance = 64.0f;
- vmd->flags = 0;
- }
- static bool isDisabled(const struct Scene *scene, ModifierData *md, bool userRenderParams)
- {
- /* disable if modifier there is no connected target object*/
- VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- if ( vmd->target ) {
- if ( vmd->target->type == OB_MESH ) {
- return false;
- }
- }
- return true;
- }
- static void requiredDataMask(Object *UNUSED(ob),
- ModifierData *md,
- CustomData_MeshMasks *r_cddata_masks)
- {
- VertexSnapModifierData* enmd = (VertexSnapModifierData*)md;
- /* Ask for vertexgroups if we need them. */
- if (enmd->vertex_group[0] != '\0') {
- r_cddata_masks->vmask |= ( CD_MASK_MDEFORMVERT );
- }
- }
- static void freeData(ModifierData *md)
- {
- VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- if (vmd->bindings && vmd->total_bindings) {
- printf("Freeing bindings...\n");
- MEM_SAFE_FREE(vmd->bindings);
- }
- vmd->total_bindings = 0;
- vmd->flags &= ~MOD_VSNAP_NEEDS_UNBIND;
- if (vmd->modifier.orig_modifier_data) {
- VertexSnapModifierData* orig_vmd = (VertexSnapModifierData*)vmd->modifier.orig_modifier_data;
- if (orig_vmd->bindings && orig_vmd->total_bindings) {
- MEM_SAFE_FREE(orig_vmd->bindings);
- }
- orig_vmd->total_bindings = 0;
- orig_vmd->flags &= ~MOD_VSNAP_NEEDS_UNBIND;
- }
- }
- static void copyData(const ModifierData *md, ModifierData *target, const int flag)
- {
- const VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- VertexSnapModifierData* target_vmd = (VertexSnapModifierData*)target;
- modifier_copyData_generic(md, target, flag);
- target_vmd->bindings = NULL;
- target_vmd->total_bindings = 0;
- // avoid a possible memory leak
- // freeData(target);
- if (vmd->bindings && vmd->total_bindings) {
- target_vmd->bindings = MEM_dupallocN(vmd->bindings);
- target_vmd->total_bindings = vmd->total_bindings;
- }
- }
- static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
- {
- VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- walk( userData, ob, &vmd->target, IDWALK_NOP );
- }
- static void updateDepsgraph(ModifierData *md,
- const ModifierUpdateDepsgraphContext *ctx)
- {
- VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- if (vmd->target != NULL) {
- DEG_add_object_relation(ctx->node, vmd->target,
- DEG_OB_COMP_GEOMETRY, "VertexSnap Modifier");
- DEG_add_object_relation(ctx->node, vmd->target,
- DEG_OB_COMP_TRANSFORM, "VertexSnap Modifier");
- }
- // make sure we're linked to our own transform
- // do we need this? Yes, we do.
- DEG_add_modifier_to_transform_relation(ctx->node, "VertexSnap Modifier");
- }
- static inline void propagate_bindings_to_original(VertexSnapModifierData* vmd) {
- if (vmd && vmd->modifier.orig_modifier_data) {
- /*
- So this is new:
- If you don't copy this information to the original modifier,
- including the rebind flag, then the original modifier never
- really gets changed and you end up in a terrible rebind loop,
- with a copy of the original "unbound + needs rebind" data
- getting passed in at certain times instead of the data you
- stuffed into a copy that no longer exists.
- */
- VertexSnapModifierData* orig_vmd = (VertexSnapModifierData*)vmd->modifier.orig_modifier_data;
- if (vmd->bindings) {
- orig_vmd->bindings = MEM_dupallocN(vmd->bindings);
- orig_vmd->total_bindings = vmd->total_bindings;
- }
- orig_vmd->flags = vmd->flags;
- }
- }
- /* binding calculations */
- static inline void calculate_closest_point_bindings(ModifierData* md, Mesh* mesh,
- Mesh* target_mesh, const float (*world_matrix)[4],
- const float (*target_inverse_matrix)[4]) {
- int index = 0;
- BVHTreeFromMesh bvh_tree = {NULL};
- BVHTreeNearest nearest = {0};
- VertexSnapModifierData* vmd = (VertexSnapModifierData*)md;
- freeData(md);
- if (!mesh) {
- // should never happen...
- modifier_setError(md, "Cannot bind-- no mesh data.");
- return;
- }
- if (!target_mesh) {
- modifier_setError(md, "Cannot bind-- no target mesh.");
- return;
- }
- vmd->bindings = (unsigned int*)MEM_mallocN(sizeof(unsigned int) * mesh->totvert, "VertexSnapModifier Bindings");
- BKE_bvhtree_from_mesh_get(&bvh_tree, target_mesh, BVHTREE_FROM_VERTS, 2);
- if (bvh_tree.tree == NULL) {
- freeData(md);
- modifier_setError((ModifierData*)md, "Out of memory");
- return;
- }
- for (index = 0; index < mesh->totvert; index++) {
- float world_coordinate[3];
- if (vmd->deform_space == MOD_VSNAP_WORLD) {
- mul_v3_m4v3(world_coordinate, world_matrix, mesh->mvert[index].co);
- mul_v3_m4v3(world_coordinate, target_inverse_matrix, world_coordinate);
- }
- else {
- copy_v3_v3(world_coordinate, mesh->mvert[index].co);
- }
- nearest.index = -1;
- nearest.dist_sq = 64.0f;
- BLI_bvhtree_find_nearest(bvh_tree.tree,
- world_coordinate,
- &nearest,
- NULL,
- &bvh_tree);
- // We're going to skip bindings whose
- // index is -1 later on.
- vmd->bindings[index] = nearest.index;
- }
- vmd->total_bindings = mesh->totvert;
- vmd->flags = 0;
- propagate_bindings_to_original(vmd);
- free_bvhtree_from_mesh(&bvh_tree);
- }
- static inline void calculate_closest_point_and_normal_bindings(ModifierData* md, Mesh* mesh, Mesh* target_mesh) {
- /*
- check out BLI_bvhtree_range_query.
- It seems to do what I want for looking
- within a radius and applies the
- callback function to each found point.
- */
- }
- typedef struct VertexSnapUserdata {
- /*const*/ VertexSnapModifierData* vmd;
- MDeformVert *dverts;
- MVert *target_mvert;
- float (*vertexCos)[3];
- float object_matrix[4][4];
- float target_matrix[4][4];
- float object_matrix_inv[4][4];
- int deform_group_index;
- } VertexSnapUserdata;
- static void VertexSnapModifier_do_task(void *__restrict userdata,
- const int iter,
- const ParallelRangeTLS *__restrict UNUSED(tls))
- {
- VertexSnapUserdata *data = (VertexSnapUserdata *)userdata;
- VertexSnapModifierData* vmd = data->vmd;
- MDeformVert *dverts = data->dverts;
- // MVert *mesh_mvert = data->mesh_mvert;
- MVert *target_mvert = data->target_mvert;
- float (*vertexCos)[3] = data->vertexCos;
- int target_index = iter;
- float blend = vmd->blend;
- const float deform_group_index = data->deform_group_index;
- if (dverts) {
- blend *= defvert_find_weight( &dverts[iter], deform_group_index);
- }
- if (!blend) {
- return;
- }
- if (vmd->binding_type != MOD_VSNAP_BIND_INDEX) {
- target_index = vmd->bindings[iter];
- if (target_index < 0) {
- // some sort of an error has happened in the bind--
- // skip this vertex
- return;
- }
- }
- if ( vmd->deform_space == MOD_VSNAP_WORLD ) {
- float object_co[3];
- float target_co[3];
- // calculate lerp in world space
- //!FIXME: This is dumb. Should calculate in object space
- mul_v3_m4v3( object_co, data->object_matrix, vertexCos[iter] );
- mul_v3_m4v3( target_co, data->target_matrix, target_mvert[target_index].co );
- interp_v3_v3v3( object_co, object_co, target_co, blend);
- // remove the world matrix of the deforming object
- // after doing the lerp
- mul_v3_m4v3( vertexCos[iter], data->object_matrix_inv, object_co );
- } else {
- interp_v3_v3v3( vertexCos[iter], vertexCos[iter], target_mvert[target_index].co, blend);
- }
- }
- static void VertexSnapModifier_do(ModifierData *md,
- const ModifierEvalContext *ctx,
- Object *ob,
- Mesh *mesh,
- float (*vertexCos)[3],
- int numVerts)
- {
- VertexSnapModifierData* vmd = (VertexSnapModifierData* )md;
- struct Object *target = vmd->target;
- MDeformVert *dverts = NULL;
- int deform_group_index = -1;
- const int vertex_count = numVerts;
- const float blend = vmd->blend;
- if ( blend == 0.0 )
- return;
- struct Mesh *target_mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(target, false);;
- if (!target_mesh) {
- modifier_setError(md, "Cannot get the target mesh object.");
- return;
- }
- if (!(target && target != ob && target->type == OB_MESH)) {
- // this shouldn't happen
- modifier_setError(md, "Target %s is not a Mesh.", target->id.name + 2);
- return;
- }
- if (vmd->binding_type == MOD_VSNAP_BIND_INDEX && vertex_count != target_mesh->totvert) {
- modifier_setError(md, "Target vertex count is %d; should be %d.",
- target_mesh->totvert, vertex_count);
- return;
- }
- invert_m4_m4( ob->imat, ob->obmat );
- invert_m4_m4( target->imat, target->obmat );
- /* bindings calculations */
- if (vmd->flags & MOD_VSNAP_NEEDS_UNBIND) {
- printf("Unbinding...\n");
- freeData(md);
- }
- // if (DEG_is_active(ctx->depsgraph)) {
- if (vmd->flags & MOD_VSNAP_NEEDS_BIND) {
- if (vmd->binding_type == MOD_VSNAP_BIND_CLOSEST) {
- calculate_closest_point_bindings(md, mesh, target_mesh, ob->obmat, target->imat);
- }
- else if (vmd->binding_type == MOD_VSNAP_BIND_NORMAL) {
- //!FIXME: Do this one
- modifier_setError(md, "Tried to rebind, but type is not Closest.");
- return;
- calculate_closest_point_and_normal_bindings(md, mesh, target_mesh);
- }
- }
- // }
- // else {
- // modifier_setError(md, "Attempt to bind from inactive dependency graph");
- // return;
- // }
- if (vmd->binding_type != MOD_VSNAP_BIND_INDEX && !vmd->bindings) {
- //##!FIXME: This shouldn't fire when it's in non-depsgraph mode
- modifier_setError(md, "Not bound.");
- return;
- }
- vmd->total_bindings = mesh->totvert;
- MOD_get_vgroup(ob, mesh, vmd->vertex_group, &dverts, &deform_group_index);
- VertexSnapUserdata data;
- data.vmd = vmd;
- data.dverts = dverts;
- copy_m4_m4(data.object_matrix, ob->obmat);
- copy_m4_m4(data.object_matrix_inv, ob->imat);
- copy_m4_m4(data.target_matrix,target->obmat);
- data.target_mvert = target_mesh->mvert;
- data.vertexCos = vertexCos;
- data.deform_group_index = deform_group_index;
- #ifdef DEBUG_TIME
- TIMEIT_START( vertex_snap_modifier );
- #endif
- ParallelRangeSettings settings;
- BLI_parallel_range_settings_defaults(&settings);
- settings.use_threading = (vertex_count > 512);
- BLI_task_parallel_range(0, vertex_count, &data, VertexSnapModifier_do_task, &settings);
- #ifdef DEBUG_TIME
- TIMEIT_END( vertex_snap_modifier );
- #endif
- }
- static void deformVerts(struct ModifierData *md,
- const struct ModifierEvalContext *ctx,
- struct Mesh *mesh,
- float (*vertexCos)[3],
- int numVerts)
- {
- Mesh *mesh_src = MOD_deform_mesh_eval_get(ctx->object, NULL, mesh,
- NULL, numVerts, false, false);
- VertexSnapModifier_do(md, ctx, ctx->object, mesh_src, vertexCos, numVerts);
- }
- static void deformVertsEM(struct ModifierData *md,
- const struct ModifierEvalContext *ctx,
- struct BMEditMesh *editData,
- struct Mesh *mesh,
- float (*vertexCos)[3],
- int numVerts)
- {
- VertexSnapModifier_do(md, ctx, ctx->object, mesh, vertexCos, numVerts);
- }
- ModifierTypeInfo modifierType_VertexSnap = {
- /* name */ "VertexSnap",
- /* structName */ "VertexSnapModifierData",
- /* structSize */ sizeof(VertexSnapModifierData),
- /* type */ eModifierTypeType_OnlyDeform,
- /* flags */ eModifierTypeFlag_AcceptsMesh |
- eModifierTypeFlag_SupportsEditmode,
- /* copyData */ copyData,
- /* deformVerts */ deformVerts,
- /* deformMatrices */ NULL,
- /* deformVertsEM */ deformVertsEM,
- /* deformMatricesEM */ NULL,
- /* applyModifier */ NULL,
- /* initData */ initData,
- /* requiredDataMask */ requiredDataMask,
- /* freeData */ freeData,
- /* isDisabled */ isDisabled,
- /* updateDepsgraph */ updateDepsgraph,
- /* dependsOnTime */ NULL,
- /* dependsOnNormals */ NULL,
- /* foreachObjectLink */ foreachObjectLink,
- /* foreachIDLink */ NULL,
- /* foreachTexLink */ NULL,
- /* freeRuntimeData */ NULL
- };
- // below was added to object_modifier.c, and properly registered.
- /************************ VertexSnap bind operator *********************/
- static bool vertexsnap_poll(bContext *C)
- {
- return true;
- // return edit_modifier_poll_generic(C, &RNA_VertexSnapModifier, 0);
- }
- static int vertexsnap_bind_exec(bContext *C, wmOperator *op)
- {
- Object *ob = ED_object_active_context(C);
- Depsgraph *depsgraph = CTX_data_depsgraph(C);
- VertexSnapModifierData *vmd = (VertexSnapModifierData *)edit_modifier_property_get(
- op, ob, eModifierType_VertexSnap);
- if (vmd == NULL) {
- return OPERATOR_CANCELLED;
- }
- VertexSnapModifierData *vmd_eval = (VertexSnapModifierData *)modifier_get_evaluated(
- depsgraph, ob, &vmd->modifier);
- if (vmd->bindings && vmd->total_bindings) {
- vmd->flags = MOD_VSNAP_NEEDS_UNBIND;
- }
- else {
- vmd->flags = MOD_VSNAP_NEEDS_BIND;
- }
- vmd_eval->flags = vmd->flags;
- object_force_modifier_bind_simple_options(depsgraph, ob, &vmd->modifier);
- vmd->flags = vmd_eval->flags = 0;
- DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
- return OPERATOR_FINISHED;
- }
- static int vertexsnap_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
- {
- if (edit_modifier_invoke_properties(C, op)) {
- return vertexsnap_bind_exec(C, op);
- }
- else {
- return OPERATOR_CANCELLED;
- }
- }
- void OBJECT_OT_vertexsnap_bind(wmOperatorType *ot)
- {
- /* identifiers */
- ot->name = "VertexSnap Bind";
- ot->description = "Bind mesh to target in VertexSnap modifier";
- ot->idname = "OBJECT_OT_vertexsnap_bind";
- /* api callbacks */
- ot->poll = vertexsnap_poll;
- ot->invoke = vertexsnap_bind_invoke;
- ot->exec = vertexsnap_bind_exec;
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
- edit_modifier_properties(ot);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement