void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) { float rot[3], loc[3], scale[3]; if (ob->parent) { float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; // factor out scale from obmat copy_v3_v3(scale, ob->size); ob->size[0] = ob->size[1] = ob->size[2] = 1.0f; object_to_mat4(ob, C); copy_v3_v3(ob->size, scale); mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL); // calculate local mat invert_m4_m4(imat, ob->parent->obmat); mul_m4_m4m4(mat, tmat, imat); // done mat4_to_eul(rot, mat); copy_v3_v3(loc, mat[3]); } else { copy_v3_v3(loc, ob->loc); copy_v3_v3(rot, ob->rot); copy_v3_v3(scale, ob->size); } add_transform(node, loc, rot, scale); }
/* Space transform */ void space_transform_from_matrixs(SpaceTransform *data, float local[4][4], float target[4][4]) { float itarget[4][4]; invert_m4_m4(itarget, target); mul_serie_m4(data->local2target, itarget, local, NULL, NULL, NULL, NULL, NULL, NULL); invert_m4_m4(data->target2local, data->local2target); }
static void envmap_transmatrix(float mat[][4], int part) { float tmat[4][4], eul[3], rotmat[4][4]; eul[0] = eul[1] = eul[2] = 0.0; if (part == 0) { /* neg z */ ; } else if (part == 1) { /* pos z */ eul[0] = M_PI; } else if (part == 2) { /* pos y */ eul[0] = M_PI / 2.0; } else if (part == 3) { /* neg x */ eul[0] = M_PI / 2.0; eul[2] = M_PI / 2.0; } else if (part == 4) { /* neg y */ eul[0] = M_PI / 2.0; eul[2] = M_PI; } else { /* pos x */ eul[0] = M_PI / 2.0; eul[2] = -M_PI / 2.0; } copy_m4_m4(tmat, mat); eul_to_mat4(rotmat, eul); mul_serie_m4(mat, tmat, rotmat, NULL, NULL, NULL, NULL, NULL, NULL); }
void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) { #if 0 float rot[3], loc[3], scale[3]; if (ob->parent) { float C[4][4], tmat[4][4], imat[4][4], mat[4][4]; // factor out scale from obmat copy_v3_v3(scale, ob->size); ob->size[0] = ob->size[1] = ob->size[2] = 1.0f; BKE_object_to_mat4(ob, C); copy_v3_v3(ob->size, scale); mul_serie_m4(tmat, ob->parent->obmat, ob->parentinv, C, NULL, NULL, NULL, NULL, NULL); // calculate local mat invert_m4_m4(imat, ob->parent->obmat); mult_m4_m4m4(mat, imat, tmat); // done mat4_to_eul(rot, mat); copy_v3_v3(loc, mat[3]); } else { copy_v3_v3(loc, ob->loc); copy_v3_v3(rot, ob->rot); copy_v3_v3(scale, ob->size); } add_transform(node, loc, rot, scale); #endif /* Using parentinv should allow use of existing curves */ if (ob->parent) { // If parentinv is identity don't add it. bool add_parinv = false; for (int i = 0; i < 16; ++i) { float f = (i % 4 == i / 4) ? 1.0f : 0.0f; add_parinv |= (ob->parentinv[i % 4][i / 4] != f); } if (add_parinv) { double dmat[4][4]; UnitConverter converter; converter.mat4_to_dae_double(dmat, ob->parentinv); node.addMatrix("parentinverse", dmat); } } add_transform(node, ob->loc, ob->rot, ob->size); }
static int object_hook_reset_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; 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; } /* reset functionality */ if(hmd->object) { bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget); if(hmd->subtarget[0] && pchan) { float imat[4][4], mat[4][4]; /* calculate the world-space matrix for the pose-channel target first, then carry on as usual */ mul_m4_m4m4(mat, pchan->pose_mat, hmd->object->obmat); invert_m4_m4(imat, mat); mul_serie_m4(hmd->parentinv, imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL); } else { invert_m4_m4(hmd->object->imat, hmd->object->obmat); mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL); } } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); return OPERATOR_FINISHED; }
static void add_hook_object(Main *bmain, Scene *scene, Object *obedit, Object *ob, int mode) { ModifierData *md=NULL; HookModifierData *hmd = NULL; float cent[3]; int tot, ok, *indexar; char name[32]; ok = object_hook_index_array(obedit, &tot, &indexar, name, cent); if (!ok) return; // XXX error("Requires selected vertices or active Vertex Group"); if (mode==OBJECT_ADDHOOK_NEWOB && !ob) { ob = add_hook_object_new(scene, obedit); /* transform cent to global coords for loc */ mul_v3_m4v3(ob->loc, obedit->obmat, cent); } md = obedit->modifiers.first; while (md && modifierType_getInfo(md->type)->type==eModifierTypeType_OnlyDeform) { md = md->next; } hmd = (HookModifierData*) modifier_new(eModifierType_Hook); BLI_insertlinkbefore(&obedit->modifiers, md, hmd); BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name+2); modifier_unique_name(&obedit->modifiers, (ModifierData*)hmd); hmd->object= ob; hmd->indexar= indexar; copy_v3_v3(hmd->cent, cent); hmd->totindex= tot; BLI_strncpy(hmd->name, name, sizeof(hmd->name)); /* matrix calculus */ /* vert x (obmat x hook->imat) x hook->obmat x ob->imat */ /* (parentinv ) */ where_is_object(scene, ob); invert_m4_m4(ob->imat, ob->obmat); /* apparently this call goes from right to left... */ mul_serie_m4(hmd->parentinv, ob->imat, obedit->obmat, NULL, NULL, NULL, NULL, NULL, NULL); DAG_scene_sort(bmain, scene); }
/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3]) // nr = to detect if this is first bone { float vec[3], ikmat[4][4]; copy_m4_m3(ikmat, ik_mat); if (pchan->parent) mul_serie_m4(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); else mul_m4_m4m4(pchan->pose_mat, pchan->chan_mat, ikmat); /* calculate head */ copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); /* calculate tail */ copy_v3_v3(vec, pchan->pose_mat[1]); mul_v3_fl(vec, pchan->bone->length); add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec); pchan->flag |= POSE_DONE; }
/* Get 4x4 transformation matrix which corresponds to * stabilization data and used for easy coordinate * transformation. * * NOTE: The reason it is 4x4 matrix is because it's * used for OpenGL drawing directly. */ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, float translation[2], float scale, float angle, float mat[4][4]) { float translation_mat[4][4], rotation_mat[4][4], scale_mat[4][4], center_mat[4][4], inv_center_mat[4][4], aspect_mat[4][4], inv_aspect_mat[4][4]; float scale_vector[3] = {scale, scale, scale}; unit_m4(translation_mat); unit_m4(rotation_mat); unit_m4(scale_mat); unit_m4(center_mat); unit_m4(aspect_mat); /* aspect ratio correction matrix */ aspect_mat[0][0] = 1.0f / aspect; invert_m4_m4(inv_aspect_mat, aspect_mat); /* image center as rotation center * * Rotation matrix is constructing in a way rotation happens around image center, * and it's matter of calculating translation in a way, that applying translation * after rotation would make it so rotation happens around median point of tracks * used for translation stabilization. */ center_mat[3][0] = (float)width / 2.0f; center_mat[3][1] = (float)height / 2.0f; invert_m4_m4(inv_center_mat, center_mat); size_to_mat4(scale_mat, scale_vector); /* scale matrix */ add_v2_v2(translation_mat[3], translation); /* translation matrix */ rotate_m4(rotation_mat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, translation_mat, center_mat, aspect_mat, rotation_mat, inv_aspect_mat, scale_mat, inv_center_mat, NULL); }
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { HookModifierData *hmd = (HookModifierData*) md; bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget); float vec[3], mat[4][4], dmat[4][4]; int i, *index_pt; const float falloff_squared= hmd->falloff * hmd->falloff; /* for faster comparisons */ int max_dvert= 0; MDeformVert *dvert= NULL; int defgrp_index = -1; /* get world-space matrix of target, corrected for the space the verts are in */ if (hmd->subtarget[0] && pchan) { /* bone target if there's a matching pose-channel */ mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat); } else { /* just object target */ copy_m4_m4(dmat, hmd->object->obmat); } invert_m4_m4(ob->imat, ob->obmat); mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv, NULL, NULL, NULL, NULL, NULL); if((defgrp_index= defgroup_name_index(ob, hmd->name)) != -1) { Mesh *me = ob->data; if(dm) { dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); if(dvert) { max_dvert = numVerts; } } else if(me->dvert) { dvert= me->dvert; if(dvert) { max_dvert = me->totvert; } } } /* Regarding index range checking below. * * This should always be true and I don't generally like * "paranoid" style code like this, but old files can have * indices that are out of range because old blender did * not correct them on exit editmode. - zr */ if(hmd->force == 0.0f) { /* do nothing, avoid annoying checks in the loop */ } else if(hmd->indexar) { /* vertex indices? */ const float fac_orig= hmd->force; float fac; const int *origindex_ar; /* if DerivedMesh is present and has original index data, * use it */ if(dm && (origindex_ar= dm->getVertDataArray(dm, CD_ORIGINDEX))) { for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { if(*index_pt < numVerts) { int j; for(j = 0; j < numVerts; j++) { if(origindex_ar[j] == *index_pt) { float *co = vertexCos[j]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { if(dvert) fac *= defvert_find_weight(dvert+j, defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } } } } else { /* missing dm or ORIGINDEX */ for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { if(*index_pt < numVerts) { float *co = vertexCos[*index_pt]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { if(dvert) fac *= defvert_find_weight(dvert+(*index_pt), defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } } } else if(dvert) { /* vertex group hook */ int i; const float fac_orig= hmd->force; for(i = 0; i < max_dvert; i++, dvert++) { float fac; float *co = vertexCos[i]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { fac *= defvert_find_weight(dvert, defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } }
void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) { MovieClip *clip = ED_space_clip_get_clip(sc); Scene *scene = CTX_data_scene(C); ImBuf *ibuf = NULL; int width, height; float zoomx, zoomy; ED_space_clip_get_size(sc, &width, &height); ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy); /* if no clip, nothing to do */ if (!clip) { ED_region_grid_draw(ar, zoomx, zoomy); return; } if (sc->flag & SC_SHOW_STABLE) { float smat[4][4], ismat[4][4]; ibuf = ED_space_clip_get_stable_buffer(sc, sc->loc, &sc->scale, &sc->angle); if (ibuf) { float translation[2]; float aspect = clip->tracking.camera.pixel_aspect; if (width != ibuf->x) mul_v2_v2fl(translation, sc->loc, (float)width / ibuf->x); else copy_v2_v2(translation, sc->loc); BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, sc->scale, sc->angle, sc->stabmat); unit_m4(smat); smat[0][0] = 1.0f / width; smat[1][1] = 1.0f / height; invert_m4_m4(ismat, smat); mul_serie_m4(sc->unistabmat, smat, sc->stabmat, ismat, NULL, NULL, NULL, NULL, NULL); } } else if ((sc->flag & SC_MUTE_FOOTAGE) == 0) { ibuf = ED_space_clip_get_buffer(sc); zero_v2(sc->loc); sc->scale = 1.0f; unit_m4(sc->stabmat); unit_m4(sc->unistabmat); } if (ibuf) { draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); } else if (sc->flag & SC_MUTE_FOOTAGE) { draw_movieclip_muted(ar, width, height, zoomx, zoomy); } else { ED_region_grid_draw(ar, zoomx, zoomy); } if (width && height) { draw_stabilization_border(sc, ar, width, height, zoomx, zoomy); draw_tracking_tracks(sc, scene, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } }
/* called from within the core BKE_pose_where_is loop, all animsystems and constraints * were executed & assigned. Now as last we do an IK pass */ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree) { float R_parmat[3][3], identity[3][3]; float iR_parmat[3][3]; float R_bonemat[3][3]; float goalrot[3][3], goalpos[3]; float rootmat[4][4], imat[4][4]; float goal[4][4], goalinv[4][4]; float irest_basis[3][3], full_basis[3][3]; float end_pose[4][4], world_pose[4][4]; float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch = NULL; float resultinf = 0.0f; int a, flag, hasstretch = 0, resultblend = 0; bPoseChannel *pchan; IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; PoseTarget *target; bKinematicConstraint *data, *poleangledata = NULL; Bone *bone; if (tree->totchannel == 0) return; iktree = MEM_mallocN(sizeof(void *) * tree->totchannel, "ik tree"); for (a = 0; a < tree->totchannel; a++) { pchan = tree->pchan[a]; bone = pchan->bone; /* set DoF flag */ flag = 0; if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) flag |= IK_XDOF; if (!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) flag |= IK_YDOF; if (!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) flag |= IK_ZDOF; if (tree->stretch && (pchan->ikstretch > 0.0f)) { flag |= IK_TRANS_YDOF; hasstretch = 1; } seg = iktree[a] = IK_CreateSegment(flag); /* find parent */ if (a == 0) parent = NULL; else parent = iktree[tree->parent[a]]; IK_SetParent(seg, parent); /* get the matrix that transforms from prevbone into this bone */ copy_m3_m4(R_bonemat, pchan->pose_mat); /* gather transformations for this IK segment */ if (pchan->parent) copy_m3_m4(R_parmat, pchan->parent->pose_mat); else unit_m3(R_parmat); /* bone offset */ if (pchan->parent && (a > 0)) sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail); else /* only root bone (a = 0) has no parent */ start[0] = start[1] = start[2] = 0.0f; /* change length based on bone size */ length = bone->length * len_v3(R_bonemat[1]); /* compute rest basis and its inverse */ copy_m3_m3(rest_basis, bone->bone_mat); copy_m3_m3(irest_basis, bone->bone_mat); transpose_m3(irest_basis); /* compute basis with rest_basis removed */ invert_m3_m3(iR_parmat, R_parmat); mul_m3_m3m3(full_basis, iR_parmat, R_bonemat); mul_m3_m3m3(basis, irest_basis, full_basis); /* basis must be pure rotation */ normalize_m3(basis); /* transform offset into local bone space */ normalize_m3(iR_parmat); mul_m3_v3(iR_parmat, start); IK_SetTransform(seg, start, rest_basis, basis, length); if (pchan->ikflag & BONE_IK_XLIMIT) IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); if (pchan->ikflag & BONE_IK_YLIMIT) IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); if (pchan->ikflag & BONE_IK_ZLIMIT) IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); if (tree->stretch && (pchan->ikstretch > 0.0f)) { const float ikstretch = pchan->ikstretch * pchan->ikstretch; /* this function does its own clamping */ IK_SetStiffness(seg, IK_TRANS_Y, 1.0f - ikstretch); IK_SetLimit(seg, IK_TRANS_Y, IK_STRETCH_STIFF_MIN, IK_STRETCH_STIFF_MAX); } } solver = IK_CreateSolver(iktree[0]); /* set solver goals */ /* first set the goal inverse transform, assuming the root of tree was done ok! */ pchan = tree->pchan[0]; if (pchan->parent) { /* transform goal by parent mat, so this rotation is not part of the * segment's basis. otherwise rotation limits do not work on the * local transform of the segment itself. */ copy_m4_m4(rootmat, pchan->parent->pose_mat); /* However, we do not want to get (i.e. reverse) parent's scale, as it generates [#31008] * kind of nasty bugs... */ normalize_m4(rootmat); } else unit_m4(rootmat); copy_v3_v3(rootmat[3], pchan->pose_head); mul_m4_m4m4(imat, ob->obmat, rootmat); invert_m4_m4(goalinv, imat); for (target = tree->targets.first; target; target = target->next) { float polepos[3]; int poleconstrain = 0; data = (bKinematicConstraint *)target->con->data; /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though * strictly speaking, it is a posechannel) */ BKE_constraint_target_matrix_get(scene, target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); /* and set and transform goal */ mul_m4_m4m4(goal, goalinv, rootmat); copy_v3_v3(goalpos, goal[3]); copy_m3_m4(goalrot, goal); normalize_m3(goalrot); /* same for pole vector target */ if (data->poletar) { BKE_constraint_target_matrix_get(scene, target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); if (data->flag & CONSTRAINT_IK_SETANGLE) { /* don't solve IK when we are setting the pole angle */ break; } else { mul_m4_m4m4(goal, goalinv, rootmat); copy_v3_v3(polepos, goal[3]); poleconstrain = 1; /* for pole targets, we blend the result of the ik solver * instead of the target position, otherwise we can't get * a smooth transition */ resultblend = 1; resultinf = target->con->enforce; if (data->flag & CONSTRAINT_IK_GETANGLE) { poleangledata = data; data->flag &= ~CONSTRAINT_IK_GETANGLE; } } } /* do we need blending? */ if (!resultblend && target->con->enforce != 1.0f) { float q1[4], q2[4], q[4]; float fac = target->con->enforce; float mfac = 1.0f - fac; pchan = tree->pchan[target->tip]; /* end effector in world space */ copy_m4_m4(end_pose, pchan->pose_mat); copy_v3_v3(end_pose[3], pchan->pose_tail); mul_serie_m4(world_pose, goalinv, ob->obmat, end_pose, NULL, NULL, NULL, NULL, NULL); /* blend position */ goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0]; goalpos[1] = fac * goalpos[1] + mfac * world_pose[3][1]; goalpos[2] = fac * goalpos[2] + mfac * world_pose[3][2]; /* blend rotation */ mat3_to_quat(q1, goalrot); mat4_to_quat(q2, world_pose); interp_qt_qtqt(q, q1, q2, mfac); quat_to_mat3(goalrot, q); } iktarget = iktree[target->tip]; if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) { if (poleconstrain) IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data)); IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); } if ((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) if ((data->flag & CONSTRAINT_IK_AUTO) == 0) IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight); } /* solve */ IK_Solve(solver, 0.0f, tree->iterations); if (poleangledata) poleangledata->poleangle = IK_SolverGetPoleAngle(solver); IK_FreeSolver(solver); /* gather basis changes */ tree->basis_change = MEM_mallocN(sizeof(float[3][3]) * tree->totchannel, "ik basis change"); if (hasstretch) ikstretch = MEM_mallocN(sizeof(float) * tree->totchannel, "ik stretch"); for (a = 0; a < tree->totchannel; a++) { IK_GetBasisChange(iktree[a], tree->basis_change[a]); if (hasstretch) { /* have to compensate for scaling received from parent */ float parentstretch, stretch; pchan = tree->pchan[a]; parentstretch = (tree->parent[a] >= 0) ? ikstretch[tree->parent[a]] : 1.0f; if (tree->stretch && (pchan->ikstretch > 0.0f)) { float trans[3], length; IK_GetTranslationChange(iktree[a], trans); length = pchan->bone->length * len_v3(pchan->pose_mat[1]); ikstretch[a] = (length == 0.0f) ? 1.0f : (trans[1] + length) / length; } else ikstretch[a] = 1.0; stretch = (parentstretch == 0.0f) ? 1.0f : ikstretch[a] / parentstretch; mul_v3_fl(tree->basis_change[a][0], stretch); mul_v3_fl(tree->basis_change[a][1], stretch); mul_v3_fl(tree->basis_change[a][2], stretch); } if (resultblend && resultinf != 1.0f) { unit_m3(identity); blend_m3_m3m3(tree->basis_change[a], identity, tree->basis_change[a], resultinf); } IK_FreeSegment(iktree[a]); } MEM_freeN(iktree); if (ikstretch) MEM_freeN(ikstretch); }
CompBuf* node_composit_transform(CompBuf *cbuf, float x, float y, float angle, float scale, int filter_type) { CompBuf *stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); ImBuf *ibuf, *obuf; float mat[4][4], lmat[4][4], rmat[4][4], smat[4][4], cmat[4][4], icmat[4][4]; float svec[3]= {scale, scale, scale}, loc[2]= {x, y}; unit_m4(rmat); unit_m4(lmat); unit_m4(smat); unit_m4(cmat); /* image center as rotation center */ cmat[3][0]= (float)cbuf->x/2.0f; cmat[3][1]= (float)cbuf->y/2.0f; invert_m4_m4(icmat, cmat); size_to_mat4(smat, svec); /* scale matrix */ add_v2_v2(lmat[3], loc); /* tranlation matrix */ rotate_m4(rmat, 'Z', angle); /* rotation matrix */ /* compose transformation matrix */ mul_serie_m4(mat, lmat, cmat, rmat, smat, icmat, NULL, NULL, NULL); invert_m4(mat); ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0); obuf= IMB_allocImBuf(stackbuf->x, stackbuf->y, 32, 0); if (ibuf && obuf) { int i, j; ibuf->rect_float= cbuf->rect; obuf->rect_float= stackbuf->rect; for (j=0; j<cbuf->y; j++) { for (i=0; i<cbuf->x;i++) { float vec[3]= {i, j, 0}; mul_v3_m4v3(vec, mat, vec); switch(filter_type) { case 0: neareast_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 1: bilinear_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; case 2: bicubic_interpolation(ibuf, obuf, vec[0], vec[1], i, j); break; } } } IMB_freeImBuf(ibuf); IMB_freeImBuf(obuf); } /* pass on output and free */ return stackbuf; }
void init_tex_mapping(TexMapping *texmap) { float smat[4][4], rmat[4][4], tmat[4][4], proj[4][4], size[3]; if (texmap->projx == PROJ_X && texmap->projy == PROJ_Y && texmap->projz == PROJ_Z && is_zero_v3(texmap->loc) && is_zero_v3(texmap->rot) && is_one_v3(texmap->size)) { unit_m4(texmap->mat); texmap->flag |= TEXMAP_UNIT_MATRIX; } else { /* axis projection */ zero_m4(proj); proj[3][3] = 1.0f; if (texmap->projx != PROJ_N) proj[texmap->projx - 1][0] = 1.0f; if (texmap->projy != PROJ_N) proj[texmap->projy - 1][1] = 1.0f; if (texmap->projz != PROJ_N) proj[texmap->projz - 1][2] = 1.0f; /* scale */ copy_v3_v3(size, texmap->size); if (ELEM(texmap->type, TEXMAP_TYPE_TEXTURE, TEXMAP_TYPE_NORMAL)) { /* keep matrix invertible */ if (fabsf(size[0]) < 1e-5f) size[0] = signf(size[0]) * 1e-5f; if (fabsf(size[1]) < 1e-5f) size[1] = signf(size[1]) * 1e-5f; if (fabsf(size[2]) < 1e-5f) size[2] = signf(size[2]) * 1e-5f; } size_to_mat4(smat, texmap->size); /* rotation */ eul_to_mat4(rmat, texmap->rot); /* translation */ unit_m4(tmat); copy_v3_v3(tmat[3], texmap->loc); if (texmap->type == TEXMAP_TYPE_TEXTURE) { /* to transform a texture, the inverse transform needs * to be applied to the texture coordinate */ mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); invert_m4(texmap->mat); } else if (texmap->type == TEXMAP_TYPE_POINT) { /* forward transform */ mul_serie_m4(texmap->mat, tmat, rmat, smat, 0, 0, 0, 0, 0); } else if (texmap->type == TEXMAP_TYPE_VECTOR) { /* no translation for vectors */ mul_m4_m4m4(texmap->mat, rmat, smat); } else if (texmap->type == TEXMAP_TYPE_NORMAL) { /* no translation for normals, and inverse transpose */ mul_m4_m4m4(texmap->mat, rmat, smat); invert_m4(texmap->mat); transpose_m4(texmap->mat); } /* projection last */ mul_m4_m4m4(texmap->mat, texmap->mat, proj); texmap->flag &= ~TEXMAP_UNIT_MATRIX; } }