static void applyObjectConstraintVec(TransInfo *t, TransDataContainer *tc, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (t->con.mode & CON_APPLY) { if (!td) { mul_m3_v3(t->con.pmtx, out); const int dims = getConstraintSpaceDimension(t); if (dims == 2) { if (!is_zero_v3(out)) { if (!isPlaneProjectionViewAligned(t)) { planeProjection(t, in, out); } } } else if (dims == 1) { float c[3]; if (t->con.mode & CON_AXIS0) { copy_v3_v3(c, t->con.mtx[0]); } else if (t->con.mode & CON_AXIS1) { copy_v3_v3(c, t->con.mtx[1]); } else if (t->con.mode & CON_AXIS2) { copy_v3_v3(c, t->con.mtx[2]); } axisProjection(t, c, in, out); } postConstraintChecks(t, out, pvec); copy_v3_v3(out, pvec); } else { int i = 0; out[0] = out[1] = out[2] = 0.0f; if (t->con.mode & CON_AXIS0) { out[0] = in[i++]; } if (t->con.mode & CON_AXIS1) { out[1] = in[i++]; } if (t->con.mode & CON_AXIS2) { out[2] = in[i++]; } mul_m3_v3(td->axismtx, out); if (t->flag & T_EDIT) { mul_m3_v3(tc->mat3_unit, out); } } } }
static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const float kink[3], float time, float freq, float shape, float amplitude, const float spiral_start[3]) { float result[3]; CLAMP(time, 0.f, 1.f); copy_v3_v3(result, state->co); { /* Creates a logarithmic spiral: * r(theta) = a * exp(b * theta) * * The "density" parameter b is defined by the shape parameter * and goes up to the Golden Spiral for 1.0 * https://en.wikipedia.org/wiki/Golden_spiral */ const float b = shape * (1.0f + sqrtf(5.0f)) / (float)M_PI * 0.25f; /* angle of the spiral against the curve (rotated opposite to make a smooth transition) */ const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) : (float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2); float spiral_axis[3], rot[3][3]; float vec[3]; float theta = freq * time * 2.0f * (float)M_PI; float radius = amplitude * expf(b * theta); /* a bit more intuitive than using negative frequency for this */ if (amplitude < 0.0f) theta = -theta; cross_v3_v3v3(spiral_axis, dir, kink); normalize_v3(spiral_axis); mul_v3_v3fl(vec, kink, -radius); axis_angle_normalized_to_mat3(rot, spiral_axis, theta); mul_m3_v3(rot, vec); madd_v3_v3fl(vec, kink, amplitude); axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle); mul_m3_v3(rot, vec); add_v3_v3v3(result, spiral_start, vec); } copy_v3_v3(state->co, result); }
static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (t->con.mode & CON_APPLY) { if (!td) { mul_m3_v3(t->con.pmtx, out); if (getConstraintSpaceDimension(t) == 2) { if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) { planeProjection(t, in, out); } } else if (getConstraintSpaceDimension(t) == 1) { float c[3]; if (t->con.mode & CON_AXIS0) { copy_v3_v3(c, t->con.mtx[0]); } else if (t->con.mode & CON_AXIS1) { copy_v3_v3(c, t->con.mtx[1]); } else if (t->con.mode & CON_AXIS2) { copy_v3_v3(c, t->con.mtx[2]); } axisProjection(t, c, in, out); } postConstraintChecks(t, out, pvec); copy_v3_v3(out, pvec); } else { int i = 0; out[0] = out[1] = out[2] = 0.0f; if (t->con.mode & CON_AXIS0) { out[0] = in[i++]; } if (t->con.mode & CON_AXIS1) { out[1] = in[i++]; } if (t->con.mode & CON_AXIS2) { out[2] = in[i++]; } mul_m3_v3(td->axismtx, out); if (t->flag & T_EDIT) { mul_m3_v3(t->obedit_mat, out); } } } }
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) { float angle, start[3], end[3]; sub_v3_v3v3(start, p1, t->center_global); sub_v3_v3v3(end, p2, t->center_global); // Angle around a constraint axis (error prone, will need debug) if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { float axis[3], tmp[3]; t->con.applyRot(t, NULL, axis, NULL); project_v3_v3v3(tmp, end, axis); sub_v3_v3v3(end, end, tmp); project_v3_v3v3(tmp, start, axis); sub_v3_v3v3(start, start, tmp); normalize_v3(end); normalize_v3(start); cross_v3_v3v3(tmp, start, end); if (dot_v3v3(tmp, axis) < 0.0f) angle = -acosf(dot_v3v3(start, end)); else angle = acosf(dot_v3v3(start, end)); } else { float mtx[3][3]; copy_m3_m4(mtx, t->viewmat); mul_m3_v3(mtx, end); mul_m3_v3(mtx, start); angle = atan2f(start[1], start[0]) - atan2f(end[1], end[0]); } if (angle > (float)M_PI) { angle = angle - 2 * (float)M_PI; } else if (angle < -((float)M_PI)) { angle = 2.0f * (float)M_PI + angle; } return angle; }
static void bake_set_vlr_dxyco(BakeShade *bs, float *uv1, float *uv2, float *uv3) { VlakRen *vlr = bs->vlr; float A, d1, d2, d3, *v1, *v2, *v3; if (bs->quad) { v1 = vlr->v1->co; v2 = vlr->v3->co; v3 = vlr->v4->co; } else { v1 = vlr->v1->co; v2 = vlr->v2->co; v3 = vlr->v3->co; } /* formula derived from barycentric coordinates: * (uvArea1*v1 + uvArea2*v2 + uvArea3*v3)/uvArea * then taking u and v partial derivatives to get dxco and dyco */ A = (uv2[0] - uv1[0]) * (uv3[1] - uv1[1]) - (uv3[0] - uv1[0]) * (uv2[1] - uv1[1]); if (fabsf(A) > FLT_EPSILON) { A = 0.5f / A; d1 = uv2[1] - uv3[1]; d2 = uv3[1] - uv1[1]; d3 = uv1[1] - uv2[1]; bs->dxco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; bs->dxco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; bs->dxco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; d1 = uv3[0] - uv2[0]; d2 = uv1[0] - uv3[0]; d3 = uv2[0] - uv1[0]; bs->dyco[0] = (v1[0] * d1 + v2[0] * d2 + v3[0] * d3) * A; bs->dyco[1] = (v1[1] * d1 + v2[1] * d2 + v3[1] * d3) * A; bs->dyco[2] = (v1[2] * d1 + v2[2] * d2 + v3[2] * d3) * A; } else { bs->dxco[0] = bs->dxco[1] = bs->dxco[2] = 0.0f; bs->dyco[0] = bs->dyco[1] = bs->dyco[2] = 0.0f; } if (bs->obi->flag & R_TRANSFORMED) { mul_m3_v3(bs->obi->nmat, bs->dxco); mul_m3_v3(bs->obi->nmat, bs->dyco); } }
/* shade sky according to sun lamps, all parameters are like shadeSkyView except sunsky*/ void shadeSunView(float col_r[3], const float view[3]) { GroupObject *go; LampRen *lar; float sview[3]; bool do_init = true; for (go=R.lights.first; go; go= go->next) { lar= go->lampren; if (lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_SKY)) { float sun_collector[3]; float colorxyz[3]; if (do_init) { normalize_v3_v3(sview, view); mul_m3_v3(R.imat, sview); if (sview[2] < 0.0f) sview[2] = 0.0f; normalize_v3(sview); do_init = false; } GetSkyXYZRadiancef(lar->sunsky, sview, colorxyz); xyz_to_rgb(colorxyz[0], colorxyz[1], colorxyz[2], &sun_collector[0], &sun_collector[1], &sun_collector[2], lar->sunsky->sky_colorspace); ramp_blend(lar->sunsky->skyblendtype, col_r, lar->sunsky->skyblendfac, sun_collector); } } }
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain = CTX_data_main(C); float *v1, *v3; float mat[3][3]; CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob->parent) { /* vectors pointed to by v1 and v3 will get modified */ v1 = ob->loc; v3 = ob->parentinv[3]; copy_m3_m4(mat, ob->parentinv); negate_v3_v3(v3, v1); mul_m3_v3(mat, v3); } DAG_id_tag_update(&ob->id, OB_RECALC_OB); } CTX_DATA_END; DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
/** * \param ray_distance Distance to the hit point * \param r_location Location of the hit point * \param r_normal Normal of the hit surface, transformed to always face the camera */ static bool walk_ray_cast(bContext *C, RegionView3D *rv3d, WalkInfo *walk, float r_location[3], float r_normal[3], float *ray_distance) { float dummy_dist_px = 0; float ray_normal[3] = {0, 0, 1}; /* forward */ float ray_start[3]; float mat[3][3]; /* 3x3 copy of the view matrix so we can move along the view axis */ bool ret; *ray_distance = TRANSFORM_DIST_MAX_RAY; copy_v3_v3(ray_start, rv3d->viewinv[3]); copy_m3_m4(mat, rv3d->viewinv); mul_m3_v3(mat, ray_normal); mul_v3_fl(ray_normal, -1); normalize_v3(ray_normal); ret = snapObjectsRayEx(CTX_data_scene(C), NULL, NULL, NULL, NULL, SCE_SNAP_MODE_FACE, NULL, NULL, ray_start, ray_normal, ray_distance, NULL, &dummy_dist_px, r_location, r_normal, SNAP_ALL); /* dot is positive if both rays are facing the same direction */ if (dot_v3v3(ray_normal, r_normal) > 0) { copy_v3_fl3(r_normal, -r_normal[0], -r_normal[1], -r_normal[2]); } /* artifically scale the distance to the scene size */ *ray_distance /= walk->grid; return ret; }
static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { mul_m3_v3(t->con.pmtx, out); // With snap, a projection is alright, no need to correct for view alignment if (!(!ELEM(t->tsnap.mode, SCE_SNAP_MODE_INCREMENT, SCE_SNAP_MODE_GRID) && activeSnap(t))) { if (getConstraintSpaceDimension(t) == 2) { if (out[0] != 0.0f || out[1] != 0.0f || out[2] != 0.0f) { planeProjection(t, in, out); } } else if (getConstraintSpaceDimension(t) == 1) { float c[3]; if (t->con.mode & CON_AXIS0) { copy_v3_v3(c, t->con.mtx[0]); } else if (t->con.mode & CON_AXIS1) { copy_v3_v3(c, t->con.mtx[1]); } else if (t->con.mode & CON_AXIS2) { copy_v3_v3(c, t->con.mtx[2]); } axisProjection(t, c, in, out); } } postConstraintChecks(t, out, pvec); } }
/* returns standard diameter */ static float new_primitive_matrix(bContext *C, float *loc, float *rot, float primmat[][4]) { Object *obedit = CTX_data_edit_object(C); View3D *v3d = CTX_wm_view3d(C); float mat[3][3], rmat[3][3], cmat[3][3], imat[3][3]; unit_m4(primmat); eul_to_mat3(rmat, rot); invert_m3(rmat); /* inverse transform for initial rotation and object */ copy_m3_m4(mat, obedit->obmat); mul_m3_m3m3(cmat, rmat, mat); invert_m3_m3(imat, cmat); copy_m4_m3(primmat, imat); /* center */ copy_v3_v3(primmat[3], loc); sub_v3_v3(primmat[3], obedit->obmat[3]); invert_m3_m3(imat, mat); mul_m3_v3(imat, primmat[3]); return v3d ? v3d->grid : 1.0f; }
static int object_hook_recenter_exec(bContext *C, wmOperator *op) { PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier); int num= RNA_enum_get(op->ptr, "modifier"); Object *ob=NULL; HookModifierData *hmd=NULL; Scene *scene = CTX_data_scene(C); float bmat[3][3], imat[3][3]; if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd= ptr.data; } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); return OPERATOR_CANCELLED; } /* recenter functionality */ copy_m3_m4(bmat, ob->obmat); invert_m3_m3(imat, bmat); sub_v3_v3v3(hmd->cent, scene->cursor, ob->obmat[3]); mul_m3_v3(imat, hmd->cent); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); return OPERATOR_FINISHED; }
/* Only view vector is important here. Result goes to col_r[3] */ void shadeSkyView(float col_r[3], const float rco[3], const float view[3], const float dxyview[2], short thread) { float zen[3], hor[3], blend, blendm; int skyflag; /* flag indicating if we render the top hemisphere */ skyflag = WO_ZENUP; /* Some view vector stuff. */ if (R.wrld.skytype & WO_SKYREAL) { blend = dot_v3v3(view, R.grvec); if (blend<0.0f) skyflag= 0; blend = fabsf(blend); } else if (R.wrld.skytype & WO_SKYPAPER) { blend= 0.5f + 0.5f * view[1]; } else { /* the fraction of how far we are above the bottom of the screen */ blend = fabsf(0.5f + view[1]); } copy_v3_v3(hor, &R.wrld.horr); copy_v3_v3(zen, &R.wrld.zenr); /* Careful: SKYTEX and SKYBLEND are NOT mutually exclusive! If */ /* SKYBLEND is active, the texture and color blend are added. */ if (R.wrld.skytype & WO_SKYTEX) { float lo[3]; copy_v3_v3(lo, view); if (R.wrld.skytype & WO_SKYREAL) { mul_m3_v3(R.imat, lo); SWAP(float, lo[1], lo[2]); } do_sky_tex(rco, view, lo, dxyview, hor, zen, &blend, skyflag, thread); } if (blend>1.0f) blend= 1.0f; blendm= 1.0f-blend; /* No clipping, no conversion! */ if (R.wrld.skytype & WO_SKYBLEND) { col_r[0] = (blendm*hor[0] + blend*zen[0]); col_r[1] = (blendm*hor[1] + blend*zen[1]); col_r[2] = (blendm*hor[2] + blend*zen[2]); } else { /* Done when a texture was grabbed. */ col_r[0]= hor[0]; col_r[1]= hor[1]; col_r[2]= hor[2]; } }
static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3]) { int i = 0; mul_m3_v3(t->con.imtx, vec); snapGridIncrement(t, vec); if (t->flag & T_NULL_ONE) { if (!(t->con.mode & CON_AXIS0)) { vec[0] = 1.0f; } if (!(t->con.mode & CON_AXIS1)) { vec[1] = 1.0f; } if (!(t->con.mode & CON_AXIS2)) { vec[2] = 1.0f; } } if (applyNumInput(&t->num, vec)) { constraintNumInput(t, vec); removeAspectRatio(t, vec); } /* autovalues is operator param, use that directly but not if snapping is forced */ if (t->flag & T_AUTOVALUES && (t->tsnap.status & SNAP_FORCED) == 0) { copy_v3_v3(vec, t->auto_values); constraintAutoValues(t, vec); /* inverse transformation at the end */ } if (t->con.mode & CON_AXIS0) { pvec[i++] = vec[0]; } if (t->con.mode & CON_AXIS1) { pvec[i++] = vec[1]; } if (t->con.mode & CON_AXIS2) { pvec[i++] = vec[2]; } mul_m3_v3(t->con.mtx, vec); }
void setBoneRollFromNormal(EditBone *bone, const float no[3], float UNUSED(invmat[4][4]), float tmat[3][3]) { if (no != NULL && !is_zero_v3(no)) { float normal[3]; copy_v3_v3(normal, no); mul_m3_v3(tmat, normal); bone->roll = ED_rollBoneToVector(bone, normal, false); } }
BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2]) { float vec[3] = {x, y, 1.0f}; mul_m3_v3(matrix, vec); uv[0] = vec[0] / vec[2]; uv[1] = vec[1] / vec[2]; deriv[0][0] = (matrix[0][0] - matrix[0][2] * uv[0]) / vec[2]; deriv[1][0] = (matrix[0][1] - matrix[0][2] * uv[1]) / vec[2]; deriv[0][1] = (matrix[1][0] - matrix[1][2] * uv[0]) / vec[2]; deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2]; }
static float ResizeBetween(TransInfo *t, const float p1[3], const float p2[3]) { float d1[3], d2[3], len_d1; sub_v3_v3v3(d1, p1, t->center_global); sub_v3_v3v3(d2, p2, t->center_global); if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { mul_m3_v3(t->con.pmtx, d1); mul_m3_v3(t->con.pmtx, d2); } project_v3_v3v3(d1, d1, d2); len_d1 = len_v3(d1); /* Use 'invalid' dist when `center == p1` (after projecting), * in this case scale will _never_ move the point in relation to the center, * so it makes no sense to take it into account when scaling. see: T46503 */ return len_d1 != 0.0f ? len_v3(d2) / len_d1 : TRANSFORM_DIST_INVALID; }
static void occ_face(const OccFace *face, float co[3], float normal[3], float *area) { ObjectInstanceRen *obi; VlakRen *vlr; float v1[3], v2[3], v3[3], v4[3]; obi = &R.objectinstance[face->obi]; vlr = RE_findOrAddVlak(obi->obr, face->facenr); if (co) { if (vlr->v4) mid_v3_v3v3(co, vlr->v1->co, vlr->v3->co); else cent_tri_v3(co, vlr->v1->co, vlr->v2->co, vlr->v3->co); if (obi->flag & R_TRANSFORMED) mul_m4_v3(obi->mat, co); } if (normal) { normal[0] = -vlr->n[0]; normal[1] = -vlr->n[1]; normal[2] = -vlr->n[2]; if (obi->flag & R_TRANSFORMED) mul_m3_v3(obi->nmat, normal); } if (area) { copy_v3_v3(v1, vlr->v1->co); copy_v3_v3(v2, vlr->v2->co); copy_v3_v3(v3, vlr->v3->co); if (vlr->v4) copy_v3_v3(v4, vlr->v4->co); if (obi->flag & R_TRANSFORMED) { mul_m4_v3(obi->mat, v1); mul_m4_v3(obi->mat, v2); mul_m4_v3(obi->mat, v3); if (vlr->v4) mul_m4_v3(obi->mat, v4); } /* todo: correct area for instances */ if (vlr->v4) *area = area_quad_v3(v1, v2, v3, v4); else *area = area_tri_v3(v1, v2, v3); } }
bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon) { float m[3][3]; BLI_quadric_to_tensor_m3(q, m); if (invert_m3_ex(m, epsilon)) { BLI_quadric_to_vector_v3(q, v); mul_m3_v3(m, v); negate_v3(v); return true; } else { return false; } }
/* Meta object density, brute force for now * (might be good enough anyway, don't need huge number of metaobs to model volumetric objects */ static float metadensity(Object *ob, const float co[3]) { float mat[4][4], imat[4][4], dens = 0.f; MetaBall *mb = (MetaBall *)ob->data; MetaElem *ml; /* transform co to meta-element */ float tco[3] = {co[0], co[1], co[2]}; mult_m4_m4m4(mat, R.viewmat, ob->obmat); invert_m4_m4(imat, mat); mul_m4_v3(imat, tco); for (ml = mb->elems.first; ml; ml = ml->next) { float bmat[3][3], dist2; /* element rotation transform */ float tp[3] = {ml->x - tco[0], ml->y - tco[1], ml->z - tco[2]}; quat_to_mat3(bmat, ml->quat); transpose_m3(bmat); /* rot.only, so inverse == transpose */ mul_m3_v3(bmat, tp); /* MB_BALL default */ switch (ml->type) { case MB_ELIPSOID: tp[0] /= ml->expx, tp[1] /= ml->expy, tp[2] /= ml->expz; break; case MB_CUBE: tp[2] = (tp[2] > ml->expz) ? (tp[2] - ml->expz) : ((tp[2] < -ml->expz) ? (tp[2] + ml->expz) : 0.f); /* no break, xy as plane */ case MB_PLANE: tp[1] = (tp[1] > ml->expy) ? (tp[1] - ml->expy) : ((tp[1] < -ml->expy) ? (tp[1] + ml->expy) : 0.f); /* no break, x as tube */ case MB_TUBE: tp[0] = (tp[0] > ml->expx) ? (tp[0] - ml->expx) : ((tp[0] < -ml->expx) ? (tp[0] + ml->expx) : 0.f); } /* ml->rad2 is not set */ dist2 = 1.0f - (dot_v3v3(tp, tp) / (ml->rad * ml->rad)); if (dist2 > 0.f) dens += (ml->flag & MB_NEGATIVE) ? -ml->s * dist2 * dist2 * dist2 : ml->s * dist2 * dist2 * dist2; } dens -= mb->thresh; return (dens < 0.f) ? 0.f : dens; }
static void rigid_add_half_edge_to_rhs(LaplacianSystem *sys, EditVert *v1, EditVert *v2, float w) { /* formula (8) */ float Rsum[3][3], rhs[3]; if (sys->vpinned[v1->tmp.l]) return; add_m3_m3m3(Rsum, sys->rigid.R[v1->tmp.l], sys->rigid.R[v2->tmp.l]); transpose_m3(Rsum); sub_v3_v3v3(rhs, sys->rigid.origco[v1->tmp.l], sys->rigid.origco[v2->tmp.l]); mul_m3_v3(Rsum, rhs); mul_v3_fl(rhs, 0.5f); mul_v3_fl(rhs, w); add_v3_v3(sys->rigid.rhs[v1->tmp.l], rhs); }
static void imapaint_tri_weights(Object *ob, const float v1[3], const float v2[3], const float v3[3], const float co[2], float w[3]) { float pv1[4], pv2[4], pv3[4], h[3], divw; float model[4][4], proj[4][4], wmat[3][3], invwmat[3][3]; GLint view[4]; /* compute barycentric coordinates */ /* get the needed opengl matrices */ glGetIntegerv(GL_VIEWPORT, view); glGetFloatv(GL_MODELVIEW_MATRIX, (float *)model); glGetFloatv(GL_PROJECTION_MATRIX, (float *)proj); view[0] = view[1] = 0; /* project the verts */ imapaint_project(ob, model, proj, v1, pv1); imapaint_project(ob, model, proj, v2, pv2); imapaint_project(ob, model, proj, v3, pv3); /* do inverse view mapping, see gluProject man page */ h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1; h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1; h[2] = 1.0f; /* solve for (w1,w2,w3)/perspdiv in: * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */ wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0]; wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1]; wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3]; invert_m3_m3(invwmat, wmat); mul_m3_v3(invwmat, h); copy_v3_v3(w, h); /* w is still divided by perspdiv, make it sum to one */ divw = w[0] + w[1] + w[2]; if (divw != 0.0f) { mul_v3_fl(w, 1.0f / divw); } }
static void applyAxisConstraintVec(TransInfo *t, TransDataContainer *UNUSED(tc), TransData *td, const float in[3], float out[3], float pvec[3]) { copy_v3_v3(out, in); if (!td && t->con.mode & CON_APPLY) { mul_m3_v3(t->con.pmtx, out); // With snap, a projection is alright, no need to correct for view alignment if (!validSnap(t)) { const int dims = getConstraintSpaceDimension(t); if (dims == 2) { if (!is_zero_v3(out)) { if (!isPlaneProjectionViewAligned(t)) { planeProjection(t, in, out); } } } else if (dims == 1) { float c[3]; if (t->con.mode & CON_AXIS0) { copy_v3_v3(c, t->con.mtx[0]); } else if (t->con.mode & CON_AXIS1) { copy_v3_v3(c, t->con.mtx[1]); } else if (t->con.mode & CON_AXIS2) { copy_v3_v3(c, t->con.mtx[2]); } axisProjection(t, c, in, out); } } postConstraintChecks(t, out, pvec); } }
static void imapaint_tri_weights(float matrix[4][4], GLint view[4], const float v1[3], const float v2[3], const float v3[3], const float co[2], float w[3]) { float pv1[4], pv2[4], pv3[4], h[3], divw; float wmat[3][3], invwmat[3][3]; /* compute barycentric coordinates */ /* project the verts */ imapaint_project(matrix, v1, pv1); imapaint_project(matrix, v2, pv2); imapaint_project(matrix, v3, pv3); /* do inverse view mapping, see gluProject man page */ h[0] = (co[0] - view[0]) * 2.0f / view[2] - 1.0f; h[1] = (co[1] - view[1]) * 2.0f / view[3] - 1.0f; h[2] = 1.0f; /* solve for (w1,w2,w3)/perspdiv in: * h * perspdiv = Project * Model * (w1 * v1 + w2 * v2 + w3 * v3) */ wmat[0][0] = pv1[0]; wmat[1][0] = pv2[0]; wmat[2][0] = pv3[0]; wmat[0][1] = pv1[1]; wmat[1][1] = pv2[1]; wmat[2][1] = pv3[1]; wmat[0][2] = pv1[3]; wmat[1][2] = pv2[3]; wmat[2][2] = pv3[3]; invert_m3_m3(invwmat, wmat); mul_m3_v3(invwmat, h); copy_v3_v3(w, h); /* w is still divided by perspdiv, make it sum to one */ divw = w[0] + w[1] + w[2]; if (divw != 0.0f) { mul_v3_fl(w, 1.0f / divw); } }
static int snap_sel_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); RegionView3D *rv3d = CTX_wm_region_data(C); TransVertStore tvs = {NULL}; TransVert *tv; float gridf, imat[3][3], bmat[3][3], vec[3]; int a; gridf = rv3d->gridview; if (obedit) { if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); if (tvs.transverts_tot == 0) return OPERATOR_CANCELLED; copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, tv->loc); mul_m3_v3(bmat, vec); add_v3_v3(vec, obedit->obmat[3]); vec[0] = gridf * floorf(0.5f + vec[0] / gridf); vec[1] = gridf * floorf(0.5f + vec[1] / gridf); vec[2] = gridf * floorf(0.5f + vec[2] / gridf); sub_v3_v3(vec, obedit->obmat[3]); mul_m3_v3(imat, vec); copy_v3_v3(tv->loc, vec); } ED_transverts_update_obedit(&tvs, obedit); ED_transverts_free(&tvs); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { if (ob->mode & OB_MODE_POSE) { bPoseChannel *pchan; bArmature *arm = ob->data; invert_m4_m4(ob->imat, ob->obmat); for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone->flag & BONE_SELECTED) { if (pchan->bone->layer & arm->layer) { if ((pchan->bone->flag & BONE_CONNECTED) == 0) { float nLoc[3]; /* get nearest grid point to snap to */ copy_v3_v3(nLoc, pchan->pose_mat[3]); /* We must operate in world space! */ mul_m4_v3(ob->obmat, nLoc); vec[0] = gridf * floorf(0.5f + nLoc[0] / gridf); vec[1] = gridf * floorf(0.5f + nLoc[1] / gridf); vec[2] = gridf * floorf(0.5f + nLoc[2] / gridf); /* Back in object space... */ mul_m4_v3(ob->imat, vec); /* Get location of grid point in pose space. */ BKE_armature_loc_pose_to_bone(pchan, vec, vec); /* adjust location */ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) pchan->loc[0] = vec[0]; if ((pchan->protectflag & OB_LOCK_LOCY) == 0) pchan->loc[1] = vec[1]; if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) pchan->loc[2] = vec[2]; /* auto-keyframing */ ED_autokeyframe_pchan(C, scene, ob, pchan, ks); } /* if the bone has a parent and is connected to the parent, * don't do anything - will break chain unless we do auto-ik. */ } } } ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } else { vec[0] = -ob->obmat[3][0] + gridf * floorf(0.5f + ob->obmat[3][0] / gridf); vec[1] = -ob->obmat[3][1] + gridf * floorf(0.5f + ob->obmat[3][1] / gridf); vec[2] = -ob->obmat[3][2] + gridf * floorf(0.5f + ob->obmat[3][2] / gridf); if (ob->parent) { float originmat[3][3]; BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, vec); } if ((ob->protectflag & OB_LOCK_LOCX) == 0) ob->loc[0] += vec[0]; if ((ob->protectflag & OB_LOCK_LOCY) == 0) ob->loc[1] += vec[1]; if ((ob->protectflag & OB_LOCK_LOCZ) == 0) ob->loc[2] += vec[2]; /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } CTX_DATA_END; } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
static bool snap_curs_to_sel_ex(bContext *C, float cursor[3]) { Object *obedit = CTX_data_edit_object(C); Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; float bmat[3][3], vec[3], min[3], max[3], centroid[3]; int count, a; count = 0; INIT_MINMAX(min, max); zero_v3(centroid); if (obedit) { if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, TM_ALL_JOINTS | TM_SKIP_HANDLES); if (tvs.transverts_tot == 0) { return false; } copy_m3_m4(bmat, obedit->obmat); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(vec, tv->loc); mul_m3_v3(bmat, vec); add_v3_v3(vec, obedit->obmat[3]); add_v3_v3(centroid, vec); minmax_v3v3_v3(min, max, vec); } if (v3d->around == V3D_AROUND_CENTER_MEAN) { mul_v3_fl(centroid, 1.0f / (float)tvs.transverts_tot); copy_v3_v3(cursor, centroid); } else { mid_v3_v3v3(cursor, min, max); } ED_transverts_free(&tvs); } else { Object *obact = CTX_data_active_object(C); if (obact && (obact->mode & OB_MODE_POSE)) { bArmature *arm = obact->data; bPoseChannel *pchan; for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if (arm->layer & pchan->bone->layer) { if (pchan->bone->flag & BONE_SELECTED) { copy_v3_v3(vec, pchan->pose_head); mul_m4_v3(obact->obmat, vec); add_v3_v3(centroid, vec); minmax_v3v3_v3(min, max, vec); count++; } } } } else { CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { copy_v3_v3(vec, ob->obmat[3]); /* special case for camera -- snap to bundles */ if (ob->type == OB_CAMERA) { /* snap to bundles should happen only when bundles are visible */ if (v3d->flag2 & V3D_SHOW_RECONSTRUCTION) { bundle_midpoint(scene, ob, vec); } } add_v3_v3(centroid, vec); minmax_v3v3_v3(min, max, vec); count++; } CTX_DATA_END; } if (count == 0) { return false; } if (v3d->around == V3D_AROUND_CENTER_MEAN) { mul_v3_fl(centroid, 1.0f / (float)count); copy_v3_v3(cursor, centroid); } else { mid_v3_v3v3(cursor, min, max); } }
static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); View3D *v3d = CTX_wm_view3d(C); TransVertStore tvs = {NULL}; TransVert *tv; float imat[3][3], bmat[3][3]; float center_global[3]; float offset_global[3]; int a; if (use_offset) { if ((v3d && v3d->around == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) { /* pass */ } else { snap_curs_to_sel_ex(C, center_global); } sub_v3_v3v3(offset_global, snap_target_global, center_global); } if (obedit) { float snap_target_local[3]; if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); if (tvs.transverts_tot == 0) return OPERATOR_CANCELLED; copy_m3_m4(bmat, obedit->obmat); invert_m3_m3(imat, bmat); /* get the cursor in object space */ sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); mul_m3_v3(imat, snap_target_local); if (use_offset) { float offset_local[3]; mul_v3_m3v3(offset_local, imat, offset_global); tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { add_v3_v3(tv->loc, offset_local); } } else { tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { copy_v3_v3(tv->loc, snap_target_local); } } ED_transverts_update_obedit(&tvs, obedit); ED_transverts_free(&tvs); } else if (obact && (obact->mode & OB_MODE_POSE)) { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); bPoseChannel *pchan; bArmature *arm = obact->data; float snap_target_local[3]; invert_m4_m4(obact->imat, obact->obmat); mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global); for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_SELECTED) && (PBONE_VISIBLE(arm, pchan->bone)) && /* if the bone has a parent and is connected to the parent, * don't do anything - will break chain unless we do auto-ik. */ (pchan->bone->flag & BONE_CONNECTED) == 0) { pchan->bone->flag |= BONE_TRANSFORM; } else { pchan->bone->flag &= ~BONE_TRANSFORM; } } for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_TRANSFORM) && /* check that our parents not transformed (if we have one) */ ((pchan->bone->parent && BKE_armature_bone_flag_test_recursive(pchan->bone->parent, BONE_TRANSFORM)) == 0)) { /* Get position in pchan (pose) space. */ float cursor_pose[3]; if (use_offset) { mul_v3_m4v3(cursor_pose, obact->obmat, pchan->pose_mat[3]); add_v3_v3(cursor_pose, offset_global); mul_m4_v3(obact->imat, cursor_pose); BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); } else { BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose); } /* copy new position */ if ((pchan->protectflag & OB_LOCK_LOCX) == 0) pchan->loc[0] = cursor_pose[0]; if ((pchan->protectflag & OB_LOCK_LOCY) == 0) pchan->loc[1] = cursor_pose[1]; if ((pchan->protectflag & OB_LOCK_LOCZ) == 0) pchan->loc[2] = cursor_pose[2]; /* auto-keyframing */ ED_autokeyframe_pchan(C, scene, obact, pchan, ks); } } for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { pchan->bone->flag &= ~BONE_TRANSFORM; } obact->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK); DAG_id_tag_update(&obact->id, OB_RECALC_DATA); } else { struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID); Main *bmain = CTX_data_main(C); ListBase ctx_data_list; CollectionPointerLink *ctx_ob; Object *ob; CTX_data_selected_editable_objects(C, &ctx_data_list); /* reset flags */ for (ob = bmain->object.first; ob; ob = ob->id.next) { ob->flag &= ~OB_DONE; } /* tag objects we're transforming */ for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { ob = ctx_ob->ptr.data; ob->flag |= OB_DONE; } for (ctx_ob = ctx_data_list.first; ctx_ob; ctx_ob = ctx_ob->next) { ob = ctx_ob->ptr.data; if ((ob->parent && BKE_object_flag_test_recursive(ob->parent, OB_DONE)) == 0) { float cursor_parent[3]; /* parent-relative */ if (use_offset) { add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); } else { copy_v3_v3(cursor_parent, snap_target_global); } sub_v3_v3(cursor_parent, ob->obmat[3]); if (ob->parent) { float originmat[3][3]; BKE_object_where_is_calc_ex(scene, NULL, ob, originmat); invert_m3_m3(imat, originmat); mul_m3_v3(imat, cursor_parent); } if ((ob->protectflag & OB_LOCK_LOCX) == 0) ob->loc[0] += cursor_parent[0]; if ((ob->protectflag & OB_LOCK_LOCY) == 0) ob->loc[1] += cursor_parent[1]; if ((ob->protectflag & OB_LOCK_LOCZ) == 0) ob->loc[2] += cursor_parent[2]; /* auto-keyframing */ ED_autokeyframe_object(C, scene, ob, ks); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } } BLI_freelistN(&ctx_data_list); } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; }
/* only valid for perspective cameras */ int camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3]) { float shift[2]; float plane_tx[4][3]; float rot_obmat[3][3]; const float zero[3]= {0,0,0}; CameraViewFrameData data_cb; unsigned int i; camera_view_frame(scene, camera_ob->data, data_cb.frame_tx); copy_m3_m4(rot_obmat, camera_ob->obmat); normalize_m3(rot_obmat); for (i= 0; i < 4; i++) { /* normalize so Z is always 1.0f*/ mul_v3_fl(data_cb.frame_tx[i], 1.0f/data_cb.frame_tx[i][2]); } /* get the shift back out of the frame */ shift[0]= (data_cb.frame_tx[0][0] + data_cb.frame_tx[1][0] + data_cb.frame_tx[2][0] + data_cb.frame_tx[3][0]) / 4.0f; shift[1]= (data_cb.frame_tx[0][1] + data_cb.frame_tx[1][1] + data_cb.frame_tx[2][1] + data_cb.frame_tx[3][1]) / 4.0f; for (i= 0; i < 4; i++) { mul_m3_v3(rot_obmat, data_cb.frame_tx[i]); } for (i= 0; i < 4; i++) { normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]); } /* initialize callback data */ data_cb.dist_vals[0]= data_cb.dist_vals[1]= data_cb.dist_vals[2]= data_cb.dist_vals[3]= FLT_MAX; data_cb.tot= 0; /* run callback on all visible points */ BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb); if (data_cb.tot <= 1) { return FALSE; } else { float plane_isect_1[3], plane_isect_1_no[3], plane_isect_1_other[3]; float plane_isect_2[3], plane_isect_2_no[3], plane_isect_2_other[3]; float plane_isect_pt_1[3], plane_isect_pt_2[3]; /* apply the dist-from-plane's to the transformed plane points */ for (i= 0; i < 4; i++) { mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]); } isect_plane_plane_v3(plane_isect_1, plane_isect_1_no, plane_tx[0], data_cb.normal_tx[0], plane_tx[2], data_cb.normal_tx[2]); isect_plane_plane_v3(plane_isect_2, plane_isect_2_no, plane_tx[1], data_cb.normal_tx[1], plane_tx[3], data_cb.normal_tx[3]); add_v3_v3v3(plane_isect_1_other, plane_isect_1, plane_isect_1_no); add_v3_v3v3(plane_isect_2_other, plane_isect_2, plane_isect_2_no); if (isect_line_line_v3(plane_isect_1, plane_isect_1_other, plane_isect_2, plane_isect_2_other, plane_isect_pt_1, plane_isect_pt_2) == 0) { return FALSE; } else { float cam_plane_no[3]= {0.0f, 0.0f, -1.0f}; float plane_isect_delta[3]; float plane_isect_delta_len; mul_m3_v3(rot_obmat, cam_plane_no); sub_v3_v3v3(plane_isect_delta, plane_isect_pt_2, plane_isect_pt_1); plane_isect_delta_len= len_v3(plane_isect_delta); if (dot_v3v3(plane_isect_delta, cam_plane_no) > 0.0f) { copy_v3_v3(r_co, plane_isect_pt_1); /* offset shift */ normalize_v3(plane_isect_1_no); madd_v3_v3fl(r_co, plane_isect_1_no, shift[1] * -plane_isect_delta_len); } else { copy_v3_v3(r_co, plane_isect_pt_2); /* offset shift */ normalize_v3(plane_isect_2_no); madd_v3_v3fl(r_co, plane_isect_2_no, shift[0] * -plane_isect_delta_len); } return TRUE; } } }
static void meshcache_do( MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm), float (*vertexCos_Real)[3], int numVerts) { const bool use_factor = mcmd->factor < 1.0f; float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ? MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL; float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real; Scene *scene = mcmd->modifier.scene; const float fps = FPS; char filepath[FILE_MAX]; const char *err_str = NULL; bool ok; float time; /* -------------------------------------------------------------------- */ /* Interpret Time (the reading functions also do some of this ) */ if (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA) { const float cfra = BKE_scene_frame_get(scene); switch (mcmd->time_mode) { case MOD_MESHCACHE_TIME_FRAME: { time = cfra; break; } case MOD_MESHCACHE_TIME_SECONDS: { time = cfra / fps; break; } case MOD_MESHCACHE_TIME_FACTOR: default: { time = cfra / fps; break; } } /* apply offset and scale */ time = (mcmd->frame_scale * time) - mcmd->frame_start; } else { /* if (mcmd->play_mode == MOD_MESHCACHE_PLAY_EVAL) { */ switch (mcmd->time_mode) { case MOD_MESHCACHE_TIME_FRAME: { time = mcmd->eval_frame; break; } case MOD_MESHCACHE_TIME_SECONDS: { time = mcmd->eval_time; break; } case MOD_MESHCACHE_TIME_FACTOR: default: { time = mcmd->eval_factor; break; } } } /* -------------------------------------------------------------------- */ /* Read the File (or error out when the file is bad) */ /* would be nice if we could avoid doing this _every_ frame */ BLI_strncpy(filepath, mcmd->filepath, sizeof(filepath)); BLI_path_abs(filepath, ID_BLEND_PATH(G.main, (ID *)ob)); switch (mcmd->type) { case MOD_MESHCACHE_TYPE_MDD: ok = MOD_meshcache_read_mdd_times(filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str); break; case MOD_MESHCACHE_TYPE_PC2: ok = MOD_meshcache_read_pc2_times(filepath, vertexCos, numVerts, mcmd->interp, time, fps, mcmd->time_mode, &err_str); break; default: ok = false; break; } /* -------------------------------------------------------------------- */ /* tricky shape key integration (slow!) */ if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) { Mesh *me = ob->data; /* we could support any object type */ if (UNLIKELY(ob->type != OB_MESH)) { modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); } else if (UNLIKELY(me->totvert != numVerts)) { modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { modifier_setError(&mcmd->modifier, "'Integrate' requires faces"); } else { /* the moons align! */ int i; float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__); float (*vertexCos_New)[3] = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__); MVert *mv = me->mvert; for (i = 0; i < numVerts; i++, mv++) { copy_v3_v3(vertexCos_Source[i], mv->co); } BKE_mesh_calc_relative_deform( me->mpoly, me->totpoly, me->mloop, me->totvert, (const float (*)[3])vertexCos_Source, /* from the original Mesh*/ (const float (*)[3])vertexCos_Real, /* the input we've been given (shape keys!) */ (const float (*)[3])vertexCos, /* the result of this modifier */ vertexCos_New /* the result of this function */ ); /* write the corrected locations back into the result */ memcpy(vertexCos, vertexCos_New, sizeof(*vertexCos) * numVerts); MEM_freeN(vertexCos_Source); MEM_freeN(vertexCos_New); } } /* -------------------------------------------------------------------- */ /* Apply the transformation matrix (if needed) */ if (UNLIKELY(err_str)) { modifier_setError(&mcmd->modifier, "%s", err_str); } else if (ok) { bool use_matrix = false; float mat[3][3]; unit_m3(mat); if (mat3_from_axis_conversion(mcmd->forward_axis, mcmd->up_axis, 1, 2, mat)) { use_matrix = true; } if (mcmd->flip_axis) { float tmat[3][3]; unit_m3(tmat); if (mcmd->flip_axis & (1 << 0)) tmat[0][0] = -1.0f; if (mcmd->flip_axis & (1 << 1)) tmat[1][1] = -1.0f; if (mcmd->flip_axis & (1 << 2)) tmat[2][2] = -1.0f; mul_m3_m3m3(mat, tmat, mat); use_matrix = true; } if (use_matrix) { int i; for (i = 0; i < numVerts; i++) { mul_m3_v3(mat, vertexCos[i]); } } } if (vertexCos_Store) { if (ok) { if (use_factor) { interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3); } else { memcpy(vertexCos_Real, vertexCos_Store, sizeof(*vertexCos_Store) * numVerts); } } MEM_freeN(vertexCos_Store); } }
/** * This function converts an object space normal map to a tangent space normal map for a given low poly mesh */ void RE_bake_normal_world_to_tangent( const BakePixel pixel_array[], const size_t num_pixels, const int depth, float result[], Mesh *me, const BakeNormalSwizzle normal_swizzle[3], float mat[4][4]) { size_t i; TriTessFace *triangles; DerivedMesh *dm = CDDM_from_mesh(me); triangles = MEM_mallocN(sizeof(TriTessFace) * (me->totface * 2), "MVerts Mesh"); mesh_calc_tri_tessface(triangles, me, true, dm); BLI_assert(num_pixels >= 3); for (i = 0; i < num_pixels; i++) { TriTessFace *triangle; float tangents[3][3]; float normals[3][3]; float signs[3]; int j; float tangent[3]; float normal[3]; float binormal[3]; float sign; float u, v, w; float tsm[3][3]; /* tangent space matrix */ float itsm[3][3]; size_t offset; float nor[3]; /* texture normal */ bool is_smooth; int primitive_id = pixel_array[i].primitive_id; offset = i * depth; if (primitive_id == -1) { copy_v3_fl3(&result[offset], 0.5f, 0.5f, 1.0f); continue; } triangle = &triangles[primitive_id]; is_smooth = triangle->is_smooth; for (j = 0; j < 3; j++) { const TSpace *ts; if (is_smooth) normal_short_to_float_v3(normals[j], triangle->mverts[j]->no); else normal[j] = triangle->normal[j]; ts = triangle->tspace[j]; copy_v3_v3(tangents[j], ts->tangent); signs[j] = ts->sign; } u = pixel_array[i].uv[0]; v = pixel_array[i].uv[1]; w = 1.0f - u - v; /* normal */ if (is_smooth) interp_barycentric_tri_v3(normals, u, v, normal); /* tangent */ interp_barycentric_tri_v3(tangents, u, v, tangent); /* sign */ /* The sign is the same at all face vertices for any non degenerate face. * Just in case we clamp the interpolated value though. */ sign = (signs[0] * u + signs[1] * v + signs[2] * w) < 0 ? (-1.0f) : 1.0f; /* binormal */ /* B = sign * cross(N, T) */ cross_v3_v3v3(binormal, normal, tangent); mul_v3_fl(binormal, sign); /* populate tangent space matrix */ copy_v3_v3(tsm[0], tangent); copy_v3_v3(tsm[1], binormal); copy_v3_v3(tsm[2], normal); /* texture values */ normal_uncompress(nor, &result[offset]); /* converts from world space to local space */ mul_transposed_mat3_m4_v3(mat, nor); invert_m3_m3(itsm, tsm); mul_m3_v3(itsm, nor); normalize_v3(nor); /* save back the values */ normal_compress(&result[offset], nor, normal_swizzle); } /* garbage collection */ MEM_freeN(triangles); if (dm) dm->release(dm); }
/* the ctrl-click method */ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) { View3D *v3d; bArmature *arm; EditBone *ebone, *newbone, *flipbone; float mat[3][3], imat[3][3]; const float *curs; int a, to_root = 0; Object *obedit; Scene *scene; scene = CTX_data_scene(C); v3d = CTX_wm_view3d(C); obedit = CTX_data_edit_object(C); arm = obedit->data; /* find the active or selected bone */ for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & BONE_TIPSEL || arm->act_edbone == ebone) break; } } if (ebone == NULL) { for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { if (EBONE_VISIBLE(arm, ebone)) { if (ebone->flag & BONE_ROOTSEL || arm->act_edbone == ebone) break; } } if (ebone == NULL) return OPERATOR_CANCELLED; to_root = 1; } ED_armature_deselect_all(obedit); /* we re-use code for mirror editing... */ flipbone = NULL; if (arm->flag & ARM_MIRROR_EDIT) flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone); for (a = 0; a < 2; a++) { if (a == 1) { if (flipbone == NULL) break; else { SWAP(EditBone *, flipbone, ebone); } } newbone = ED_armature_edit_bone_add(arm, ebone->name); arm->act_edbone = newbone; if (to_root) { copy_v3_v3(newbone->head, ebone->head); newbone->rad_head = ebone->rad_tail; newbone->parent = ebone->parent; } else { copy_v3_v3(newbone->head, ebone->tail); newbone->rad_head = ebone->rad_tail; newbone->parent = ebone; newbone->flag |= BONE_CONNECTED; } curs = ED_view3d_cursor3d_get(scene, v3d); copy_v3_v3(newbone->tail, curs); sub_v3_v3v3(newbone->tail, newbone->tail, obedit->obmat[3]); if (a == 1) newbone->tail[0] = -newbone->tail[0]; copy_m3_m4(mat, obedit->obmat); invert_m3_m3(imat, mat); mul_m3_v3(imat, newbone->tail); newbone->length = len_v3v3(newbone->head, newbone->tail); newbone->rad_tail = newbone->length * 0.05f; newbone->dist = newbone->length * 0.25f; } ED_armature_sync_selection(arm->edbo); WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); return OPERATOR_FINISHED; }