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