|
Blender
V2.59
|
00001 /* 00002 * $Id: constraint.c 37512 2011-06-15 14:06:25Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * 00025 * Contributor(s): 2007, Joshua Leung, major recode 00026 * 00027 * ***** END GPL LICENSE BLOCK ***** 00028 */ 00029 00035 #include <stdio.h> 00036 #include <stddef.h> 00037 #include <string.h> 00038 #include <math.h> 00039 #include <float.h> 00040 00041 #include "MEM_guardedalloc.h" 00042 00043 #include "BLI_blenlib.h" 00044 #include "BLI_listbase.h" 00045 #include "BLI_math.h" 00046 #include "BLI_editVert.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "DNA_armature_types.h" 00050 #include "DNA_constraint_types.h" 00051 #include "DNA_modifier_types.h" 00052 #include "DNA_object_types.h" 00053 #include "DNA_action_types.h" 00054 #include "DNA_curve_types.h" 00055 #include "DNA_mesh_types.h" 00056 #include "DNA_meshdata_types.h" 00057 #include "DNA_lattice_types.h" 00058 #include "DNA_scene_types.h" 00059 #include "DNA_text_types.h" 00060 00061 00062 #include "BKE_action.h" 00063 #include "BKE_anim.h" /* for the curve calculation part */ 00064 #include "BKE_armature.h" 00065 #include "BKE_blender.h" 00066 #include "BKE_constraint.h" 00067 #include "BKE_displist.h" 00068 #include "BKE_deform.h" 00069 #include "BKE_DerivedMesh.h" /* for geometry targets */ 00070 #include "BKE_cdderivedmesh.h" /* for geometry targets */ 00071 #include "BKE_object.h" 00072 #include "BKE_ipo.h" 00073 #include "BKE_global.h" 00074 #include "BKE_library.h" 00075 #include "BKE_idprop.h" 00076 #include "BKE_shrinkwrap.h" 00077 #include "BKE_mesh.h" 00078 00079 #ifdef WITH_PYTHON 00080 #include "BPY_extern.h" 00081 #endif 00082 00083 #ifndef M_PI 00084 #define M_PI 3.14159265358979323846 00085 #endif 00086 00087 00088 00089 /* ************************ Constraints - General Utilities *************************** */ 00090 /* These functions here don't act on any specific constraints, and are therefore should/will 00091 * not require any of the special function-pointers afforded by the relevant constraint 00092 * type-info structs. 00093 */ 00094 00095 /* -------------- Naming -------------- */ 00096 00097 /* Find the first available, non-duplicate name for a given constraint */ 00098 void unique_constraint_name (bConstraint *con, ListBase *list) 00099 { 00100 BLI_uniquename(list, con, "Const", '.', offsetof(bConstraint, name), sizeof(con->name)); 00101 } 00102 00103 /* ----------------- Evaluation Loop Preparation --------------- */ 00104 00105 /* package an object/bone for use in constraint evaluation */ 00106 /* This function MEM_calloc's a bConstraintOb struct, that will need to be freed after evaluation */ 00107 bConstraintOb *constraints_make_evalob (Scene *scene, Object *ob, void *subdata, short datatype) 00108 { 00109 bConstraintOb *cob; 00110 00111 /* create regardless of whether we have any data! */ 00112 cob= MEM_callocN(sizeof(bConstraintOb), "bConstraintOb"); 00113 00114 /* for system time, part of deglobalization, code nicer later with local time (ton) */ 00115 cob->scene= scene; 00116 00117 /* based on type of available data */ 00118 switch (datatype) { 00119 case CONSTRAINT_OBTYPE_OBJECT: 00120 { 00121 /* disregard subdata... calloc should set other values right */ 00122 if (ob) { 00123 cob->ob = ob; 00124 cob->type = datatype; 00125 cob->rotOrder = EULER_ORDER_DEFAULT; // TODO: when objects have rotation order too, use that 00126 copy_m4_m4(cob->matrix, ob->obmat); 00127 } 00128 else 00129 unit_m4(cob->matrix); 00130 00131 copy_m4_m4(cob->startmat, cob->matrix); 00132 } 00133 break; 00134 case CONSTRAINT_OBTYPE_BONE: 00135 { 00136 /* only set if we have valid bone, otherwise default */ 00137 if (ob && subdata) { 00138 cob->ob = ob; 00139 cob->pchan = (bPoseChannel *)subdata; 00140 cob->type = datatype; 00141 00142 if (cob->pchan->rotmode > 0) { 00143 /* should be some type of Euler order */ 00144 cob->rotOrder= cob->pchan->rotmode; 00145 } 00146 else { 00147 /* Quats, so eulers should just use default order */ 00148 cob->rotOrder= EULER_ORDER_DEFAULT; 00149 } 00150 00151 /* matrix in world-space */ 00152 mul_m4_m4m4(cob->matrix, cob->pchan->pose_mat, ob->obmat); 00153 } 00154 else 00155 unit_m4(cob->matrix); 00156 00157 copy_m4_m4(cob->startmat, cob->matrix); 00158 } 00159 break; 00160 00161 default: /* other types not yet handled */ 00162 unit_m4(cob->matrix); 00163 unit_m4(cob->startmat); 00164 break; 00165 } 00166 00167 return cob; 00168 } 00169 00170 /* cleanup after constraint evaluation */ 00171 void constraints_clear_evalob (bConstraintOb *cob) 00172 { 00173 float delta[4][4], imat[4][4]; 00174 00175 /* prevent crashes */ 00176 if (cob == NULL) 00177 return; 00178 00179 /* calculate delta of constraints evaluation */ 00180 invert_m4_m4(imat, cob->startmat); 00181 mul_m4_m4m4(delta, imat, cob->matrix); 00182 00183 /* copy matrices back to source */ 00184 switch (cob->type) { 00185 case CONSTRAINT_OBTYPE_OBJECT: 00186 { 00187 /* cob->ob might not exist! */ 00188 if (cob->ob) { 00189 /* copy new ob-matrix back to owner */ 00190 copy_m4_m4(cob->ob->obmat, cob->matrix); 00191 00192 /* copy inverse of delta back to owner */ 00193 invert_m4_m4(cob->ob->constinv, delta); 00194 } 00195 } 00196 break; 00197 case CONSTRAINT_OBTYPE_BONE: 00198 { 00199 /* cob->ob or cob->pchan might not exist */ 00200 if (cob->ob && cob->pchan) { 00201 /* copy new pose-matrix back to owner */ 00202 mul_m4_m4m4(cob->pchan->pose_mat, cob->matrix, cob->ob->imat); 00203 00204 /* copy inverse of delta back to owner */ 00205 invert_m4_m4(cob->pchan->constinv, delta); 00206 } 00207 } 00208 break; 00209 } 00210 00211 /* free tempolary struct */ 00212 MEM_freeN(cob); 00213 } 00214 00215 /* -------------- Space-Conversion API -------------- */ 00216 00217 /* This function is responsible for the correct transformations/conversions 00218 * of a matrix from one space to another for constraint evaluation. 00219 * For now, this is only implemented for Objects and PoseChannels. 00220 */ 00221 void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4], short from, short to) 00222 { 00223 float tempmat[4][4]; 00224 float diff_mat[4][4]; 00225 float imat[4][4]; 00226 00227 /* prevent crashes in these unlikely events */ 00228 if (ob==NULL || mat==NULL) return; 00229 /* optimise trick - check if need to do anything */ 00230 if (from == to) return; 00231 00232 /* are we dealing with pose-channels or objects */ 00233 if (pchan) { 00234 /* pose channels */ 00235 switch (from) { 00236 case CONSTRAINT_SPACE_WORLD: /* ---------- FROM WORLDSPACE ---------- */ 00237 { 00238 /* world to pose */ 00239 invert_m4_m4(imat, ob->obmat); 00240 copy_m4_m4(tempmat, mat); 00241 mul_m4_m4m4(mat, tempmat, imat); 00242 00243 /* use pose-space as stepping stone for other spaces... */ 00244 if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { 00245 /* call self with slightly different values */ 00246 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); 00247 } 00248 } 00249 break; 00250 case CONSTRAINT_SPACE_POSE: /* ---------- FROM POSESPACE ---------- */ 00251 { 00252 /* pose to world */ 00253 if (to == CONSTRAINT_SPACE_WORLD) { 00254 copy_m4_m4(tempmat, mat); 00255 mul_m4_m4m4(mat, tempmat, ob->obmat); 00256 } 00257 /* pose to local */ 00258 else if (to == CONSTRAINT_SPACE_LOCAL) { 00259 if (pchan->bone) { 00260 if (pchan->parent) { 00261 float offs_bone[4][4]; 00262 00263 /* construct offs_bone the same way it is done in armature.c */ 00264 copy_m4_m3(offs_bone, pchan->bone->bone_mat); 00265 copy_v3_v3(offs_bone[3], pchan->bone->head); 00266 offs_bone[3][1]+= pchan->bone->parent->length; 00267 00268 if (pchan->bone->flag & BONE_HINGE) { 00269 /* pose_mat = par_pose-space_location * chan_mat */ 00270 float tmat[4][4]; 00271 00272 /* the rotation of the parent restposition */ 00273 copy_m4_m4(tmat, pchan->bone->parent->arm_mat); 00274 00275 /* the location of actual parent transform */ 00276 copy_v3_v3(tmat[3], offs_bone[3]); 00277 offs_bone[3][0]= offs_bone[3][1]= offs_bone[3][2]= 0.0f; 00278 mul_m4_v3(pchan->parent->pose_mat, tmat[3]); 00279 00280 mul_m4_m4m4(diff_mat, offs_bone, tmat); 00281 invert_m4_m4(imat, diff_mat); 00282 } 00283 else { 00284 /* pose_mat = par_pose_mat * bone_mat * chan_mat */ 00285 mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat); 00286 invert_m4_m4(imat, diff_mat); 00287 } 00288 } 00289 else { 00290 /* pose_mat = chan_mat * arm_mat */ 00291 invert_m4_m4(imat, pchan->bone->arm_mat); 00292 } 00293 00294 copy_m4_m4(tempmat, mat); 00295 mul_m4_m4m4(mat, tempmat, imat); 00296 } 00297 } 00298 /* pose to local with parent */ 00299 else if (to == CONSTRAINT_SPACE_PARLOCAL) { 00300 if (pchan->bone) { 00301 invert_m4_m4(imat, pchan->bone->arm_mat); 00302 copy_m4_m4(tempmat, mat); 00303 mul_m4_m4m4(mat, tempmat, imat); 00304 } 00305 } 00306 } 00307 break; 00308 case CONSTRAINT_SPACE_LOCAL: /* ------------ FROM LOCALSPACE --------- */ 00309 { 00310 /* local to pose - do inverse procedure that was done for pose to local */ 00311 if (pchan->bone) { 00312 /* we need the posespace_matrix = local_matrix + (parent_posespace_matrix + restpos) */ 00313 if (pchan->parent) { 00314 float offs_bone[4][4]; 00315 00316 /* construct offs_bone the same way it is done in armature.c */ 00317 copy_m4_m3(offs_bone, pchan->bone->bone_mat); 00318 copy_v3_v3(offs_bone[3], pchan->bone->head); 00319 offs_bone[3][1]+= pchan->bone->parent->length; 00320 00321 if (pchan->bone->flag & BONE_HINGE) { 00322 /* pose_mat = par_pose-space_location * chan_mat */ 00323 float tmat[4][4]; 00324 00325 /* the rotation of the parent restposition */ 00326 copy_m4_m4(tmat, pchan->bone->parent->arm_mat); 00327 00328 /* the location of actual parent transform */ 00329 copy_v3_v3(tmat[3], offs_bone[3]); 00330 zero_v3(offs_bone[3]); 00331 mul_m4_v3(pchan->parent->pose_mat, tmat[3]); 00332 00333 mul_m4_m4m4(diff_mat, offs_bone, tmat); 00334 copy_m4_m4(tempmat, mat); 00335 mul_m4_m4m4(mat, tempmat, diff_mat); 00336 } 00337 else { 00338 /* pose_mat = par_pose_mat * bone_mat * chan_mat */ 00339 mul_m4_m4m4(diff_mat, offs_bone, pchan->parent->pose_mat); 00340 copy_m4_m4(tempmat, mat); 00341 mul_m4_m4m4(mat, tempmat, diff_mat); 00342 } 00343 } 00344 else { 00345 copy_m4_m4(diff_mat, pchan->bone->arm_mat); 00346 00347 copy_m4_m4(tempmat, mat); 00348 mul_m4_m4m4(mat, tempmat, diff_mat); 00349 } 00350 } 00351 00352 /* use pose-space as stepping stone for other spaces */ 00353 if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { 00354 /* call self with slightly different values */ 00355 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); 00356 } 00357 } 00358 break; 00359 case CONSTRAINT_SPACE_PARLOCAL: /* -------------- FROM LOCAL WITH PARENT ---------- */ 00360 { 00361 /* local + parent to pose */ 00362 if (pchan->bone) { 00363 copy_m4_m4(diff_mat, pchan->bone->arm_mat); 00364 copy_m4_m4(tempmat, mat); 00365 mul_m4_m4m4(mat, diff_mat, tempmat); 00366 } 00367 00368 /* use pose-space as stepping stone for other spaces */ 00369 if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { 00370 /* call self with slightly different values */ 00371 constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); 00372 } 00373 } 00374 break; 00375 } 00376 } 00377 else { 00378 /* objects */ 00379 if (from==CONSTRAINT_SPACE_WORLD && to==CONSTRAINT_SPACE_LOCAL) { 00380 /* check if object has a parent */ 00381 if (ob->parent) { 00382 /* 'subtract' parent's effects from owner */ 00383 mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat); 00384 invert_m4_m4(imat, diff_mat); 00385 copy_m4_m4(tempmat, mat); 00386 mul_m4_m4m4(mat, tempmat, imat); 00387 } 00388 else { 00389 /* Local space in this case will have to be defined as local to the owner's 00390 * transform-property-rotated axes. So subtract this rotation component. 00391 */ 00392 object_to_mat4(ob, diff_mat); 00393 normalize_m4(diff_mat); 00394 zero_v3(diff_mat[3]); 00395 00396 invert_m4_m4(imat, diff_mat); 00397 copy_m4_m4(tempmat, mat); 00398 mul_m4_m4m4(mat, tempmat, imat); 00399 } 00400 } 00401 else if (from==CONSTRAINT_SPACE_LOCAL && to==CONSTRAINT_SPACE_WORLD) { 00402 /* check that object has a parent - otherwise this won't work */ 00403 if (ob->parent) { 00404 /* 'add' parent's effect back to owner */ 00405 copy_m4_m4(tempmat, mat); 00406 mul_m4_m4m4(diff_mat, ob->parentinv, ob->parent->obmat); 00407 mul_m4_m4m4(mat, tempmat, diff_mat); 00408 } 00409 else { 00410 /* Local space in this case will have to be defined as local to the owner's 00411 * transform-property-rotated axes. So add back this rotation component. 00412 */ 00413 object_to_mat4(ob, diff_mat); 00414 normalize_m4(diff_mat); 00415 zero_v3(diff_mat[3]); 00416 00417 copy_m4_m4(tempmat, mat); 00418 mul_m4_m4m4(mat, tempmat, diff_mat); 00419 } 00420 } 00421 } 00422 } 00423 00424 /* ------------ General Target Matrix Tools ---------- */ 00425 00426 /* function that sets the given matrix based on given vertex group in mesh */ 00427 static void contarget_get_mesh_mat (Object *ob, const char *substring, float mat[][4]) 00428 { 00429 DerivedMesh *dm = NULL; 00430 Mesh *me= ob->data; 00431 EditMesh *em = BKE_mesh_get_editmesh(me); 00432 float vec[3] = {0.0f, 0.0f, 0.0f}; 00433 float normal[3] = {0.0f, 0.0f, 0.0f}, plane[3]; 00434 float imat[3][3], tmat[3][3]; 00435 int dgroup; 00436 short freeDM = 0; 00437 00438 /* initialize target matrix using target matrix */ 00439 copy_m4_m4(mat, ob->obmat); 00440 00441 /* get index of vertex group */ 00442 dgroup = defgroup_name_index(ob, substring); 00443 if (dgroup < 0) return; 00444 00445 /* get DerivedMesh */ 00446 if (em) { 00447 /* target is in editmode, so get a special derived mesh */ 00448 dm = CDDM_from_editmesh(em, ob->data); 00449 freeDM= 1; 00450 } 00451 else { 00452 /* when not in EditMode, use the 'final' derived mesh, depsgraph 00453 * ensures we build with CD_MDEFORMVERT layer */ 00454 dm = (DerivedMesh *)ob->derivedFinal; 00455 } 00456 00457 /* only continue if there's a valid DerivedMesh */ 00458 if (dm) { 00459 MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); 00460 int numVerts = dm->getNumVerts(dm); 00461 int i, j, count = 0; 00462 float co[3], nor[3]; 00463 00464 /* check that dvert is a valid pointers (just in case) */ 00465 if (dvert) { 00466 /* get the average of all verts with that are in the vertex-group */ 00467 for (i = 0; i < numVerts; i++) { 00468 for (j = 0; j < dvert[i].totweight; j++) { 00469 /* does this vertex belong to nominated vertex group? */ 00470 if (dvert[i].dw[j].def_nr == dgroup) { 00471 dm->getVertCo(dm, i, co); 00472 dm->getVertNo(dm, i, nor); 00473 add_v3_v3(vec, co); 00474 add_v3_v3(normal, nor); 00475 count++; 00476 break; 00477 } 00478 00479 } 00480 } 00481 00482 00483 /* calculate averages of normal and coordinates */ 00484 if (count > 0) { 00485 mul_v3_fl(vec, 1.0f / count); 00486 mul_v3_fl(normal, 1.0f / count); 00487 } 00488 00489 00490 /* derive the rotation from the average normal: 00491 * - code taken from transform_manipulator.c, 00492 * calc_manipulator_stats, V3D_MANIP_NORMAL case 00493 */ 00494 /* we need the transpose of the inverse for a normal... */ 00495 copy_m3_m4(imat, ob->obmat); 00496 00497 invert_m3_m3(tmat, imat); 00498 transpose_m3(tmat); 00499 mul_m3_v3(tmat, normal); 00500 00501 normalize_v3(normal); 00502 copy_v3_v3(plane, tmat[1]); 00503 00504 copy_v3_v3(tmat[2], normal); 00505 cross_v3_v3v3(tmat[0], normal, plane); 00506 cross_v3_v3v3(tmat[1], tmat[2], tmat[0]); 00507 00508 copy_m4_m3(mat, tmat); 00509 normalize_m4(mat); 00510 00511 00512 /* apply the average coordinate as the new location */ 00513 mul_v3_m4v3(mat[3], ob->obmat, vec); 00514 } 00515 } 00516 00517 /* free temporary DerivedMesh created (in EditMode case) */ 00518 if (dm && freeDM) 00519 dm->release(dm); 00520 if (em) 00521 BKE_mesh_end_editmesh(me, em); 00522 } 00523 00524 /* function that sets the given matrix based on given vertex group in lattice */ 00525 static void contarget_get_lattice_mat (Object *ob, const char *substring, float mat[][4]) 00526 { 00527 Lattice *lt= (Lattice *)ob->data; 00528 00529 DispList *dl = find_displist(&ob->disp, DL_VERTS); 00530 float *co = dl?dl->verts:NULL; 00531 BPoint *bp = lt->def; 00532 00533 MDeformVert *dvert = lt->dvert; 00534 int tot_verts= lt->pntsu*lt->pntsv*lt->pntsw; 00535 float vec[3]= {0.0f, 0.0f, 0.0f}, tvec[3]; 00536 int dgroup=0, grouped=0; 00537 int i, n; 00538 00539 /* initialize target matrix using target matrix */ 00540 copy_m4_m4(mat, ob->obmat); 00541 00542 /* get index of vertex group */ 00543 dgroup = defgroup_name_index(ob, substring); 00544 if (dgroup < 0) return; 00545 if (dvert == NULL) return; 00546 00547 /* 1. Loop through control-points checking if in nominated vertex-group. 00548 * 2. If it is, add it to vec to find the average point. 00549 */ 00550 for (i=0; i < tot_verts; i++, dvert++) { 00551 for (n= 0; n < dvert->totweight; n++) { 00552 /* found match - vert is in vgroup */ 00553 if (dvert->dw[n].def_nr == dgroup) { 00554 /* copy coordinates of point to temporary vector, then add to find average */ 00555 if (co) 00556 memcpy(tvec, co, 3*sizeof(float)); 00557 else 00558 memcpy(tvec, bp->vec, 3*sizeof(float)); 00559 00560 add_v3_v3(vec, tvec); 00561 grouped++; 00562 00563 break; 00564 } 00565 } 00566 00567 /* advance pointer to coordinate data */ 00568 if (co) co+= 3; 00569 else bp++; 00570 } 00571 00572 /* find average location, then multiply by ob->obmat to find world-space location */ 00573 if (grouped) 00574 mul_v3_fl(vec, 1.0f / grouped); 00575 mul_v3_m4v3(tvec, ob->obmat, vec); 00576 00577 /* copy new location to matrix */ 00578 copy_v3_v3(mat[3], tvec); 00579 } 00580 00581 /* generic function to get the appropriate matrix for most target cases */ 00582 /* The cases where the target can be object data have not been implemented */ 00583 static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to, float headtail) 00584 { 00585 /* Case OBJECT */ 00586 if (!strlen(substring)) { 00587 copy_m4_m4(mat, ob->obmat); 00588 constraint_mat_convertspace(ob, NULL, mat, from, to); 00589 } 00590 /* Case VERTEXGROUP */ 00591 /* Current method just takes the average location of all the points in the 00592 * VertexGroup, and uses that as the location value of the targets. Where 00593 * possible, the orientation will also be calculated, by calculating an 00594 * 'average' vertex normal, and deriving the rotaation from that. 00595 * 00596 * NOTE: EditMode is not currently supported, and will most likely remain that 00597 * way as constraints can only really affect things on object/bone level. 00598 */ 00599 else if (ob->type == OB_MESH) { 00600 contarget_get_mesh_mat(ob, substring, mat); 00601 constraint_mat_convertspace(ob, NULL, mat, from, to); 00602 } 00603 else if (ob->type == OB_LATTICE) { 00604 contarget_get_lattice_mat(ob, substring, mat); 00605 constraint_mat_convertspace(ob, NULL, mat, from, to); 00606 } 00607 /* Case BONE */ 00608 else { 00609 bPoseChannel *pchan; 00610 00611 pchan = get_pose_channel(ob->pose, substring); 00612 if (pchan) { 00613 /* Multiply the PoseSpace accumulation/final matrix for this 00614 * PoseChannel by the Armature Object's Matrix to get a worldspace 00615 * matrix. 00616 */ 00617 if (headtail < 0.000001f) { 00618 /* skip length interpolation if set to head */ 00619 mul_m4_m4m4(mat, pchan->pose_mat, ob->obmat); 00620 } 00621 else { 00622 float tempmat[4][4], loc[3]; 00623 00624 /* interpolate along length of bone */ 00625 interp_v3_v3v3(loc, pchan->pose_head, pchan->pose_tail, headtail); 00626 00627 /* use interpolated distance for subtarget */ 00628 copy_m4_m4(tempmat, pchan->pose_mat); 00629 copy_v3_v3(tempmat[3], loc); 00630 00631 mul_m4_m4m4(mat, tempmat, ob->obmat); 00632 } 00633 } 00634 else 00635 copy_m4_m4(mat, ob->obmat); 00636 00637 /* convert matrix space as required */ 00638 constraint_mat_convertspace(ob, pchan, mat, from, to); 00639 } 00640 } 00641 00642 /* ************************* Specific Constraints ***************************** */ 00643 /* Each constraint defines a set of functions, which will be called at the appropriate 00644 * times. In addition to this, each constraint should have a type-info struct, where 00645 * its functions are attached for use. 00646 */ 00647 00648 /* Template for type-info data: 00649 * - make a copy of this when creating new constraints, and just change the functions 00650 * pointed to as necessary 00651 * - although the naming of functions doesn't matter, it would help for code 00652 * readability, to follow the same naming convention as is presented here 00653 * - any functions that a constraint doesn't need to define, don't define 00654 * for such cases, just use NULL 00655 * - these should be defined after all the functions have been defined, so that 00656 * forward-definitions/prototypes don't need to be used! 00657 * - keep this copy #if-def'd so that future constraints can get based off this 00658 */ 00659 #if 0 00660 static bConstraintTypeInfo CTI_CONSTRNAME = { 00661 CONSTRAINT_TYPE_CONSTRNAME, /* type */ 00662 sizeof(bConstrNameConstraint), /* size */ 00663 "ConstrName", /* name */ 00664 "bConstrNameConstraint", /* struct name */ 00665 constrname_free, /* free data */ 00666 constrname_relink, /* relink data */ 00667 constrname_id_looper, /* id looper */ 00668 constrname_copy, /* copy data */ 00669 constrname_new_data, /* new data */ 00670 constrname_get_tars, /* get constraint targets */ 00671 constrname_flush_tars, /* flush constraint targets */ 00672 constrname_get_tarmat, /* get target matrix */ 00673 constrname_evaluate /* evaluate */ 00674 }; 00675 #endif 00676 00677 /* This function should be used for the get_target_matrix member of all 00678 * constraints that are not picky about what happens to their target matrix. 00679 */ 00680 static void default_get_tarmat (bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime)) 00681 { 00682 if (VALID_CONS_TARGET(ct)) 00683 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); 00684 else if (ct) 00685 unit_m4(ct->matrix); 00686 } 00687 00688 /* This following macro should be used for all standard single-target *_get_tars functions 00689 * to save typing and reduce maintainance woes. 00690 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are 00691 * really just to help this code easier to read) 00692 */ 00693 // TODO: cope with getting rotation order... 00694 #define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \ 00695 { \ 00696 ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ 00697 \ 00698 ct->tar= datatar; \ 00699 BLI_strncpy(ct->subtarget, datasubtarget, sizeof(ct->subtarget)); \ 00700 ct->space= con->tarspace; \ 00701 ct->flag= CONSTRAINT_TAR_TEMP; \ 00702 \ 00703 if (ct->tar) { \ 00704 if ((ct->tar->type==OB_ARMATURE) && (ct->subtarget[0])) { \ 00705 bPoseChannel *pchan= get_pose_channel(ct->tar->pose, ct->subtarget); \ 00706 ct->type = CONSTRAINT_OBTYPE_BONE; \ 00707 ct->rotOrder= (pchan) ? (pchan->rotmode) : EULER_ORDER_DEFAULT; \ 00708 }\ 00709 else if (ELEM(ct->tar->type, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { \ 00710 ct->type = CONSTRAINT_OBTYPE_VERT; \ 00711 ct->rotOrder = EULER_ORDER_DEFAULT; \ 00712 } \ 00713 else {\ 00714 ct->type = CONSTRAINT_OBTYPE_OBJECT; \ 00715 ct->rotOrder= ct->tar->rotmode; \ 00716 } \ 00717 } \ 00718 \ 00719 BLI_addtail(list, ct); \ 00720 } 00721 00722 /* This following macro should be used for all standard single-target *_get_tars functions 00723 * to save typing and reduce maintainance woes. It does not do the subtarget related operations 00724 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are 00725 * really just to help this code easier to read) 00726 */ 00727 // TODO: cope with getting rotation order... 00728 #define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \ 00729 { \ 00730 ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ 00731 \ 00732 ct->tar= datatar; \ 00733 ct->space= con->tarspace; \ 00734 ct->flag= CONSTRAINT_TAR_TEMP; \ 00735 \ 00736 if (ct->tar) ct->type = CONSTRAINT_OBTYPE_OBJECT; \ 00737 \ 00738 BLI_addtail(list, ct); \ 00739 } 00740 00741 /* This following macro should be used for all standard single-target *_flush_tars functions 00742 * to save typing and reduce maintainance woes. 00743 * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) 00744 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are 00745 * really just to help this code easier to read) 00746 */ 00747 #define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, nocopy) \ 00748 { \ 00749 if (ct) { \ 00750 bConstraintTarget *ctn = ct->next; \ 00751 if (nocopy == 0) { \ 00752 datatar= ct->tar; \ 00753 BLI_strncpy(datasubtarget, ct->subtarget, sizeof(datasubtarget)); \ 00754 con->tarspace= (char)ct->space; \ 00755 } \ 00756 \ 00757 BLI_freelinkN(list, ct); \ 00758 ct= ctn; \ 00759 } \ 00760 } 00761 00762 /* This following macro should be used for all standard single-target *_flush_tars functions 00763 * to save typing and reduce maintainance woes. It does not do the subtarget related operations. 00764 * Note: the pointer to ct will be changed to point to the next in the list (as it gets removed) 00765 * (Hopefully all compilers will be happy with the lines with just a space on them. Those are 00766 * really just to help this code easier to read) 00767 */ 00768 #define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, nocopy) \ 00769 { \ 00770 if (ct) { \ 00771 bConstraintTarget *ctn = ct->next; \ 00772 if (nocopy == 0) { \ 00773 datatar= ct->tar; \ 00774 con->tarspace= (char)ct->space; \ 00775 } \ 00776 \ 00777 BLI_freelinkN(list, ct); \ 00778 ct= ctn; \ 00779 } \ 00780 } 00781 00782 /* --------- ChildOf Constraint ------------ */ 00783 00784 static void childof_new_data (void *cdata) 00785 { 00786 bChildOfConstraint *data= (bChildOfConstraint *)cdata; 00787 00788 data->flag = (CHILDOF_LOCX | CHILDOF_LOCY | CHILDOF_LOCZ | 00789 CHILDOF_ROTX |CHILDOF_ROTY | CHILDOF_ROTZ | 00790 CHILDOF_SIZEX | CHILDOF_SIZEY | CHILDOF_SIZEZ); 00791 unit_m4(data->invmat); 00792 } 00793 00794 static void childof_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 00795 { 00796 bChildOfConstraint *data= con->data; 00797 00798 /* target only */ 00799 func(con, (ID**)&data->tar, userdata); 00800 } 00801 00802 static int childof_get_tars (bConstraint *con, ListBase *list) 00803 { 00804 if (con && list) { 00805 bChildOfConstraint *data= con->data; 00806 bConstraintTarget *ct; 00807 00808 /* standard target-getting macro for single-target constraints */ 00809 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 00810 00811 return 1; 00812 } 00813 00814 return 0; 00815 } 00816 00817 static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy) 00818 { 00819 if (con && list) { 00820 bChildOfConstraint *data= con->data; 00821 bConstraintTarget *ct= list->first; 00822 00823 /* the following macro is used for all standard single-target constraints */ 00824 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 00825 } 00826 } 00827 00828 static void childof_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 00829 { 00830 bChildOfConstraint *data= con->data; 00831 bConstraintTarget *ct= targets->first; 00832 00833 /* only evaluate if there is a target */ 00834 if (VALID_CONS_TARGET(ct)) { 00835 float parmat[4][4]; 00836 00837 /* simple matrix parenting */ 00838 if(data->flag == CHILDOF_ALL) { 00839 00840 /* multiply target (parent matrix) by offset (parent inverse) to get 00841 * the effect of the parent that will be exherted on the owner 00842 */ 00843 mul_m4_m4m4(parmat, data->invmat, ct->matrix); 00844 00845 /* now multiply the parent matrix by the owner matrix to get the 00846 * the effect of this constraint (i.e. owner is 'parented' to parent) 00847 */ 00848 mul_m4_m4m4(cob->matrix, cob->matrix, parmat); 00849 } 00850 else { 00851 float invmat[4][4], tempmat[4][4]; 00852 float loc[3], eul[3], size[3]; 00853 float loco[3], eulo[3], sizo[3]; 00854 00855 /* get offset (parent-inverse) matrix */ 00856 copy_m4_m4(invmat, data->invmat); 00857 00858 /* extract components of both matrices */ 00859 copy_v3_v3(loc, ct->matrix[3]); 00860 mat4_to_eulO(eul, ct->rotOrder, ct->matrix); 00861 mat4_to_size(size, ct->matrix); 00862 00863 copy_v3_v3(loco, invmat[3]); 00864 mat4_to_eulO(eulo, cob->rotOrder, invmat); 00865 mat4_to_size(sizo, invmat); 00866 00867 /* disable channels not enabled */ 00868 if (!(data->flag & CHILDOF_LOCX)) loc[0]= loco[0]= 0.0f; 00869 if (!(data->flag & CHILDOF_LOCY)) loc[1]= loco[1]= 0.0f; 00870 if (!(data->flag & CHILDOF_LOCZ)) loc[2]= loco[2]= 0.0f; 00871 if (!(data->flag & CHILDOF_ROTX)) eul[0]= eulo[0]= 0.0f; 00872 if (!(data->flag & CHILDOF_ROTY)) eul[1]= eulo[1]= 0.0f; 00873 if (!(data->flag & CHILDOF_ROTZ)) eul[2]= eulo[2]= 0.0f; 00874 if (!(data->flag & CHILDOF_SIZEX)) size[0]= sizo[0]= 1.0f; 00875 if (!(data->flag & CHILDOF_SIZEY)) size[1]= sizo[1]= 1.0f; 00876 if (!(data->flag & CHILDOF_SIZEZ)) size[2]= sizo[2]= 1.0f; 00877 00878 /* make new target mat and offset mat */ 00879 loc_eulO_size_to_mat4(ct->matrix, loc, eul, size, ct->rotOrder); 00880 loc_eulO_size_to_mat4(invmat, loco, eulo, sizo, cob->rotOrder); 00881 00882 /* multiply target (parent matrix) by offset (parent inverse) to get 00883 * the effect of the parent that will be exherted on the owner 00884 */ 00885 mul_m4_m4m4(parmat, invmat, ct->matrix); 00886 00887 /* now multiply the parent matrix by the owner matrix to get the 00888 * the effect of this constraint (i.e. owner is 'parented' to parent) 00889 */ 00890 copy_m4_m4(tempmat, cob->matrix); 00891 mul_m4_m4m4(cob->matrix, tempmat, parmat); 00892 00893 /* without this, changes to scale and rotation can change location 00894 * of a parentless bone or a disconnected bone. Even though its set 00895 * to zero above. */ 00896 if (!(data->flag & CHILDOF_LOCX)) cob->matrix[3][0]= tempmat[3][0]; 00897 if (!(data->flag & CHILDOF_LOCY)) cob->matrix[3][1]= tempmat[3][1]; 00898 if (!(data->flag & CHILDOF_LOCZ)) cob->matrix[3][2]= tempmat[3][2]; 00899 } 00900 } 00901 } 00902 00903 /* XXX note, con->flag should be CONSTRAINT_SPACEONCE for bone-childof, patched in readfile.c */ 00904 static bConstraintTypeInfo CTI_CHILDOF = { 00905 CONSTRAINT_TYPE_CHILDOF, /* type */ 00906 sizeof(bChildOfConstraint), /* size */ 00907 "ChildOf", /* name */ 00908 "bChildOfConstraint", /* struct name */ 00909 NULL, /* free data */ 00910 NULL, /* relink data */ 00911 childof_id_looper, /* id looper */ 00912 NULL, /* copy data */ 00913 childof_new_data, /* new data */ 00914 childof_get_tars, /* get constraint targets */ 00915 childof_flush_tars, /* flush constraint targets */ 00916 default_get_tarmat, /* get a target matrix */ 00917 childof_evaluate /* evaluate */ 00918 }; 00919 00920 /* -------- TrackTo Constraint ------- */ 00921 00922 static void trackto_new_data (void *cdata) 00923 { 00924 bTrackToConstraint *data= (bTrackToConstraint *)cdata; 00925 00926 data->reserved1 = TRACK_Y; 00927 data->reserved2 = UP_Z; 00928 } 00929 00930 static void trackto_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 00931 { 00932 bTrackToConstraint *data= con->data; 00933 00934 /* target only */ 00935 func(con, (ID**)&data->tar, userdata); 00936 } 00937 00938 static int trackto_get_tars (bConstraint *con, ListBase *list) 00939 { 00940 if (con && list) { 00941 bTrackToConstraint *data= con->data; 00942 bConstraintTarget *ct; 00943 00944 /* standard target-getting macro for single-target constraints */ 00945 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 00946 00947 return 1; 00948 } 00949 00950 return 0; 00951 } 00952 00953 static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy) 00954 { 00955 if (con && list) { 00956 bTrackToConstraint *data= con->data; 00957 bConstraintTarget *ct= list->first; 00958 00959 /* the following macro is used for all standard single-target constraints */ 00960 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 00961 } 00962 } 00963 00964 00965 static int basis_cross (int n, int m) 00966 { 00967 switch (n-m) { 00968 case 1: 00969 case -2: 00970 return 1; 00971 00972 case -1: 00973 case 2: 00974 return -1; 00975 00976 default: 00977 return 0; 00978 } 00979 } 00980 00981 static void vectomat (float *vec, float *target_up, short axis, short upflag, short flags, float m[][3]) 00982 { 00983 float n[3]; 00984 float u[3]; /* vector specifying the up axis */ 00985 float proj[3]; 00986 float right[3]; 00987 float neg = -1; 00988 int right_index; 00989 00990 if (normalize_v3_v3(n, vec) == 0.0f) { 00991 n[0] = 0.0f; 00992 n[1] = 0.0f; 00993 n[2] = 1.0f; 00994 } 00995 if (axis > 2) axis -= 3; 00996 else negate_v3(n); 00997 00998 /* n specifies the transformation of the track axis */ 00999 if (flags & TARGET_Z_UP) { 01000 /* target Z axis is the global up axis */ 01001 copy_v3_v3(u, target_up); 01002 } 01003 else { 01004 /* world Z axis is the global up axis */ 01005 u[0] = 0; 01006 u[1] = 0; 01007 u[2] = 1; 01008 } 01009 01010 /* project the up vector onto the plane specified by n */ 01011 project_v3_v3v3(proj, u, n); /* first u onto n... */ 01012 sub_v3_v3v3(proj, u, proj); /* then onto the plane */ 01013 /* proj specifies the transformation of the up axis */ 01014 01015 if (normalize_v3(proj) == 0.0f) { /* degenerate projection */ 01016 proj[0] = 0.0f; 01017 proj[1] = 1.0f; 01018 proj[2] = 0.0f; 01019 } 01020 01021 /* Normalized cross product of n and proj specifies transformation of the right axis */ 01022 cross_v3_v3v3(right, proj, n); 01023 normalize_v3(right); 01024 01025 if (axis != upflag) { 01026 right_index = 3 - axis - upflag; 01027 neg = (float)basis_cross(axis, upflag); 01028 01029 /* account for up direction, track direction */ 01030 m[right_index][0] = neg * right[0]; 01031 m[right_index][1] = neg * right[1]; 01032 m[right_index][2] = neg * right[2]; 01033 01034 copy_v3_v3(m[upflag], proj); 01035 01036 copy_v3_v3(m[axis], n); 01037 } 01038 /* identity matrix - don't do anything if the two axes are the same */ 01039 else { 01040 unit_m3(m); 01041 } 01042 } 01043 01044 01045 static void trackto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 01046 { 01047 bTrackToConstraint *data= con->data; 01048 bConstraintTarget *ct= targets->first; 01049 01050 if (VALID_CONS_TARGET(ct)) { 01051 float size[3], vec[3]; 01052 float totmat[3][3]; 01053 float tmat[4][4]; 01054 01055 /* Get size property, since ob->size is only the object's own relative size, not its global one */ 01056 mat4_to_size(size, cob->matrix); 01057 01058 /* Clear the object's rotation */ 01059 cob->matrix[0][0]=size[0]; 01060 cob->matrix[0][1]=0; 01061 cob->matrix[0][2]=0; 01062 cob->matrix[1][0]=0; 01063 cob->matrix[1][1]=size[1]; 01064 cob->matrix[1][2]=0; 01065 cob->matrix[2][0]=0; 01066 cob->matrix[2][1]=0; 01067 cob->matrix[2][2]=size[2]; 01068 01069 /* targetmat[2] instead of ownermat[2] is passed to vectomat 01070 * for backwards compatability it seems... (Aligorith) 01071 */ 01072 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]); 01073 vectomat(vec, ct->matrix[2], 01074 (short)data->reserved1, (short)data->reserved2, 01075 data->flags, totmat); 01076 01077 copy_m4_m4(tmat, cob->matrix); 01078 mul_m4_m3m4(cob->matrix, totmat, tmat); 01079 } 01080 } 01081 01082 static bConstraintTypeInfo CTI_TRACKTO = { 01083 CONSTRAINT_TYPE_TRACKTO, /* type */ 01084 sizeof(bTrackToConstraint), /* size */ 01085 "TrackTo", /* name */ 01086 "bTrackToConstraint", /* struct name */ 01087 NULL, /* free data */ 01088 NULL, /* relink data */ 01089 trackto_id_looper, /* id looper */ 01090 NULL, /* copy data */ 01091 trackto_new_data, /* new data */ 01092 trackto_get_tars, /* get constraint targets */ 01093 trackto_flush_tars, /* flush constraint targets */ 01094 default_get_tarmat, /* get target matrix */ 01095 trackto_evaluate /* evaluate */ 01096 }; 01097 01098 /* --------- Inverse-Kinemetics --------- */ 01099 01100 static void kinematic_new_data (void *cdata) 01101 { 01102 bKinematicConstraint *data= (bKinematicConstraint *)cdata; 01103 01104 data->weight= (float)1.0; 01105 data->orientweight= (float)1.0; 01106 data->iterations = 500; 01107 data->dist= (float)1.0; 01108 data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS; 01109 } 01110 01111 static void kinematic_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01112 { 01113 bKinematicConstraint *data= con->data; 01114 01115 /* chain target */ 01116 func(con, (ID**)&data->tar, userdata); 01117 01118 /* poletarget */ 01119 func(con, (ID**)&data->poletar, userdata); 01120 } 01121 01122 static int kinematic_get_tars (bConstraint *con, ListBase *list) 01123 { 01124 if (con && list) { 01125 bKinematicConstraint *data= con->data; 01126 bConstraintTarget *ct; 01127 01128 /* standard target-getting macro for single-target constraints is used twice here */ 01129 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 01130 SINGLETARGET_GET_TARS(con, data->poletar, data->polesubtarget, ct, list) 01131 01132 return 2; 01133 } 01134 01135 return 0; 01136 } 01137 01138 static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01139 { 01140 if (con && list) { 01141 bKinematicConstraint *data= con->data; 01142 bConstraintTarget *ct= list->first; 01143 01144 /* the following macro is used for all standard single-target constraints */ 01145 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 01146 SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, nocopy) 01147 } 01148 } 01149 01150 static void kinematic_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 01151 { 01152 bKinematicConstraint *data= con->data; 01153 01154 if (VALID_CONS_TARGET(ct)) 01155 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); 01156 else if (ct) { 01157 if (data->flag & CONSTRAINT_IK_AUTO) { 01158 Object *ob= cob->ob; 01159 01160 if (ob == NULL) { 01161 unit_m4(ct->matrix); 01162 } 01163 else { 01164 float vec[3]; 01165 /* move grabtarget into world space */ 01166 mul_v3_m4v3(vec, ob->obmat, data->grabtarget); 01167 copy_m4_m4(ct->matrix, ob->obmat); 01168 copy_v3_v3(ct->matrix[3], vec); 01169 } 01170 } 01171 else 01172 unit_m4(ct->matrix); 01173 } 01174 } 01175 01176 static bConstraintTypeInfo CTI_KINEMATIC = { 01177 CONSTRAINT_TYPE_KINEMATIC, /* type */ 01178 sizeof(bKinematicConstraint), /* size */ 01179 "IK", /* name */ 01180 "bKinematicConstraint", /* struct name */ 01181 NULL, /* free data */ 01182 NULL, /* relink data */ 01183 kinematic_id_looper, /* id looper */ 01184 NULL, /* copy data */ 01185 kinematic_new_data, /* new data */ 01186 kinematic_get_tars, /* get constraint targets */ 01187 kinematic_flush_tars, /* flush constraint targets */ 01188 kinematic_get_tarmat, /* get target matrix */ 01189 NULL /* evaluate - solved as separate loop */ 01190 }; 01191 01192 /* -------- Follow-Path Constraint ---------- */ 01193 01194 static void followpath_new_data (void *cdata) 01195 { 01196 bFollowPathConstraint *data= (bFollowPathConstraint *)cdata; 01197 01198 data->trackflag = TRACK_Y; 01199 data->upflag = UP_Z; 01200 data->offset = 0; 01201 data->followflag = 0; 01202 } 01203 01204 static void followpath_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01205 { 01206 bFollowPathConstraint *data= con->data; 01207 01208 /* target only */ 01209 func(con, (ID**)&data->tar, userdata); 01210 } 01211 01212 static int followpath_get_tars (bConstraint *con, ListBase *list) 01213 { 01214 if (con && list) { 01215 bFollowPathConstraint *data= con->data; 01216 bConstraintTarget *ct; 01217 01218 /* standard target-getting macro for single-target constraints without subtargets */ 01219 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) 01220 01221 return 1; 01222 } 01223 01224 return 0; 01225 } 01226 01227 static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01228 { 01229 if (con && list) { 01230 bFollowPathConstraint *data= con->data; 01231 bConstraintTarget *ct= list->first; 01232 01233 /* the following macro is used for all standard single-target constraints */ 01234 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) 01235 } 01236 } 01237 01238 static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 01239 { 01240 bFollowPathConstraint *data= con->data; 01241 01242 if (VALID_CONS_TARGET(ct)) { 01243 Curve *cu= ct->tar->data; 01244 float vec[4], dir[3], radius; 01245 float totmat[4][4]= MAT4_UNITY; 01246 float curvetime; 01247 01248 unit_m4(ct->matrix); 01249 01250 /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, 01251 * currently for paths to work it needs to go through the bevlist/displist system (ton) 01252 */ 01253 01254 /* only happens on reload file, but violates depsgraph still... fix! */ 01255 if (cu->path==NULL || cu->path->data==NULL) 01256 makeDispListCurveTypes(cob->scene, ct->tar, 0); 01257 01258 if (cu->path && cu->path->data) { 01259 float quat[4]; 01260 if ((data->followflag & FOLLOWPATH_STATIC) == 0) { 01261 /* animated position along curve depending on time */ 01262 if (cob->scene) 01263 curvetime= bsystem_time(cob->scene, ct->tar, cu->ctime, 0.0) - data->offset; 01264 else 01265 curvetime= cu->ctime - data->offset; 01266 01267 /* ctime is now a proper var setting of Curve which gets set by Animato like any other var that's animated, 01268 * but this will only work if it actually is animated... 01269 * 01270 * we divide the curvetime calculated in the previous step by the length of the path, to get a time 01271 * factor, which then gets clamped to lie within 0.0 - 1.0 range 01272 */ 01273 curvetime /= cu->pathlen; 01274 CLAMP(curvetime, 0.0f, 1.0f); 01275 } 01276 else { 01277 /* fixed position along curve */ 01278 curvetime= data->offset_fac; 01279 } 01280 01281 if ( where_on_path(ct->tar, curvetime, vec, dir, (data->followflag & FOLLOWPATH_FOLLOW) ? quat : NULL, &radius, NULL) ) { /* quat_pt is quat or NULL*/ 01282 if (data->followflag & FOLLOWPATH_FOLLOW) { 01283 #if 0 01284 float x1, q[4]; 01285 vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag); 01286 01287 normalize_v3(dir); 01288 q[0]= (float)cos(0.5*vec[3]); 01289 x1= (float)sin(0.5*vec[3]); 01290 q[1]= -x1*dir[0]; 01291 q[2]= -x1*dir[1]; 01292 q[3]= -x1*dir[2]; 01293 mul_qt_qtqt(quat, q, quat); 01294 #else 01295 quat_apply_track(quat, data->trackflag, data->upflag); 01296 #endif 01297 01298 quat_to_mat4(totmat, quat); 01299 } 01300 01301 if (data->followflag & FOLLOWPATH_RADIUS) { 01302 float tmat[4][4], rmat[4][4]; 01303 scale_m4_fl(tmat, radius); 01304 mul_m4_m4m4(rmat, totmat, tmat); 01305 copy_m4_m4(totmat, rmat); 01306 } 01307 01308 copy_v3_v3(totmat[3], vec); 01309 01310 mul_serie_m4(ct->matrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL); 01311 } 01312 } 01313 } 01314 else if (ct) 01315 unit_m4(ct->matrix); 01316 } 01317 01318 static void followpath_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 01319 { 01320 bConstraintTarget *ct= targets->first; 01321 01322 /* only evaluate if there is a target */ 01323 if (VALID_CONS_TARGET(ct)) { 01324 float obmat[4][4]; 01325 float size[3]; 01326 bFollowPathConstraint *data= con->data; 01327 01328 /* get Object transform (loc/rot/size) to determine transformation from path */ 01329 // TODO: this used to be local at one point, but is probably more useful as-is 01330 copy_m4_m4(obmat, cob->matrix); 01331 01332 /* get scaling of object before applying constraint */ 01333 mat4_to_size(size, cob->matrix); 01334 01335 /* apply targetmat - containing location on path, and rotation */ 01336 mul_serie_m4(cob->matrix, ct->matrix, obmat, NULL, NULL, NULL, NULL, NULL, NULL); 01337 01338 /* un-apply scaling caused by path */ 01339 if ((data->followflag & FOLLOWPATH_RADIUS)==0) { /* XXX - assume that scale correction means that radius will have some scale error in it - Campbell */ 01340 float obsize[3]; 01341 01342 mat4_to_size( obsize,cob->matrix); 01343 if (obsize[0]) 01344 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]); 01345 if (obsize[1]) 01346 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]); 01347 if (obsize[2]) 01348 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]); 01349 } 01350 } 01351 } 01352 01353 static bConstraintTypeInfo CTI_FOLLOWPATH = { 01354 CONSTRAINT_TYPE_FOLLOWPATH, /* type */ 01355 sizeof(bFollowPathConstraint), /* size */ 01356 "Follow Path", /* name */ 01357 "bFollowPathConstraint", /* struct name */ 01358 NULL, /* free data */ 01359 NULL, /* relink data */ 01360 followpath_id_looper, /* id looper */ 01361 NULL, /* copy data */ 01362 followpath_new_data, /* new data */ 01363 followpath_get_tars, /* get constraint targets */ 01364 followpath_flush_tars, /* flush constraint targets */ 01365 followpath_get_tarmat, /* get target matrix */ 01366 followpath_evaluate /* evaluate */ 01367 }; 01368 01369 /* --------- Limit Location --------- */ 01370 01371 01372 static void loclimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) 01373 { 01374 bLocLimitConstraint *data = con->data; 01375 01376 if (data->flag & LIMIT_XMIN) { 01377 if (cob->matrix[3][0] < data->xmin) 01378 cob->matrix[3][0] = data->xmin; 01379 } 01380 if (data->flag & LIMIT_XMAX) { 01381 if (cob->matrix[3][0] > data->xmax) 01382 cob->matrix[3][0] = data->xmax; 01383 } 01384 if (data->flag & LIMIT_YMIN) { 01385 if (cob->matrix[3][1] < data->ymin) 01386 cob->matrix[3][1] = data->ymin; 01387 } 01388 if (data->flag & LIMIT_YMAX) { 01389 if (cob->matrix[3][1] > data->ymax) 01390 cob->matrix[3][1] = data->ymax; 01391 } 01392 if (data->flag & LIMIT_ZMIN) { 01393 if (cob->matrix[3][2] < data->zmin) 01394 cob->matrix[3][2] = data->zmin; 01395 } 01396 if (data->flag & LIMIT_ZMAX) { 01397 if (cob->matrix[3][2] > data->zmax) 01398 cob->matrix[3][2] = data->zmax; 01399 } 01400 } 01401 01402 static bConstraintTypeInfo CTI_LOCLIMIT = { 01403 CONSTRAINT_TYPE_LOCLIMIT, /* type */ 01404 sizeof(bLocLimitConstraint), /* size */ 01405 "Limit Location", /* name */ 01406 "bLocLimitConstraint", /* struct name */ 01407 NULL, /* free data */ 01408 NULL, /* relink data */ 01409 NULL, /* id looper */ 01410 NULL, /* copy data */ 01411 NULL, /* new data */ 01412 NULL, /* get constraint targets */ 01413 NULL, /* flush constraint targets */ 01414 NULL, /* get target matrix */ 01415 loclimit_evaluate /* evaluate */ 01416 }; 01417 01418 /* -------- Limit Rotation --------- */ 01419 01420 static void rotlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) 01421 { 01422 bRotLimitConstraint *data = con->data; 01423 float loc[3]; 01424 float eul[3]; 01425 float size[3]; 01426 01427 copy_v3_v3(loc, cob->matrix[3]); 01428 mat4_to_size(size, cob->matrix); 01429 01430 mat4_to_eulO(eul, cob->rotOrder, cob->matrix); 01431 01432 /* constraint data uses radians internally */ 01433 01434 /* limiting of euler values... */ 01435 if (data->flag & LIMIT_XROT) { 01436 if (eul[0] < data->xmin) 01437 eul[0] = data->xmin; 01438 01439 if (eul[0] > data->xmax) 01440 eul[0] = data->xmax; 01441 } 01442 if (data->flag & LIMIT_YROT) { 01443 if (eul[1] < data->ymin) 01444 eul[1] = data->ymin; 01445 01446 if (eul[1] > data->ymax) 01447 eul[1] = data->ymax; 01448 } 01449 if (data->flag & LIMIT_ZROT) { 01450 if (eul[2] < data->zmin) 01451 eul[2] = data->zmin; 01452 01453 if (eul[2] > data->zmax) 01454 eul[2] = data->zmax; 01455 } 01456 01457 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); 01458 } 01459 01460 static bConstraintTypeInfo CTI_ROTLIMIT = { 01461 CONSTRAINT_TYPE_ROTLIMIT, /* type */ 01462 sizeof(bRotLimitConstraint), /* size */ 01463 "Limit Rotation", /* name */ 01464 "bRotLimitConstraint", /* struct name */ 01465 NULL, /* free data */ 01466 NULL, /* relink data */ 01467 NULL, /* id looper */ 01468 NULL, /* copy data */ 01469 NULL, /* new data */ 01470 NULL, /* get constraint targets */ 01471 NULL, /* flush constraint targets */ 01472 NULL, /* get target matrix */ 01473 rotlimit_evaluate /* evaluate */ 01474 }; 01475 01476 /* --------- Limit Scaling --------- */ 01477 01478 01479 static void sizelimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) 01480 { 01481 bSizeLimitConstraint *data = con->data; 01482 float obsize[3], size[3]; 01483 01484 mat4_to_size( size,cob->matrix); 01485 mat4_to_size( obsize,cob->matrix); 01486 01487 if (data->flag & LIMIT_XMIN) { 01488 if (size[0] < data->xmin) 01489 size[0] = data->xmin; 01490 } 01491 if (data->flag & LIMIT_XMAX) { 01492 if (size[0] > data->xmax) 01493 size[0] = data->xmax; 01494 } 01495 if (data->flag & LIMIT_YMIN) { 01496 if (size[1] < data->ymin) 01497 size[1] = data->ymin; 01498 } 01499 if (data->flag & LIMIT_YMAX) { 01500 if (size[1] > data->ymax) 01501 size[1] = data->ymax; 01502 } 01503 if (data->flag & LIMIT_ZMIN) { 01504 if (size[2] < data->zmin) 01505 size[2] = data->zmin; 01506 } 01507 if (data->flag & LIMIT_ZMAX) { 01508 if (size[2] > data->zmax) 01509 size[2] = data->zmax; 01510 } 01511 01512 if (obsize[0]) 01513 mul_v3_fl(cob->matrix[0], size[0]/obsize[0]); 01514 if (obsize[1]) 01515 mul_v3_fl(cob->matrix[1], size[1]/obsize[1]); 01516 if (obsize[2]) 01517 mul_v3_fl(cob->matrix[2], size[2]/obsize[2]); 01518 } 01519 01520 static bConstraintTypeInfo CTI_SIZELIMIT = { 01521 CONSTRAINT_TYPE_SIZELIMIT, /* type */ 01522 sizeof(bSizeLimitConstraint), /* size */ 01523 "Limit Scaling", /* name */ 01524 "bSizeLimitConstraint", /* struct name */ 01525 NULL, /* free data */ 01526 NULL, /* relink data */ 01527 NULL, /* id looper */ 01528 NULL, /* copy data */ 01529 NULL, /* new data */ 01530 NULL, /* get constraint targets */ 01531 NULL, /* flush constraint targets */ 01532 NULL, /* get target matrix */ 01533 sizelimit_evaluate /* evaluate */ 01534 }; 01535 01536 /* ----------- Copy Location ------------- */ 01537 01538 static void loclike_new_data (void *cdata) 01539 { 01540 bLocateLikeConstraint *data= (bLocateLikeConstraint *)cdata; 01541 01542 data->flag = LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z; 01543 } 01544 01545 static void loclike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01546 { 01547 bLocateLikeConstraint *data= con->data; 01548 01549 /* target only */ 01550 func(con, (ID**)&data->tar, userdata); 01551 } 01552 01553 static int loclike_get_tars (bConstraint *con, ListBase *list) 01554 { 01555 if (con && list) { 01556 bLocateLikeConstraint *data= con->data; 01557 bConstraintTarget *ct; 01558 01559 /* standard target-getting macro for single-target constraints */ 01560 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 01561 01562 return 1; 01563 } 01564 01565 return 0; 01566 } 01567 01568 static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01569 { 01570 if (con && list) { 01571 bLocateLikeConstraint *data= con->data; 01572 bConstraintTarget *ct= list->first; 01573 01574 /* the following macro is used for all standard single-target constraints */ 01575 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 01576 } 01577 } 01578 01579 static void loclike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 01580 { 01581 bLocateLikeConstraint *data= con->data; 01582 bConstraintTarget *ct= targets->first; 01583 01584 if (VALID_CONS_TARGET(ct)) { 01585 float offset[3] = {0.0f, 0.0f, 0.0f}; 01586 01587 if (data->flag & LOCLIKE_OFFSET) 01588 copy_v3_v3(offset, cob->matrix[3]); 01589 01590 if (data->flag & LOCLIKE_X) { 01591 cob->matrix[3][0] = ct->matrix[3][0]; 01592 01593 if (data->flag & LOCLIKE_X_INVERT) cob->matrix[3][0] *= -1; 01594 cob->matrix[3][0] += offset[0]; 01595 } 01596 if (data->flag & LOCLIKE_Y) { 01597 cob->matrix[3][1] = ct->matrix[3][1]; 01598 01599 if (data->flag & LOCLIKE_Y_INVERT) cob->matrix[3][1] *= -1; 01600 cob->matrix[3][1] += offset[1]; 01601 } 01602 if (data->flag & LOCLIKE_Z) { 01603 cob->matrix[3][2] = ct->matrix[3][2]; 01604 01605 if (data->flag & LOCLIKE_Z_INVERT) cob->matrix[3][2] *= -1; 01606 cob->matrix[3][2] += offset[2]; 01607 } 01608 } 01609 } 01610 01611 static bConstraintTypeInfo CTI_LOCLIKE = { 01612 CONSTRAINT_TYPE_LOCLIKE, /* type */ 01613 sizeof(bLocateLikeConstraint), /* size */ 01614 "Copy Location", /* name */ 01615 "bLocateLikeConstraint", /* struct name */ 01616 NULL, /* free data */ 01617 NULL, /* relink data */ 01618 loclike_id_looper, /* id looper */ 01619 NULL, /* copy data */ 01620 loclike_new_data, /* new data */ 01621 loclike_get_tars, /* get constraint targets */ 01622 loclike_flush_tars, /* flush constraint targets */ 01623 default_get_tarmat, /* get target matrix */ 01624 loclike_evaluate /* evaluate */ 01625 }; 01626 01627 /* ----------- Copy Rotation ------------- */ 01628 01629 static void rotlike_new_data (void *cdata) 01630 { 01631 bRotateLikeConstraint *data= (bRotateLikeConstraint *)cdata; 01632 01633 data->flag = ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z; 01634 } 01635 01636 static void rotlike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01637 { 01638 bChildOfConstraint *data= con->data; 01639 01640 /* target only */ 01641 func(con, (ID**)&data->tar, userdata); 01642 } 01643 01644 static int rotlike_get_tars (bConstraint *con, ListBase *list) 01645 { 01646 if (con && list) { 01647 bRotateLikeConstraint *data= con->data; 01648 bConstraintTarget *ct; 01649 01650 /* standard target-getting macro for single-target constraints */ 01651 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 01652 01653 return 1; 01654 } 01655 01656 return 0; 01657 } 01658 01659 static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01660 { 01661 if (con && list) { 01662 bRotateLikeConstraint *data= con->data; 01663 bConstraintTarget *ct= list->first; 01664 01665 /* the following macro is used for all standard single-target constraints */ 01666 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 01667 } 01668 } 01669 01670 static void rotlike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 01671 { 01672 bRotateLikeConstraint *data= con->data; 01673 bConstraintTarget *ct= targets->first; 01674 01675 if (VALID_CONS_TARGET(ct)) { 01676 float loc[3]; 01677 float eul[3], obeul[3]; 01678 float size[3]; 01679 01680 copy_v3_v3(loc, cob->matrix[3]); 01681 mat4_to_size(size, cob->matrix); 01682 01683 /* to allow compatible rotations, must get both rotations in the order of the owner... */ 01684 mat4_to_eulO(obeul, cob->rotOrder, cob->matrix); 01685 /* we must get compatible eulers from the beginning because some of them can be modified below (see bug #21875) */ 01686 mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix); 01687 01688 if ((data->flag & ROTLIKE_X)==0) 01689 eul[0] = obeul[0]; 01690 else { 01691 if (data->flag & ROTLIKE_OFFSET) 01692 rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]); 01693 01694 if (data->flag & ROTLIKE_X_INVERT) 01695 eul[0] *= -1; 01696 } 01697 01698 if ((data->flag & ROTLIKE_Y)==0) 01699 eul[1] = obeul[1]; 01700 else { 01701 if (data->flag & ROTLIKE_OFFSET) 01702 rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]); 01703 01704 if (data->flag & ROTLIKE_Y_INVERT) 01705 eul[1] *= -1; 01706 } 01707 01708 if ((data->flag & ROTLIKE_Z)==0) 01709 eul[2] = obeul[2]; 01710 else { 01711 if (data->flag & ROTLIKE_OFFSET) 01712 rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]); 01713 01714 if (data->flag & ROTLIKE_Z_INVERT) 01715 eul[2] *= -1; 01716 } 01717 01718 /* good to make eulers compatible again, since we don't know how much they were changed above */ 01719 compatible_eul(eul, obeul); 01720 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); 01721 } 01722 } 01723 01724 static bConstraintTypeInfo CTI_ROTLIKE = { 01725 CONSTRAINT_TYPE_ROTLIKE, /* type */ 01726 sizeof(bRotateLikeConstraint), /* size */ 01727 "Copy Rotation", /* name */ 01728 "bRotateLikeConstraint", /* struct name */ 01729 NULL, /* free data */ 01730 NULL, /* relink data */ 01731 rotlike_id_looper, /* id looper */ 01732 NULL, /* copy data */ 01733 rotlike_new_data, /* new data */ 01734 rotlike_get_tars, /* get constraint targets */ 01735 rotlike_flush_tars, /* flush constraint targets */ 01736 default_get_tarmat, /* get target matrix */ 01737 rotlike_evaluate /* evaluate */ 01738 }; 01739 01740 /* ---------- Copy Scaling ---------- */ 01741 01742 static void sizelike_new_data (void *cdata) 01743 { 01744 bSizeLikeConstraint *data= (bSizeLikeConstraint *)cdata; 01745 01746 data->flag = SIZELIKE_X|SIZELIKE_Y|SIZELIKE_Z; 01747 } 01748 01749 static void sizelike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01750 { 01751 bSizeLikeConstraint *data= con->data; 01752 01753 /* target only */ 01754 func(con, (ID**)&data->tar, userdata); 01755 } 01756 01757 static int sizelike_get_tars (bConstraint *con, ListBase *list) 01758 { 01759 if (con && list) { 01760 bSizeLikeConstraint *data= con->data; 01761 bConstraintTarget *ct; 01762 01763 /* standard target-getting macro for single-target constraints */ 01764 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 01765 01766 return 1; 01767 } 01768 01769 return 0; 01770 } 01771 01772 static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01773 { 01774 if (con && list) { 01775 bSizeLikeConstraint *data= con->data; 01776 bConstraintTarget *ct= list->first; 01777 01778 /* the following macro is used for all standard single-target constraints */ 01779 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 01780 } 01781 } 01782 01783 static void sizelike_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 01784 { 01785 bSizeLikeConstraint *data= con->data; 01786 bConstraintTarget *ct= targets->first; 01787 01788 if (VALID_CONS_TARGET(ct)) { 01789 float obsize[3], size[3]; 01790 01791 mat4_to_size(size, ct->matrix); 01792 mat4_to_size(obsize, cob->matrix); 01793 01794 if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) { 01795 if (data->flag & SIZELIKE_OFFSET) { 01796 size[0] += (obsize[0] - 1.0f); 01797 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]); 01798 } 01799 else 01800 mul_v3_fl(cob->matrix[0], size[0] / obsize[0]); 01801 } 01802 if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) { 01803 if (data->flag & SIZELIKE_OFFSET) { 01804 size[1] += (obsize[1] - 1.0f); 01805 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]); 01806 } 01807 else 01808 mul_v3_fl(cob->matrix[1], size[1] / obsize[1]); 01809 } 01810 if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) { 01811 if (data->flag & SIZELIKE_OFFSET) { 01812 size[2] += (obsize[2] - 1.0f); 01813 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]); 01814 } 01815 else 01816 mul_v3_fl(cob->matrix[2], size[2] / obsize[2]); 01817 } 01818 } 01819 } 01820 01821 static bConstraintTypeInfo CTI_SIZELIKE = { 01822 CONSTRAINT_TYPE_SIZELIKE, /* type */ 01823 sizeof(bSizeLikeConstraint), /* size */ 01824 "Copy Scale", /* name */ 01825 "bSizeLikeConstraint", /* struct name */ 01826 NULL, /* free data */ 01827 NULL, /* relink data */ 01828 sizelike_id_looper, /* id looper */ 01829 NULL, /* copy data */ 01830 sizelike_new_data, /* new data */ 01831 sizelike_get_tars, /* get constraint targets */ 01832 sizelike_flush_tars, /* flush constraint targets */ 01833 default_get_tarmat, /* get target matrix */ 01834 sizelike_evaluate /* evaluate */ 01835 }; 01836 01837 /* ----------- Copy Transforms ------------- */ 01838 01839 static void translike_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 01840 { 01841 bTransLikeConstraint *data= con->data; 01842 01843 /* target only */ 01844 func(con, (ID**)&data->tar, userdata); 01845 } 01846 01847 static int translike_get_tars (bConstraint *con, ListBase *list) 01848 { 01849 if (con && list) { 01850 bTransLikeConstraint *data= con->data; 01851 bConstraintTarget *ct; 01852 01853 /* standard target-getting macro for single-target constraints */ 01854 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 01855 01856 return 1; 01857 } 01858 01859 return 0; 01860 } 01861 01862 static void translike_flush_tars (bConstraint *con, ListBase *list, short nocopy) 01863 { 01864 if (con && list) { 01865 bTransLikeConstraint *data= con->data; 01866 bConstraintTarget *ct= list->first; 01867 01868 /* the following macro is used for all standard single-target constraints */ 01869 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 01870 } 01871 } 01872 01873 static void translike_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) 01874 { 01875 bConstraintTarget *ct= targets->first; 01876 01877 if (VALID_CONS_TARGET(ct)) { 01878 /* just copy the entire transform matrix of the target */ 01879 copy_m4_m4(cob->matrix, ct->matrix); 01880 } 01881 } 01882 01883 static bConstraintTypeInfo CTI_TRANSLIKE = { 01884 CONSTRAINT_TYPE_TRANSLIKE, /* type */ 01885 sizeof(bTransLikeConstraint), /* size */ 01886 "Copy Transforms", /* name */ 01887 "bTransLikeConstraint", /* struct name */ 01888 NULL, /* free data */ 01889 NULL, /* relink data */ 01890 translike_id_looper, /* id looper */ 01891 NULL, /* copy data */ 01892 NULL, /* new data */ 01893 translike_get_tars, /* get constraint targets */ 01894 translike_flush_tars, /* flush constraint targets */ 01895 default_get_tarmat, /* get target matrix */ 01896 translike_evaluate /* evaluate */ 01897 }; 01898 01899 /* ---------- Maintain Volume ---------- */ 01900 01901 static void samevolume_new_data (void *cdata) 01902 { 01903 bSameVolumeConstraint *data= (bSameVolumeConstraint *)cdata; 01904 01905 data->flag = SAMEVOL_Y; 01906 data->volume = 1.0f; 01907 } 01908 01909 static void samevolume_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) 01910 { 01911 bSameVolumeConstraint *data= con->data; 01912 01913 float volume = data->volume; 01914 float fac = 1.0f; 01915 float obsize[3]; 01916 01917 mat4_to_size(obsize, cob->matrix); 01918 01919 /* calculate normalising scale factor for non-essential values */ 01920 if (obsize[data->flag] != 0) 01921 fac = sqrtf(volume / obsize[data->flag]) / obsize[data->flag]; 01922 01923 /* apply scaling factor to the channels not being kept */ 01924 switch (data->flag) { 01925 case SAMEVOL_X: 01926 mul_v3_fl(cob->matrix[1], fac); 01927 mul_v3_fl(cob->matrix[2], fac); 01928 break; 01929 case SAMEVOL_Y: 01930 mul_v3_fl(cob->matrix[0], fac); 01931 mul_v3_fl(cob->matrix[2], fac); 01932 break; 01933 case SAMEVOL_Z: 01934 mul_v3_fl(cob->matrix[0], fac); 01935 mul_v3_fl(cob->matrix[1], fac); 01936 break; 01937 } 01938 } 01939 01940 static bConstraintTypeInfo CTI_SAMEVOL = { 01941 CONSTRAINT_TYPE_SAMEVOL, /* type */ 01942 sizeof(bSameVolumeConstraint), /* size */ 01943 "Maintain Volume", /* name */ 01944 "bSameVolumeConstraint", /* struct name */ 01945 NULL, /* free data */ 01946 NULL, /* relink data */ 01947 NULL, /* id looper */ 01948 NULL, /* copy data */ 01949 samevolume_new_data, /* new data */ 01950 NULL, /* get constraint targets */ 01951 NULL, /* flush constraint targets */ 01952 NULL, /* get target matrix */ 01953 samevolume_evaluate /* evaluate */ 01954 }; 01955 01956 /* ----------- Python Constraint -------------- */ 01957 01958 static void pycon_free (bConstraint *con) 01959 { 01960 bPythonConstraint *data= con->data; 01961 01962 /* id-properties */ 01963 IDP_FreeProperty(data->prop); 01964 MEM_freeN(data->prop); 01965 01966 /* multiple targets */ 01967 BLI_freelistN(&data->targets); 01968 } 01969 01970 static void pycon_relink (bConstraint *con) 01971 { 01972 bPythonConstraint *data= con->data; 01973 01974 ID_NEW(data->text); 01975 } 01976 01977 static void pycon_copy (bConstraint *con, bConstraint *srccon) 01978 { 01979 bPythonConstraint *pycon = (bPythonConstraint *)con->data; 01980 bPythonConstraint *opycon = (bPythonConstraint *)srccon->data; 01981 01982 pycon->prop = IDP_CopyProperty(opycon->prop); 01983 BLI_duplicatelist(&pycon->targets, &opycon->targets); 01984 } 01985 01986 static void pycon_new_data (void *cdata) 01987 { 01988 bPythonConstraint *data= (bPythonConstraint *)cdata; 01989 01990 /* everything should be set correctly by calloc, except for the prop->type constant.*/ 01991 data->prop = MEM_callocN(sizeof(IDProperty), "PyConstraintProps"); 01992 data->prop->type = IDP_GROUP; 01993 } 01994 01995 static int pycon_get_tars (bConstraint *con, ListBase *list) 01996 { 01997 if (con && list) { 01998 bPythonConstraint *data= con->data; 01999 02000 list->first = data->targets.first; 02001 list->last = data->targets.last; 02002 02003 return data->tarnum; 02004 } 02005 02006 return 0; 02007 } 02008 02009 static void pycon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02010 { 02011 bPythonConstraint *data= con->data; 02012 bConstraintTarget *ct; 02013 02014 /* targets */ 02015 for (ct= data->targets.first; ct; ct= ct->next) 02016 func(con, (ID**)&ct->tar, userdata); 02017 02018 /* script */ 02019 func(con, (ID**)&data->text, userdata); 02020 } 02021 02022 /* Whether this approach is maintained remains to be seen (aligorith) */ 02023 static void pycon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 02024 { 02025 #ifdef WITH_PYTHON 02026 bPythonConstraint *data= con->data; 02027 #endif 02028 02029 if (VALID_CONS_TARGET(ct)) { 02030 /* special exception for curves - depsgraph issues */ 02031 if (ct->tar->type == OB_CURVE) { 02032 Curve *cu= ct->tar->data; 02033 02034 /* this check is to make sure curve objects get updated on file load correctly.*/ 02035 if (cu->path==NULL || cu->path->data==NULL) /* only happens on reload file, but violates depsgraph still... fix! */ 02036 makeDispListCurveTypes(cob->scene, ct->tar, 0); 02037 } 02038 02039 /* firstly calculate the matrix the normal way, then let the py-function override 02040 * this matrix if it needs to do so 02041 */ 02042 constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); 02043 02044 /* only execute target calculation if allowed */ 02045 #ifdef WITH_PYTHON 02046 if (G.f & G_SCRIPT_AUTOEXEC) 02047 BPY_pyconstraint_target(data, ct); 02048 #endif 02049 } 02050 else if (ct) 02051 unit_m4(ct->matrix); 02052 } 02053 02054 static void pycon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 02055 { 02056 #ifndef WITH_PYTHON 02057 (void)con; (void)cob; (void)targets; /* unused */ 02058 return; 02059 #else 02060 bPythonConstraint *data= con->data; 02061 02062 /* only evaluate in python if we're allowed to do so */ 02063 if ((G.f & G_SCRIPT_AUTOEXEC)==0) return; 02064 02065 /* currently removed, until I this can be re-implemented for multiple targets */ 02066 #if 0 02067 /* Firstly, run the 'driver' function which has direct access to the objects involved 02068 * Technically, this is potentially dangerous as users may abuse this and cause dependency-problems, 02069 * but it also allows certain 'clever' rigging hacks to work. 02070 */ 02071 BPY_pyconstraint_driver(data, cob, targets); 02072 #endif 02073 02074 /* Now, run the actual 'constraint' function, which should only access the matrices */ 02075 BPY_pyconstraint_exec(data, cob, targets); 02076 #endif /* WITH_PYTHON */ 02077 } 02078 02079 static bConstraintTypeInfo CTI_PYTHON = { 02080 CONSTRAINT_TYPE_PYTHON, /* type */ 02081 sizeof(bPythonConstraint), /* size */ 02082 "Script", /* name */ 02083 "bPythonConstraint", /* struct name */ 02084 pycon_free, /* free data */ 02085 pycon_relink, /* relink data */ 02086 pycon_id_looper, /* id looper */ 02087 pycon_copy, /* copy data */ 02088 pycon_new_data, /* new data */ 02089 pycon_get_tars, /* get constraint targets */ 02090 NULL, /* flush constraint targets */ 02091 pycon_get_tarmat, /* get target matrix */ 02092 pycon_evaluate /* evaluate */ 02093 }; 02094 02095 /* -------- Action Constraint ----------- */ 02096 02097 static void actcon_relink (bConstraint *con) 02098 { 02099 bActionConstraint *data= con->data; 02100 ID_NEW(data->act); 02101 } 02102 02103 static void actcon_new_data (void *cdata) 02104 { 02105 bActionConstraint *data= (bActionConstraint *)cdata; 02106 02107 /* set type to 20 (Loc X), as 0 is Rot X for backwards compatability */ 02108 data->type = 20; 02109 } 02110 02111 static void actcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02112 { 02113 bActionConstraint *data= con->data; 02114 02115 /* target */ 02116 func(con, (ID**)&data->tar, userdata); 02117 02118 /* action */ 02119 func(con, (ID**)&data->act, userdata); 02120 } 02121 02122 static int actcon_get_tars (bConstraint *con, ListBase *list) 02123 { 02124 if (con && list) { 02125 bActionConstraint *data= con->data; 02126 bConstraintTarget *ct; 02127 02128 /* standard target-getting macro for single-target constraints */ 02129 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 02130 02131 return 1; 02132 } 02133 02134 return 0; 02135 } 02136 02137 static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy) 02138 { 02139 if (con && list) { 02140 bActionConstraint *data= con->data; 02141 bConstraintTarget *ct= list->first; 02142 02143 /* the following macro is used for all standard single-target constraints */ 02144 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 02145 } 02146 } 02147 02148 static void actcon_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 02149 { 02150 bActionConstraint *data = con->data; 02151 02152 if (VALID_CONS_TARGET(ct)) { 02153 float tempmat[4][4], vec[3]; 02154 float s, t; 02155 short axis; 02156 02157 /* initialise return matrix */ 02158 unit_m4(ct->matrix); 02159 02160 /* get the transform matrix of the target */ 02161 constraint_target_to_mat4(ct->tar, ct->subtarget, tempmat, CONSTRAINT_SPACE_WORLD, ct->space, con->headtail); 02162 02163 /* determine where in transform range target is */ 02164 /* data->type is mapped as follows for backwards compatability: 02165 * 00,01,02 - rotation (it used to be like this) 02166 * 10,11,12 - scaling 02167 * 20,21,22 - location 02168 */ 02169 if (data->type < 10) { 02170 /* extract rotation (is in whatever space target should be in) */ 02171 mat4_to_eul(vec, tempmat); 02172 mul_v3_fl(vec, (float)(180.0/M_PI)); /* rad -> deg */ 02173 axis= data->type; 02174 } 02175 else if (data->type < 20) { 02176 /* extract scaling (is in whatever space target should be in) */ 02177 mat4_to_size(vec, tempmat); 02178 axis= data->type - 10; 02179 } 02180 else { 02181 /* extract location */ 02182 copy_v3_v3(vec, tempmat[3]); 02183 axis= data->type - 20; 02184 } 02185 02186 /* Target defines the animation */ 02187 s = (vec[axis]-data->min) / (data->max-data->min); 02188 CLAMP(s, 0, 1); 02189 t = (s * (data->end-data->start)) + data->start; 02190 02191 if (G.f & G_DEBUG) 02192 printf("do Action Constraint %s - Ob %s Pchan %s \n", con->name, cob->ob->id.name+2, (cob->pchan)?cob->pchan->name:NULL); 02193 02194 /* Get the appropriate information from the action */ 02195 if (cob->type == CONSTRAINT_OBTYPE_BONE) { 02196 Object workob; 02197 bPose *pose; 02198 bPoseChannel *pchan, *tchan; 02199 02200 /* make a temporary pose and evaluate using that */ 02201 pose = MEM_callocN(sizeof(bPose), "pose"); 02202 02203 /* make a copy of the bone of interest in the temp pose before evaluating action, so that it can get set 02204 * - we need to manually copy over a few settings, including rotation order, otherwise this fails 02205 */ 02206 pchan = cob->pchan; 02207 02208 tchan= verify_pose_channel(pose, pchan->name); 02209 tchan->rotmode= pchan->rotmode; 02210 02211 /* evaluate action using workob (it will only set the PoseChannel in question) */ 02212 what_does_obaction(cob->ob, &workob, pose, data->act, pchan->name, t); 02213 02214 /* convert animation to matrices for use here */ 02215 pchan_calc_mat(tchan); 02216 copy_m4_m4(ct->matrix, tchan->chan_mat); 02217 02218 /* Clean up */ 02219 free_pose(pose); 02220 } 02221 else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) { 02222 Object workob; 02223 02224 /* evaluate using workob */ 02225 // FIXME: we don't have any consistent standards on limiting effects on object... 02226 what_does_obaction(cob->ob, &workob, NULL, data->act, NULL, t); 02227 object_to_mat4(&workob, ct->matrix); 02228 } 02229 else { 02230 /* behaviour undefined... */ 02231 puts("Error: unknown owner type for Action Constraint"); 02232 } 02233 } 02234 } 02235 02236 static void actcon_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) 02237 { 02238 bConstraintTarget *ct= targets->first; 02239 02240 if (VALID_CONS_TARGET(ct)) { 02241 float temp[4][4]; 02242 02243 /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix 02244 * function has already taken care of everything else. 02245 */ 02246 copy_m4_m4(temp, cob->matrix); 02247 mul_m4_m4m4(cob->matrix, ct->matrix, temp); 02248 } 02249 } 02250 02251 static bConstraintTypeInfo CTI_ACTION = { 02252 CONSTRAINT_TYPE_ACTION, /* type */ 02253 sizeof(bActionConstraint), /* size */ 02254 "Action", /* name */ 02255 "bActionConstraint", /* struct name */ 02256 NULL, /* free data */ 02257 actcon_relink, /* relink data */ 02258 actcon_id_looper, /* id looper */ 02259 NULL, /* copy data */ 02260 actcon_new_data, /* new data */ 02261 actcon_get_tars, /* get constraint targets */ 02262 actcon_flush_tars, /* flush constraint targets */ 02263 actcon_get_tarmat, /* get target matrix */ 02264 actcon_evaluate /* evaluate */ 02265 }; 02266 02267 /* --------- Locked Track ---------- */ 02268 02269 static void locktrack_new_data (void *cdata) 02270 { 02271 bLockTrackConstraint *data= (bLockTrackConstraint *)cdata; 02272 02273 data->trackflag = TRACK_Y; 02274 data->lockflag = LOCK_Z; 02275 } 02276 02277 static void locktrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02278 { 02279 bLockTrackConstraint *data= con->data; 02280 02281 /* target only */ 02282 func(con, (ID**)&data->tar, userdata); 02283 } 02284 02285 static int locktrack_get_tars (bConstraint *con, ListBase *list) 02286 { 02287 if (con && list) { 02288 bLockTrackConstraint *data= con->data; 02289 bConstraintTarget *ct; 02290 02291 /* the following macro is used for all standard single-target constraints */ 02292 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 02293 02294 return 1; 02295 } 02296 02297 return 0; 02298 } 02299 02300 static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy) 02301 { 02302 if (con && list) { 02303 bLockTrackConstraint *data= con->data; 02304 bConstraintTarget *ct= list->first; 02305 02306 /* the following macro is used for all standard single-target constraints */ 02307 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 02308 } 02309 } 02310 02311 static void locktrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 02312 { 02313 bLockTrackConstraint *data= con->data; 02314 bConstraintTarget *ct= targets->first; 02315 02316 if (VALID_CONS_TARGET(ct)) { 02317 float vec[3],vec2[3]; 02318 float totmat[3][3]; 02319 float tmpmat[3][3]; 02320 float invmat[3][3]; 02321 float tmat[4][4]; 02322 float mdet; 02323 02324 /* Vector object -> target */ 02325 sub_v3_v3v3(vec, ct->matrix[3], cob->matrix[3]); 02326 switch (data->lockflag){ 02327 case LOCK_X: /* LOCK X */ 02328 { 02329 switch (data->trackflag) { 02330 case TRACK_Y: /* LOCK X TRACK Y */ 02331 { 02332 /* Projection of Vector on the plane */ 02333 project_v3_v3v3(vec2, vec, cob->matrix[0]); 02334 sub_v3_v3v3(totmat[1], vec, vec2); 02335 normalize_v3(totmat[1]); 02336 02337 /* the x axis is fixed */ 02338 normalize_v3_v3(totmat[0], cob->matrix[0]); 02339 02340 /* the z axis gets mapped onto a third orthogonal vector */ 02341 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]); 02342 } 02343 break; 02344 case TRACK_Z: /* LOCK X TRACK Z */ 02345 { 02346 /* Projection of Vector on the plane */ 02347 project_v3_v3v3(vec2, vec, cob->matrix[0]); 02348 sub_v3_v3v3(totmat[2], vec, vec2); 02349 normalize_v3(totmat[2]); 02350 02351 /* the x axis is fixed */ 02352 normalize_v3_v3(totmat[0], cob->matrix[0]); 02353 02354 /* the z axis gets mapped onto a third orthogonal vector */ 02355 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]); 02356 } 02357 break; 02358 case TRACK_nY: /* LOCK X TRACK -Y */ 02359 { 02360 /* Projection of Vector on the plane */ 02361 project_v3_v3v3(vec2, vec, cob->matrix[0]); 02362 sub_v3_v3v3(totmat[1], vec, vec2); 02363 normalize_v3(totmat[1]); 02364 negate_v3(totmat[1]); 02365 02366 /* the x axis is fixed */ 02367 normalize_v3_v3(totmat[0], cob->matrix[0]); 02368 02369 /* the z axis gets mapped onto a third orthogonal vector */ 02370 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]); 02371 } 02372 break; 02373 case TRACK_nZ: /* LOCK X TRACK -Z */ 02374 { 02375 /* Projection of Vector on the plane */ 02376 project_v3_v3v3(vec2, vec, cob->matrix[0]); 02377 sub_v3_v3v3(totmat[2], vec, vec2); 02378 normalize_v3(totmat[2]); 02379 negate_v3(totmat[2]); 02380 02381 /* the x axis is fixed */ 02382 normalize_v3_v3(totmat[0], cob->matrix[0]); 02383 02384 /* the z axis gets mapped onto a third orthogonal vector */ 02385 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]); 02386 } 02387 break; 02388 default: 02389 { 02390 unit_m3(totmat); 02391 } 02392 break; 02393 } 02394 } 02395 break; 02396 case LOCK_Y: /* LOCK Y */ 02397 { 02398 switch (data->trackflag) { 02399 case TRACK_X: /* LOCK Y TRACK X */ 02400 { 02401 /* Projection of Vector on the plane */ 02402 project_v3_v3v3(vec2, vec, cob->matrix[1]); 02403 sub_v3_v3v3(totmat[0], vec, vec2); 02404 normalize_v3(totmat[0]); 02405 02406 /* the y axis is fixed */ 02407 normalize_v3_v3(totmat[1], cob->matrix[1]); 02408 02409 /* the z axis gets mapped onto a third orthogonal vector */ 02410 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]); 02411 } 02412 break; 02413 case TRACK_Z: /* LOCK Y TRACK Z */ 02414 { 02415 /* Projection of Vector on the plane */ 02416 project_v3_v3v3(vec2, vec, cob->matrix[1]); 02417 sub_v3_v3v3(totmat[2], vec, vec2); 02418 normalize_v3(totmat[2]); 02419 02420 /* the y axis is fixed */ 02421 normalize_v3_v3(totmat[1], cob->matrix[1]); 02422 02423 /* the z axis gets mapped onto a third orthogonal vector */ 02424 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]); 02425 } 02426 break; 02427 case TRACK_nX: /* LOCK Y TRACK -X */ 02428 { 02429 /* Projection of Vector on the plane */ 02430 project_v3_v3v3(vec2, vec, cob->matrix[1]); 02431 sub_v3_v3v3(totmat[0], vec, vec2); 02432 normalize_v3(totmat[0]); 02433 negate_v3(totmat[0]); 02434 02435 /* the y axis is fixed */ 02436 normalize_v3_v3(totmat[1], cob->matrix[1]); 02437 02438 /* the z axis gets mapped onto a third orthogonal vector */ 02439 cross_v3_v3v3(totmat[2], totmat[0], totmat[1]); 02440 } 02441 break; 02442 case TRACK_nZ: /* LOCK Y TRACK -Z */ 02443 { 02444 /* Projection of Vector on the plane */ 02445 project_v3_v3v3(vec2, vec, cob->matrix[1]); 02446 sub_v3_v3v3(totmat[2], vec, vec2); 02447 normalize_v3(totmat[2]); 02448 negate_v3(totmat[2]); 02449 02450 /* the y axis is fixed */ 02451 normalize_v3_v3(totmat[1], cob->matrix[1]); 02452 02453 /* the z axis gets mapped onto a third orthogonal vector */ 02454 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]); 02455 } 02456 break; 02457 default: 02458 { 02459 unit_m3(totmat); 02460 } 02461 break; 02462 } 02463 } 02464 break; 02465 case LOCK_Z: /* LOCK Z */ 02466 { 02467 switch (data->trackflag) { 02468 case TRACK_X: /* LOCK Z TRACK X */ 02469 { 02470 /* Projection of Vector on the plane */ 02471 project_v3_v3v3(vec2, vec, cob->matrix[2]); 02472 sub_v3_v3v3(totmat[0], vec, vec2); 02473 normalize_v3(totmat[0]); 02474 02475 /* the z axis is fixed */ 02476 normalize_v3_v3(totmat[2], cob->matrix[2]); 02477 02478 /* the x axis gets mapped onto a third orthogonal vector */ 02479 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]); 02480 } 02481 break; 02482 case TRACK_Y: /* LOCK Z TRACK Y */ 02483 { 02484 /* Projection of Vector on the plane */ 02485 project_v3_v3v3(vec2, vec, cob->matrix[2]); 02486 sub_v3_v3v3(totmat[1], vec, vec2); 02487 normalize_v3(totmat[1]); 02488 02489 /* the z axis is fixed */ 02490 normalize_v3_v3(totmat[2], cob->matrix[2]); 02491 02492 /* the x axis gets mapped onto a third orthogonal vector */ 02493 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]); 02494 } 02495 break; 02496 case TRACK_nX: /* LOCK Z TRACK -X */ 02497 { 02498 /* Projection of Vector on the plane */ 02499 project_v3_v3v3(vec2, vec, cob->matrix[2]); 02500 sub_v3_v3v3(totmat[0], vec, vec2); 02501 normalize_v3(totmat[0]); 02502 negate_v3(totmat[0]); 02503 02504 /* the z axis is fixed */ 02505 normalize_v3_v3(totmat[2], cob->matrix[2]); 02506 02507 /* the x axis gets mapped onto a third orthogonal vector */ 02508 cross_v3_v3v3(totmat[1], totmat[2], totmat[0]); 02509 } 02510 break; 02511 case TRACK_nY: /* LOCK Z TRACK -Y */ 02512 { 02513 /* Projection of Vector on the plane */ 02514 project_v3_v3v3(vec2, vec, cob->matrix[2]); 02515 sub_v3_v3v3(totmat[1], vec, vec2); 02516 normalize_v3(totmat[1]); 02517 negate_v3(totmat[1]); 02518 02519 /* the z axis is fixed */ 02520 normalize_v3_v3(totmat[2], cob->matrix[2]); 02521 02522 /* the x axis gets mapped onto a third orthogonal vector */ 02523 cross_v3_v3v3(totmat[0], totmat[1], totmat[2]); 02524 } 02525 break; 02526 default: 02527 { 02528 unit_m3(totmat); 02529 } 02530 break; 02531 } 02532 } 02533 break; 02534 default: 02535 { 02536 unit_m3(totmat); 02537 } 02538 break; 02539 } 02540 /* Block to keep matrix heading */ 02541 copy_m3_m4(tmpmat, cob->matrix); 02542 normalize_m3(tmpmat); 02543 invert_m3_m3(invmat, tmpmat); 02544 mul_m3_m3m3(tmpmat, totmat, invmat); 02545 totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2]; 02546 totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2]; 02547 totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2]; 02548 02549 copy_m4_m4(tmat, cob->matrix); 02550 02551 mdet = determinant_m3( totmat[0][0],totmat[0][1],totmat[0][2], 02552 totmat[1][0],totmat[1][1],totmat[1][2], 02553 totmat[2][0],totmat[2][1],totmat[2][2]); 02554 if (mdet==0) { 02555 unit_m3(totmat); 02556 } 02557 02558 /* apply out transformaton to the object */ 02559 mul_m4_m3m4(cob->matrix, totmat, tmat); 02560 } 02561 } 02562 02563 static bConstraintTypeInfo CTI_LOCKTRACK = { 02564 CONSTRAINT_TYPE_LOCKTRACK, /* type */ 02565 sizeof(bLockTrackConstraint), /* size */ 02566 "Locked Track", /* name */ 02567 "bLockTrackConstraint", /* struct name */ 02568 NULL, /* free data */ 02569 NULL, /* relink data */ 02570 locktrack_id_looper, /* id looper */ 02571 NULL, /* copy data */ 02572 locktrack_new_data, /* new data */ 02573 locktrack_get_tars, /* get constraint targets */ 02574 locktrack_flush_tars, /* flush constraint targets */ 02575 default_get_tarmat, /* get target matrix */ 02576 locktrack_evaluate /* evaluate */ 02577 }; 02578 02579 /* ---------- Limit Distance Constraint ----------- */ 02580 02581 static void distlimit_new_data (void *cdata) 02582 { 02583 bDistLimitConstraint *data= (bDistLimitConstraint *)cdata; 02584 02585 data->dist= 0.0f; 02586 } 02587 02588 static void distlimit_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02589 { 02590 bDistLimitConstraint *data= con->data; 02591 02592 /* target only */ 02593 func(con, (ID**)&data->tar, userdata); 02594 } 02595 02596 static int distlimit_get_tars (bConstraint *con, ListBase *list) 02597 { 02598 if (con && list) { 02599 bDistLimitConstraint *data= con->data; 02600 bConstraintTarget *ct; 02601 02602 /* standard target-getting macro for single-target constraints */ 02603 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 02604 02605 return 1; 02606 } 02607 02608 return 0; 02609 } 02610 02611 static void distlimit_flush_tars (bConstraint *con, ListBase *list, short nocopy) 02612 { 02613 if (con && list) { 02614 bDistLimitConstraint *data= con->data; 02615 bConstraintTarget *ct= list->first; 02616 02617 /* the following macro is used for all standard single-target constraints */ 02618 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 02619 } 02620 } 02621 02622 static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 02623 { 02624 bDistLimitConstraint *data= con->data; 02625 bConstraintTarget *ct= targets->first; 02626 02627 /* only evaluate if there is a target */ 02628 if (VALID_CONS_TARGET(ct)) { 02629 float dvec[3], dist=0.0f, sfac=1.0f; 02630 short clamp_surf= 0; 02631 02632 /* calculate our current distance from the target */ 02633 dist= len_v3v3(cob->matrix[3], ct->matrix[3]); 02634 02635 /* set distance (flag is only set when user demands it) */ 02636 if (data->dist == 0) 02637 data->dist= dist; 02638 02639 /* check if we're which way to clamp from, and calculate interpolation factor (if needed) */ 02640 if (data->mode == LIMITDIST_OUTSIDE) { 02641 /* if inside, then move to surface */ 02642 if (dist <= data->dist) { 02643 clamp_surf= 1; 02644 sfac= data->dist / dist; 02645 } 02646 /* if soft-distance is enabled, start fading once owner is dist+softdist from the target */ 02647 else if (data->flag & LIMITDIST_USESOFT) { 02648 if (dist <= (data->dist + data->soft)) { 02649 02650 } 02651 } 02652 } 02653 else if (data->mode == LIMITDIST_INSIDE) { 02654 /* if outside, then move to surface */ 02655 if (dist >= data->dist) { 02656 clamp_surf= 1; 02657 sfac= data->dist / dist; 02658 } 02659 /* if soft-distance is enabled, start fading once owner is dist-soft from the target */ 02660 else if (data->flag & LIMITDIST_USESOFT) { 02661 // FIXME: there's a problem with "jumping" when this kicks in 02662 if (dist >= (data->dist - data->soft)) { 02663 sfac = (float)( data->soft*(1.0f - expf(-(dist - data->dist)/data->soft)) + data->dist ); 02664 sfac /= dist; 02665 02666 clamp_surf= 1; 02667 } 02668 } 02669 } 02670 else { 02671 if (IS_EQF(dist, data->dist)==0) { 02672 clamp_surf= 1; 02673 sfac= data->dist / dist; 02674 } 02675 } 02676 02677 /* clamp to 'surface' (i.e. move owner so that dist == data->dist) */ 02678 if (clamp_surf) { 02679 /* simply interpolate along line formed by target -> owner */ 02680 interp_v3_v3v3(dvec, ct->matrix[3], cob->matrix[3], sfac); 02681 02682 /* copy new vector onto owner */ 02683 copy_v3_v3(cob->matrix[3], dvec); 02684 } 02685 } 02686 } 02687 02688 static bConstraintTypeInfo CTI_DISTLIMIT = { 02689 CONSTRAINT_TYPE_DISTLIMIT, /* type */ 02690 sizeof(bDistLimitConstraint), /* size */ 02691 "Limit Distance", /* name */ 02692 "bDistLimitConstraint", /* struct name */ 02693 NULL, /* free data */ 02694 NULL, /* relink data */ 02695 distlimit_id_looper, /* id looper */ 02696 NULL, /* copy data */ 02697 distlimit_new_data, /* new data */ 02698 distlimit_get_tars, /* get constraint targets */ 02699 distlimit_flush_tars, /* flush constraint targets */ 02700 default_get_tarmat, /* get a target matrix */ 02701 distlimit_evaluate /* evaluate */ 02702 }; 02703 02704 /* ---------- Stretch To ------------ */ 02705 02706 static void stretchto_new_data (void *cdata) 02707 { 02708 bStretchToConstraint *data= (bStretchToConstraint *)cdata; 02709 02710 data->volmode = 0; 02711 data->plane = 0; 02712 data->orglength = 0.0; 02713 data->bulge = 1.0; 02714 } 02715 02716 static void stretchto_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02717 { 02718 bStretchToConstraint *data= con->data; 02719 02720 /* target only */ 02721 func(con, (ID**)&data->tar, userdata); 02722 } 02723 02724 static int stretchto_get_tars (bConstraint *con, ListBase *list) 02725 { 02726 if (con && list) { 02727 bStretchToConstraint *data= con->data; 02728 bConstraintTarget *ct; 02729 02730 /* standard target-getting macro for single-target constraints */ 02731 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 02732 02733 return 1; 02734 } 02735 02736 return 0; 02737 } 02738 02739 static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy) 02740 { 02741 if (con && list) { 02742 bStretchToConstraint *data= con->data; 02743 bConstraintTarget *ct= list->first; 02744 02745 /* the following macro is used for all standard single-target constraints */ 02746 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 02747 } 02748 } 02749 02750 static void stretchto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 02751 { 02752 bStretchToConstraint *data= con->data; 02753 bConstraintTarget *ct= targets->first; 02754 02755 /* only evaluate if there is a target */ 02756 if (VALID_CONS_TARGET(ct)) { 02757 float size[3], scale[3], vec[3], xx[3], zz[3], orth[3]; 02758 float totmat[3][3]; 02759 float tmat[4][4]; 02760 float dist; 02761 02762 /* store scaling before destroying obmat */ 02763 mat4_to_size(size, cob->matrix); 02764 02765 /* store X orientation before destroying obmat */ 02766 normalize_v3_v3(xx, cob->matrix[0]); 02767 02768 /* store Z orientation before destroying obmat */ 02769 normalize_v3_v3(zz, cob->matrix[2]); 02770 02771 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]); 02772 vec[0] /= size[0]; 02773 vec[1] /= size[1]; 02774 vec[2] /= size[2]; 02775 02776 dist = normalize_v3(vec); 02777 //dist = len_v3v3( ob->obmat[3], targetmat[3]); 02778 02779 /* data->orglength==0 occurs on first run, and after 'R' button is clicked */ 02780 if (data->orglength == 0) 02781 data->orglength = dist; 02782 if (data->bulge == 0) 02783 data->bulge = 1.0; 02784 02785 scale[1] = dist/data->orglength; 02786 switch (data->volmode) { 02787 /* volume preserving scaling */ 02788 case VOLUME_XZ : 02789 scale[0] = 1.0f - (float)sqrt(data->bulge) + (float)sqrt(data->bulge*(data->orglength/dist)); 02790 scale[2] = scale[0]; 02791 break; 02792 case VOLUME_X: 02793 scale[0] = 1.0f + data->bulge * (data->orglength /dist - 1); 02794 scale[2] = 1.0; 02795 break; 02796 case VOLUME_Z: 02797 scale[0] = 1.0; 02798 scale[2] = 1.0f + data->bulge * (data->orglength /dist - 1); 02799 break; 02800 /* don't care for volume */ 02801 case NO_VOLUME: 02802 scale[0] = 1.0; 02803 scale[2] = 1.0; 02804 break; 02805 default: /* should not happen, but in case*/ 02806 return; 02807 } /* switch (data->volmode) */ 02808 02809 /* Clear the object's rotation and scale */ 02810 cob->matrix[0][0]=size[0]*scale[0]; 02811 cob->matrix[0][1]=0; 02812 cob->matrix[0][2]=0; 02813 cob->matrix[1][0]=0; 02814 cob->matrix[1][1]=size[1]*scale[1]; 02815 cob->matrix[1][2]=0; 02816 cob->matrix[2][0]=0; 02817 cob->matrix[2][1]=0; 02818 cob->matrix[2][2]=size[2]*scale[2]; 02819 02820 sub_v3_v3v3(vec, cob->matrix[3], ct->matrix[3]); 02821 normalize_v3(vec); 02822 02823 /* new Y aligns object target connection*/ 02824 negate_v3_v3(totmat[1], vec); 02825 switch (data->plane) { 02826 case PLANE_X: 02827 /* build new Z vector */ 02828 /* othogonal to "new Y" "old X! plane */ 02829 cross_v3_v3v3(orth, vec, xx); 02830 normalize_v3(orth); 02831 02832 /* new Z*/ 02833 copy_v3_v3(totmat[2], orth); 02834 02835 /* we decided to keep X plane*/ 02836 cross_v3_v3v3(xx, orth, vec); 02837 normalize_v3_v3(totmat[0], xx); 02838 break; 02839 case PLANE_Z: 02840 /* build new X vector */ 02841 /* othogonal to "new Y" "old Z! plane */ 02842 cross_v3_v3v3(orth, vec, zz); 02843 normalize_v3(orth); 02844 02845 /* new X */ 02846 negate_v3_v3(totmat[0], orth); 02847 02848 /* we decided to keep Z */ 02849 cross_v3_v3v3(zz, orth, vec); 02850 normalize_v3_v3(totmat[2], zz); 02851 break; 02852 } /* switch (data->plane) */ 02853 02854 copy_m4_m4(tmat, cob->matrix); 02855 mul_m4_m3m4(cob->matrix, totmat, tmat); 02856 } 02857 } 02858 02859 static bConstraintTypeInfo CTI_STRETCHTO = { 02860 CONSTRAINT_TYPE_STRETCHTO, /* type */ 02861 sizeof(bStretchToConstraint), /* size */ 02862 "Stretch To", /* name */ 02863 "bStretchToConstraint", /* struct name */ 02864 NULL, /* free data */ 02865 NULL, /* relink data */ 02866 stretchto_id_looper, /* id looper */ 02867 NULL, /* copy data */ 02868 stretchto_new_data, /* new data */ 02869 stretchto_get_tars, /* get constraint targets */ 02870 stretchto_flush_tars, /* flush constraint targets */ 02871 default_get_tarmat, /* get target matrix */ 02872 stretchto_evaluate /* evaluate */ 02873 }; 02874 02875 /* ---------- Floor ------------ */ 02876 02877 static void minmax_new_data (void *cdata) 02878 { 02879 bMinMaxConstraint *data= (bMinMaxConstraint *)cdata; 02880 02881 data->minmaxflag = TRACK_Z; 02882 data->offset = 0.0f; 02883 data->cache[0] = data->cache[1] = data->cache[2] = 0.0f; 02884 data->flag = 0; 02885 } 02886 02887 static void minmax_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 02888 { 02889 bMinMaxConstraint *data= con->data; 02890 02891 /* target only */ 02892 func(con, (ID**)&data->tar, userdata); 02893 } 02894 02895 static int minmax_get_tars (bConstraint *con, ListBase *list) 02896 { 02897 if (con && list) { 02898 bMinMaxConstraint *data= con->data; 02899 bConstraintTarget *ct; 02900 02901 /* standard target-getting macro for single-target constraints */ 02902 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 02903 02904 return 1; 02905 } 02906 02907 return 0; 02908 } 02909 02910 static void minmax_flush_tars (bConstraint *con, ListBase *list, short nocopy) 02911 { 02912 if (con && list) { 02913 bMinMaxConstraint *data= con->data; 02914 bConstraintTarget *ct= list->first; 02915 02916 /* the following macro is used for all standard single-target constraints */ 02917 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 02918 } 02919 } 02920 02921 static void minmax_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 02922 { 02923 bMinMaxConstraint *data= con->data; 02924 bConstraintTarget *ct= targets->first; 02925 02926 /* only evaluate if there is a target */ 02927 if (VALID_CONS_TARGET(ct)) { 02928 float obmat[4][4], imat[4][4], tarmat[4][4], tmat[4][4]; 02929 float val1, val2; 02930 int index; 02931 02932 copy_m4_m4(obmat, cob->matrix); 02933 copy_m4_m4(tarmat, ct->matrix); 02934 02935 if (data->flag & MINMAX_USEROT) { 02936 /* take rotation of target into account by doing the transaction in target's localspace */ 02937 invert_m4_m4(imat, tarmat); 02938 mul_m4_m4m4(tmat, obmat, imat); 02939 copy_m4_m4(obmat, tmat); 02940 unit_m4(tarmat); 02941 } 02942 02943 switch (data->minmaxflag) { 02944 case TRACK_Z: 02945 val1 = tarmat[3][2]; 02946 val2 = obmat[3][2]-data->offset; 02947 index = 2; 02948 break; 02949 case TRACK_Y: 02950 val1 = tarmat[3][1]; 02951 val2 = obmat[3][1]-data->offset; 02952 index = 1; 02953 break; 02954 case TRACK_X: 02955 val1 = tarmat[3][0]; 02956 val2 = obmat[3][0]-data->offset; 02957 index = 0; 02958 break; 02959 case TRACK_nZ: 02960 val2 = tarmat[3][2]; 02961 val1 = obmat[3][2]-data->offset; 02962 index = 2; 02963 break; 02964 case TRACK_nY: 02965 val2 = tarmat[3][1]; 02966 val1 = obmat[3][1]-data->offset; 02967 index = 1; 02968 break; 02969 case TRACK_nX: 02970 val2 = tarmat[3][0]; 02971 val1 = obmat[3][0]-data->offset; 02972 index = 0; 02973 break; 02974 default: 02975 return; 02976 } 02977 02978 if (val1 > val2) { 02979 obmat[3][index] = tarmat[3][index] + data->offset; 02980 if (data->flag & MINMAX_STICKY) { 02981 if (data->flag & MINMAX_STUCK) { 02982 copy_v3_v3(obmat[3], data->cache); 02983 } 02984 else { 02985 copy_v3_v3(data->cache, obmat[3]); 02986 data->flag |= MINMAX_STUCK; 02987 } 02988 } 02989 if (data->flag & MINMAX_USEROT) { 02990 /* get out of localspace */ 02991 mul_m4_m4m4(tmat, obmat, ct->matrix); 02992 copy_m4_m4(cob->matrix, tmat); 02993 } 02994 else { 02995 copy_v3_v3(cob->matrix[3], obmat[3]); 02996 } 02997 } 02998 else { 02999 data->flag &= ~MINMAX_STUCK; 03000 } 03001 } 03002 } 03003 03004 static bConstraintTypeInfo CTI_MINMAX = { 03005 CONSTRAINT_TYPE_MINMAX, /* type */ 03006 sizeof(bMinMaxConstraint), /* size */ 03007 "Floor", /* name */ 03008 "bMinMaxConstraint", /* struct name */ 03009 NULL, /* free data */ 03010 NULL, /* relink data */ 03011 minmax_id_looper, /* id looper */ 03012 NULL, /* copy data */ 03013 minmax_new_data, /* new data */ 03014 minmax_get_tars, /* get constraint targets */ 03015 minmax_flush_tars, /* flush constraint targets */ 03016 default_get_tarmat, /* get target matrix */ 03017 minmax_evaluate /* evaluate */ 03018 }; 03019 03020 /* ------- RigidBody Joint ---------- */ 03021 03022 static void rbj_new_data (void *cdata) 03023 { 03024 bRigidBodyJointConstraint *data= (bRigidBodyJointConstraint *)cdata; 03025 03026 // removed code which set target of this constraint 03027 data->type=1; 03028 } 03029 03030 static void rbj_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03031 { 03032 bRigidBodyJointConstraint *data= con->data; 03033 03034 /* target only */ 03035 func(con, (ID**)&data->tar, userdata); 03036 func(con, (ID**)&data->child, userdata); 03037 } 03038 03039 static int rbj_get_tars (bConstraint *con, ListBase *list) 03040 { 03041 if (con && list) { 03042 bRigidBodyJointConstraint *data= con->data; 03043 bConstraintTarget *ct; 03044 03045 /* standard target-getting macro for single-target constraints without subtargets */ 03046 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) 03047 03048 return 1; 03049 } 03050 03051 return 0; 03052 } 03053 03054 static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03055 { 03056 if (con && list) { 03057 bRigidBodyJointConstraint *data= con->data; 03058 bConstraintTarget *ct= list->first; 03059 03060 /* the following macro is used for all standard single-target constraints */ 03061 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) 03062 } 03063 } 03064 03065 static bConstraintTypeInfo CTI_RIGIDBODYJOINT = { 03066 CONSTRAINT_TYPE_RIGIDBODYJOINT, /* type */ 03067 sizeof(bRigidBodyJointConstraint), /* size */ 03068 "Rigid Body Joint", /* name */ 03069 "bRigidBodyJointConstraint", /* struct name */ 03070 NULL, /* free data */ 03071 NULL, /* relink data */ 03072 rbj_id_looper, /* id looper */ 03073 NULL, /* copy data */ 03074 rbj_new_data, /* new data */ 03075 rbj_get_tars, /* get constraint targets */ 03076 rbj_flush_tars, /* flush constraint targets */ 03077 default_get_tarmat, /* get target matrix */ 03078 NULL /* evaluate - this is not solved here... is just an interface for game-engine */ 03079 }; 03080 03081 /* -------- Clamp To ---------- */ 03082 03083 static void clampto_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03084 { 03085 bClampToConstraint *data= con->data; 03086 03087 /* target only */ 03088 func(con, (ID**)&data->tar, userdata); 03089 } 03090 03091 static int clampto_get_tars (bConstraint *con, ListBase *list) 03092 { 03093 if (con && list) { 03094 bClampToConstraint *data= con->data; 03095 bConstraintTarget *ct; 03096 03097 /* standard target-getting macro for single-target constraints without subtargets */ 03098 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) 03099 03100 return 1; 03101 } 03102 03103 return 0; 03104 } 03105 03106 static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03107 { 03108 if (con && list) { 03109 bClampToConstraint *data= con->data; 03110 bConstraintTarget *ct= list->first; 03111 03112 /* the following macro is used for all standard single-target constraints */ 03113 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) 03114 } 03115 } 03116 03117 static void clampto_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 03118 { 03119 if (VALID_CONS_TARGET(ct)) { 03120 Curve *cu= ct->tar->data; 03121 03122 /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, 03123 * currently for paths to work it needs to go through the bevlist/displist system (ton) 03124 */ 03125 03126 /* only happens on reload file, but violates depsgraph still... fix! */ 03127 if (cu->path==NULL || cu->path->data==NULL) 03128 makeDispListCurveTypes(cob->scene, ct->tar, 0); 03129 } 03130 03131 /* technically, this isn't really needed for evaluation, but we don't know what else 03132 * might end up calling this... 03133 */ 03134 if (ct) 03135 unit_m4(ct->matrix); 03136 } 03137 03138 static void clampto_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 03139 { 03140 bClampToConstraint *data= con->data; 03141 bConstraintTarget *ct= targets->first; 03142 03143 /* only evaluate if there is a target and it is a curve */ 03144 if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) { 03145 Curve *cu= data->tar->data; 03146 float obmat[4][4], ownLoc[3]; 03147 float curveMin[3], curveMax[3]; 03148 float targetMatrix[4][4]= MAT4_UNITY; 03149 03150 copy_m4_m4(obmat, cob->matrix); 03151 copy_v3_v3(ownLoc, obmat[3]); 03152 03153 INIT_MINMAX(curveMin, curveMax) 03154 minmax_object(ct->tar, curveMin, curveMax); 03155 03156 /* get targetmatrix */ 03157 if (cu->path && cu->path->data) { 03158 float vec[4], dir[3], totmat[4][4]; 03159 float curvetime; 03160 short clamp_axis; 03161 03162 /* find best position on curve */ 03163 /* 1. determine which axis to sample on? */ 03164 if (data->flag == CLAMPTO_AUTO) { 03165 float size[3]; 03166 sub_v3_v3v3(size, curveMax, curveMin); 03167 03168 /* find axis along which the bounding box has the greatest 03169 * extent. Otherwise, default to the x-axis, as that is quite 03170 * frequently used. 03171 */ 03172 if ((size[2]>size[0]) && (size[2]>size[1])) 03173 clamp_axis= CLAMPTO_Z - 1; 03174 else if ((size[1]>size[0]) && (size[1]>size[2])) 03175 clamp_axis= CLAMPTO_Y - 1; 03176 else 03177 clamp_axis = CLAMPTO_X - 1; 03178 } 03179 else 03180 clamp_axis= data->flag - 1; 03181 03182 /* 2. determine position relative to curve on a 0-1 scale based on bounding box */ 03183 if (data->flag2 & CLAMPTO_CYCLIC) { 03184 /* cyclic, so offset within relative bounding box is used */ 03185 float len= (curveMax[clamp_axis] - curveMin[clamp_axis]); 03186 float offset; 03187 03188 /* check to make sure len is not so close to zero that it'll cause errors */ 03189 if (IS_EQ(len, 0) == 0) { 03190 /* find bounding-box range where target is located */ 03191 if (ownLoc[clamp_axis] < curveMin[clamp_axis]) { 03192 /* bounding-box range is before */ 03193 offset= curveMin[clamp_axis]; 03194 03195 while (ownLoc[clamp_axis] < offset) 03196 offset -= len; 03197 03198 /* now, we calculate as per normal, except using offset instead of curveMin[clamp_axis] */ 03199 curvetime = (ownLoc[clamp_axis] - offset) / (len); 03200 } 03201 else if (ownLoc[clamp_axis] > curveMax[clamp_axis]) { 03202 /* bounding-box range is after */ 03203 offset= curveMax[clamp_axis]; 03204 03205 while (ownLoc[clamp_axis] > offset) { 03206 if ((offset + len) > ownLoc[clamp_axis]) 03207 break; 03208 else 03209 offset += len; 03210 } 03211 03212 /* now, we calculate as per normal, except using offset instead of curveMax[clamp_axis] */ 03213 curvetime = (ownLoc[clamp_axis] - offset) / (len); 03214 } 03215 else { 03216 /* as the location falls within bounds, just calculate */ 03217 curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (len); 03218 } 03219 } 03220 else { 03221 /* as length is close to zero, curvetime by default should be 0 (i.e. the start) */ 03222 curvetime= 0.0f; 03223 } 03224 } 03225 else { 03226 /* no cyclic, so position is clamped to within the bounding box */ 03227 if (ownLoc[clamp_axis] <= curveMin[clamp_axis]) 03228 curvetime = 0.0f; 03229 else if (ownLoc[clamp_axis] >= curveMax[clamp_axis]) 03230 curvetime = 1.0f; 03231 else if ( IS_EQ((curveMax[clamp_axis] - curveMin[clamp_axis]), 0) == 0 ) 03232 curvetime = (ownLoc[clamp_axis] - curveMin[clamp_axis]) / (curveMax[clamp_axis] - curveMin[clamp_axis]); 03233 else 03234 curvetime = 0.0f; 03235 } 03236 03237 /* 3. position on curve */ 03238 if (where_on_path(ct->tar, curvetime, vec, dir, NULL, NULL, NULL) ) { 03239 unit_m4(totmat); 03240 copy_v3_v3(totmat[3], vec); 03241 03242 mul_serie_m4(targetMatrix, ct->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL); 03243 } 03244 } 03245 03246 /* obtain final object position */ 03247 copy_v3_v3(cob->matrix[3], targetMatrix[3]); 03248 } 03249 } 03250 03251 static bConstraintTypeInfo CTI_CLAMPTO = { 03252 CONSTRAINT_TYPE_CLAMPTO, /* type */ 03253 sizeof(bClampToConstraint), /* size */ 03254 "Clamp To", /* name */ 03255 "bClampToConstraint", /* struct name */ 03256 NULL, /* free data */ 03257 NULL, /* relink data */ 03258 clampto_id_looper, /* id looper */ 03259 NULL, /* copy data */ 03260 NULL, /* new data */ 03261 clampto_get_tars, /* get constraint targets */ 03262 clampto_flush_tars, /* flush constraint targets */ 03263 clampto_get_tarmat, /* get target matrix */ 03264 clampto_evaluate /* evaluate */ 03265 }; 03266 03267 /* ---------- Transform Constraint ----------- */ 03268 03269 static void transform_new_data (void *cdata) 03270 { 03271 bTransformConstraint *data= (bTransformConstraint *)cdata; 03272 03273 data->map[0]= 0; 03274 data->map[1]= 1; 03275 data->map[2]= 2; 03276 } 03277 03278 static void transform_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03279 { 03280 bTransformConstraint *data= con->data; 03281 03282 /* target only */ 03283 func(con, (ID**)&data->tar, userdata); 03284 } 03285 03286 static int transform_get_tars (bConstraint *con, ListBase *list) 03287 { 03288 if (con && list) { 03289 bTransformConstraint *data= con->data; 03290 bConstraintTarget *ct; 03291 03292 /* standard target-getting macro for single-target constraints */ 03293 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 03294 03295 return 1; 03296 } 03297 03298 return 0; 03299 } 03300 03301 static void transform_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03302 { 03303 if (con && list) { 03304 bTransformConstraint *data= con->data; 03305 bConstraintTarget *ct= list->first; 03306 03307 /* the following macro is used for all standard single-target constraints */ 03308 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 03309 } 03310 } 03311 03312 static void transform_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 03313 { 03314 bTransformConstraint *data= con->data; 03315 bConstraintTarget *ct= targets->first; 03316 03317 /* only evaluate if there is a target */ 03318 if (VALID_CONS_TARGET(ct)) { 03319 float loc[3], eul[3], size[3]; 03320 float dvec[3], sval[3]; 03321 int i; 03322 03323 /* obtain target effect */ 03324 switch (data->from) { 03325 case 2: /* scale */ 03326 mat4_to_size( dvec,ct->matrix); 03327 break; 03328 case 1: /* rotation (convert to degrees first) */ 03329 mat4_to_eulO(dvec, cob->rotOrder, ct->matrix); 03330 mul_v3_fl(dvec, (float)(180.0/M_PI)); /* rad -> deg */ 03331 break; 03332 default: /* location */ 03333 copy_v3_v3(dvec, ct->matrix[3]); 03334 break; 03335 } 03336 03337 /* extract components of owner's matrix */ 03338 copy_v3_v3(loc, cob->matrix[3]); 03339 mat4_to_eulO(eul, cob->rotOrder, cob->matrix); 03340 mat4_to_size(size, cob->matrix); 03341 03342 /* determine where in range current transforms lie */ 03343 if (data->expo) { 03344 for (i=0; i<3; i++) { 03345 if (data->from_max[i] - data->from_min[i]) 03346 sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]); 03347 else 03348 sval[i]= 0.0f; 03349 } 03350 } 03351 else { 03352 /* clamp transforms out of range */ 03353 for (i=0; i<3; i++) { 03354 CLAMP(dvec[i], data->from_min[i], data->from_max[i]); 03355 if (data->from_max[i] - data->from_min[i]) 03356 sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]); 03357 else 03358 sval[i]= 0.0f; 03359 } 03360 } 03361 03362 03363 /* apply transforms */ 03364 switch (data->to) { 03365 case 2: /* scaling */ 03366 for (i=0; i<3; i++) 03367 size[i]= data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i])); 03368 break; 03369 case 1: /* rotation */ 03370 for (i=0; i<3; i++) { 03371 float tmin, tmax; 03372 03373 tmin= data->to_min[i]; 03374 tmax= data->to_max[i]; 03375 03376 /* all values here should be in degrees */ 03377 eul[i]= tmin + (sval[(int)data->map[i]] * (tmax - tmin)); 03378 03379 /* now convert final value back to radians */ 03380 eul[i] = DEG2RADF(eul[i]); 03381 } 03382 break; 03383 default: /* location */ 03384 /* get new location */ 03385 for (i=0; i<3; i++) 03386 loc[i]= (data->to_min[i] + (sval[(int)data->map[i]] * (data->to_max[i] - data->to_min[i]))); 03387 03388 /* add original location back on (so that it can still be moved) */ 03389 add_v3_v3v3(loc, cob->matrix[3], loc); 03390 break; 03391 } 03392 03393 /* apply to matrix */ 03394 loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder); 03395 } 03396 } 03397 03398 static bConstraintTypeInfo CTI_TRANSFORM = { 03399 CONSTRAINT_TYPE_TRANSFORM, /* type */ 03400 sizeof(bTransformConstraint), /* size */ 03401 "Transform", /* name */ 03402 "bTransformConstraint", /* struct name */ 03403 NULL, /* free data */ 03404 NULL, /* relink data */ 03405 transform_id_looper, /* id looper */ 03406 NULL, /* copy data */ 03407 transform_new_data, /* new data */ 03408 transform_get_tars, /* get constraint targets */ 03409 transform_flush_tars, /* flush constraint targets */ 03410 default_get_tarmat, /* get a target matrix */ 03411 transform_evaluate /* evaluate */ 03412 }; 03413 03414 /* ---------- Shrinkwrap Constraint ----------- */ 03415 03416 static void shrinkwrap_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03417 { 03418 bShrinkwrapConstraint *data= con->data; 03419 03420 /* target only */ 03421 func(con, (ID**)&data->target, userdata); 03422 } 03423 03424 static int shrinkwrap_get_tars (bConstraint *con, ListBase *list) 03425 { 03426 if (con && list) { 03427 bShrinkwrapConstraint *data = con->data; 03428 bConstraintTarget *ct; 03429 03430 SINGLETARGETNS_GET_TARS(con, data->target, ct, list) 03431 03432 return 1; 03433 } 03434 03435 return 0; 03436 } 03437 03438 03439 static void shrinkwrap_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03440 { 03441 if (con && list) { 03442 bShrinkwrapConstraint *data = con->data; 03443 bConstraintTarget *ct= list->first; 03444 03445 SINGLETARGETNS_FLUSH_TARS(con, data->target, ct, list, nocopy) 03446 } 03447 } 03448 03449 03450 static void shrinkwrap_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 03451 { 03452 bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; 03453 03454 if( VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) ) 03455 { 03456 int fail = FALSE; 03457 float co[3] = {0.0f, 0.0f, 0.0f}; 03458 float no[3] = {0.0f, 0.0f, 0.0f}; 03459 float dist; 03460 03461 SpaceTransform transform; 03462 DerivedMesh *target = object_get_derived_final(ct->tar); 03463 BVHTreeRayHit hit; 03464 BVHTreeNearest nearest; 03465 03466 BVHTreeFromMesh treeData= {NULL}; 03467 03468 nearest.index = -1; 03469 nearest.dist = FLT_MAX; 03470 03471 hit.index = -1; 03472 hit.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it 03473 03474 unit_m4(ct->matrix); 03475 03476 if(target != NULL) 03477 { 03478 space_transform_from_matrixs(&transform, cob->matrix, ct->tar->obmat); 03479 03480 switch(scon->shrinkType) 03481 { 03482 case MOD_SHRINKWRAP_NEAREST_SURFACE: 03483 case MOD_SHRINKWRAP_NEAREST_VERTEX: 03484 03485 if(scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) 03486 bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6); 03487 else 03488 bvhtree_from_mesh_faces(&treeData, target, 0.0, 2, 6); 03489 03490 if(treeData.tree == NULL) 03491 { 03492 fail = TRUE; 03493 break; 03494 } 03495 03496 space_transform_apply(&transform, co); 03497 03498 BLI_bvhtree_find_nearest(treeData.tree, co, &nearest, treeData.nearest_callback, &treeData); 03499 03500 dist = len_v3v3(co, nearest.co); 03501 if(dist != 0.0f) { 03502 interp_v3_v3v3(co, co, nearest.co, (dist - scon->dist)/dist); /* linear interpolation */ 03503 } 03504 space_transform_invert(&transform, co); 03505 break; 03506 03507 case MOD_SHRINKWRAP_PROJECT: 03508 if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f; 03509 if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f; 03510 if(scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f; 03511 03512 if(INPR(no,no) < FLT_EPSILON) 03513 { 03514 fail = TRUE; 03515 break; 03516 } 03517 03518 normalize_v3(no); 03519 03520 03521 bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6); 03522 if(treeData.tree == NULL) 03523 { 03524 fail = TRUE; 03525 break; 03526 } 03527 03528 if(normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE) 03529 { 03530 fail = TRUE; 03531 break; 03532 } 03533 copy_v3_v3(co, hit.co); 03534 break; 03535 } 03536 03537 free_bvhtree_from_mesh(&treeData); 03538 03539 target->release(target); 03540 03541 if(fail == TRUE) 03542 { 03543 /* Don't move the point */ 03544 co[0] = co[1] = co[2] = 0.0f; 03545 } 03546 03547 /* co is in local object coordinates, change it to global and update target position */ 03548 mul_m4_v3(cob->matrix, co); 03549 copy_v3_v3(ct->matrix[3], co); 03550 } 03551 } 03552 } 03553 03554 static void shrinkwrap_evaluate (bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets) 03555 { 03556 bConstraintTarget *ct= targets->first; 03557 03558 /* only evaluate if there is a target */ 03559 if (VALID_CONS_TARGET(ct)) 03560 { 03561 copy_v3_v3(cob->matrix[3], ct->matrix[3]); 03562 } 03563 } 03564 03565 static bConstraintTypeInfo CTI_SHRINKWRAP = { 03566 CONSTRAINT_TYPE_SHRINKWRAP, /* type */ 03567 sizeof(bShrinkwrapConstraint), /* size */ 03568 "Shrinkwrap", /* name */ 03569 "bShrinkwrapConstraint", /* struct name */ 03570 NULL, /* free data */ 03571 NULL, /* relink data */ 03572 shrinkwrap_id_looper, /* id looper */ 03573 NULL, /* copy data */ 03574 NULL, /* new data */ 03575 shrinkwrap_get_tars, /* get constraint targets */ 03576 shrinkwrap_flush_tars, /* flush constraint targets */ 03577 shrinkwrap_get_tarmat, /* get a target matrix */ 03578 shrinkwrap_evaluate /* evaluate */ 03579 }; 03580 03581 /* --------- Damped Track ---------- */ 03582 03583 static void damptrack_new_data (void *cdata) 03584 { 03585 bDampTrackConstraint *data= (bDampTrackConstraint *)cdata; 03586 03587 data->trackflag = TRACK_Y; 03588 } 03589 03590 static void damptrack_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03591 { 03592 bDampTrackConstraint *data= con->data; 03593 03594 /* target only */ 03595 func(con, (ID**)&data->tar, userdata); 03596 } 03597 03598 static int damptrack_get_tars (bConstraint *con, ListBase *list) 03599 { 03600 if (con && list) { 03601 bDampTrackConstraint *data= con->data; 03602 bConstraintTarget *ct; 03603 03604 /* the following macro is used for all standard single-target constraints */ 03605 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 03606 03607 return 1; 03608 } 03609 03610 return 0; 03611 } 03612 03613 static void damptrack_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03614 { 03615 if (con && list) { 03616 bDampTrackConstraint *data= con->data; 03617 bConstraintTarget *ct= list->first; 03618 03619 /* the following macro is used for all standard single-target constraints */ 03620 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 03621 } 03622 } 03623 03624 /* array of direction vectors for the tracking flags */ 03625 static const float track_dir_vecs[6][3] = { 03626 {+1,0,0}, {0,+1,0}, {0,0,+1}, /* TRACK_X, TRACK_Y, TRACK_Z */ 03627 {-1,0,0}, {0,-1,0}, {0,0,-1} /* TRACK_NX, TRACK_NY, TRACK_NZ */ 03628 }; 03629 03630 static void damptrack_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 03631 { 03632 bDampTrackConstraint *data= con->data; 03633 bConstraintTarget *ct= targets->first; 03634 03635 if (VALID_CONS_TARGET(ct)) { 03636 float obvec[3], tarvec[3], obloc[3]; 03637 float raxis[3], rangle; 03638 float rmat[3][3], tmat[4][4]; 03639 03640 /* find the (unit) direction that the axis we're interested in currently points 03641 * - mul_mat3_m4_v3() only takes the 3x3 (rotation+scaling) components of the 4x4 matrix 03642 * - the normalisation step at the end should take care of any unwanted scaling 03643 * left over in the 3x3 matrix we used 03644 */ 03645 copy_v3_v3(obvec, track_dir_vecs[data->trackflag]); 03646 mul_mat3_m4_v3(cob->matrix, obvec); 03647 03648 if (normalize_v3(obvec) == 0.0f) { 03649 /* exceptional case - just use the track vector as appropriate */ 03650 copy_v3_v3(obvec, track_dir_vecs[data->trackflag]); 03651 } 03652 03653 /* find the (unit) direction vector going from the owner to the target */ 03654 copy_v3_v3(obloc, cob->matrix[3]); 03655 sub_v3_v3v3(tarvec, ct->matrix[3], obloc); 03656 03657 if (normalize_v3(tarvec) == 0.0f) { 03658 /* the target is sitting on the owner, so just make them use the same direction vectors */ 03659 // FIXME: or would it be better to use the pure direction vector? 03660 copy_v3_v3(tarvec, obvec); 03661 //copy_v3_v3(tarvec, track_dir_vecs[data->trackflag]); 03662 } 03663 03664 /* determine the axis-angle rotation, which represents the smallest possible rotation 03665 * between the two rotation vectors (i.e. the 'damping' referred to in the name) 03666 * - we take this to be the rotation around the normal axis/vector to the plane defined 03667 * by the current and destination vectors, which will 'map' the current axis to the 03668 * destination vector 03669 * - the min/max wrappers around (obvec . tarvec) result (stored temporarily in rangle) 03670 * are used to ensure that the smallest angle is chosen 03671 */ 03672 cross_v3_v3v3(raxis, obvec, tarvec); 03673 03674 rangle= dot_v3v3(obvec, tarvec); 03675 rangle= acos( MAX2(-1.0f, MIN2(1.0f, rangle)) ); 03676 03677 /* construct rotation matrix from the axis-angle rotation found above 03678 * - this call takes care to make sure that the axis provided is a unit vector first 03679 */ 03680 axis_angle_to_mat3(rmat, raxis, rangle); 03681 03682 /* rotate the owner in the way defined by this rotation matrix, then reapply the location since 03683 * we may have destroyed that in the process of multiplying the matrix 03684 */ 03685 unit_m4(tmat); 03686 mul_m4_m3m4(tmat, rmat, cob->matrix); // m1, m3, m2 03687 03688 copy_m4_m4(cob->matrix, tmat); 03689 copy_v3_v3(cob->matrix[3], obloc); 03690 } 03691 } 03692 03693 static bConstraintTypeInfo CTI_DAMPTRACK = { 03694 CONSTRAINT_TYPE_DAMPTRACK, /* type */ 03695 sizeof(bDampTrackConstraint), /* size */ 03696 "Damped Track", /* name */ 03697 "bDampTrackConstraint", /* struct name */ 03698 NULL, /* free data */ 03699 NULL, /* relink data */ 03700 damptrack_id_looper, /* id looper */ 03701 NULL, /* copy data */ 03702 damptrack_new_data, /* new data */ 03703 damptrack_get_tars, /* get constraint targets */ 03704 damptrack_flush_tars, /* flush constraint targets */ 03705 default_get_tarmat, /* get target matrix */ 03706 damptrack_evaluate /* evaluate */ 03707 }; 03708 03709 /* ----------- Spline IK ------------ */ 03710 03711 static void splineik_free (bConstraint *con) 03712 { 03713 bSplineIKConstraint *data= con->data; 03714 03715 /* binding array */ 03716 if (data->points) 03717 MEM_freeN(data->points); 03718 } 03719 03720 static void splineik_copy (bConstraint *con, bConstraint *srccon) 03721 { 03722 bSplineIKConstraint *src= srccon->data; 03723 bSplineIKConstraint *dst= con->data; 03724 03725 /* copy the binding array */ 03726 dst->points= MEM_dupallocN(src->points); 03727 } 03728 03729 static void splineik_new_data (void *cdata) 03730 { 03731 bSplineIKConstraint *data= (bSplineIKConstraint *)cdata; 03732 03733 data->chainlen= 1; 03734 } 03735 03736 static void splineik_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03737 { 03738 bSplineIKConstraint *data= con->data; 03739 03740 /* target only */ 03741 func(con, (ID**)&data->tar, userdata); 03742 } 03743 03744 static int splineik_get_tars (bConstraint *con, ListBase *list) 03745 { 03746 if (con && list) { 03747 bSplineIKConstraint *data= con->data; 03748 bConstraintTarget *ct; 03749 03750 /* standard target-getting macro for single-target constraints without subtargets */ 03751 SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) 03752 03753 return 1; 03754 } 03755 03756 return 0; 03757 } 03758 03759 static void splineik_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03760 { 03761 if (con && list) { 03762 bSplineIKConstraint *data= con->data; 03763 bConstraintTarget *ct= list->first; 03764 03765 /* the following macro is used for all standard single-target constraints */ 03766 SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) 03767 } 03768 } 03769 03770 static void splineik_get_tarmat (bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) 03771 { 03772 if (VALID_CONS_TARGET(ct)) { 03773 Curve *cu= ct->tar->data; 03774 03775 /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, 03776 * currently for paths to work it needs to go through the bevlist/displist system (ton) 03777 */ 03778 03779 /* only happens on reload file, but violates depsgraph still... fix! */ 03780 if (cu->path==NULL || cu->path->data==NULL) 03781 makeDispListCurveTypes(cob->scene, ct->tar, 0); 03782 } 03783 03784 /* technically, this isn't really needed for evaluation, but we don't know what else 03785 * might end up calling this... 03786 */ 03787 if (ct) 03788 unit_m4(ct->matrix); 03789 } 03790 03791 static bConstraintTypeInfo CTI_SPLINEIK = { 03792 CONSTRAINT_TYPE_SPLINEIK, /* type */ 03793 sizeof(bSplineIKConstraint), /* size */ 03794 "Spline IK", /* name */ 03795 "bSplineIKConstraint", /* struct name */ 03796 splineik_free, /* free data */ 03797 NULL, /* relink data */ 03798 splineik_id_looper, /* id looper */ 03799 splineik_copy, /* copy data */ 03800 splineik_new_data, /* new data */ 03801 splineik_get_tars, /* get constraint targets */ 03802 splineik_flush_tars, /* flush constraint targets */ 03803 splineik_get_tarmat, /* get target matrix */ 03804 NULL /* evaluate - solved as separate loop */ 03805 }; 03806 03807 /* ----------- Pivot ------------- */ 03808 03809 static void pivotcon_id_looper (bConstraint *con, ConstraintIDFunc func, void *userdata) 03810 { 03811 bPivotConstraint *data= con->data; 03812 03813 /* target only */ 03814 func(con, (ID**)&data->tar, userdata); 03815 } 03816 03817 static int pivotcon_get_tars (bConstraint *con, ListBase *list) 03818 { 03819 if (con && list) { 03820 bPivotConstraint *data= con->data; 03821 bConstraintTarget *ct; 03822 03823 /* standard target-getting macro for single-target constraints */ 03824 SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) 03825 03826 return 1; 03827 } 03828 03829 return 0; 03830 } 03831 03832 static void pivotcon_flush_tars (bConstraint *con, ListBase *list, short nocopy) 03833 { 03834 if (con && list) { 03835 bPivotConstraint *data= con->data; 03836 bConstraintTarget *ct= list->first; 03837 03838 /* the following macro is used for all standard single-target constraints */ 03839 SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) 03840 } 03841 } 03842 03843 static void pivotcon_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *targets) 03844 { 03845 bPivotConstraint *data= con->data; 03846 bConstraintTarget *ct= targets->first; 03847 03848 float pivot[3], vec[3]; 03849 float rotMat[3][3]; 03850 03851 /* pivot correction */ 03852 float axis[3], angle; 03853 03854 /* firstly, check if pivoting should take place based on the current rotation */ 03855 if (data->rotAxis != PIVOTCON_AXIS_NONE) { 03856 float rot[3]; 03857 03858 /* extract euler-rotation of target */ 03859 mat4_to_eulO(rot, cob->rotOrder, cob->matrix); 03860 03861 /* check which range might be violated */ 03862 if (data->rotAxis < PIVOTCON_AXIS_X) { 03863 /* negative rotations (data->rotAxis = 0 -> 2) */ 03864 if (rot[data->rotAxis] > 0.0f) 03865 return; 03866 } 03867 else { 03868 /* positive rotations (data->rotAxis = 3 -> 5 */ 03869 if (rot[data->rotAxis - PIVOTCON_AXIS_X] < 0.0f) 03870 return; 03871 } 03872 } 03873 03874 /* find the pivot-point to use */ 03875 if (VALID_CONS_TARGET(ct)) { 03876 /* apply offset to target location */ 03877 add_v3_v3v3(pivot, ct->matrix[3], data->offset); 03878 } 03879 else { 03880 /* no targets to worry about... */ 03881 if ((data->flag & PIVOTCON_FLAG_OFFSET_ABS) == 0) { 03882 /* offset is relative to owner */ 03883 add_v3_v3v3(pivot, cob->matrix[3], data->offset); 03884 } 03885 else { 03886 /* directly use the 'offset' specified as an absolute position instead */ 03887 copy_v3_v3(pivot, data->offset); 03888 } 03889 } 03890 03891 /* get rotation matrix representing the rotation of the owner */ 03892 // TODO: perhaps we might want to include scaling based on the pivot too? 03893 copy_m3_m4(rotMat, cob->matrix); 03894 normalize_m3(rotMat); 03895 03896 03897 /* correct the pivot by the rotation axis otherwise the pivot translates when it shouldnt */ 03898 mat3_to_axis_angle(axis, &angle, rotMat); 03899 if(angle) { 03900 float dvec[3]; 03901 sub_v3_v3v3(vec, pivot, cob->matrix[3]); 03902 project_v3_v3v3(dvec, vec, axis); 03903 sub_v3_v3(pivot, dvec); 03904 } 03905 03906 /* perform the pivoting... */ 03907 /* 1. take the vector from owner to the pivot */ 03908 sub_v3_v3v3(vec, cob->matrix[3], pivot); 03909 /* 2. rotate this vector by the rotation of the object... */ 03910 mul_m3_v3(rotMat, vec); 03911 /* 3. make the rotation in terms of the pivot now */ 03912 add_v3_v3v3(cob->matrix[3], pivot, vec); 03913 } 03914 03915 03916 static bConstraintTypeInfo CTI_PIVOT = { 03917 CONSTRAINT_TYPE_PIVOT, /* type */ 03918 sizeof(bPivotConstraint), /* size */ 03919 "Pivot", /* name */ 03920 "bPivotConstraint", /* struct name */ 03921 NULL, /* free data */ 03922 NULL, /* relink data */ 03923 pivotcon_id_looper, /* id looper */ 03924 NULL, /* copy data */ 03925 NULL, /* new data */ // XXX: might be needed to get 'normal' pivot behaviour... 03926 pivotcon_get_tars, /* get constraint targets */ 03927 pivotcon_flush_tars, /* flush constraint targets */ 03928 default_get_tarmat, /* get target matrix */ 03929 pivotcon_evaluate /* evaluate */ 03930 }; 03931 03932 /* ************************* Constraints Type-Info *************************** */ 03933 /* All of the constraints api functions use bConstraintTypeInfo structs to carry out 03934 * and operations that involve constraint specific code. 03935 */ 03936 03937 /* These globals only ever get directly accessed in this file */ 03938 static bConstraintTypeInfo *constraintsTypeInfo[NUM_CONSTRAINT_TYPES]; 03939 static short CTI_INIT= 1; /* when non-zero, the list needs to be updated */ 03940 03941 /* This function only gets called when CTI_INIT is non-zero */ 03942 static void constraints_init_typeinfo (void) { 03943 constraintsTypeInfo[0]= NULL; /* 'Null' Constraint */ 03944 constraintsTypeInfo[1]= &CTI_CHILDOF; /* ChildOf Constraint */ 03945 constraintsTypeInfo[2]= &CTI_TRACKTO; /* TrackTo Constraint */ 03946 constraintsTypeInfo[3]= &CTI_KINEMATIC; /* IK Constraint */ 03947 constraintsTypeInfo[4]= &CTI_FOLLOWPATH; /* Follow-Path Constraint */ 03948 constraintsTypeInfo[5]= &CTI_ROTLIMIT; /* Limit Rotation Constraint */ 03949 constraintsTypeInfo[6]= &CTI_LOCLIMIT; /* Limit Location Constraint */ 03950 constraintsTypeInfo[7]= &CTI_SIZELIMIT; /* Limit Scaling Constraint */ 03951 constraintsTypeInfo[8]= &CTI_ROTLIKE; /* Copy Rotation Constraint */ 03952 constraintsTypeInfo[9]= &CTI_LOCLIKE; /* Copy Location Constraint */ 03953 constraintsTypeInfo[10]= &CTI_SIZELIKE; /* Copy Scaling Constraint */ 03954 constraintsTypeInfo[11]= &CTI_PYTHON; /* Python/Script Constraint */ 03955 constraintsTypeInfo[12]= &CTI_ACTION; /* Action Constraint */ 03956 constraintsTypeInfo[13]= &CTI_LOCKTRACK; /* Locked-Track Constraint */ 03957 constraintsTypeInfo[14]= &CTI_DISTLIMIT; /* Limit Distance Constraint */ 03958 constraintsTypeInfo[15]= &CTI_STRETCHTO; /* StretchTo Constaint */ 03959 constraintsTypeInfo[16]= &CTI_MINMAX; /* Floor Constraint */ 03960 constraintsTypeInfo[17]= &CTI_RIGIDBODYJOINT; /* RigidBody Constraint */ 03961 constraintsTypeInfo[18]= &CTI_CLAMPTO; /* ClampTo Constraint */ 03962 constraintsTypeInfo[19]= &CTI_TRANSFORM; /* Transformation Constraint */ 03963 constraintsTypeInfo[20]= &CTI_SHRINKWRAP; /* Shrinkwrap Constraint */ 03964 constraintsTypeInfo[21]= &CTI_DAMPTRACK; /* Damped TrackTo Constraint */ 03965 constraintsTypeInfo[22]= &CTI_SPLINEIK; /* Spline IK Constraint */ 03966 constraintsTypeInfo[23]= &CTI_TRANSLIKE; /* Copy Transforms Constraint */ 03967 constraintsTypeInfo[24]= &CTI_SAMEVOL; /* Maintain Volume Constraint */ 03968 constraintsTypeInfo[25]= &CTI_PIVOT; /* Pivot Constraint */ 03969 } 03970 03971 /* This function should be used for getting the appropriate type-info when only 03972 * a constraint type is known 03973 */ 03974 bConstraintTypeInfo *get_constraint_typeinfo (int type) 03975 { 03976 /* initialise the type-info list? */ 03977 if (CTI_INIT) { 03978 constraints_init_typeinfo(); 03979 CTI_INIT = 0; 03980 } 03981 03982 /* only return for valid types */ 03983 if ( (type >= CONSTRAINT_TYPE_NULL) && 03984 (type < NUM_CONSTRAINT_TYPES ) ) 03985 { 03986 /* there shouldn't be any segfaults here... */ 03987 return constraintsTypeInfo[type]; 03988 } 03989 else { 03990 printf("No valid constraint type-info data available. Type = %i \n", type); 03991 } 03992 03993 return NULL; 03994 } 03995 03996 /* This function should always be used to get the appropriate type-info, as it 03997 * has checks which prevent segfaults in some weird cases. 03998 */ 03999 bConstraintTypeInfo *constraint_get_typeinfo (bConstraint *con) 04000 { 04001 /* only return typeinfo for valid constraints */ 04002 if (con) 04003 return get_constraint_typeinfo(con->type); 04004 else 04005 return NULL; 04006 } 04007 04008 /* ************************* General Constraints API ************************** */ 04009 /* The functions here are called by various parts of Blender. Very few (should be none if possible) 04010 * constraint-specific code should occur here. 04011 */ 04012 04013 /* ---------- Data Management ------- */ 04014 04015 /* Free data of a specific constraint if it has any info. 04016 * be sure to run BIK_clear_data() when freeing an IK constraint, 04017 * unless DAG_scene_sort is called. */ 04018 void free_constraint_data (bConstraint *con) 04019 { 04020 if (con->data) { 04021 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04022 04023 /* perform any special freeing constraint may have */ 04024 if (cti && cti->free_data) 04025 cti->free_data(con); 04026 04027 /* free constraint data now */ 04028 MEM_freeN(con->data); 04029 } 04030 } 04031 04032 /* Free all constraints from a constraint-stack */ 04033 void free_constraints (ListBase *list) 04034 { 04035 bConstraint *con; 04036 04037 /* Free constraint data and also any extra data */ 04038 for (con= list->first; con; con= con->next) 04039 free_constraint_data(con); 04040 04041 /* Free the whole list */ 04042 BLI_freelistN(list); 04043 } 04044 04045 04046 /* Remove the specified constraint from the given constraint stack */ 04047 int remove_constraint (ListBase *list, bConstraint *con) 04048 { 04049 if (con) { 04050 free_constraint_data(con); 04051 BLI_freelinkN(list, con); 04052 return 1; 04053 } 04054 else 04055 return 0; 04056 } 04057 04058 /* Remove all the constraints of the specified type from the given constraint stack */ 04059 void remove_constraints_type (ListBase *list, short type, short last_only) 04060 { 04061 bConstraint *con, *conp; 04062 04063 if (list == NULL) 04064 return; 04065 04066 /* remove from the end of the list to make it faster to find the last instance */ 04067 for (con= list->last; con; con= conp) { 04068 conp= con->prev; 04069 04070 if (con->type == type) { 04071 remove_constraint(list, con); 04072 if (last_only) 04073 return; 04074 } 04075 } 04076 } 04077 04078 /* ......... */ 04079 04080 /* Creates a new constraint, initialises its data, and returns it */ 04081 static bConstraint *add_new_constraint_internal (const char *name, short type) 04082 { 04083 bConstraint *con= MEM_callocN(sizeof(bConstraint), "Constraint"); 04084 bConstraintTypeInfo *cti= get_constraint_typeinfo(type); 04085 const char *newName; 04086 04087 /* Set up a generic constraint datablock */ 04088 con->type = type; 04089 con->flag |= CONSTRAINT_EXPAND; 04090 con->enforce = 1.0f; 04091 04092 /* Determine a basic name, and info */ 04093 if (cti) { 04094 /* initialise constraint data */ 04095 con->data = MEM_callocN(cti->size, cti->structName); 04096 04097 /* only constraints that change any settings need this */ 04098 if (cti->new_data) 04099 cti->new_data(con->data); 04100 04101 /* if no name is provided, use the type of the constraint as the name */ 04102 newName= (name && name[0]) ? name : cti->name; 04103 } 04104 else { 04105 /* if no name is provided, use the generic "Const" name */ 04106 // NOTE: any constraint type that gets here really shouldn't get added... 04107 newName= (name && name[0]) ? name : "Const"; 04108 } 04109 04110 /* copy the name */ 04111 BLI_strncpy(con->name, newName, sizeof(con->name)); 04112 04113 /* return the new constraint */ 04114 return con; 04115 } 04116 04117 /* if pchan is not NULL then assume we're adding a pose constraint */ 04118 static bConstraint *add_new_constraint (Object *ob, bPoseChannel *pchan, const char *name, short type) 04119 { 04120 bConstraint *con; 04121 ListBase *list; 04122 04123 /* add the constraint */ 04124 con= add_new_constraint_internal(name, type); 04125 04126 /* find the constraint stack - bone or object? */ 04127 list = (pchan) ? (&pchan->constraints) : (&ob->constraints); 04128 04129 if (list) { 04130 /* add new constraint to end of list of constraints before ensuring that it has a unique name 04131 * (otherwise unique-naming code will fail, since it assumes element exists in list) 04132 */ 04133 BLI_addtail(list, con); 04134 unique_constraint_name(con, list); 04135 04136 /* if the target list is a list on some PoseChannel belonging to a proxy-protected 04137 * Armature layer, we must tag newly added constraints with a flag which allows them 04138 * to persist after proxy syncing has been done 04139 */ 04140 if (proxylocked_constraints_owner(ob, pchan)) 04141 con->flag |= CONSTRAINT_PROXY_LOCAL; 04142 04143 /* make this constraint the active one */ 04144 constraints_set_active(list, con); 04145 } 04146 04147 /* set type+owner specific immutable settings */ 04148 // TODO: does action constraint need anything here - i.e. spaceonce? 04149 switch (type) { 04150 case CONSTRAINT_TYPE_CHILDOF: 04151 { 04152 /* if this constraint is being added to a posechannel, make sure 04153 * the constraint gets evaluated in pose-space */ 04154 if (pchan) { 04155 con->ownspace = CONSTRAINT_SPACE_POSE; 04156 con->flag |= CONSTRAINT_SPACEONCE; 04157 } 04158 } 04159 break; 04160 } 04161 04162 return con; 04163 } 04164 04165 /* ......... */ 04166 04167 /* Add new constraint for the given bone */ 04168 bConstraint *add_pose_constraint (Object *ob, bPoseChannel *pchan, const char *name, short type) 04169 { 04170 if (pchan == NULL) 04171 return NULL; 04172 04173 return add_new_constraint(ob, pchan, name, type); 04174 } 04175 04176 /* Add new constraint for the given object */ 04177 bConstraint *add_ob_constraint(Object *ob, const char *name, short type) 04178 { 04179 return add_new_constraint(ob, NULL, name, type); 04180 } 04181 04182 /* ......... */ 04183 04184 /* Reassign links that constraints have to other data (called during file loading?) */ 04185 void relink_constraints (ListBase *conlist) 04186 { 04187 bConstraint *con; 04188 bConstraintTarget *ct; 04189 04190 for (con= conlist->first; con; con= con->next) { 04191 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04192 04193 if (cti) { 04194 /* relink any targets */ 04195 if (cti->get_constraint_targets) { 04196 ListBase targets = {NULL, NULL}; 04197 04198 cti->get_constraint_targets(con, &targets); 04199 for (ct= targets.first; ct; ct= ct->next) { 04200 ID_NEW(ct->tar); 04201 } 04202 04203 if (cti->flush_constraint_targets) 04204 cti->flush_constraint_targets(con, &targets, 0); 04205 } 04206 04207 /* relink any other special data */ 04208 if (cti->relink_data) 04209 cti->relink_data(con); 04210 } 04211 } 04212 } 04213 04214 /* Run the given callback on all ID-blocks in list of constraints */ 04215 void id_loop_constraints (ListBase *conlist, ConstraintIDFunc func, void *userdata) 04216 { 04217 bConstraint *con; 04218 04219 for (con= conlist->first; con; con= con->next) { 04220 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04221 04222 if (cti) { 04223 if (cti->id_looper) 04224 cti->id_looper(con, func, userdata); 04225 } 04226 } 04227 } 04228 04229 /* ......... */ 04230 04231 /* helper for copy_constraints(), to be used for making sure that ID's are valid */ 04232 static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, void *UNUSED(userData)) 04233 { 04234 if (*idpoin && (*idpoin)->lib) 04235 id_lib_extern(*idpoin); 04236 } 04237 04238 /* duplicate all of the constraints in a constraint stack */ 04239 void copy_constraints (ListBase *dst, const ListBase *src, int do_extern) 04240 { 04241 bConstraint *con, *srccon; 04242 04243 dst->first= dst->last= NULL; 04244 BLI_duplicatelist(dst, src); 04245 04246 for (con=dst->first, srccon=src->first; con && srccon; srccon=srccon->next, con=con->next) { 04247 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04248 04249 /* make a new copy of the constraint's data */ 04250 con->data = MEM_dupallocN(con->data); 04251 04252 /* only do specific constraints if required */ 04253 if (cti) { 04254 /* perform custom copying operations if needed */ 04255 if (cti->copy_data) 04256 cti->copy_data(con, srccon); 04257 04258 /* for proxies we dont want to make extern */ 04259 if (do_extern) { 04260 /* go over used ID-links for this constraint to ensure that they are valid for proxies */ 04261 if (cti->id_looper) 04262 cti->id_looper(con, con_extern_cb, NULL); 04263 } 04264 } 04265 } 04266 } 04267 04268 /* ......... */ 04269 04270 bConstraint *constraints_findByName(ListBase *list, const char *name) 04271 { 04272 return BLI_findstring(list, name, offsetof(bConstraint, name)); 04273 } 04274 04275 /* finds the 'active' constraint in a constraint stack */ 04276 bConstraint *constraints_get_active (ListBase *list) 04277 { 04278 bConstraint *con; 04279 04280 /* search for the first constraint with the 'active' flag set */ 04281 if (list) { 04282 for (con= list->first; con; con= con->next) { 04283 if (con->flag & CONSTRAINT_ACTIVE) 04284 return con; 04285 } 04286 } 04287 04288 /* no active constraint found */ 04289 return NULL; 04290 } 04291 04292 /* Set the given constraint as the active one (clearing all the others) */ 04293 void constraints_set_active (ListBase *list, bConstraint *con) 04294 { 04295 bConstraint *c; 04296 04297 if (list) { 04298 for (c= list->first; c; c= c->next) { 04299 if (c == con) 04300 c->flag |= CONSTRAINT_ACTIVE; 04301 else 04302 c->flag &= ~CONSTRAINT_ACTIVE; 04303 } 04304 } 04305 } 04306 04307 /* -------- Constraints and Proxies ------- */ 04308 04309 /* Rescue all constraints tagged as being CONSTRAINT_PROXY_LOCAL (i.e. added to bone that's proxy-synced in this file) */ 04310 void extract_proxylocal_constraints (ListBase *dst, ListBase *src) 04311 { 04312 bConstraint *con, *next; 04313 04314 /* for each tagged constraint, remove from src and move to dst */ 04315 for (con= src->first; con; con= next) { 04316 next= con->next; 04317 04318 /* check if tagged */ 04319 if (con->flag & CONSTRAINT_PROXY_LOCAL) { 04320 BLI_remlink(src, con); 04321 BLI_addtail(dst, con); 04322 } 04323 } 04324 } 04325 04326 /* Returns if the owner of the constraint is proxy-protected */ 04327 short proxylocked_constraints_owner (Object *ob, bPoseChannel *pchan) 04328 { 04329 /* Currently, constraints can only be on object or bone level */ 04330 if (ob && ob->proxy) { 04331 if (ob->pose && pchan) { 04332 bArmature *arm= ob->data; 04333 04334 /* On bone-level, check if bone is on proxy-protected layer */ 04335 if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected)) 04336 return 1; 04337 } 04338 else { 04339 /* FIXME: constraints on object-level are not handled well yet */ 04340 return 1; 04341 } 04342 } 04343 04344 return 0; 04345 } 04346 04347 /* -------- Target-Matrix Stuff ------- */ 04348 04349 /* This function is a relic from the prior implementations of the constraints system, when all 04350 * constraints either had one or no targets. It used to be called during the main constraint solving 04351 * loop, but is now only used for the remaining cases for a few constraints. 04352 * 04353 * None of the actual calculations of the matricies should be done here! Also, this function is 04354 * not to be used by any new constraints, particularly any that have multiple targets. 04355 */ 04356 void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime) 04357 { 04358 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04359 ListBase targets = {NULL, NULL}; 04360 bConstraintOb *cob; 04361 bConstraintTarget *ct; 04362 04363 if (cti && cti->get_constraint_targets) { 04364 /* make 'constraint-ob' */ 04365 cob= MEM_callocN(sizeof(bConstraintOb), "tempConstraintOb"); 04366 cob->type= ownertype; 04367 cob->scene = scene; 04368 switch (ownertype) { 04369 case CONSTRAINT_OBTYPE_OBJECT: /* it is usually this case */ 04370 { 04371 cob->ob= (Object *)ownerdata; 04372 cob->pchan= NULL; 04373 if (cob->ob) { 04374 copy_m4_m4(cob->matrix, cob->ob->obmat); 04375 copy_m4_m4(cob->startmat, cob->matrix); 04376 } 04377 else { 04378 unit_m4(cob->matrix); 04379 unit_m4(cob->startmat); 04380 } 04381 } 04382 break; 04383 case CONSTRAINT_OBTYPE_BONE: /* this may occur in some cases */ 04384 { 04385 cob->ob= NULL; /* this might not work at all :/ */ 04386 cob->pchan= (bPoseChannel *)ownerdata; 04387 if (cob->pchan) { 04388 copy_m4_m4(cob->matrix, cob->pchan->pose_mat); 04389 copy_m4_m4(cob->startmat, cob->matrix); 04390 } 04391 else { 04392 unit_m4(cob->matrix); 04393 unit_m4(cob->startmat); 04394 } 04395 } 04396 break; 04397 } 04398 04399 /* get targets - we only need the first one though (and there should only be one) */ 04400 cti->get_constraint_targets(con, &targets); 04401 04402 /* only calculate the target matrix on the first target */ 04403 ct= (bConstraintTarget *)targets.first; 04404 while(ct && n-- > 0) 04405 ct= ct->next; 04406 04407 if (ct) { 04408 if (cti->get_target_matrix) 04409 cti->get_target_matrix(con, cob, ct, ctime); 04410 copy_m4_m4(mat, ct->matrix); 04411 } 04412 04413 /* free targets + 'constraint-ob' */ 04414 if (cti->flush_constraint_targets) 04415 cti->flush_constraint_targets(con, &targets, 1); 04416 MEM_freeN(cob); 04417 } 04418 else { 04419 /* invalid constraint - perhaps... */ 04420 unit_m4(mat); 04421 } 04422 } 04423 04424 /* ---------- Evaluation ----------- */ 04425 04426 /* This function is called whenever constraints need to be evaluated. Currently, all 04427 * constraints that can be evaluated are everytime this gets run. 04428 * 04429 * constraints_make_evalob and constraints_clear_evalob should be called before and 04430 * after running this function, to sort out cob 04431 */ 04432 void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) 04433 { 04434 bConstraint *con; 04435 float oldmat[4][4]; 04436 float enf; 04437 04438 /* check that there is a valid constraint object to evaluate */ 04439 if (cob == NULL) 04440 return; 04441 04442 /* loop over available constraints, solving and blending them */ 04443 for (con= conlist->first; con; con= con->next) { 04444 bConstraintTypeInfo *cti= constraint_get_typeinfo(con); 04445 ListBase targets = {NULL, NULL}; 04446 04447 /* these we can skip completely (invalid constraints...) */ 04448 if (cti == NULL) continue; 04449 if (con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF)) continue; 04450 /* these constraints can't be evaluated anyway */ 04451 if (cti->evaluate_constraint == NULL) continue; 04452 /* influence == 0 should be ignored */ 04453 if (con->enforce == 0.0f) continue; 04454 04455 /* influence of constraint 04456 * - value should have been set from animation data already 04457 */ 04458 enf = con->enforce; 04459 04460 /* make copy of worldspace matrix pre-constraint for use with blending later */ 04461 copy_m4_m4(oldmat, cob->matrix); 04462 04463 /* move owner matrix into right space */ 04464 constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); 04465 04466 /* prepare targets for constraint solving */ 04467 if (cti->get_constraint_targets) { 04468 bConstraintTarget *ct; 04469 04470 /* get targets 04471 * - constraints should use ct->matrix, not directly accessing values 04472 * - ct->matrix members have not yet been calculated here! 04473 */ 04474 cti->get_constraint_targets(con, &targets); 04475 04476 /* set matrices 04477 * - calculate if possible, otherwise just initialise as identity matrix 04478 */ 04479 if (cti->get_target_matrix) { 04480 for (ct= targets.first; ct; ct= ct->next) 04481 cti->get_target_matrix(con, cob, ct, ctime); 04482 } 04483 else { 04484 for (ct= targets.first; ct; ct= ct->next) 04485 unit_m4(ct->matrix); 04486 } 04487 } 04488 04489 /* Solve the constraint and put result in cob->matrix */ 04490 cti->evaluate_constraint(con, cob, &targets); 04491 04492 /* clear targets after use 04493 * - this should free temp targets but no data should be copied back 04494 * as constraints may have done some nasty things to it... 04495 */ 04496 if (cti->flush_constraint_targets) { 04497 cti->flush_constraint_targets(con, &targets, 1); 04498 } 04499 04500 /* move owner back into worldspace for next constraint/other business */ 04501 if ((con->flag & CONSTRAINT_SPACEONCE) == 0) 04502 constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); 04503 04504 /* Interpolate the enforcement, to blend result of constraint into final owner transform 04505 * - all this happens in worldspace to prevent any weirdness creeping in ([#26014] and [#25725]), 04506 * since some constraints may not convert the solution back to the input space before blending 04507 * but all are guaranteed to end up in good "worldspace" result 04508 */ 04509 /* Note: all kind of stuff here before (caused trouble), much easier to just interpolate, or did I miss something? -jahka */ 04510 if (enf < 1.0f) { 04511 float solution[4][4]; 04512 copy_m4_m4(solution, cob->matrix); 04513 blend_m4_m4m4(cob->matrix, oldmat, solution, enf); 04514 } 04515 } 04516 }