Esempio n. 1
0
/* calculates offset for co, based on fractal, sphere or smooth settings  */
static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
                     BMVert *vsta, BMVert *vend)
{
	float tvec[3], prev_co[3], fac;
	float *co = NULL;
	int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
	
	BM_vert_normal_update_all(v);

	co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey);
	copy_v3_v3(co, v->co);
	copy_v3_v3(prev_co, co);

	if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
		normalize_v3(co);
		mul_v3_fl(co, params->smooth);
	}
	else if (params->use_smooth) {
		/* we calculate an offset vector vec1[], to be added to *co */
		float len, nor[3], nor1[3], nor2[3], val;

		sub_v3_v3v3(nor, vsta->co, vend->co);
		len = 0.5f * normalize_v3(nor);

		copy_v3_v3(nor1, vsta->no);
		copy_v3_v3(nor2, vend->no);

		/* cosine angle */
		fac = dot_v3v3(nor, nor1);
		mul_v3_v3fl(tvec, nor1, fac);

		/* cosine angle */
		fac = -dot_v3v3(nor, nor2);
		madd_v3_v3fl(tvec, nor2, fac);

		/* falloff for multi subdivide */
		val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));

		switch (params->smooth_falloff) {
			case SUBD_FALLOFF_SMOOTH:
				val = 3.0f * val * val - 2.0f * val * val * val;
				break;
			case SUBD_FALLOFF_SPHERE:
				val = sqrtf(2.0f * val - val * val);
				break;
			case SUBD_FALLOFF_ROOT:
				val = sqrtf(val);
				break;
			case SUBD_FALLOFF_SHARP:
				val = val * val;
				break;
			case SUBD_FALLOFF_LIN:
				break;
			default:
				BLI_assert(0);
		}

		mul_v3_fl(tvec, params->smooth * val * len);

		add_v3_v3(co, tvec);
	}

	if (params->use_fractal) {
		float len = len_v3v3(vsta->co, vend->co);
		float normal[3] = {0.0f, 0.0f, 0.0f}, co2[3], base1[3], base2[3];

		fac = params->fractal * len;

		mid_v3_v3v3(normal, vsta->no, vend->no);
		ortho_basis_v3v3_v3(base1, base2, normal);

		add_v3_v3v3(co2, v->co, params->fractal_ofs);
		mul_v3_fl(co2, 10.0f);

		tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
		tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
		tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);

		/* add displacement */
		madd_v3_v3fl(co, normal, tvec[0]);
		madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
		madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
	}

	/* apply the new difference to the rest of the shape keys,
	 * note that this doesn't take rotations into account, we _could_ support
	 * this by getting the normals and coords for each shape key and
	 * re-calculate the smooth value for each but this is quite involved.
	 * for now its ok to simply apply the difference IMHO - campbell */
	sub_v3_v3v3(tvec, prev_co, co);

	for (i = 0; i < totlayer; i++) {
		if (params->origkey != i) {
			co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
			sub_v3_v3(co, tvec);
		}
	}

}
Esempio n. 2
0
/* calculates offset for co, based on fractal, sphere or smooth settings  */
static void alter_co(BMVert *v, BMEdge *UNUSED(origed), const SubDParams *params, float perc,
                     BMVert *vsta, BMVert *vend)
{
	float tvec[3], fac;
	float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
	int i;

	copy_v3_v3(co, v->co);

	if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
		normalize_v3(co);
		mul_v3_fl(co, params->smooth);
	}
	else if (params->use_smooth) {
		/* we calculate an offset vector vec1[], to be added to *co */
		float len, nor[3], nor1[3], nor2[3], val;

		sub_v3_v3v3(nor, vsta->co, vend->co);
		len = 0.5f * normalize_v3(nor);

		copy_v3_v3(nor1, vsta->no);
		copy_v3_v3(nor2, vend->no);

		/* cosine angle */
		fac = dot_v3v3(nor, nor1);
		mul_v3_v3fl(tvec, nor1, fac);

		/* cosine angle */
		fac = -dot_v3v3(nor, nor2);
		madd_v3_v3fl(tvec, nor2, fac);

		/* falloff for multi subdivide */
		val = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
		val = bmesh_subd_falloff_calc(params->smooth_falloff, val);

		if (params->use_smooth_even) {
			val *= BM_vert_calc_shell_factor(v);
		}

		mul_v3_fl(tvec, params->smooth * val * len);

		add_v3_v3(co, tvec);
	}

	if (params->use_fractal) {
		const float len = len_v3v3(vsta->co, vend->co);
		float normal[3], co2[3], base1[3], base2[3];

		fac = params->fractal * len;

		mid_v3_v3v3(normal, vsta->no, vend->no);
		ortho_basis_v3v3_v3(base1, base2, normal);

		add_v3_v3v3(co2, v->co, params->fractal_ofs);
		mul_v3_fl(co2, 10.0f);

		tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
		tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
		tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);

		/* add displacement */
		madd_v3_v3fl(co, normal, tvec[0]);
		madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
		madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
	}

	/* apply the new difference to the rest of the shape keys,
	 * note that this doesn't take rotations into account, we _could_ support
	 * this by getting the normals and coords for each shape key and
	 * re-calculate the smooth value for each but this is quite involved.
	 * for now its ok to simply apply the difference IMHO - campbell */
	sub_v3_v3v3(tvec, v->co, co);

	if (params->shape_info.totlayer > 1) {
		/* skip the last layer since its the temp */
		i = params->shape_info.totlayer - 1;
		co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
		while (i--) {
			BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
			sub_v3_v3(co += 3, tvec);
		}
	}
}
/* calculates offset for co, based on fractal, sphere or smooth settings  */
static void alter_co(
        BMVert *v, BMEdge *UNUSED(e_orig),
        const SubDParams *params, const float perc,
        const BMVert *v_a, const BMVert *v_b)
{
	float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp);
	int i;

	copy_v3_v3(co, v->co);

	if (UNLIKELY(params->use_sphere)) { /* subdivide sphere */
		normalize_v3(co);
		mul_v3_fl(co, params->smooth);
	}
	else if (params->use_smooth) {
		/* calculating twice and blending gives smoother results,
		 * removing visible seams. */
#define USE_SPHERE_DUAL_BLEND

		const float eps_unit_vec = 1e-5f;
		float smooth;
		float no_dir[3];

#ifdef USE_SPHERE_DUAL_BLEND
		float no_reflect[3], co_a[3], co_b[3];
#endif

		sub_v3_v3v3(no_dir, v_a->co, v_b->co);
		normalize_v3(no_dir);

#ifndef USE_SPHERE_DUAL_BLEND
		if (len_squared_v3v3(v_a->no, v_b->no) < eps_unit_vec) {
			interp_v3_v3v3(co, v_a->co, v_b->co, perc);
		}
		else {
			interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, v_b->no, no_dir, perc, co);
		}
#else
		/* sphere-a */
		reflect_v3_v3v3(no_reflect, v_a->no, no_dir);
		if (len_squared_v3v3(v_a->no, no_reflect) < eps_unit_vec) {
			interp_v3_v3v3(co_a, v_a->co, v_b->co, perc);
		}
		else {
			interp_slerp_co_no_v3(v_a->co, v_a->no, v_b->co, no_reflect, no_dir, perc, co_a);
		}

		/* sphere-b */
		reflect_v3_v3v3(no_reflect, v_b->no, no_dir);
		if (len_squared_v3v3(v_b->no, no_reflect) < eps_unit_vec) {
			interp_v3_v3v3(co_b, v_a->co, v_b->co, perc);
		}
		else {
			interp_slerp_co_no_v3(v_a->co, no_reflect, v_b->co, v_b->no, no_dir, perc, co_b);
		}

		/* blend both spheres */
		interp_v3_v3v3(co, co_a, co_b, perc);
#endif  /* USE_SPHERE_DUAL_BLEND */

		/* apply falloff */
		if (params->smooth_falloff == SUBD_FALLOFF_LIN) {
			smooth = 1.0f;
		}
		else {
			smooth = fabsf(1.0f - 2.0f * fabsf(0.5f - perc));
			smooth = 1.0f + bmesh_subd_falloff_calc(params->smooth_falloff, smooth);
		}

		if (params->use_smooth_even) {
			smooth *= shell_v3v3_mid_normalized_to_dist(v_a->no, v_b->no);
		}

		smooth *= params->smooth;
		if (smooth != 1.0f) {
			float co_flat[3];
			interp_v3_v3v3(co_flat, v_a->co, v_b->co, perc);
			interp_v3_v3v3(co, co_flat, co, smooth);
		}

#undef USE_SPHERE_DUAL_BLEND
	}

	if (params->use_fractal) {
		float normal[3], co2[3], base1[3], base2[3], tvec[3];
		const float len = len_v3v3(v_a->co, v_b->co);
		float fac;

		fac = params->fractal * len;

		mid_v3_v3v3(normal, v_a->no, v_b->no);
		ortho_basis_v3v3_v3(base1, base2, normal);

		add_v3_v3v3(co2, v->co, params->fractal_ofs);
		mul_v3_fl(co2, 10.0f);

		tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f);
		tvec[1] = fac * (BLI_gTurbulence(1.0, co2[1], co2[0], co2[2], 15, 0, 2) - 0.5f);
		tvec[2] = fac * (BLI_gTurbulence(1.0, co2[1], co2[2], co2[0], 15, 0, 2) - 0.5f);

		/* add displacement */
		madd_v3_v3fl(co, normal, tvec[0]);
		madd_v3_v3fl(co, base1, tvec[1] * (1.0f - params->along_normal));
		madd_v3_v3fl(co, base2, tvec[2] * (1.0f - params->along_normal));
	}

	/* apply the new difference to the rest of the shape keys,
	 * note that this doesn't take rotations into account, we _could_ support
	 * this by getting the normals and coords for each shape key and
	 * re-calculate the smooth value for each but this is quite involved.
	 * for now its ok to simply apply the difference IMHO - campbell */

	if (params->shape_info.totlayer > 1) {
		float tvec[3];

		sub_v3_v3v3(tvec, v->co, co);

		/* skip the last layer since its the temp */
		i = params->shape_info.totlayer - 1;
		co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset);
		while (i--) {
			BLI_assert(co != BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp));
			sub_v3_v3(co += 3, tvec);
		}
	}
}