void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]) { float rot[3][3]; /* rotation between segments */ rotation_between_vecs_to_mat3(rot, dir_old, dir_new); /* rotate the frame */ mul_m3_m3m3(mat, rot, mat); }
void applyProject(TransInfo *t) { /* XXX FLICKER IN OBJECT MODE */ if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { TransData *td = t->data; float tvec[3]; float imat[4][4]; int i; if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; invert_m4_m4(imat, ob->obmat); } for (i = 0; i < t->total; i++, td++) { float iloc[3], loc[3], no[3]; float mval_fl[2]; float dist_px = TRANSFORM_DIST_MAX_PX; if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) continue; copy_v3_v3(iloc, td->loc); if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; mul_m4_v3(ob->obmat, iloc); } else if (t->flag & T_OBJECT) { /* TODO(sergey): Ideally force update is not needed here. */ td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; BKE_object_handle_update(G.main->eval_ctx, t->scene, td->ob); copy_v3_v3(iloc, td->ob->obmat[3]); } if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { if (snapObjectsTransform( t, mval_fl, &dist_px, loc, no)) { // if (t->flag & (T_EDIT|T_POSE)) { // mul_m4_v3(imat, loc); // } sub_v3_v3v3(tvec, loc, iloc); mul_m3_v3(td->smtx, tvec); add_v3_v3(td->loc, tvec); if (t->tsnap.align && (t->flag & T_OBJECT)) { /* handle alignment as well */ const float *original_normal; float mat[3][3]; /* In pose mode, we want to align normals with Y axis of bones... */ original_normal = td->axismtx[2]; rotation_between_vecs_to_mat3(mat, original_normal, no); transform_data_ext_rotate(td, mat, true); /* TODO support constraints for rotation too? see ElementRotation */ } } } //XXX constraintTransLim(t, td); } } }