static void hook_co_apply(struct HookData_cb *hd, const int j)
{
	float *co = hd->vertexCos[j];
	float fac;

	if (hd->use_falloff) {
		float len_sq;

		if (hd->use_uniform) {
			float co_uniform[3];
			mul_v3_m3v3(co_uniform, hd->mat_uniform, co);
			len_sq = len_squared_v3v3(hd->cent, co_uniform);
		}
		else {
			len_sq = len_squared_v3v3(hd->cent, co);
		}

		fac = hook_falloff(hd, len_sq);
	}
	else {
		fac = hd->fac_orig;
	}

	if (fac) {
		if (hd->dvert) {
			fac *= defvert_find_weight(&hd->dvert[j], hd->defgrp_index);
		}

		if (fac) {
			float co_tmp[3];
			mul_v3_m4v3(co_tmp, hd->mat, co);
			interp_v3_v3v3(co, co, co_tmp, fac);
		}
	}
}
Beispiel #2
0
static void deformVerts(ModifierData *md, Object *ob,
						DerivedMesh *dm,
						float (*vertexCos)[3],
						int numVerts,
						int UNUSED(useRenderParams),
						int UNUSED(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, *index_pt;
	const float falloff_squared= hmd->falloff * hmd->falloff; /* for faster comparisons */
	
	int max_dvert= 0;
	MDeformVert *dvert= NULL;
	int defgrp_index = -1;
	
	/* 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);

	if((defgrp_index= defgroup_name_index(ob, hmd->name)) != -1) {
		Mesh *me = ob->data;
		if(dm) {
			dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT);
			if(dvert) {
				max_dvert = numVerts;
			}
		}
		else if(me->dvert) {
			dvert= me->dvert;
			if(dvert) {
				max_dvert = me->totvert;
			}
		}
	}

	/* Regarding index range checking below.
	 *
	 * 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(hmd->force == 0.0f) {
		/* do nothing, avoid annoying checks in the loop */
	}
	else if(hmd->indexar) { /* vertex indices? */
		const float fac_orig= hmd->force;
		float fac;
		const int *origindex_ar;

		/* if DerivedMesh is present and has original index data,
		* use it
		*/
		if(dm && (origindex_ar= dm->getVertDataArray(dm, CD_ORIGINDEX))) {
			for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) {
				if(*index_pt < numVerts) {
					int j;

					for(j = 0; j < numVerts; j++) {
						if(origindex_ar[j] == *index_pt) {
							float *co = vertexCos[j];
							if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
								if(dvert)
									fac *= defvert_find_weight(dvert+j, defgrp_index);

								if(fac) {
									mul_v3_m4v3(vec, mat, co);
									interp_v3_v3v3(co, co, vec, fac);
								}
							}
						}
					}
				}
			}
		}
		else { /* missing dm or ORIGINDEX */
			for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) {
				if(*index_pt < numVerts) {
					float *co = vertexCos[*index_pt];
					if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
						if(dvert)
							fac *= defvert_find_weight(dvert+(*index_pt), defgrp_index);

						if(fac) {
							mul_v3_m4v3(vec, mat, co);
							interp_v3_v3v3(co, co, vec, fac);
						}
					}
				}
			}
		}
	}
	else if(dvert) {	/* vertex group hook */
		int i;
		const float fac_orig= hmd->force;

		for(i = 0; i < max_dvert; i++, dvert++) {
			float fac;
			float *co = vertexCos[i];

			if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) {
				fac *= defvert_find_weight(dvert, defgrp_index);
				if(fac) {
					mul_v3_m4v3(vec, mat, co);
					interp_v3_v3v3(co, co, vec, fac);
				}
			}
		}
	}
}