/* 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); } } }
/* 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); } } }