/* 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], prev_co[3], fac; float *co = BM_ELEM_CD_GET_VOID_P(v, params->shape_info.cd_vert_shape_offset_tmp); int i; BM_vert_normal_update_all(v); 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)); 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, prev_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(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); } } }