Exemple #1
0
static void do_huecorrect(bNode *node, float *out, float *in)
{
	float hsv[3], f;
	
	rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
	
	/* adjust hue, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 0, hsv[0]);
	hsv[0] += f-0.5f;
	
	/* adjust saturation, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 1, hsv[0]);
	hsv[1] *= (f * 2.f);
	
	/* adjust value, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 2, hsv[0]);
	hsv[2] *= (f * 2.f);
	
	hsv[0] = hsv[0] - floor(hsv[0]); /* mod 1.0 */
	CLAMP(hsv[1], 0.f, 1.f);
	
	/* convert back to rgb */
	hsv_to_rgb(hsv[0], hsv[1], hsv[2], out, out+1, out+2);
	
	out[3]= in[3];
}
Exemple #2
0
static void do_huecorrect_fac(bNode *node, float *out, float *in, float *fac)
{
	float hsv[3], rgb[3], f;
	const float mfac = 1.f-*fac;
	
	rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
	
	/* adjust hue, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 0, hsv[0]);
	hsv[0] += f-0.5f;
	
	/* adjust saturation, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 1, hsv[0]);
	hsv[1] *= (f * 2.f);
	
	/* adjust value, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(node->storage, 2, hsv[0]);
	hsv[2] *= (f * 2.f);
	
	hsv[0] = hsv[0] - floor(hsv[0]);  /* mod 1.0 */
	CLAMP(hsv[1], 0.f, 1.f);
	
	/* convert back to rgb */
	hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
	
	out[0]= mfac*in[0] + *fac*rgb[0];
	out[1]= mfac*in[1] + *fac*rgb[1];
	out[2]= mfac*in[2] + *fac*rgb[2];
	out[3]= in[3];
}
void HueSaturationValueCorrectOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
{
	float hsv[4], f;

	this->m_inputProgram->readSampled(hsv, x, y, sampler);

	/* adjust hue, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(this->m_curveMapping, 0, hsv[0]);
	hsv[0] += f - 0.5f;

	/* adjust saturation, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(this->m_curveMapping, 1, hsv[0]);
	hsv[1] *= (f * 2.0f);

	/* adjust value, scaling returned default 0.5 up to 1 */
	f = curvemapping_evaluateF(this->m_curveMapping, 2, hsv[0]);
	hsv[2] *= (f * 2.0f);

	hsv[0] = hsv[0] - floorf(hsv[0]);  /* mod 1.0 */
	CLAMP(hsv[1], 0.0f, 1.0f);

	output[0] = hsv[0];
	output[1] = hsv[1];
	output[2] = hsv[2];
	output[3] = hsv[3];
}
Exemple #4
0
static void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
                                unsigned char *mask_rect, float *mask_rect_float, void *data_v)
{
	CurveMapping *curve_mapping = (CurveMapping *) data_v;
	int x, y;

	for (y = 0; y < height; y++) {
		for (x = 0; x < width; x++) {
			int pixel_index = (y * width + x) * 4;
			float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f};
			float hsv[3], f;

			if (rect_float)
				copy_v3_v3(pixel, rect_float + pixel_index);
			else
				rgb_uchar_to_float(pixel, rect + pixel_index);

			rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2);

			/* adjust hue, scaling returned default 0.5 up to 1 */
			f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]);
			hsv[0] += f - 0.5f;

			/* adjust saturation, scaling returned default 0.5 up to 1 */
			f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]);
			hsv[1] *= (f * 2.0f);

			/* adjust value, scaling returned default 0.5 up to 1 */
			f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]);
			hsv[2] *= (f * 2.f);

			hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
			CLAMP(hsv[1], 0.0f, 1.0f);

			/* convert back to rgb */
			hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2);

			if (mask_rect_float)
				copy_v3_v3(mask, mask_rect_float + pixel_index);
			else if (mask_rect)
				rgb_uchar_to_float(mask, mask_rect + pixel_index);

			result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0];
			result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1];
			result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2];

			if (rect_float)
				copy_v3_v3(rect_float + pixel_index, result);
			else
				rgb_float_to_uchar(rect + pixel_index, result);
		}
	}
}
Exemple #5
0
static PyObject *Freestyle_evaluateCurveMappingF(PyObject *self, PyObject *args)
{
	BPy_StructRNA *py_srna;
	CurveMapping *cumap;
	int cur;
	float value;

	if (!(PyArg_ParseTuple(args, "O!if", &pyrna_struct_Type, &py_srna, &cur, &value)))
		return NULL;
	if (!RNA_struct_is_a(py_srna->ptr.type, &RNA_CurveMapping)) {
		PyErr_SetString(PyExc_TypeError, "1st argument is not a CurveMapping object");
		return NULL;
	}
	if (cur < 0 || cur > 3) {
		PyErr_SetString(PyExc_ValueError, "2nd argument is out of range");
		return NULL;
	}
	cumap = (CurveMapping *)py_srna->ptr.data;
	curvemapping_initialize(cumap);
	/* disable extrapolation if enabled */
	if ((cumap->cm[cur].flag & CUMA_EXTEND_EXTRAPOLATE)) {
		cumap->cm[cur].flag &= ~(CUMA_EXTEND_EXTRAPOLATE);
		curvemapping_changed(cumap, 0);
	}
	return PyFloat_FromDouble(curvemapping_evaluateF(cumap, cur, value));
}
void TimeNode::convertToOperations(NodeConverter &converter, const CompositorContext &context) const
{
	SetValueOperation *operation = new SetValueOperation();
	bNode *node = this->getbNode();

	/* stack order output: fac */
	float fac = 0.0f;
	const int framenumber = context.getFramenumber();

	if (framenumber < node->custom1) {
		fac = 0.0f;
	}
	else if (framenumber > node->custom2) {
		fac = 1.0f;
	}
	else if (node->custom1 < node->custom2) {
		fac = (context.getFramenumber() - node->custom1) / (float)(node->custom2 - node->custom1);
	}

	curvemapping_initialize((CurveMapping *)node->storage);
	fac = curvemapping_evaluateF((CurveMapping *)node->storage, 0, fac);
	operation->setValue(clamp_f(fac, 0.0f, 1.0f));
	converter.addOperation(operation);

	converter.mapOutputSocket(getOutputSocket(0), operation->getOutputSocket());
}
void TimeNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
{
	SetValueOperation *operation = new SetValueOperation();
	this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket());
	bNode *node = this->getbNode();

	/* stack order output: fac */
	float fac = 0.0f;
	const int framenumber = context->getFramenumber();

	if (framenumber < node->custom1) {
		fac = 0.0f;
	}
	else if (framenumber > node->custom2) {
		fac = 1.0f;
	}
	else if (node->custom1 < node->custom2) {
		fac = (context->getFramenumber() - node->custom1) / (float)(node->custom2 - node->custom1);
	}

	curvemapping_initialize((CurveMapping *)node->storage);
	fac = curvemapping_evaluateF((CurveMapping *)node->storage, 0, fac);
	operation->setValue(CLAMPIS(fac, 0.0f, 1.0f));
	graph->addOperation(operation);
}
static float do_clump_level(float result[3], const float co[3], const float par_co[3], float time,
                            float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
{
	float clump = 0.0f;

	if (clumpcurve) {
		clump = pa_clump * (1.0f - clamp_f(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));

		interp_v3_v3v3(result, co, par_co, clump);
	}
	else if (clumpfac != 0.0f) {
		float cpow;

		if (clumppow < 0.0f)
			cpow = 1.0f + clumppow;
		else
			cpow = 1.0f + 9.0f * clumppow;

		if (clumpfac < 0.0f) /* clump roots instead of tips */
			clump = -clumpfac * pa_clump * (float)pow(1.0 - (double)time, (double)cpow);
		else
			clump = clumpfac * pa_clump * (float)pow((double)time, (double)cpow);

		interp_v3_v3v3(result, co, par_co, clump);
	}

	return clump;
}
Exemple #9
0
/* same as above but can return negative values if the curve enables
 * used for sculpt only */
float BKE_brush_curve_strength(Brush *br, float p, const float len)
{
	if (p >= len)
		p = 1.0f;
	else
		p = p / len;

	return curvemapping_evaluateF(br->curve, 0, p);
}
Exemple #10
0
/* Uses the brush curve control to find a strength value between 0 and 1 */
float brush_curve_strength_clamp(Brush *br, float p, const float len)
{
	if(p >= len)	return 0;
	else			p= p/len;

	p= curvemapping_evaluateF(br->curve, 0, p);
	if(p < 0.0f)		p= 0.0f;
	else if(p > 1.0f)	p= 1.0f;
	return p;
}
Exemple #11
0
/* Uses the brush curve control to find a strength value */
float BKE_brush_curve_strength(Brush *br, float p, const float len)
{
	float strength;

	if (p >= len) return 0;
	else p = p / len;

	strength = curvemapping_evaluateF(br->curve, 0, p);

	return strength;
}
Exemple #12
0
static void time_colorfn(float *out, TexParams *p, bNode *node, bNodeStack **UNUSED(in), short UNUSED(thread))
{
	/* stack order output: fac */
	float fac= 0.0f;
	
	if (node->custom1 < node->custom2)
		fac = (p->cfra - node->custom1)/(float)(node->custom2-node->custom1);
	
	fac = curvemapping_evaluateF(node->storage, 0, fac);
	out[0] = CLAMPIS(fac, 0.0f, 1.0f);
}
static void node_composit_exec_curves_time(void *data, bNode *node, bNodeStack **UNUSED(in), bNodeStack **out)
{
	RenderData *rd= data;
	/* stack order output: fac */
	float fac= 0.0f;
	
	if (node->custom1 < node->custom2)
		fac= (rd->cfra - node->custom1)/(float)(node->custom2-node->custom1);
	
	fac= curvemapping_evaluateF(node->storage, 0, fac);
	out[0]->vec[0]= CLAMPIS(fac, 0.0f, 1.0f);
}
/* Maps new_w weights in place, using either one of the predefined functions, or a custom curve.
 * Return values are in new_w.
 * If indices is not NULL, it must be a table of same length as org_w and new_w, mapping to the real
 * vertex index (in case the weight tables do not cover the whole vertices...).
 * cmap might be NULL, in which case curve mapping mode will return unmodified data.
 */
void weightvg_do_map(int num, float *new_w, short falloff_type, CurveMapping *cmap, RNG *rng)
{
	int i;

	/* Return immediately, if we have nothing to do! */
	/* Also security checks... */
	if (((falloff_type == MOD_WVG_MAPPING_CURVE) && (cmap == NULL)) ||
	    !ELEM(falloff_type, MOD_WVG_MAPPING_CURVE, MOD_WVG_MAPPING_SHARP, MOD_WVG_MAPPING_SMOOTH,
	          MOD_WVG_MAPPING_ROOT, MOD_WVG_MAPPING_SPHERE, MOD_WVG_MAPPING_RANDOM,
	          MOD_WVG_MAPPING_STEP))
	{
		return;
	}

	if (cmap && falloff_type == MOD_WVG_MAPPING_CURVE) {
		curvemapping_initialize(cmap);
	}

	/* Map each weight (vertex) to its new value, accordingly to the chosen mode. */
	for (i = 0; i < num; ++i) {
		float fac = new_w[i];

		/* Code borrowed from the warp modifier. */
		/* Closely matches PROP_SMOOTH and similar. */
		switch (falloff_type) {
			case MOD_WVG_MAPPING_CURVE:
				fac = curvemapping_evaluateF(cmap, 0, fac);
				break;
			case MOD_WVG_MAPPING_SHARP:
				fac = fac * fac;
				break;
			case MOD_WVG_MAPPING_SMOOTH:
				fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
				break;
			case MOD_WVG_MAPPING_ROOT:
				fac = sqrtf(fac);
				break;
			case MOD_WVG_MAPPING_SPHERE:
				fac = sqrtf(2 * fac - fac * fac);
				break;
			case MOD_WVG_MAPPING_RANDOM:
				fac = BLI_rng_get_float(rng) * fac;
				break;
			case MOD_WVG_MAPPING_STEP:
				fac = (fac >= 0.5f) ? 1.0f : 0.0f;
				break;
		}

		new_w[i] = fac;
	}
}
Exemple #15
0
static float curvemapping_integrate_clamped(CurveMapping *curve,
                                            float start, float end, float step)
{
	float integral = 0.0f;
	float x = start;
	while (x < end) {
		float y = curvemapping_evaluateF(curve, 0, x);
		y = clamp_f(y, 0.0f, 1.0f);
		/* TODO(sergey): Clamp last step to end. */
		integral += y * step;
		x += step;
	}
	return integral;
}
Exemple #16
0
static void accum_density(void *userdata, int index, float squared_dist)
{
	PointDensityRangeData *pdr = (PointDensityRangeData *)userdata;
	const float dist = (pdr->squared_radius - squared_dist) / pdr->squared_radius * 0.5f;
	float density = 0.0f;
	
	if (pdr->point_data_used & POINT_DATA_VEL) {
		pdr->vec[0] += pdr->point_data[index*3 + 0]; // * density;
		pdr->vec[1] += pdr->point_data[index*3 + 1]; // * density;
		pdr->vec[2] += pdr->point_data[index*3 + 2]; // * density;
	}
	if (pdr->point_data_used & POINT_DATA_LIFE) {
		*pdr->age += pdr->point_data[pdr->offset + index]; // * density;
	}
	
	if (pdr->falloff_type == TEX_PD_FALLOFF_STD)
		density = dist;
	else if (pdr->falloff_type == TEX_PD_FALLOFF_SMOOTH)
		density = 3.0f*dist*dist - 2.0f*dist*dist*dist;
	else if (pdr->falloff_type == TEX_PD_FALLOFF_SOFT)
		density = pow(dist, pdr->softness);
	else if (pdr->falloff_type == TEX_PD_FALLOFF_CONSTANT)
		density = pdr->squared_radius;
	else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT)
		density = sqrtf(dist);
	else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) {
		if (pdr->point_data_used & POINT_DATA_LIFE)
			density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f);
		else
			density = dist;
	}
	else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) {
		if (pdr->point_data_used & POINT_DATA_VEL)
			density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale;
		else
			density = dist;
	}
	
	if (pdr->density_curve && dist != 0.0f) {
		curvemapping_initialize(pdr->density_curve);
		density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist;
	}
	
	*pdr->density += density;
}
Exemple #17
0
static void do_rough_curve(const float loc[3], float mat[4][4], float time, float fac, float size, CurveMapping *roughcurve, ParticleKey *state)
{
	float rough[3];
	float rco[3];

	if (!roughcurve)
		return;

	fac *= clamp_f(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);

	copy_v3_v3(rco, loc);
	mul_v3_fl(rco, time);
	rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
	rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
	rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);

	madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
	madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
	madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
}
Exemple #18
0
/* RGB case, no black/white points, no premult */
void curvemapping_evaluateRGBF(CurveMapping *cumap, float vecout[3], const float vecin[3])
{
	vecout[0] = curvemapping_evaluateF(cumap, 0, curvemapping_evaluateF(cumap, 3, vecin[0]));
	vecout[1] = curvemapping_evaluateF(cumap, 1, curvemapping_evaluateF(cumap, 3, vecin[1]));
	vecout[2] = curvemapping_evaluateF(cumap, 2, curvemapping_evaluateF(cumap, 3, vecin[2]));
}
Exemple #19
0
/* vector case */
void curvemapping_evaluate3F(CurveMapping *cumap, float *vecout, const float *vecin)
{
	vecout[0]= curvemapping_evaluateF(cumap, 0, vecin[0]);
	vecout[1]= curvemapping_evaluateF(cumap, 1, vecin[1]);
	vecout[2]= curvemapping_evaluateF(cumap, 2, vecin[2]);
}
Exemple #20
0
static void warpModifier_do(WarpModifierData *wmd,
                            const ModifierEvalContext *ctx,
                            Mesh *mesh,
                            float (*vertexCos)[3],
                            int numVerts)
{
  Object *ob = ctx->object;
  float obinv[4][4];
  float mat_from[4][4];
  float mat_from_inv[4][4];
  float mat_to[4][4];
  float mat_unit[4][4];
  float mat_final[4][4];

  float tmat[4][4];

  const float falloff_radius_sq = SQUARE(wmd->falloff_radius);
  float strength = wmd->strength;
  float fac = 1.0f, weight;
  int i;
  int defgrp_index;
  MDeformVert *dvert, *dv = NULL;

  float(*tex_co)[3] = NULL;

  if (!(wmd->object_from && wmd->object_to)) {
    return;
  }

  MOD_get_vgroup(ob, mesh, wmd->defgrp_name, &dvert, &defgrp_index);
  if (dvert == NULL) {
    defgrp_index = -1;
  }

  if (wmd->curfalloff == NULL) { /* should never happen, but bad lib linking could cause it */
    wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
  }

  if (wmd->curfalloff) {
    curvemapping_initialize(wmd->curfalloff);
  }

  invert_m4_m4(obinv, ob->obmat);

  mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat);
  mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat);

  invert_m4_m4(tmat, mat_from);  // swap?
  mul_m4_m4m4(mat_final, tmat, mat_to);

  invert_m4_m4(mat_from_inv, mat_from);

  unit_m4(mat_unit);

  if (strength < 0.0f) {
    float loc[3];
    strength = -strength;

    /* inverted location is not useful, just use the negative */
    copy_v3_v3(loc, mat_final[3]);
    invert_m4(mat_final);
    negate_v3_v3(mat_final[3], loc);
  }
  weight = strength;

  Tex *tex_target = wmd->texture;
  if (mesh != NULL && tex_target != NULL) {
    tex_co = MEM_malloc_arrayN(numVerts, sizeof(*tex_co), "warpModifier_do tex_co");
    MOD_get_texture_coords((MappingInfoModifierData *)wmd, ctx, ob, mesh, vertexCos, tex_co);

    MOD_init_texture((MappingInfoModifierData *)wmd, ctx);
  }

  for (i = 0; i < numVerts; i++) {
    float *co = vertexCos[i];

    if (wmd->falloff_type == eWarp_Falloff_None ||
        ((fac = len_squared_v3v3(co, mat_from[3])) < falloff_radius_sq &&
         (fac = (wmd->falloff_radius - sqrtf(fac)) / wmd->falloff_radius))) {
      /* skip if no vert group found */
      if (defgrp_index != -1) {
        dv = &dvert[i];
        weight = defvert_find_weight(dv, defgrp_index) * strength;
        if (weight <= 0.0f) {
          continue;
        }
      }

      /* closely match PROP_SMOOTH and similar */
      switch (wmd->falloff_type) {
        case eWarp_Falloff_None:
          fac = 1.0f;
          break;
        case eWarp_Falloff_Curve:
          fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac);
          break;
        case eWarp_Falloff_Sharp:
          fac = fac * fac;
          break;
        case eWarp_Falloff_Smooth:
          fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
          break;
        case eWarp_Falloff_Root:
          fac = sqrtf(fac);
          break;
        case eWarp_Falloff_Linear:
          /* pass */
          break;
        case eWarp_Falloff_Const:
          fac = 1.0f;
          break;
        case eWarp_Falloff_Sphere:
          fac = sqrtf(2 * fac - fac * fac);
          break;
        case eWarp_Falloff_InvSquare:
          fac = fac * (2.0f - fac);
          break;
      }

      fac *= weight;

      if (tex_co) {
        struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph);
        TexResult texres;
        texres.nor = NULL;
        BKE_texture_get_value(scene, tex_target, tex_co[i], &texres, false);
        fac *= texres.tin;
      }

      if (fac != 0.0f) {
        /* into the 'from' objects space */
        mul_m4_v3(mat_from_inv, co);

        if (fac == 1.0f) {
          mul_m4_v3(mat_final, co);
        }
        else {
          if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
            /* interpolate the matrix for nicer locations */
            blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
            mul_m4_v3(tmat, co);
          }
          else {
            float tvec[3];
            mul_v3_m4v3(tvec, mat_final, co);
            interp_v3_v3v3(co, co, tvec, fac);
          }
        }

        /* out of the 'from' objects space */
        mul_m4_v3(mat_from, co);
      }
    }
  }

  if (tex_co) {
    MEM_freeN(tex_co);
  }
}
Exemple #21
0
static void warpModifier_do(WarpModifierData *wmd, Object *ob,
                            DerivedMesh *dm, float (*vertexCos)[3], int numVerts)
{
	float obinv[4][4];
	float mat_from[4][4];
	float mat_from_inv[4][4];
	float mat_to[4][4];
	float mat_unit[4][4];
	float mat_final[4][4];

	float tmat[4][4];

	float strength = wmd->strength;
	float fac = 1.0f, weight;
	int i;
	int defgrp_index;
	MDeformVert *dvert, *dv = NULL;

	float (*tex_co)[3] = NULL;

	if (!(wmd->object_from && wmd->object_to))
		return;

	modifier_get_vgroup(ob, dm, wmd->defgrp_name, &dvert, &defgrp_index);

	if (wmd->curfalloff == NULL) /* should never happen, but bad lib linking could cause it */
		wmd->curfalloff = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);

	if (wmd->curfalloff) {
		curvemapping_initialize(wmd->curfalloff);
	}

	invert_m4_m4(obinv, ob->obmat);

	mul_m4_m4m4(mat_from, obinv, wmd->object_from->obmat);
	mul_m4_m4m4(mat_to, obinv, wmd->object_to->obmat);

	invert_m4_m4(tmat, mat_from); // swap?
	mul_m4_m4m4(mat_final, tmat, mat_to);

	invert_m4_m4(mat_from_inv, mat_from);

	unit_m4(mat_unit);

	if (strength < 0.0f) {
		float loc[3];
		strength = -strength;

		/* inverted location is not useful, just use the negative */
		copy_v3_v3(loc, mat_final[3]);
		invert_m4(mat_final);
		negate_v3_v3(mat_final[3], loc);

	}
	weight = strength;

	if (wmd->texture) {
		tex_co = MEM_mallocN(sizeof(*tex_co) * numVerts, "warpModifier_do tex_co");
		get_texture_coords((MappingInfoModifierData *)wmd, ob, dm, vertexCos, tex_co, numVerts);

		modifier_init_texture(wmd->modifier.scene, wmd->texture);
	}

	for (i = 0; i < numVerts; i++) {
		float *co = vertexCos[i];

		if (wmd->falloff_type == eWarp_Falloff_None ||
		    ((fac = len_v3v3(co, mat_from[3])) < wmd->falloff_radius &&
		     (fac = (wmd->falloff_radius - fac) / wmd->falloff_radius)))
		{
			/* skip if no vert group found */
			if (dvert && defgrp_index != -1) {
				dv = &dvert[i];

				if (dv) {
					weight = defvert_find_weight(dv, defgrp_index) * strength;
					if (weight <= 0.0f) /* Should never occure... */
						continue;
				}
			}


			/* closely match PROP_SMOOTH and similar */
			switch (wmd->falloff_type) {
				case eWarp_Falloff_None:
					fac = 1.0f;
					break;
				case eWarp_Falloff_Curve:
					fac = curvemapping_evaluateF(wmd->curfalloff, 0, fac);
					break;
				case eWarp_Falloff_Sharp:
					fac = fac * fac;
					break;
				case eWarp_Falloff_Smooth:
					fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
					break;
				case eWarp_Falloff_Root:
					fac = (float)sqrt(fac);
					break;
				case eWarp_Falloff_Linear:
					/* pass */
					break;
				case eWarp_Falloff_Const:
					fac = 1.0f;
					break;
				case eWarp_Falloff_Sphere:
					fac = (float)sqrt(2 * fac - fac * fac);
					break;
			}

			fac *= weight;

			if (tex_co) {
				TexResult texres;
				texres.nor = NULL;
				get_texture_value(wmd->modifier.scene, wmd->texture, tex_co[i], &texres, false);
				fac *= texres.tin;
			}

			/* into the 'from' objects space */
			mul_m4_v3(mat_from_inv, co);

			if (fac >= 1.0f) {
				mul_m4_v3(mat_final, co);
			}
			else if (fac > 0.0f) {
				if (wmd->flag & MOD_WARP_VOLUME_PRESERVE) {
					/* interpolate the matrix for nicer locations */
					blend_m4_m4m4(tmat, mat_unit, mat_final, fac);
					mul_m4_v3(tmat, co);
				}
				else {
					float tvec[3];
					mul_v3_m4v3(tvec, mat_final, co);
					interp_v3_v3v3(co, co, tvec, fac);
				}
			}

			/* out of the 'from' objects space */
			mul_m4_v3(mat_from, co);
		}
	}

	if (tex_co)
		MEM_freeN(tex_co);

}
static float hook_falloff(
        const struct HookData_cb *hd,
        const float len_sq)
{
	BLI_assert(hd->falloff_sq);
	if (len_sq > hd->falloff_sq) {
		return 0.0f;
	}
	else if (len_sq > 0.0f) {
		float fac;

		if (hd->falloff_type == eHook_Falloff_Const) {
			fac = 1.0f;
			goto finally;
		}
		else if (hd->falloff_type == eHook_Falloff_InvSquare) {
			/* avoid sqrt below */
			fac = 1.0f - (len_sq / hd->falloff_sq);
			goto finally;
		}

		fac = 1.0f - (sqrtf(len_sq) / hd->falloff);

		/* closely match PROP_SMOOTH and similar */
		switch (hd->falloff_type) {
#if 0
			case eHook_Falloff_None:
				fac = 1.0f;
				break;
#endif
			case eHook_Falloff_Curve:
				fac = curvemapping_evaluateF(hd->curfalloff, 0, fac);
				break;
			case eHook_Falloff_Sharp:
				fac = fac * fac;
				break;
			case eHook_Falloff_Smooth:
				fac = 3.0f * fac * fac - 2.0f * fac * fac * fac;
				break;
			case eHook_Falloff_Root:
				fac = sqrtf(fac);
				break;
			case eHook_Falloff_Linear:
				/* pass */
				break;
#if 0
			case eHook_Falloff_Const:
				fac = 1.0f;
				break;
#endif
			case eHook_Falloff_Sphere:
				fac = sqrtf(2 * fac - fac * fac);
				break;
#if 0
			case eHook_Falloff_InvSquare:
				fac = fac * (2.0f - fac);
				break;
#endif
		}

finally:
		return fac * hd->fac_orig;
	}
	else {
		return hd->fac_orig;
	}
}