2010-04-11 22:12:30 +00:00
|
|
|
/*
|
2010-04-11 23:20:03 +00:00
|
|
|
* $Id$
|
2010-04-11 22:12:30 +00:00
|
|
|
*
|
|
|
|
* ***** 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): Daniel Dunbar
|
|
|
|
* Ton Roosendaal,
|
|
|
|
* Ben Batt,
|
|
|
|
* Brecht Van Lommel,
|
|
|
|
* Campbell Barton
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-04-12 00:36:50 +00:00
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
2010-04-11 22:12:30 +00:00
|
|
|
|
2010-04-12 22:33:43 +00:00
|
|
|
#include "BLI_math.h"
|
2010-04-11 22:12:30 +00:00
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_cdderivedmesh.h"
|
|
|
|
#include "BKE_modifier.h"
|
|
|
|
#include "BKE_deform.h"
|
|
|
|
|
2010-04-12 22:33:43 +00:00
|
|
|
#include "depsgraph_private.h"
|
|
|
|
#include "MEM_guardedalloc.h"
|
2010-04-11 22:12:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void initData(ModifierData *md)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
hmd->force= 1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void copyData(ModifierData *md, ModifierData *target)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
HookModifierData *thmd = (HookModifierData*) target;
|
|
|
|
|
2010-04-12 00:36:50 +00:00
|
|
|
copy_v3_v3(thmd->cent, hmd->cent);
|
2010-04-11 22:12:30 +00:00
|
|
|
thmd->falloff = hmd->falloff;
|
|
|
|
thmd->force = hmd->force;
|
|
|
|
thmd->object = hmd->object;
|
|
|
|
thmd->totindex = hmd->totindex;
|
|
|
|
thmd->indexar = MEM_dupallocN(hmd->indexar);
|
|
|
|
memcpy(thmd->parentinv, hmd->parentinv, sizeof(hmd->parentinv));
|
|
|
|
strncpy(thmd->name, hmd->name, 32);
|
|
|
|
strncpy(thmd->subtarget, hmd->subtarget, 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
static CustomDataMask requiredDataMask(Object *ob, ModifierData *md)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData *)md;
|
|
|
|
CustomDataMask dataMask = 0;
|
|
|
|
|
|
|
|
/* ask for vertexgroups if we need them */
|
|
|
|
if(!hmd->indexar && hmd->name[0]) dataMask |= (1 << CD_MDEFORMVERT);
|
|
|
|
|
|
|
|
return dataMask;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void freeData(ModifierData *md)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
if (hmd->indexar) MEM_freeN(hmd->indexar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int isDisabled(ModifierData *md, int useRenderParams)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
return !hmd->object;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void foreachObjectLink(
|
|
|
|
ModifierData *md, Object *ob,
|
|
|
|
void (*walk)(void *userData, Object *ob, Object **obpoin),
|
|
|
|
void *userData)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
walk(userData, ob, &hmd->object);
|
|
|
|
}
|
|
|
|
|
2010-04-12 00:36:50 +00:00
|
|
|
static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *scene,
|
2010-04-11 22:12:30 +00:00
|
|
|
Object *ob, DagNode *obNode)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
|
|
|
|
if (hmd->object) {
|
|
|
|
DagNode *curNode = dag_get_node(forest, hmd->object);
|
|
|
|
|
|
|
|
if (hmd->subtarget[0])
|
|
|
|
dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA|DAG_RL_DATA_DATA, "Hook Modifier");
|
|
|
|
else
|
|
|
|
dag_add_relation(forest, curNode, obNode, DAG_RL_OB_DATA, "Hook Modifier");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void deformVerts(
|
|
|
|
ModifierData *md, Object *ob, DerivedMesh *derivedData,
|
|
|
|
float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
|
|
|
|
{
|
|
|
|
HookModifierData *hmd = (HookModifierData*) md;
|
|
|
|
bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget);
|
|
|
|
float vec[3], mat[4][4], dmat[4][4];
|
|
|
|
int i;
|
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
/* get world-space matrix of target, corrected for the space the verts are in */
|
|
|
|
if (hmd->subtarget[0] && pchan) {
|
|
|
|
/* bone target if there's a matching pose-channel */
|
|
|
|
mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* just object target */
|
|
|
|
copy_m4_m4(dmat, hmd->object->obmat);
|
|
|
|
}
|
|
|
|
invert_m4_m4(ob->imat, ob->obmat);
|
|
|
|
mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv,
|
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
/* vertex indices? */
|
|
|
|
if(hmd->indexar) {
|
|
|
|
for(i = 0; i < hmd->totindex; i++) {
|
|
|
|
int index = hmd->indexar[i];
|
|
|
|
|
|
|
|
/* This should always be true and I don't generally like
|
|
|
|
* "paranoid" style code like this, but old files can have
|
|
|
|
* indices that are out of range because old blender did
|
|
|
|
* not correct them on exit editmode. - zr
|
|
|
|
*/
|
|
|
|
if(index < numVerts) {
|
|
|
|
float *co = vertexCos[index];
|
|
|
|
float fac = hmd->force;
|
|
|
|
|
|
|
|
/* if DerivedMesh is present and has original index data,
|
|
|
|
* use it
|
|
|
|
*/
|
|
|
|
if(dm && dm->getVertDataArray(dm, CD_ORIGINDEX)) {
|
|
|
|
int j;
|
|
|
|
int orig_index;
|
|
|
|
for(j = 0; j < numVerts; ++j) {
|
|
|
|
fac = hmd->force;
|
|
|
|
orig_index = *(int *)dm->getVertData(dm, j,
|
|
|
|
CD_ORIGINDEX);
|
|
|
|
if(orig_index == index) {
|
|
|
|
co = vertexCos[j];
|
|
|
|
if(hmd->falloff != 0.0) {
|
|
|
|
float len = len_v3v3(co, hmd->cent);
|
|
|
|
if(len > hmd->falloff) fac = 0.0;
|
|
|
|
else if(len > 0.0)
|
|
|
|
fac *= sqrt(1.0 - len / hmd->falloff);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fac != 0.0) {
|
|
|
|
mul_v3_m4v3(vec, mat, co);
|
|
|
|
interp_v3_v3v3(co, co, vec, fac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if(hmd->falloff != 0.0) {
|
|
|
|
float len = len_v3v3(co, hmd->cent);
|
|
|
|
if(len > hmd->falloff) fac = 0.0;
|
|
|
|
else if(len > 0.0)
|
|
|
|
fac *= sqrt(1.0 - len / hmd->falloff);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fac != 0.0) {
|
|
|
|
mul_v3_m4v3(vec, mat, co);
|
|
|
|
interp_v3_v3v3(co, co, vec, fac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(hmd->name[0]) { /* vertex group hook */
|
|
|
|
Mesh *me = ob->data;
|
|
|
|
int use_dverts = 0;
|
|
|
|
int maxVerts = 0;
|
|
|
|
int defgrp_index = defgroup_name_index(ob, hmd->name);
|
|
|
|
|
|
|
|
if(dm) {
|
|
|
|
if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) {
|
|
|
|
maxVerts = dm->getNumVerts(dm);
|
|
|
|
use_dverts = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(me->dvert) {
|
|
|
|
maxVerts = me->totvert;
|
|
|
|
use_dverts = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(defgrp_index >= 0 && use_dverts) {
|
|
|
|
MDeformVert *dvert = me->dvert;
|
2010-06-13 00:11:42 +00:00
|
|
|
int i;
|
|
|
|
float fac;
|
2010-04-11 22:12:30 +00:00
|
|
|
|
|
|
|
for(i = 0; i < maxVerts; i++, dvert++) {
|
|
|
|
if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
|
|
|
|
|
2010-06-13 00:11:42 +00:00
|
|
|
fac= defvert_find_weight(dvert, defgrp_index);
|
|
|
|
|
|
|
|
if(fac > 0.0f) {
|
|
|
|
float *co = vertexCos[i];
|
|
|
|
|
|
|
|
if(hmd->falloff != 0.0) {
|
|
|
|
float len = len_v3v3(co, hmd->cent);
|
|
|
|
if(len > hmd->falloff) fac = 0.0;
|
|
|
|
else if(len > 0.0)
|
|
|
|
fac *= sqrt(1.0 - len / hmd->falloff);
|
2010-04-11 22:12:30 +00:00
|
|
|
}
|
2010-06-13 00:11:42 +00:00
|
|
|
|
|
|
|
mul_v3_m4v3(vec, mat, co);
|
|
|
|
interp_v3_v3v3(co, co, vec, fac);
|
2010-04-11 22:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void deformVertsEM(
|
2010-04-12 00:36:50 +00:00
|
|
|
ModifierData *md, Object *ob, struct EditMesh *editData,
|
2010-04-11 22:12:30 +00:00
|
|
|
DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
|
|
|
|
{
|
|
|
|
DerivedMesh *dm = derivedData;
|
|
|
|
|
|
|
|
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
|
|
|
|
|
|
|
|
deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
|
|
|
|
|
|
|
|
if(!derivedData) dm->release(dm);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ModifierTypeInfo modifierType_Hook = {
|
|
|
|
/* name */ "Hook",
|
|
|
|
/* structName */ "HookModifierData",
|
|
|
|
/* structSize */ sizeof(HookModifierData),
|
|
|
|
/* type */ eModifierTypeType_OnlyDeform,
|
|
|
|
/* flags */ eModifierTypeFlag_AcceptsCVs
|
|
|
|
| eModifierTypeFlag_SupportsEditmode,
|
|
|
|
/* copyData */ copyData,
|
|
|
|
/* deformVerts */ deformVerts,
|
|
|
|
/* deformVertsEM */ deformVertsEM,
|
|
|
|
/* deformMatricesEM */ 0,
|
|
|
|
/* applyModifier */ 0,
|
|
|
|
/* applyModifierEM */ 0,
|
|
|
|
/* initData */ initData,
|
|
|
|
/* requiredDataMask */ requiredDataMask,
|
|
|
|
/* freeData */ freeData,
|
|
|
|
/* isDisabled */ isDisabled,
|
|
|
|
/* updateDepgraph */ updateDepgraph,
|
|
|
|
/* dependsOnTime */ 0,
|
|
|
|
/* foreachObjectLink */ foreachObjectLink,
|
|
|
|
/* foreachIDLink */ 0,
|
|
|
|
};
|