| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  |  * ***** BEGIN GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							| 
									
										
										
										
											2010-02-12 13:34:04 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Original author: Benoit Bolsee | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  |  * Contributor(s): | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-02-27 20:24:49 +00:00
										 |  |  | /** \file blender/ikplugin/intern/itasc_plugin.cpp
 | 
					
						
							|  |  |  |  *  \ingroup ikplugin | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // iTaSC headers
 | 
					
						
							| 
									
										
										
										
											2010-09-12 12:27:12 +00:00
										 |  |  | #ifdef WITH_IK_ITASC
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include "Armature.hpp"
 | 
					
						
							|  |  |  | #include "MovingFrame.hpp"
 | 
					
						
							|  |  |  | #include "CopyPose.hpp"
 | 
					
						
							|  |  |  | #include "WSDLSSolver.hpp"
 | 
					
						
							|  |  |  | #include "WDLSSolver.hpp"
 | 
					
						
							|  |  |  | #include "Scene.hpp"
 | 
					
						
							|  |  |  | #include "Cache.hpp"
 | 
					
						
							|  |  |  | #include "Distance.hpp"
 | 
					
						
							| 
									
										
										
										
											2010-09-12 12:27:12 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #include "BIK_api.h"
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 18:36:47 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_armature.h"
 | 
					
						
							|  |  |  | #include "BKE_action.h"
 | 
					
						
							|  |  |  | #include "BKE_constraint.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_action_types.h"
 | 
					
						
							|  |  |  | #include "DNA_constraint_types.h"
 | 
					
						
							|  |  |  | #include "DNA_armature_types.h"
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "itasc_plugin.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // default parameters
 | 
					
						
							| 
									
										
										
										
											2014-09-16 09:06:56 +10:00
										 |  |  | static bItasc DefIKParam; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // in case of animation mode, feedback and timestep is fixed
 | 
					
						
							| 
									
										
										
										
											2013-12-30 10:53:09 +11:00
										 |  |  | // #define ANIM_TIMESTEP   1.0
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | #define ANIM_FEEDBACK   0.8
 | 
					
						
							| 
									
										
										
										
											2013-12-30 10:53:09 +11:00
										 |  |  | // #define ANIM_QMAX       0.52
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Structure pointed by bPose.ikdata
 | 
					
						
							|  |  |  | // It contains everything needed to simulate the armatures
 | 
					
						
							|  |  |  | // There can be several simulation islands independent to each other
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | struct IK_Data { | 
					
						
							|  |  |  | 	struct IK_Scene *first; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef float Vector3[3]; | 
					
						
							|  |  |  | typedef float Vector4[4]; | 
					
						
							|  |  |  | struct IK_Target; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | typedef void (*ErrorCallback)(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // one structure for each target in the scene
 | 
					
						
							| 
									
										
										
										
											2015-04-07 11:25:42 +10:00
										 |  |  | struct IK_Target { | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 	struct Scene			*blscene; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	iTaSC::MovingFrame*		target; | 
					
						
							|  |  |  | 	iTaSC::ConstraintSet*	constraint; | 
					
						
							|  |  |  | 	struct bConstraint*		blenderConstraint; | 
					
						
							|  |  |  | 	struct bPoseChannel*    rootChannel; | 
					
						
							|  |  |  | 	Object*					owner;			//for auto IK
 | 
					
						
							|  |  |  | 	ErrorCallback			errorCallback; | 
					
						
							|  |  |  | 	std::string				targetName; | 
					
						
							|  |  |  | 	std::string				constraintName; | 
					
						
							|  |  |  | 	unsigned short			controlType; | 
					
						
							|  |  |  | 	short					channel;		//index in IK channel array of channel on which this target is defined
 | 
					
						
							|  |  |  | 	short					ee;				//end effector number
 | 
					
						
							|  |  |  | 	bool					simulation;		//true when simulation mode is used (update feedback)
 | 
					
						
							|  |  |  | 	bool					eeBlend;		//end effector affected by enforce blending
 | 
					
						
							|  |  |  | 	float					eeRest[4][4];	//end effector initial pose relative to armature
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	IK_Target() { | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 		blscene = NULL; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		target = NULL; | 
					
						
							|  |  |  | 		constraint = NULL; | 
					
						
							|  |  |  | 		blenderConstraint = NULL; | 
					
						
							|  |  |  | 		rootChannel = NULL; | 
					
						
							|  |  |  | 		owner = NULL; | 
					
						
							|  |  |  | 		controlType = 0; | 
					
						
							|  |  |  | 		channel = 0; | 
					
						
							|  |  |  | 		ee = 0; | 
					
						
							|  |  |  | 		eeBlend = true; | 
					
						
							|  |  |  | 		simulation = true; | 
					
						
							|  |  |  | 		targetName.reserve(32); | 
					
						
							|  |  |  | 		constraintName.reserve(32); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	~IK_Target() { | 
					
						
							|  |  |  | 		if (constraint) | 
					
						
							|  |  |  | 			delete constraint; | 
					
						
							|  |  |  | 		if (target) | 
					
						
							|  |  |  | 			delete target; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct IK_Channel { | 
					
						
							|  |  |  | 	bPoseChannel*	pchan;		// channel where we must copy matrix back
 | 
					
						
							|  |  |  | 	KDL::Frame		frame;		// frame of the bone relative to object base, not armature base
 | 
					
						
							|  |  |  | 	std::string		tail;		// segment name of the joint from which we get the bone tail
 | 
					
						
							|  |  |  | 	std::string     head;		// segment name of the joint from which we get the bone head
 | 
					
						
							|  |  |  | 	int				parent;		// index in this array of the parent channel
 | 
					
						
							|  |  |  | 	short			jointType;	// type of joint, combination of IK_SegmentFlag
 | 
					
						
							|  |  |  | 	char			ndof;		// number of joint angles for this channel
 | 
					
						
							|  |  |  | 	char			jointValid;	// set to 1 when jointValue has been computed
 | 
					
						
							|  |  |  | 	// for joint constraint
 | 
					
						
							|  |  |  | 	Object*			owner;				// for pose and IK param
 | 
					
						
							|  |  |  | 	double			jointValue[4];		// computed joint value
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	IK_Channel() { | 
					
						
							|  |  |  | 		pchan = NULL; | 
					
						
							|  |  |  | 		parent = -1; | 
					
						
							|  |  |  | 		jointType = 0; | 
					
						
							|  |  |  | 		ndof = 0; | 
					
						
							|  |  |  | 		jointValid = 0; | 
					
						
							|  |  |  | 		owner = NULL; | 
					
						
							|  |  |  | 		jointValue[0] = 0.0; | 
					
						
							|  |  |  | 		jointValue[1] = 0.0; | 
					
						
							|  |  |  | 		jointValue[2] = 0.0; | 
					
						
							|  |  |  | 		jointValue[3] = 0.0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | struct IK_Scene { | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 	struct Scene		*blscene; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	IK_Scene*			next; | 
					
						
							|  |  |  | 	int					numchan;	// number of channel in pchan
 | 
					
						
							|  |  |  | 	int					numjoint;	// number of joint in jointArray
 | 
					
						
							|  |  |  | 	// array of bone information, one per channel in the tree
 | 
					
						
							|  |  |  | 	IK_Channel*			channels; | 
					
						
							|  |  |  | 	iTaSC::Armature*	armature; | 
					
						
							|  |  |  | 	iTaSC::Cache*		cache; | 
					
						
							|  |  |  | 	iTaSC::Scene*		scene; | 
					
						
							|  |  |  | 	iTaSC::MovingFrame* base;		// armature base object
 | 
					
						
							|  |  |  | 	KDL::Frame			baseFrame;	// frame of armature base relative to blArmature
 | 
					
						
							|  |  |  | 	KDL::JntArray		jointArray;	// buffer for storing temporary joint array
 | 
					
						
							|  |  |  | 	iTaSC::Solver*		solver; | 
					
						
							|  |  |  | 	Object*				blArmature; | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 	float				blScale;	// scale of the Armature object (assume uniform scaling)
 | 
					
						
							|  |  |  | 	float				blInvScale;	// inverse of Armature object scale
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	struct bConstraint*	polarConstraint; | 
					
						
							|  |  |  | 	std::vector<IK_Target*>		targets; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	IK_Scene() { | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 		blscene = NULL; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		next = NULL; | 
					
						
							|  |  |  | 		channels = NULL; | 
					
						
							|  |  |  | 		armature = NULL; | 
					
						
							|  |  |  | 		cache = NULL; | 
					
						
							|  |  |  | 		scene = NULL; | 
					
						
							|  |  |  | 		base = NULL; | 
					
						
							|  |  |  | 		solver = NULL; | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		blScale = blInvScale = 1.0f; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		blArmature = NULL; | 
					
						
							|  |  |  | 		numchan = 0; | 
					
						
							|  |  |  | 		numjoint = 0; | 
					
						
							|  |  |  | 		polarConstraint = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	~IK_Scene() { | 
					
						
							|  |  |  | 		// delete scene first
 | 
					
						
							|  |  |  | 		if (scene) | 
					
						
							|  |  |  | 			delete scene; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (std::vector<IK_Target *>::iterator it = targets.begin(); it != targets.end(); ++it) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			delete (*it); | 
					
						
							|  |  |  | 		targets.clear(); | 
					
						
							|  |  |  | 		if (channels) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			delete[] channels; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (solver) | 
					
						
							|  |  |  | 			delete solver; | 
					
						
							|  |  |  | 		if (armature) | 
					
						
							|  |  |  | 			delete armature; | 
					
						
							|  |  |  | 		if (base) | 
					
						
							|  |  |  | 			delete base; | 
					
						
							|  |  |  | 		// delete cache last
 | 
					
						
							|  |  |  | 		if (cache) | 
					
						
							|  |  |  | 			delete cache; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // type of IK joint, can be combined to list the joints corresponding to a bone
 | 
					
						
							|  |  |  | enum IK_SegmentFlag { | 
					
						
							|  |  |  | 	IK_XDOF = 1, | 
					
						
							|  |  |  | 	IK_YDOF = 2, | 
					
						
							|  |  |  | 	IK_ZDOF = 4, | 
					
						
							|  |  |  | 	IK_SWING = 8, | 
					
						
							|  |  |  | 	IK_REVOLUTE = 16, | 
					
						
							|  |  |  | 	IK_TRANSY = 32, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum IK_SegmentAxis { | 
					
						
							|  |  |  | 	IK_X = 0, | 
					
						
							|  |  |  | 	IK_Y = 1, | 
					
						
							|  |  |  | 	IK_Z = 2, | 
					
						
							|  |  |  | 	IK_TRANS_X = 3, | 
					
						
							|  |  |  | 	IK_TRANS_Y = 4, | 
					
						
							|  |  |  | 	IK_TRANS_Z = 5 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int initialize_chain(Object *ob, bPoseChannel *pchan_tip, bConstraint *con) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	bPoseChannel *curchan, *pchan_root = NULL, *chanlist[256], **oldchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	PoseTree *tree; | 
					
						
							|  |  |  | 	PoseTarget *target; | 
					
						
							|  |  |  | 	bKinematicConstraint *data; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	int a, t, segcount = 0, size, newsize, *oldparent, parent, rootbone, treecount; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	data = (bKinematicConstraint *)con->data; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* exclude tip from chain? */ | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 	if (!(data->flag & CONSTRAINT_IK_TIP)) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		pchan_tip = pchan_tip->parent; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	rootbone = data->rootbone; | 
					
						
							|  |  |  | 	/* Find the chain's root & count the segments needed */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (curchan = pchan_tip; curchan; curchan = curchan->parent) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		pchan_root = curchan; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (++segcount > 255)       // 255 is weak
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if (segcount == rootbone) { | 
					
						
							|  |  |  | 			// reached this end of the chain but if the chain is overlapping with a
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// previous one, we must go back up to the root of the other chain
 | 
					
						
							| 
									
										
										
										
											2014-02-08 06:07:10 +11:00
										 |  |  | 			if ((curchan->flag & POSE_CHAIN) && BLI_listbase_is_empty(&curchan->iktree)) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				rootbone++; | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-08 06:07:10 +11:00
										 |  |  | 		if (BLI_listbase_is_empty(&curchan->iktree) == false) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			// Oh oh, there is already a chain starting from this channel and our chain is longer...
 | 
					
						
							| 
									
										
										
										
											2012-03-02 16:05:54 +00:00
										 |  |  | 			// Should handle this by moving the previous chain up to the beginning of our chain
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// For now we just stop here
 | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!segcount) return 0; | 
					
						
							|  |  |  | 	// we reached a limit and still not the end of a previous chain, quit
 | 
					
						
							| 
									
										
										
										
											2014-02-08 06:07:10 +11:00
										 |  |  | 	if ((pchan_root->flag & POSE_CHAIN) && BLI_listbase_is_empty(&pchan_root->iktree)) return 0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// now that we know how many segment we have, set the flag
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (rootbone = segcount, segcount = 0, curchan = pchan_tip; segcount < rootbone; segcount++, curchan = curchan->parent) { | 
					
						
							|  |  |  | 		chanlist[segcount] = curchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		curchan->flag |= POSE_CHAIN; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* setup the chain data */ | 
					
						
							|  |  |  | 	/* create a target */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	target = (PoseTarget *)MEM_callocN(sizeof(PoseTarget), "posetarget"); | 
					
						
							|  |  |  | 	target->con = con; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// by contruction there can be only one tree per channel and each channel can be part of at most one tree.
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	tree = (PoseTree *)pchan_root->iktree.first; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (tree == NULL) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		/* make new tree */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		tree = (PoseTree *)MEM_callocN(sizeof(PoseTree), "posetree"); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		tree->iterations = data->iterations; | 
					
						
							|  |  |  | 		tree->totchannel = segcount; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		tree->pchan = (bPoseChannel **)MEM_callocN(segcount * sizeof(void *), "ik tree pchan"); | 
					
						
							|  |  |  | 		tree->parent = (int *)MEM_callocN(segcount * sizeof(int), "ik tree parent"); | 
					
						
							|  |  |  | 		for (a = 0; a < segcount; a++) { | 
					
						
							|  |  |  | 			tree->pchan[a] = chanlist[segcount - a - 1]; | 
					
						
							|  |  |  | 			tree->parent[a] = a - 1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		target->tip = segcount - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		/* AND! link the tree to the root */ | 
					
						
							|  |  |  | 		BLI_addtail(&pchan_root->iktree, tree); | 
					
						
							|  |  |  | 		// new tree
 | 
					
						
							|  |  |  | 		treecount = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		tree->iterations = MAX2(data->iterations, tree->iterations); | 
					
						
							|  |  |  | 		tree->stretch = tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/* skip common pose channels and add remaining*/ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		size = MIN2(segcount, tree->totchannel); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		a = t = 0; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		while (a < size && t < tree->totchannel) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// locate first matching channel
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			for (; t < tree->totchannel && tree->pchan[t] != chanlist[segcount - a - 1]; t++) ; | 
					
						
							|  |  |  | 			if (t >= tree->totchannel) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			for (; a < size && t < tree->totchannel && tree->pchan[t] == chanlist[segcount - a - 1]; a++, t++) ; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2011-11-13 13:08:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		segcount = segcount - a; | 
					
						
							|  |  |  | 		target->tip = tree->totchannel + segcount - 1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (segcount > 0) { | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 			for (parent = a - 1; parent < tree->totchannel; parent++) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				if (tree->pchan[parent] == chanlist[segcount - 1]->parent) | 
					
						
							| 
									
										
										
										
											2011-11-13 13:08:15 +00:00
										 |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-11-13 13:08:15 +00:00
										 |  |  | 			/* shouldn't happen, but could with dependency cycles */ | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 			if (parent == tree->totchannel) | 
					
						
							| 
									
										
										
										
											2011-11-13 13:08:15 +00:00
										 |  |  | 				parent = a - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			/* resize array */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			newsize = tree->totchannel + segcount; | 
					
						
							|  |  |  | 			oldchan = tree->pchan; | 
					
						
							|  |  |  | 			oldparent = tree->parent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tree->pchan = (bPoseChannel **)MEM_callocN(newsize * sizeof(void *), "ik tree pchan"); | 
					
						
							|  |  |  | 			tree->parent = (int *)MEM_callocN(newsize * sizeof(int), "ik tree parent"); | 
					
						
							|  |  |  | 			memcpy(tree->pchan, oldchan, sizeof(void *) * tree->totchannel); | 
					
						
							|  |  |  | 			memcpy(tree->parent, oldparent, sizeof(int) * tree->totchannel); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			MEM_freeN(oldchan); | 
					
						
							|  |  |  | 			MEM_freeN(oldparent); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			/* add new pose channels at the end, in reverse order */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			for (a = 0; a < segcount; a++) { | 
					
						
							|  |  |  | 				tree->pchan[tree->totchannel + a] = chanlist[segcount - a - 1]; | 
					
						
							|  |  |  | 				tree->parent[tree->totchannel + a] = tree->totchannel + a - 1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			tree->parent[tree->totchannel] = parent; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			tree->totchannel = newsize; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// reusing tree
 | 
					
						
							|  |  |  | 		treecount = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* add target to the tree */ | 
					
						
							|  |  |  | 	BLI_addtail(&tree->targets, target); | 
					
						
							|  |  |  | 	/* mark root channel having an IK tree */ | 
					
						
							|  |  |  | 	pchan_root->flag |= POSE_IKTREE; | 
					
						
							|  |  |  | 	return treecount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool is_cartesian_constraint(bConstraint *con) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-12-28 14:19:05 +00:00
										 |  |  | 	//bKinematicConstraint* data=(bKinematicConstraint *)con->data;
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool constraint_valid(bConstraint *con) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	bKinematicConstraint *data = (bKinematicConstraint *)con->data; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (data->flag & CONSTRAINT_IK_AUTO) | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2014-01-14 14:40:18 -02:00
										 |  |  | 	if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	if (is_cartesian_constraint(con)) { | 
					
						
							|  |  |  | 		/* cartesian space constraint */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if (data->tar == NULL) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			return false; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if (data->tar->type == OB_ARMATURE && data->subtarget[0] == 0) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-09-16 00:26:36 +00:00
										 |  |  | static int initialize_scene(Object *ob, bPoseChannel *pchan_tip) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bConstraint *con; | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | 	int treecount; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* find all IK constraints and validate them */ | 
					
						
							|  |  |  | 	treecount = 0; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (con = (bConstraint *)pchan_tip->constraints.first; con; con = (bConstraint *)con->next) { | 
					
						
							|  |  |  | 		if (con->type == CONSTRAINT_TYPE_KINEMATIC) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (constraint_valid(con)) | 
					
						
							|  |  |  | 				treecount += initialize_chain(ob, pchan_tip, con); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return treecount; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static IK_Data *get_ikdata(bPose *pose) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (pose->ikdata) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		return (IK_Data *)pose->ikdata; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	pose->ikdata = MEM_callocN(sizeof(IK_Data), "iTaSC ikdata"); | 
					
						
							|  |  |  | 	// here init ikdata if needed
 | 
					
						
							|  |  |  | 	// now that we have scene, make sure the default param are initialized
 | 
					
						
							|  |  |  | 	if (!DefIKParam.iksolver) | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | 		BKE_pose_itasc_init(&DefIKParam); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	return (IK_Data *)pose->ikdata; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | static double EulerAngleFromMatrix(const KDL::Rotation& R, int axis) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	double t = KDL::sqrt(R(0, 0) * R(0, 0) + R(0, 1) * R(0, 1)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (t > 16.0 * KDL::epsilon) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		if (axis == 0) return -KDL::atan2(R(1, 2), R(2, 2)); | 
					
						
							|  |  |  | 		else if (axis == 1) return KDL::atan2(-R(0, 2), t); | 
					
						
							|  |  |  | 		else return -KDL::atan2(R(0, 1), R(0, 0)); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		if (axis == 0) return -KDL::atan2(-R(2, 1), R(1, 1)); | 
					
						
							|  |  |  | 		else if (axis == 1) return KDL::atan2(-R(0, 2), t); | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  | 		else return 0.0f; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static double ComputeTwist(const KDL::Rotation& R) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// qy and qw are the y and w components of the quaternion from R
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 	double qy = R(0, 2) - R(2, 0); | 
					
						
							|  |  |  | 	double qw = R(0, 0) + R(1, 1) + R(2, 2) + 1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	double tau = 2 * KDL::atan2(qy, qw); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return tau; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void RemoveEulerAngleFromMatrix(KDL::Rotation& R, double angle, int axis) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// compute twist parameter
 | 
					
						
							|  |  |  | 	KDL::Rotation T; | 
					
						
							|  |  |  | 	switch (axis) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		case 0: | 
					
						
							|  |  |  | 			T = KDL::Rotation::RotX(-angle); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 1: | 
					
						
							|  |  |  | 			T = KDL::Rotation::RotY(-angle); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case 2: | 
					
						
							|  |  |  | 			T = KDL::Rotation::RotZ(-angle); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// remove angle
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	R = R * T; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | #if 0
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | static void GetEulerXZY(const KDL::Rotation& R, double& X, double& Z, double& Y) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (fabs(R(0, 1)) > 1.0 - KDL::epsilon) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		X = -KDL::sign(R(0, 1)) * KDL::atan2(R(1, 2), R(1, 0)); | 
					
						
							|  |  |  | 		Z = -KDL::sign(R(0, 1)) * KDL::PI / 2; | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  | 		Y = 0.0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		X = KDL::atan2(R(2, 1), R(1, 1)); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		Z = KDL::atan2(-R(0, 1), KDL::sqrt(KDL::sqr(R(0, 0)) + KDL::sqr(R(0, 2)))); | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		Y = KDL::atan2(R(0, 2), R(0, 0)); | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | static void GetEulerXYZ(const KDL::Rotation& R, double& X, double& Y, double& Z) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (fabs(R(0, 2)) > 1.0 - KDL::epsilon) { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		X = KDL::sign(R(0, 2)) * KDL::atan2(-R(1, 0), R(1, 1)); | 
					
						
							|  |  |  | 		Y = KDL::sign(R(0, 2)) * KDL::PI / 2; | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  | 		Z = 0.0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		X = KDL::atan2(-R(1, 2), R(2, 2)); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		Y = KDL::atan2(R(0, 2), KDL::sqrt(KDL::sqr(R(0, 0)) + KDL::sqr(R(0, 1)))); | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 		Z = KDL::atan2(-R(0, 1), R(0, 0)); | 
					
						
							| 
									
										
										
										
											2012-03-24 07:36:32 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static void GetJointRotation(KDL::Rotation& boneRot, int type, double *rot) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	switch (type & ~IK_TRANSY) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			// fixed bone, no joint
 | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_XDOF: | 
					
						
							|  |  |  | 			// RX only, get the X rotation
 | 
					
						
							|  |  |  | 			rot[0] = EulerAngleFromMatrix(boneRot, 0); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_YDOF: | 
					
						
							|  |  |  | 			// RY only, get the Y rotation
 | 
					
						
							|  |  |  | 			rot[0] = ComputeTwist(boneRot); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_ZDOF: | 
					
						
							|  |  |  | 			// RZ only, get the Z rotation
 | 
					
						
							|  |  |  | 			rot[0] = EulerAngleFromMatrix(boneRot, 2); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_XDOF | IK_YDOF: | 
					
						
							|  |  |  | 			rot[1] = ComputeTwist(boneRot); | 
					
						
							|  |  |  | 			RemoveEulerAngleFromMatrix(boneRot, rot[1], 1); | 
					
						
							|  |  |  | 			rot[0] = EulerAngleFromMatrix(boneRot, 0); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_SWING: | 
					
						
							|  |  |  | 			// RX+RZ
 | 
					
						
							|  |  |  | 			boneRot.GetXZRot().GetValue(rot); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_YDOF | IK_ZDOF: | 
					
						
							|  |  |  | 			// RZ+RY
 | 
					
						
							|  |  |  | 			rot[1] = ComputeTwist(boneRot); | 
					
						
							|  |  |  | 			RemoveEulerAngleFromMatrix(boneRot, rot[1], 1); | 
					
						
							|  |  |  | 			rot[0] = EulerAngleFromMatrix(boneRot, 2); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_SWING | IK_YDOF: | 
					
						
							|  |  |  | 			rot[2] = ComputeTwist(boneRot); | 
					
						
							|  |  |  | 			RemoveEulerAngleFromMatrix(boneRot, rot[2], 1); | 
					
						
							|  |  |  | 			boneRot.GetXZRot().GetValue(rot); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_REVOLUTE: | 
					
						
							|  |  |  | 			boneRot.GetRot().GetValue(rot); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static bool target_callback(struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Target *target = (IK_Target *)param; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// compute next target position
 | 
					
						
							|  |  |  | 	// get target matrix from constraint.
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	bConstraint *constraint = (bConstraint *)target->blenderConstraint; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	float tarmat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 	BKE_constraint_target_matrix_get(eval_ctx, target->blscene, constraint, 0, CONSTRAINT_OBTYPE_OBJECT, target->owner, tarmat, 1.0); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// rootmat contains the target pose in world coordinate
 | 
					
						
							|  |  |  | 	// if enforce is != 1.0, blend the target position with the end effector position
 | 
					
						
							|  |  |  | 	// if the armature was in rest position. This information is available in eeRest
 | 
					
						
							|  |  |  | 	if (constraint->enforce != 1.0f && target->eeBlend) { | 
					
						
							|  |  |  | 		// eeRest is relative to the reference frame of the IK root
 | 
					
						
							|  |  |  | 		// get this frame in world reference
 | 
					
						
							|  |  |  | 		float restmat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		bPoseChannel *pchan = target->rootChannel; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (pchan->parent) { | 
					
						
							|  |  |  | 			pchan = pchan->parent; | 
					
						
							|  |  |  | 			float chanmat[4][4]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			copy_m4_m4(chanmat, pchan->pose_mat); | 
					
						
							| 
									
										
										
										
											2011-11-07 01:38:32 +00:00
										 |  |  | 			copy_v3_v3(chanmat[3], pchan->pose_tail); | 
					
						
							| 
									
										
										
										
											2014-07-21 18:55:12 +10:00
										 |  |  | 			mul_m4_series(restmat, target->owner->obmat, chanmat, target->eeRest); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 			mul_m4_m4m4(restmat, target->owner->obmat, target->eeRest); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		// blend the target
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		blend_m4_m4m4(tarmat, restmat, tarmat, constraint->enforce); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	next.setValue(&tarmat[0][0]); | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static bool base_callback(struct EvaluationContext *eval_ctx, const iTaSC::Timestamp& timestamp, const iTaSC::Frame& current, iTaSC::Frame& next, void *param) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Scene *ikscene = (IK_Scene *)param; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// compute next armature base pose
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	// algorithm:
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// ikscene->pchan[0] is the root channel of the tree
 | 
					
						
							|  |  |  | 	// if it has a parent, get the pose matrix from it and replace [3] by parent pchan->tail
 | 
					
						
							|  |  |  | 	// then multiply by the armature matrix to get ikscene->armature base position
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	bPoseChannel *pchan = ikscene->channels[0].pchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	float rootmat[4][4]; | 
					
						
							|  |  |  | 	if (pchan->parent) { | 
					
						
							|  |  |  | 		pchan = pchan->parent; | 
					
						
							|  |  |  | 		float chanmat[4][4]; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_m4_m4(chanmat, pchan->pose_mat); | 
					
						
							| 
									
										
										
										
											2011-11-07 01:38:32 +00:00
										 |  |  | 		copy_v3_v3(chanmat[3], pchan->pose_tail); | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		// save the base as a frame too so that we can compute deformation after simulation
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikscene->baseFrame.setValue(&chanmat[0][0]); | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		// iTaSC armature is scaled to object scale, scale the base frame too
 | 
					
						
							|  |  |  | 		ikscene->baseFrame.p *= ikscene->blScale; | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 		mul_m4_m4m4(rootmat, ikscene->blArmature->obmat, chanmat); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_m4_m4(rootmat, ikscene->blArmature->obmat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikscene->baseFrame = iTaSC::F_identity; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	next.setValue(&rootmat[0][0]); | 
					
						
							|  |  |  | 	// if there is a polar target (only during solving otherwise we don't have end efffector)
 | 
					
						
							|  |  |  | 	if (ikscene->polarConstraint && timestamp.update) { | 
					
						
							|  |  |  | 		// compute additional rotation of base frame so that armature follows the polar target
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		float imat[4][4];       // IK tree base inverse matrix
 | 
					
						
							|  |  |  | 		float polemat[4][4];    // polar target in IK tree base frame
 | 
					
						
							|  |  |  | 		float goalmat[4][4];    // target in IK tree base frame
 | 
					
						
							|  |  |  | 		float mat[4][4];        // temp matrix
 | 
					
						
							|  |  |  | 		bKinematicConstraint *poledata = (bKinematicConstraint *)ikscene->polarConstraint->data; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		invert_m4_m4(imat, rootmat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// polar constraint imply only one target
 | 
					
						
							|  |  |  | 		IK_Target *iktarget = ikscene->targets[0]; | 
					
						
							|  |  |  | 		// root channel from which we take the bone initial orientation
 | 
					
						
							|  |  |  | 		IK_Channel &rootchan = ikscene->channels[0]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// get polar target matrix in world space
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 		BKE_constraint_target_matrix_get(eval_ctx, ikscene->blscene, ikscene->polarConstraint, 1, CONSTRAINT_OBTYPE_OBJECT, ikscene->blArmature, mat, 1.0); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// convert to armature space
 | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 		mul_m4_m4m4(polemat, imat, mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// get the target in world space (was computed before as target object are defined before base object)
 | 
					
						
							|  |  |  | 		iktarget->target->getPose().getValue(mat[0]); | 
					
						
							|  |  |  | 		// convert to armature space
 | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 		mul_m4_m4m4(goalmat, imat, mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// take position of target, polar target, end effector, in armature space
 | 
					
						
							|  |  |  | 		KDL::Vector goalpos(goalmat[3]); | 
					
						
							|  |  |  | 		KDL::Vector polepos(polemat[3]); | 
					
						
							|  |  |  | 		KDL::Vector endpos = ikscene->armature->getPose(iktarget->ee).p; | 
					
						
							|  |  |  | 		// get root bone orientation
 | 
					
						
							|  |  |  | 		KDL::Frame rootframe; | 
					
						
							|  |  |  | 		ikscene->armature->getRelativeFrame(rootframe, rootchan.tail); | 
					
						
							|  |  |  | 		KDL::Vector rootx = rootframe.M.UnitX(); | 
					
						
							|  |  |  | 		KDL::Vector rootz = rootframe.M.UnitZ(); | 
					
						
							|  |  |  | 		// and compute root bone head
 | 
					
						
							|  |  |  | 		double q_rest[3], q[3], length; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		const KDL::Joint *joint; | 
					
						
							|  |  |  | 		const KDL::Frame *tip; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikscene->armature->getSegment(rootchan.tail, 3, joint, q_rest[0], q[0], tip); | 
					
						
							|  |  |  | 		length = (joint->getType() == KDL::Joint::TransY) ? q[0] : tip->p(1); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		KDL::Vector rootpos = rootframe.p - length *rootframe.M.UnitY(); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		// compute main directions
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		KDL::Vector dir = KDL::Normalize(endpos - rootpos); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		KDL::Vector poledir = KDL::Normalize(goalpos - rootpos); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// compute up directions
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		KDL::Vector poleup = KDL::Normalize(polepos - rootpos); | 
					
						
							|  |  |  | 		KDL::Vector up = rootx * KDL::cos(poledata->poleangle) + rootz *KDL::sin(poledata->poleangle); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// from which we build rotation matrix
 | 
					
						
							|  |  |  | 		KDL::Rotation endrot, polerot; | 
					
						
							|  |  |  | 		// for the armature, using the root bone orientation
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		KDL::Vector x = KDL::Normalize(dir * up); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		endrot.UnitX(x); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		endrot.UnitY(KDL::Normalize(x * dir)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		endrot.UnitZ(-dir); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		// for the polar target
 | 
					
						
							|  |  |  | 		x = KDL::Normalize(poledir * poleup); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		polerot.UnitX(x); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		polerot.UnitY(KDL::Normalize(x * poledir)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		polerot.UnitZ(-poledir); | 
					
						
							|  |  |  | 		// the difference between the two is the rotation we want to apply
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		KDL::Rotation result(polerot * endrot.Inverse()); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// apply on base frame as this is an artificial additional rotation
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		next.M = next.M * result; | 
					
						
							|  |  |  | 		ikscene->baseFrame.M = ikscene->baseFrame.M * result; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static bool copypose_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues *const _values, unsigned int _nvalues, void *_param) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Target *iktarget = (IK_Target *)_param; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	bKinematicConstraint *condata = (bKinematicConstraint *)iktarget->blenderConstraint->data; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	iTaSC::ConstraintValues *values = _values; | 
					
						
							|  |  |  | 	bItasc *ikparam = (bItasc *) iktarget->owner->pose->ikparam; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// we need default parameters
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (!ikparam) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikparam = &DefIKParam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (iktarget->blenderConstraint->flag & CONSTRAINT_OFF) { | 
					
						
							|  |  |  | 		if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { | 
					
						
							|  |  |  | 			values->alpha = 0.0; | 
					
						
							|  |  |  | 			values->action = iTaSC::ACT_ALPHA; | 
					
						
							|  |  |  | 			values++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { | 
					
						
							|  |  |  | 			values->alpha = 0.0; | 
					
						
							|  |  |  | 			values->action = iTaSC::ACT_ALPHA; | 
					
						
							|  |  |  | 			values++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { | 
					
						
							|  |  |  | 			// update error
 | 
					
						
							|  |  |  | 			values->alpha = condata->weight; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			values->action = iTaSC::ACT_ALPHA | iTaSC::ACT_FEEDBACK; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; | 
					
						
							|  |  |  | 			values++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { | 
					
						
							|  |  |  | 			// update error
 | 
					
						
							|  |  |  | 			values->alpha = condata->orientweight; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			values->action = iTaSC::ACT_ALPHA | iTaSC::ACT_FEEDBACK; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; | 
					
						
							|  |  |  | 			values++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static void copypose_error(const iTaSC::ConstraintValues *values, unsigned int nvalues, IK_Target *iktarget) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	iTaSC::ConstraintSingleValue *value; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	double error; | 
					
						
							|  |  |  | 	int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (iktarget->controlType & iTaSC::CopyPose::CTL_POSITION) { | 
					
						
							|  |  |  | 		// update error
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (i = 0, error = 0.0, value = values->values; i < values->number; ++i, ++value) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			error += KDL::sqr(value->y - value->yd); | 
					
						
							|  |  |  | 		iktarget->blenderConstraint->lin_error = (float)KDL::sqrt(error); | 
					
						
							|  |  |  | 		values++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (iktarget->controlType & iTaSC::CopyPose::CTL_ROTATION) { | 
					
						
							|  |  |  | 		// update error
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (i = 0, error = 0.0, value = values->values; i < values->number; ++i, ++value) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			error += KDL::sqr(value->y - value->yd); | 
					
						
							|  |  |  | 		iktarget->blenderConstraint->rot_error = (float)KDL::sqrt(error); | 
					
						
							|  |  |  | 		values++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static bool distance_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues *const _values, unsigned int _nvalues, void *_param) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Target *iktarget = (IK_Target *)_param; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	bKinematicConstraint *condata = (bKinematicConstraint *)iktarget->blenderConstraint->data; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	iTaSC::ConstraintValues *values = _values; | 
					
						
							|  |  |  | 	bItasc *ikparam = (bItasc *) iktarget->owner->pose->ikparam; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// we need default parameters
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (!ikparam) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikparam = &DefIKParam; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// update weight according to mode
 | 
					
						
							|  |  |  | 	if (iktarget->blenderConstraint->flag & CONSTRAINT_OFF) { | 
					
						
							|  |  |  | 		values->alpha = 0.0; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		switch (condata->mode) { | 
					
						
							|  |  |  | 			case LIMITDIST_INSIDE: | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				values->alpha = (values->values[0].y > condata->dist) ? condata->weight : 0.0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case LIMITDIST_OUTSIDE: | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				values->alpha = (values->values[0].y < condata->dist) ? condata->weight : 0.0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			default: | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				values->alpha = condata->weight; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (!timestamp.substep) { | 
					
						
							|  |  |  | 			// only update value on first timestep
 | 
					
						
							|  |  |  | 			switch (condata->mode) { | 
					
						
							|  |  |  | 				case LIMITDIST_INSIDE: | 
					
						
							|  |  |  | 					values->values[0].yd = condata->dist * 0.95; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case LIMITDIST_OUTSIDE: | 
					
						
							|  |  |  | 					values->values[0].yd = condata->dist * 1.05; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					values->values[0].yd = condata->dist; | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			values->values[0].action = iTaSC::ACT_VALUE | iTaSC::ACT_FEEDBACK; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			values->feedback = (iktarget->simulation) ? ikparam->feedback : ANIM_FEEDBACK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	values->action |= iTaSC::ACT_ALPHA; | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static void distance_error(const iTaSC::ConstraintValues *values, unsigned int _nvalues, IK_Target *iktarget) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	iktarget->blenderConstraint->lin_error = (float)(values->values[0].y - values->values[0].yd); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | static bool joint_callback(const iTaSC::Timestamp& timestamp, iTaSC::ConstraintValues *const _values, unsigned int _nvalues, void *_param) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Channel *ikchan = (IK_Channel *)_param; | 
					
						
							|  |  |  | 	bItasc *ikparam = (bItasc *)ikchan->owner->pose->ikparam; | 
					
						
							|  |  |  | 	bPoseChannel *chan = ikchan->pchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	int dof; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// a channel can be splitted into multiple joints, so we get called multiple
 | 
					
						
							|  |  |  | 	// times for one channel (this callback is only for 1 joint in the armature)
 | 
					
						
							|  |  |  | 	// the IK_JointTarget structure is shared between multiple joint constraint
 | 
					
						
							|  |  |  | 	// and the target joint values is computed only once, remember this in jointValid
 | 
					
						
							|  |  |  | 	// Don't forget to reset it before each frame
 | 
					
						
							|  |  |  | 	if (!ikchan->jointValid) { | 
					
						
							|  |  |  | 		float rmat[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (chan->rotmode > 0) { | 
					
						
							|  |  |  | 			/* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			eulO_to_mat3(rmat, chan->eul, chan->rotmode); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-28 10:19:20 +00:00
										 |  |  | 		else if (chan->rotmode == ROT_MODE_AXISANGLE) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			/* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			axis_angle_to_mat3(rmat, &chan->quat[1], chan->quat[0]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2012-07-03 19:09:07 +00:00
										 |  |  | 			/* quats are normalized before use to eliminate scaling issues */ | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			normalize_qt(chan->quat); | 
					
						
							| 
									
										
										
										
											2012-04-29 15:47:02 +00:00
										 |  |  | 			quat_to_mat3(rmat, chan->quat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		KDL::Rotation jointRot( | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		    rmat[0][0], rmat[1][0], rmat[2][0], | 
					
						
							|  |  |  | 		    rmat[0][1], rmat[1][1], rmat[2][1], | 
					
						
							|  |  |  | 		    rmat[0][2], rmat[1][2], rmat[2][2]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		GetJointRotation(jointRot, ikchan->jointType, ikchan->jointValue); | 
					
						
							|  |  |  | 		ikchan->jointValid = 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// determine which part of jointValue is used for this joint
 | 
					
						
							|  |  |  | 	// closely related to the way the joints are defined
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 	switch (ikchan->jointType & ~IK_TRANSY) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		case IK_XDOF: | 
					
						
							|  |  |  | 		case IK_YDOF: | 
					
						
							|  |  |  | 		case IK_ZDOF: | 
					
						
							|  |  |  | 			dof = 0; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_XDOF | IK_YDOF: | 
					
						
							|  |  |  | 			// X + Y
 | 
					
						
							|  |  |  | 			dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RX) ? 0 : 1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_SWING: | 
					
						
							|  |  |  | 			// XZ
 | 
					
						
							|  |  |  | 			dof = 0; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_YDOF | IK_ZDOF: | 
					
						
							|  |  |  | 			// Z + Y
 | 
					
						
							|  |  |  | 			dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RZ) ? 0 : 1; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_SWING | IK_YDOF: | 
					
						
							|  |  |  | 			// XZ + Y
 | 
					
						
							|  |  |  | 			dof = (_values[0].id == iTaSC::Armature::ID_JOINT_RY) ? 2 : 0; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case IK_REVOLUTE: | 
					
						
							|  |  |  | 			dof = 0; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			dof = -1; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (dof >= 0) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (unsigned int i = 0; i < _nvalues; i++, dof++) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			_values[i].values[0].yd = ikchan->jointValue[dof]; | 
					
						
							|  |  |  | 			_values[i].alpha = chan->ikrotweight; | 
					
						
							|  |  |  | 			_values[i].feedback = ikparam->feedback; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // build array of joint corresponding to IK chain
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static int convert_channels(struct EvaluationContext *eval_ctx, IK_Scene *ikscene, PoseTree *tree, float ctime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	IK_Channel *ikchan; | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							|  |  |  | 	int a, flag, njoint; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	njoint = 0; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (a = 0, ikchan = ikscene->channels; a < ikscene->numchan; ++a, ++ikchan) { | 
					
						
							|  |  |  | 		pchan = tree->pchan[a]; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikchan->pchan = pchan; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		ikchan->parent = (a > 0) ? tree->parent[a] : -1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		ikchan->owner = ikscene->blArmature; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 		// the constraint and channels must be applied before we build the iTaSC scene,
 | 
					
						
							|  |  |  | 		// this is because some of the pose data (e.g. pose head) don't have corresponding 
 | 
					
						
							|  |  |  | 		// joint angles and can't be applied to the iTaSC armature dynamically
 | 
					
						
							|  |  |  | 		if (!(pchan->flag & POSE_DONE)) | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 			BKE_pose_where_is_bone(eval_ctx, ikscene->blscene, ikscene->blArmature, pchan, ctime, 1); | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 		// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
 | 
					
						
							|  |  |  | 		pchan->flag |= (POSE_DONE | POSE_CHAIN); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		/* set DoF flag */ | 
					
						
							|  |  |  | 		flag = 0; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		if (!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP) && | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		    (!(pchan->ikflag & BONE_IK_XLIMIT) || pchan->limitmin[0] < 0.f || pchan->limitmax[0] > 0.f)) | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			flag |= IK_XDOF; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		if (!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP) && | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		    (!(pchan->ikflag & BONE_IK_YLIMIT) || pchan->limitmin[1] < 0.f || pchan->limitmax[1] > 0.f)) | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			flag |= IK_YDOF; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		if (!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP) && | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		    (!(pchan->ikflag & BONE_IK_ZLIMIT) || pchan->limitmin[2] < 0.f || pchan->limitmax[2] > 0.f)) | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			flag |= IK_ZDOF; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		if (tree->stretch && (pchan->ikstretch > 0.0)) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			flag |= IK_TRANSY; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		/*
 | 
					
						
							| 
									
										
										
										
											2012-03-09 18:28:30 +00:00
										 |  |  | 		 * Logic to create the segments: | 
					
						
							|  |  |  | 		 * RX,RY,RZ = rotational joints with no length | 
					
						
							|  |  |  | 		 * RY(tip) = rotational joints with a fixed length arm = (0,length,0) | 
					
						
							|  |  |  | 		 * TY = translational joint on Y axis | 
					
						
							|  |  |  | 		 * F(pos) = fixed joint with an arm at position pos | 
					
						
							|  |  |  | 		 * Conversion rule of the above flags: | 
					
						
							|  |  |  | 		 * -   ==> F(tip) | 
					
						
							|  |  |  | 		 * X   ==> RX(tip) | 
					
						
							|  |  |  | 		 * Y   ==> RY(tip) | 
					
						
							|  |  |  | 		 * Z   ==> RZ(tip) | 
					
						
							|  |  |  | 		 * XY  ==> RX+RY(tip) | 
					
						
							|  |  |  | 		 * XZ  ==> RX+RZ(tip) | 
					
						
							|  |  |  | 		 * YZ  ==> RZ+RY(tip) | 
					
						
							|  |  |  | 		 * XYZ ==> full spherical unless there are limits, in which case RX+RZ+RY(tip) | 
					
						
							|  |  |  | 		 * In case of stretch, tip=(0,0,0) and there is an additional TY joint | 
					
						
							|  |  |  | 		 * The frame at last of these joints represents the tail of the bone. | 
					
						
							|  |  |  | 		 * The head is computed by a reverse translation on Y axis of the bone length | 
					
						
							|  |  |  | 		 * or in case of TY joint, by the frame at previous joint. | 
					
						
							|  |  |  | 		 * In case of separation of bones, there is an additional F(head) joint | 
					
						
							|  |  |  | 		 * | 
					
						
							|  |  |  | 		 * Computing rest pose and length is complicated: the solver works in world space | 
					
						
							|  |  |  | 		 * Here is the logic: | 
					
						
							|  |  |  | 		 * rest position is computed only from bone->bone_mat. | 
					
						
							|  |  |  | 		 * bone length is computed from bone->length multiplied by the scaling factor of | 
					
						
							|  |  |  | 		 * the armature. Non-uniform scaling will give bad result! | 
					
						
							|  |  |  | 		 */ | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		switch (flag & (IK_XDOF | IK_YDOF | IK_ZDOF)) { | 
					
						
							|  |  |  | 			default: | 
					
						
							|  |  |  | 				ikchan->jointType = 0; | 
					
						
							|  |  |  | 				ikchan->ndof = 0; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF: | 
					
						
							|  |  |  | 				// RX only, get the X rotation
 | 
					
						
							|  |  |  | 				ikchan->jointType = IK_XDOF; | 
					
						
							|  |  |  | 				ikchan->ndof = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_YDOF: | 
					
						
							|  |  |  | 				// RY only, get the Y rotation
 | 
					
						
							|  |  |  | 				ikchan->jointType = IK_YDOF; | 
					
						
							|  |  |  | 				ikchan->ndof = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_ZDOF: | 
					
						
							|  |  |  | 				// RZ only, get the Zz rotation
 | 
					
						
							|  |  |  | 				ikchan->jointType = IK_ZDOF; | 
					
						
							|  |  |  | 				ikchan->ndof = 1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF | IK_YDOF: | 
					
						
							|  |  |  | 				ikchan->jointType = IK_XDOF | IK_YDOF; | 
					
						
							|  |  |  | 				ikchan->ndof = 2; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF | IK_ZDOF: | 
					
						
							|  |  |  | 				// RX+RZ
 | 
					
						
							|  |  |  | 				ikchan->jointType = IK_SWING; | 
					
						
							|  |  |  | 				ikchan->ndof = 2; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_YDOF | IK_ZDOF: | 
					
						
							|  |  |  | 				// RZ+RY
 | 
					
						
							|  |  |  | 				ikchan->jointType = IK_ZDOF | IK_YDOF; | 
					
						
							|  |  |  | 				ikchan->ndof = 2; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF | IK_YDOF | IK_ZDOF: | 
					
						
							|  |  |  | 				// spherical joint
 | 
					
						
							|  |  |  | 				if (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_YLIMIT | BONE_IK_ZLIMIT)) | 
					
						
							|  |  |  | 					// decompose in a Swing+RotY joint
 | 
					
						
							|  |  |  | 					ikchan->jointType = IK_SWING | IK_YDOF; | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					ikchan->jointType = IK_REVOLUTE; | 
					
						
							|  |  |  | 				ikchan->ndof = 3; | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (flag & IK_TRANSY) { | 
					
						
							|  |  |  | 			ikchan->jointType |= IK_TRANSY; | 
					
						
							|  |  |  | 			ikchan->ndof++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		njoint += ikchan->ndof; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// njoint is the joint coordinate, create the Joint Array
 | 
					
						
							|  |  |  | 	ikscene->jointArray.resize(njoint); | 
					
						
							|  |  |  | 	ikscene->numjoint = njoint; | 
					
						
							|  |  |  | 	return njoint; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // compute array of joint value corresponding to current pose
 | 
					
						
							|  |  |  | static void convert_pose(IK_Scene *ikscene) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	KDL::Rotation boneRot; | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							|  |  |  | 	IK_Channel *ikchan; | 
					
						
							|  |  |  | 	Bone *bone; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	float rmat[4][4];   // rest pose of bone with parent taken into account
 | 
					
						
							|  |  |  | 	float bmat[4][4];   // difference
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	float scale; | 
					
						
							|  |  |  | 	double *rot; | 
					
						
							|  |  |  | 	int a, joint; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// assume uniform scaling and take Y scale as general scale for the armature
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	scale = len_v3(ikscene->blArmature->obmat[1]); | 
					
						
							| 
									
										
										
										
											2012-06-07 08:16:41 +00:00
										 |  |  | 	rot = ikscene->jointArray(0); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (joint = a = 0, ikchan = ikscene->channels; a < ikscene->numchan && joint < ikscene->numjoint; ++a, ++ikchan) { | 
					
						
							|  |  |  | 		pchan = ikchan->pchan; | 
					
						
							|  |  |  | 		bone = pchan->bone; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (pchan->parent) { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			unit_m4(bmat); | 
					
						
							|  |  |  | 			mul_m4_m4m3(bmat, pchan->parent->pose_mat, bone->bone_mat); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 			copy_m4_m4(bmat, bone->arm_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		invert_m4_m4(rmat, bmat); | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 		mul_m4_m4m4(bmat, rmat, pchan->pose_mat); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		normalize_m4(bmat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		boneRot.setValue(bmat[0]); | 
					
						
							|  |  |  | 		GetJointRotation(boneRot, ikchan->jointType, rot); | 
					
						
							|  |  |  | 		if (ikchan->jointType & IK_TRANSY) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			// compute actual length
 | 
					
						
							|  |  |  | 			rot[ikchan->ndof - 1] = len_v3v3(pchan->pose_tail, pchan->pose_head) * scale; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		rot += ikchan->ndof; | 
					
						
							|  |  |  | 		joint += ikchan->ndof; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // compute array of joint value corresponding to current pose
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | static void BKE_pose_rest(IK_Scene *ikscene) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							|  |  |  | 	IK_Channel *ikchan; | 
					
						
							|  |  |  | 	Bone *bone; | 
					
						
							|  |  |  | 	float scale; | 
					
						
							|  |  |  | 	double *rot; | 
					
						
							|  |  |  | 	int a, joint; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// assume uniform scaling and take Y scale as general scale for the armature
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 	scale = len_v3(ikscene->blArmature->obmat[1]); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	// rest pose is 0
 | 
					
						
							| 
									
										
										
										
											2012-02-28 05:19:54 +00:00
										 |  |  | 	SetToZero(ikscene->jointArray); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// except for transY joints
 | 
					
						
							| 
									
										
										
										
											2012-06-07 08:16:41 +00:00
										 |  |  | 	rot = ikscene->jointArray(0); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (joint = a = 0, ikchan = ikscene->channels; a < ikscene->numchan && joint < ikscene->numjoint; ++a, ++ikchan) { | 
					
						
							|  |  |  | 		pchan = ikchan->pchan; | 
					
						
							|  |  |  | 		bone = pchan->bone; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (ikchan->jointType & IK_TRANSY) | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			rot[ikchan->ndof - 1] = bone->length * scale; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		rot += ikchan->ndof; | 
					
						
							|  |  |  | 		joint += ikchan->ndof; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static IK_Scene *convert_tree(struct EvaluationContext *eval_ctx, Scene *blscene, Object *ob, bPoseChannel *pchan, float ctime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	PoseTree *tree = (PoseTree *)pchan->iktree.first; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	PoseTarget *target; | 
					
						
							|  |  |  | 	bKinematicConstraint *condata; | 
					
						
							|  |  |  | 	bConstraint *polarcon; | 
					
						
							|  |  |  | 	bItasc *ikparam; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	iTaSC::Armature *arm; | 
					
						
							|  |  |  | 	iTaSC::Scene *scene; | 
					
						
							|  |  |  | 	IK_Scene *ikscene; | 
					
						
							|  |  |  | 	IK_Channel *ikchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KDL::Frame initPose; | 
					
						
							|  |  |  | 	KDL::Rotation boneRot; | 
					
						
							|  |  |  | 	Bone *bone; | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | 	int a, numtarget; | 
					
						
							|  |  |  | 	unsigned int t; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	float length; | 
					
						
							|  |  |  | 	bool ret = true, ingame; | 
					
						
							|  |  |  | 	double *rot; | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 	float start[3]; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (tree->totchannel == 0) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ikscene = new IK_Scene; | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 	ikscene->blscene = blscene; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	arm = new iTaSC::Armature(); | 
					
						
							|  |  |  | 	scene = new iTaSC::Scene(); | 
					
						
							|  |  |  | 	ikscene->channels = new IK_Channel[tree->totchannel]; | 
					
						
							|  |  |  | 	ikscene->numchan = tree->totchannel; | 
					
						
							|  |  |  | 	ikscene->armature = arm; | 
					
						
							|  |  |  | 	ikscene->scene = scene; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	ikparam = (bItasc *)ob->pose->ikparam; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ingame = (ob->pose->flag & POSE_GAME_ENGINE); | 
					
						
							|  |  |  | 	if (!ikparam) { | 
					
						
							|  |  |  | 		// you must have our own copy
 | 
					
						
							|  |  |  | 		ikparam = &DefIKParam; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else if (ingame) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// tweak the param when in game to have efficient stepping
 | 
					
						
							|  |  |  | 		// using fixed substep is not effecient since frames in the GE are often
 | 
					
						
							|  |  |  | 		// shorter than in animation => move to auto step automatically and set
 | 
					
						
							|  |  |  | 		// the target substep duration via min/max
 | 
					
						
							|  |  |  | 		if (!(ikparam->flag & ITASC_AUTO_STEP)) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			float timestep = blscene->r.frs_sec_base / blscene->r.frs_sec; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (ikparam->numstep > 0) | 
					
						
							|  |  |  | 				timestep /= ikparam->numstep; | 
					
						
							|  |  |  | 			// with equal min and max, the algorythm will take this step and the indicative substep most of the time
 | 
					
						
							|  |  |  | 			ikparam->minstep = ikparam->maxstep = timestep; | 
					
						
							|  |  |  | 			ikparam->flag |= ITASC_AUTO_STEP; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if ((ikparam->flag & ITASC_SIMULATION) && !ingame) | 
					
						
							|  |  |  | 		// no cache in animation mode
 | 
					
						
							|  |  |  | 		ikscene->cache = new iTaSC::Cache(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (ikparam->solver) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		case ITASC_SOLVER_SDLS: | 
					
						
							|  |  |  | 			ikscene->solver = new iTaSC::WSDLSSolver(); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case ITASC_SOLVER_DLS: | 
					
						
							|  |  |  | 			ikscene->solver = new iTaSC::WDLSSolver(); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			delete ikscene; | 
					
						
							|  |  |  | 			return NULL; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	ikscene->blArmature = ob; | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 	// assume uniform scaling and take Y scale as general scale for the armature
 | 
					
						
							|  |  |  | 	ikscene->blScale = len_v3(ob->obmat[1]); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	ikscene->blInvScale = (ikscene->blScale < KDL::epsilon) ? 0.0f : 1.0f / ikscene->blScale; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	std::string joint; | 
					
						
							|  |  |  | 	std::string root("root"); | 
					
						
							|  |  |  | 	std::string parent; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	std::vector<double> weights; | 
					
						
							|  |  |  | 	double weight[3]; | 
					
						
							|  |  |  | 	// build the array of joints corresponding to the IK chain
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 	convert_channels(eval_ctx, ikscene, tree, ctime); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (ingame) { | 
					
						
							|  |  |  | 		// in the GE, set the initial joint angle to match the current pose
 | 
					
						
							|  |  |  | 		// this will update the jointArray in ikscene
 | 
					
						
							|  |  |  | 		convert_pose(ikscene); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// in Blender, the rest pose is always 0 for joints
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | 		BKE_pose_rest(ikscene); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-06-07 08:16:41 +00:00
										 |  |  | 	rot = ikscene->jointArray(0); | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (a = 0, ikchan = ikscene->channels; a < tree->totchannel; ++a, ++ikchan) { | 
					
						
							|  |  |  | 		pchan = ikchan->pchan; | 
					
						
							|  |  |  | 		bone = pchan->bone; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		KDL::Frame tip(iTaSC::F_identity); | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 		// compute the position and rotation of the head from previous segment
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		Vector3 *fl = bone->bone_mat; | 
					
						
							| 
									
										
										
										
											2009-10-20 15:51:18 +00:00
										 |  |  | 		KDL::Rotation brot( | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		    fl[0][0], fl[1][0], fl[2][0], | 
					
						
							|  |  |  | 		    fl[0][1], fl[1][1], fl[2][1], | 
					
						
							|  |  |  | 		    fl[0][2], fl[1][2], fl[2][2]); | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 		// if the bone is disconnected, the head is movable in pose mode
 | 
					
						
							|  |  |  | 		// take that into account by using pose matrix instead of bone
 | 
					
						
							|  |  |  | 		// Note that pose is expressed in armature space, convert to previous bone space
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			float R_parmat[3][3]; | 
					
						
							|  |  |  | 			float iR_parmat[3][3]; | 
					
						
							|  |  |  | 			if (pchan->parent) | 
					
						
							|  |  |  | 				copy_m3_m4(R_parmat, pchan->parent->pose_mat); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				unit_m3(R_parmat); | 
					
						
							|  |  |  | 			if (pchan->parent) | 
					
						
							|  |  |  | 				sub_v3_v3v3(start, pchan->pose_head, pchan->parent->pose_tail); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				start[0] = start[1] = start[2] = 0.0f; | 
					
						
							|  |  |  | 			invert_m3_m3(iR_parmat, R_parmat); | 
					
						
							|  |  |  | 			normalize_m3(iR_parmat); | 
					
						
							|  |  |  | 			mul_m3_v3(iR_parmat, start); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		KDL::Vector bpos(start[0], start[1], start[2]); | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		bpos *= ikscene->blScale; | 
					
						
							| 
									
										
										
										
											2009-10-20 15:51:18 +00:00
										 |  |  | 		KDL::Frame head(brot, bpos); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// rest pose length of the bone taking scaling into account
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		length = bone->length * ikscene->blScale; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		parent = (a > 0) ? ikscene->channels[tree->parent[a]].tail : root; | 
					
						
							|  |  |  | 		// first the fixed segment to the bone head
 | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 		if (!(ikchan->pchan->bone->flag & BONE_CONNECTED) || head.M.GetRot().Norm() > KDL::epsilon) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":H"; | 
					
						
							|  |  |  | 			ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, head); | 
					
						
							|  |  |  | 			parent = joint; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!(ikchan->jointType & IK_TRANSY)) { | 
					
						
							|  |  |  | 			// fixed length, put it in tip
 | 
					
						
							|  |  |  | 			tip.p[1] = length; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		joint = bone->name; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		weight[0] = (1.0 - pchan->stiffness[0]); | 
					
						
							|  |  |  | 		weight[1] = (1.0 - pchan->stiffness[1]); | 
					
						
							|  |  |  | 		weight[2] = (1.0 - pchan->stiffness[2]); | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 		switch (ikchan->jointType & ~IK_TRANSY) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			case 0: | 
					
						
							|  |  |  | 				// fixed bone
 | 
					
						
							| 
									
										
										
										
											2012-10-05 13:11:16 +00:00
										 |  |  | 				joint += ":F"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::None, 0.0, tip); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF: | 
					
						
							|  |  |  | 				// RX only, get the X rotation
 | 
					
						
							|  |  |  | 				joint += ":RX"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::RotX, rot[0], tip); | 
					
						
							|  |  |  | 				weights.push_back(weight[0]); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_YDOF: | 
					
						
							|  |  |  | 				// RY only, get the Y rotation
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				joint += ":RY"; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[0], tip); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				weights.push_back(weight[1]); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_ZDOF: | 
					
						
							|  |  |  | 				// RZ only, get the Zz rotation
 | 
					
						
							|  |  |  | 				joint += ":RZ"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::RotZ, rot[0], tip); | 
					
						
							|  |  |  | 				weights.push_back(weight[2]); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_XDOF | IK_YDOF: | 
					
						
							|  |  |  | 				joint += ":RX"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::RotX, rot[0]); | 
					
						
							|  |  |  | 				weights.push_back(weight[0]); | 
					
						
							|  |  |  | 				if (ret) { | 
					
						
							|  |  |  | 					parent = joint; | 
					
						
							|  |  |  | 					joint = bone->name; | 
					
						
							|  |  |  | 					joint += ":RY"; | 
					
						
							|  |  |  | 					ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[1], tip); | 
					
						
							|  |  |  | 					weights.push_back(weight[1]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_SWING: | 
					
						
							|  |  |  | 				joint += ":SW"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::Swing, rot[0], tip); | 
					
						
							|  |  |  | 				weights.push_back(weight[0]); | 
					
						
							|  |  |  | 				weights.push_back(weight[2]); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_YDOF | IK_ZDOF: | 
					
						
							|  |  |  | 				// RZ+RY
 | 
					
						
							|  |  |  | 				joint += ":RZ"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::RotZ, rot[0]); | 
					
						
							|  |  |  | 				weights.push_back(weight[2]); | 
					
						
							|  |  |  | 				if (ret) { | 
					
						
							|  |  |  | 					parent = joint; | 
					
						
							|  |  |  | 					joint = bone->name; | 
					
						
							|  |  |  | 					joint += ":RY"; | 
					
						
							|  |  |  | 					ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[1], tip); | 
					
						
							|  |  |  | 					weights.push_back(weight[1]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_SWING | IK_YDOF: | 
					
						
							|  |  |  | 				// decompose in a Swing+RotY joint
 | 
					
						
							|  |  |  | 				joint += ":SW"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::Swing, rot[0]); | 
					
						
							|  |  |  | 				weights.push_back(weight[0]); | 
					
						
							|  |  |  | 				weights.push_back(weight[2]); | 
					
						
							|  |  |  | 				if (ret) { | 
					
						
							|  |  |  | 					parent = joint; | 
					
						
							|  |  |  | 					joint = bone->name; | 
					
						
							|  |  |  | 					joint += ":RY"; | 
					
						
							|  |  |  | 					ret = arm->addSegment(joint, parent, KDL::Joint::RotY, rot[2], tip); | 
					
						
							|  |  |  | 					weights.push_back(weight[1]); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case IK_REVOLUTE: | 
					
						
							|  |  |  | 				joint += ":SJ"; | 
					
						
							|  |  |  | 				ret = arm->addSegment(joint, parent, KDL::Joint::Sphere, rot[0], tip); | 
					
						
							|  |  |  | 				weights.push_back(weight[0]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				weights.push_back(weight[1]); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				weights.push_back(weight[2]); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (ret && (ikchan->jointType & IK_TRANSY)) { | 
					
						
							|  |  |  | 			parent = joint; | 
					
						
							|  |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":TY"; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			ret = arm->addSegment(joint, parent, KDL::Joint::TransY, rot[ikchan->ndof - 1]); | 
					
						
							| 
									
										
										
										
											2012-07-29 17:49:14 +00:00
										 |  |  | 			const float ikstretch = pchan->ikstretch * pchan->ikstretch; | 
					
						
							|  |  |  | 			/* why invert twice here? */ | 
					
						
							| 
									
										
										
										
											2012-10-23 13:28:22 +00:00
										 |  |  | 			weight[1] = (1.0 - min_ff(1.0 - ikstretch, 1.0f - 0.001f)); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			weights.push_back(weight[1]); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!ret) | 
					
						
							|  |  |  | 			// error making the armature??
 | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		// joint points to the segment that correspond to the bone per say
 | 
					
						
							|  |  |  | 		ikchan->tail = joint; | 
					
						
							|  |  |  | 		ikchan->head = parent; | 
					
						
							|  |  |  | 		// in case of error
 | 
					
						
							|  |  |  | 		ret = false; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if ((ikchan->jointType & IK_XDOF) && (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ROTCTL))) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":RX"; | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_XLIMIT) { | 
					
						
							|  |  |  | 				if (arm->addLimitConstraint(joint, 0, pchan->limitmin[0], pchan->limitmax[0]) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ROTCTL) { | 
					
						
							|  |  |  | 				if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if ((ikchan->jointType & IK_YDOF) && (pchan->ikflag & (BONE_IK_YLIMIT | BONE_IK_ROTCTL))) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":RY"; | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_YLIMIT) { | 
					
						
							|  |  |  | 				if (arm->addLimitConstraint(joint, 0, pchan->limitmin[1], pchan->limitmax[1]) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ROTCTL) { | 
					
						
							|  |  |  | 				if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if ((ikchan->jointType & IK_ZDOF) && (pchan->ikflag & (BONE_IK_ZLIMIT | BONE_IK_ROTCTL))) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":RZ"; | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ZLIMIT) { | 
					
						
							|  |  |  | 				if (arm->addLimitConstraint(joint, 0, pchan->limitmin[2], pchan->limitmax[2]) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ROTCTL) { | 
					
						
							|  |  |  | 				if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		if ((ikchan->jointType & IK_SWING) && (pchan->ikflag & (BONE_IK_XLIMIT | BONE_IK_ZLIMIT | BONE_IK_ROTCTL))) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":SW"; | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_XLIMIT) { | 
					
						
							|  |  |  | 				if (arm->addLimitConstraint(joint, 0, pchan->limitmin[0], pchan->limitmax[0]) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ZLIMIT) { | 
					
						
							|  |  |  | 				if (arm->addLimitConstraint(joint, 1, pchan->limitmin[2], pchan->limitmax[2]) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (pchan->ikflag & BONE_IK_ROTCTL) { | 
					
						
							|  |  |  | 				if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ((ikchan->jointType & IK_REVOLUTE) && (pchan->ikflag & BONE_IK_ROTCTL)) { | 
					
						
							|  |  |  | 			joint = bone->name; | 
					
						
							|  |  |  | 			joint += ":SJ"; | 
					
						
							|  |  |  | 			if (arm->addConstraint(joint, joint_callback, ikchan, false, false) < 0) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		//  no error, so restore
 | 
					
						
							|  |  |  | 		ret = true; | 
					
						
							|  |  |  | 		rot += ikchan->ndof; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!ret) { | 
					
						
							|  |  |  | 		delete ikscene; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// for each target, we need to add an end effector in the armature
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (numtarget = 0, polarcon = NULL, ret = true, target = (PoseTarget *)tree->targets.first; target; target = (PoseTarget *)target->next) { | 
					
						
							|  |  |  | 		condata = (bKinematicConstraint *)target->con->data; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		pchan = tree->pchan[target->tip]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (is_cartesian_constraint(target->con)) { | 
					
						
							|  |  |  | 			// add the end effector
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			IK_Target *iktarget = new IK_Target(); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			ikscene->targets.push_back(iktarget); | 
					
						
							|  |  |  | 			iktarget->ee = arm->addEndEffector(ikscene->channels[target->tip].tail); | 
					
						
							|  |  |  | 			if (iktarget->ee == -1) { | 
					
						
							|  |  |  | 				ret = false; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// initialize all the fields that we can set at this time
 | 
					
						
							|  |  |  | 			iktarget->blenderConstraint = target->con; | 
					
						
							|  |  |  | 			iktarget->channel = target->tip; | 
					
						
							|  |  |  | 			iktarget->simulation = (ikparam->flag & ITASC_SIMULATION); | 
					
						
							|  |  |  | 			iktarget->rootChannel = ikscene->channels[0].pchan; | 
					
						
							|  |  |  | 			iktarget->owner = ob; | 
					
						
							|  |  |  | 			iktarget->targetName = pchan->bone->name; | 
					
						
							|  |  |  | 			iktarget->targetName += ":T:"; | 
					
						
							|  |  |  | 			iktarget->targetName += target->con->name; | 
					
						
							|  |  |  | 			iktarget->constraintName = pchan->bone->name; | 
					
						
							|  |  |  | 			iktarget->constraintName += ":C:"; | 
					
						
							|  |  |  | 			iktarget->constraintName += target->con->name; | 
					
						
							|  |  |  | 			numtarget++; | 
					
						
							|  |  |  | 			if (condata->poletar) | 
					
						
							|  |  |  | 				// this constraint has a polar target
 | 
					
						
							|  |  |  | 				polarcon = target->con; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// deal with polar target if any
 | 
					
						
							|  |  |  | 	if (numtarget == 1 && polarcon) { | 
					
						
							|  |  |  | 		ikscene->polarConstraint = polarcon; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// we can now add the armature
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	// the armature is based on a moving frame.
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// initialize with the correct position in case there is no cache
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 	base_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, ikscene); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	ikscene->base = new iTaSC::MovingFrame(initPose); | 
					
						
							|  |  |  | 	ikscene->base->setCallback(base_callback, ikscene); | 
					
						
							|  |  |  | 	std::string armname; | 
					
						
							|  |  |  | 	armname = ob->id.name; | 
					
						
							|  |  |  | 	armname += ":B"; | 
					
						
							|  |  |  | 	ret = scene->addObject(armname, ikscene->base); | 
					
						
							|  |  |  | 	armname = ob->id.name; | 
					
						
							|  |  |  | 	armname += ":AR"; | 
					
						
							|  |  |  | 	if (ret) | 
					
						
							|  |  |  | 		ret = scene->addObject(armname, ikscene->armature, ikscene->base); | 
					
						
							|  |  |  | 	if (!ret) { | 
					
						
							|  |  |  | 		delete ikscene; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// set the weight
 | 
					
						
							|  |  |  | 	e_matrix& Wq = arm->getWq(); | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | 	assert(Wq.cols() == (int)weights.size()); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (int q = 0; q < Wq.cols(); q++) | 
					
						
							|  |  |  | 		Wq(q, q) = weights[q]; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// get the inverse rest pose frame of the base to compute relative rest pose of end effectors
 | 
					
						
							|  |  |  | 	// this is needed to handle the enforce parameter
 | 
					
						
							|  |  |  | 	// ikscene->pchan[0] is the root channel of the tree
 | 
					
						
							|  |  |  | 	// if it has no parent, then it's just the identify Frame
 | 
					
						
							|  |  |  | 	float invBaseFrame[4][4]; | 
					
						
							|  |  |  | 	pchan = ikscene->channels[0].pchan; | 
					
						
							|  |  |  | 	if (pchan->parent) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		// it has a parent, get the pose matrix from it
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		float baseFrame[4][4]; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		pchan = pchan->parent; | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_m4_m4(baseFrame, pchan->bone->arm_mat); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// move to the tail and scale to get rest pose of armature base
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_v3_v3(baseFrame[3], pchan->bone->arm_tail); | 
					
						
							|  |  |  | 		invert_m4_m4(invBaseFrame, baseFrame); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		unit_m4(invBaseFrame); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// finally add the constraint
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (t = 0; t < ikscene->targets.size(); t++) { | 
					
						
							|  |  |  | 		IK_Target *iktarget = ikscene->targets[t]; | 
					
						
							| 
									
										
										
										
											2009-10-12 09:39:57 +00:00
										 |  |  | 		iktarget->blscene = blscene; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		condata = (bKinematicConstraint *)iktarget->blenderConstraint->data; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		pchan = tree->pchan[iktarget->channel]; | 
					
						
							|  |  |  | 		unsigned int controltype, bonecnt; | 
					
						
							|  |  |  | 		double bonelen; | 
					
						
							|  |  |  | 		float mat[4][4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// add the end effector
 | 
					
						
							|  |  |  | 		// estimate the average bone length, used to clamp feedback error
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (bonecnt = 0, bonelen = 0.f, a = iktarget->channel; a >= 0; a = tree->parent[a], bonecnt++) | 
					
						
							|  |  |  | 			bonelen += ikscene->blScale * tree->pchan[a]->bone->length; | 
					
						
							|  |  |  | 		bonelen /= bonecnt; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// store the rest pose of the end effector to compute enforce target
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		copy_m4_m4(mat, pchan->bone->arm_mat); | 
					
						
							|  |  |  | 		copy_v3_v3(mat[3], pchan->bone->arm_tail); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// get the rest pose relative to the armature base
 | 
					
						
							| 
									
										
										
										
											2013-05-26 18:36:25 +00:00
										 |  |  | 		mul_m4_m4m4(iktarget->eeRest, invBaseFrame, mat); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		iktarget->eeBlend = (!ikscene->polarConstraint && condata->type == CONSTRAINT_IK_COPYPOSE) ? true : false; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// use target_callback to make sure the initPose includes enforce coefficient
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 		target_callback(eval_ctx, iTaSC::Timestamp(), iTaSC::F_identity, initPose, iktarget); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		iktarget->target = new iTaSC::MovingFrame(initPose); | 
					
						
							|  |  |  | 		iktarget->target->setCallback(target_callback, iktarget); | 
					
						
							|  |  |  | 		ret = scene->addObject(iktarget->targetName, iktarget->target); | 
					
						
							|  |  |  | 		if (!ret) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch (condata->type) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			case CONSTRAINT_IK_COPYPOSE: | 
					
						
							|  |  |  | 				controltype = 0; | 
					
						
							|  |  |  | 				if (condata->flag & CONSTRAINT_IK_ROT) { | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_ROT_X)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_ROTATIONX; | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Y)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_ROTATIONY; | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Z)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_ROTATIONZ; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (condata->flag & CONSTRAINT_IK_POS) { | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_POS_X)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_POSITIONX; | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_POS_Y)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_POSITIONY; | 
					
						
							|  |  |  | 					if (!(condata->flag & CONSTRAINT_IK_NO_POS_Z)) | 
					
						
							|  |  |  | 						controltype |= iTaSC::CopyPose::CTL_POSITIONZ; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (controltype) { | 
					
						
							|  |  |  | 					iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen); | 
					
						
							|  |  |  | 					// set the gain
 | 
					
						
							|  |  |  | 					if (controltype & iTaSC::CopyPose::CTL_POSITION) | 
					
						
							|  |  |  | 						iktarget->constraint->setControlParameter(iTaSC::CopyPose::ID_POSITION, iTaSC::ACT_ALPHA, condata->weight); | 
					
						
							|  |  |  | 					if (controltype & iTaSC::CopyPose::CTL_ROTATION) | 
					
						
							|  |  |  | 						iktarget->constraint->setControlParameter(iTaSC::CopyPose::ID_ROTATION, iTaSC::ACT_ALPHA, condata->orientweight); | 
					
						
							|  |  |  | 					iktarget->constraint->registerCallback(copypose_callback, iktarget); | 
					
						
							|  |  |  | 					iktarget->errorCallback = copypose_error; | 
					
						
							|  |  |  | 					iktarget->controlType = controltype; | 
					
						
							|  |  |  | 					// add the constraint
 | 
					
						
							|  |  |  | 					if (condata->flag & CONSTRAINT_IK_TARGETAXIS) | 
					
						
							|  |  |  | 						ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, iktarget->targetName, armname, "", ikscene->channels[iktarget->channel].tail); | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case CONSTRAINT_IK_DISTANCE: | 
					
						
							|  |  |  | 				iktarget->constraint = new iTaSC::Distance(bonelen); | 
					
						
							|  |  |  | 				iktarget->constraint->setControlParameter(iTaSC::Distance::ID_DISTANCE, iTaSC::ACT_VALUE, condata->dist); | 
					
						
							|  |  |  | 				iktarget->constraint->registerCallback(distance_callback, iktarget); | 
					
						
							|  |  |  | 				iktarget->errorCallback = distance_error; | 
					
						
							|  |  |  | 				// we can update the weight on each substep
 | 
					
						
							|  |  |  | 				iktarget->constraint->substep(true); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				// add the constraint
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (!ret) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (!ret || | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	    !scene->addCache(ikscene->cache) || | 
					
						
							|  |  |  | 	    !scene->addSolver(ikscene->solver) || | 
					
						
							| 
									
										
										
										
											2013-03-01 14:47:06 +00:00
										 |  |  | 	    !scene->initialize()) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		delete ikscene; | 
					
						
							|  |  |  | 		ikscene = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ikscene; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static void create_scene(struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create the IK scene
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = (bPoseChannel *)pchan->next) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// by construction there is only one tree
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		PoseTree *tree = (PoseTree *)pchan->iktree.first; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (tree) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			IK_Data *ikdata = get_ikdata(ob->pose); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// convert tree in iTaSC::Scene
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 			IK_Scene *ikscene = convert_tree(eval_ctx, scene, ob, pchan, ctime); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (ikscene) { | 
					
						
							|  |  |  | 				ikscene->next = ikdata->first; | 
					
						
							|  |  |  | 				ikdata->first = ikscene; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// delete the trees once we are done
 | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			while (tree) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				BLI_remlink(&pchan->iktree, tree); | 
					
						
							|  |  |  | 				BLI_freelistN(&tree->targets); | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 				if (tree->pchan) MEM_freeN(tree->pchan); | 
					
						
							|  |  |  | 				if (tree->parent) MEM_freeN(tree->parent); | 
					
						
							|  |  |  | 				if (tree->basis_change) MEM_freeN(tree->basis_change); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				MEM_freeN(tree); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				tree = (PoseTree *)pchan->iktree.first; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | /* returns 1 if scaling has changed and tree must be reinitialized */ | 
					
						
							|  |  |  | static int init_scene(Object *ob) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 	// check also if scaling has changed
 | 
					
						
							|  |  |  | 	float scale = len_v3(ob->obmat[1]); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Scene *scene; | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (ob->pose->ikdata) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (scene = ((IK_Data *)ob->pose->ikdata)->first; | 
					
						
							|  |  |  | 		     scene != NULL; | 
					
						
							| 
									
										
										
										
											2013-03-01 14:47:06 +00:00
										 |  |  | 		     scene = scene->next) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 			if (fabs(scene->blScale - scale) > KDL::epsilon) | 
					
						
							|  |  |  | 				return 1; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			scene->channels[0].pchan->flag |= POSE_IKTREE; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | static void execute_scene(struct EvaluationContext *eval_ctx, Scene *blscene, IK_Scene *ikscene, bItasc *ikparam, float ctime, float frtime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	int i; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	IK_Channel *ikchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (ikparam->flag & ITASC_SIMULATION) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (i = 0, ikchan = ikscene->channels; i < ikscene->numchan; i++, ++ikchan) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// In simulation mode we don't allow external contraint to change our bones, mark the channel done
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | 			// also tell Blender that this channel is part of IK tree (cleared on each BKE_pose_where_is()
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			ikchan->pchan->flag |= (POSE_DONE | POSE_CHAIN); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			ikchan->jointValid = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// in animation mode, we must get the bone position from action and constraints
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (i = 0, ikchan = ikscene->channels; i < ikscene->numchan; i++, ++ikchan) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (!(ikchan->pchan->flag & POSE_DONE)) | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 				BKE_pose_where_is_bone(eval_ctx, blscene, ikscene->blArmature, ikchan->pchan, ctime, 1); | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | 			// tell blender that this channel was controlled by IK, it's cleared on each BKE_pose_where_is()
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			ikchan->pchan->flag |= (POSE_DONE | POSE_CHAIN); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			ikchan->jointValid = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// only run execute the scene if at least one of our target is enabled
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (i = ikscene->targets.size(); i > 0; --i) { | 
					
						
							|  |  |  | 		IK_Target *iktarget = ikscene->targets[i - 1]; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (i == 0 && ikscene->armature->getNrOfConstraints() == 0) | 
					
						
							|  |  |  | 		// all constraint disabled
 | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// compute timestep
 | 
					
						
							|  |  |  | 	double timestamp = ctime * frtime + 2147483.648; | 
					
						
							|  |  |  | 	double timestep = frtime; | 
					
						
							|  |  |  | 	bool reiterate = (ikparam->flag & ITASC_REITERATION) ? true : false; | 
					
						
							|  |  |  | 	int numstep = (ikparam->flag & ITASC_AUTO_STEP) ? 0 : ikparam->numstep; | 
					
						
							|  |  |  | 	bool simulation = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ikparam->flag & ITASC_SIMULATION) { | 
					
						
							|  |  |  | 		ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, ikparam->maxvel); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	else { | 
					
						
							|  |  |  | 		// in animation mode we start from the pose after action and constraint
 | 
					
						
							|  |  |  | 		convert_pose(ikscene); | 
					
						
							|  |  |  | 		ikscene->armature->setJointArray(ikscene->jointArray); | 
					
						
							|  |  |  | 		// and we don't handle velocity
 | 
					
						
							|  |  |  | 		reiterate = true; | 
					
						
							|  |  |  | 		simulation = false; | 
					
						
							|  |  |  | 		// time is virtual, so take fixed value for velocity parameters (see itasc_update_param)
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		// and choose 1s timestep to allow having velocity parameters in radiant
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		timestep = 1.0; | 
					
						
							|  |  |  | 		// use auto setup to let the solver test the variation of the joints
 | 
					
						
							|  |  |  | 		numstep = 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (ikscene->cache && !reiterate && simulation) { | 
					
						
							| 
									
										
										
										
											2009-09-25 09:33:46 +00:00
										 |  |  | 		iTaSC::CacheTS sts, cts; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		sts = cts = (iTaSC::CacheTS)(timestamp * 1000.0 + 0.5); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (ikscene->cache->getPreviousCacheItem(ikscene->armature, 0, &cts) == NULL || cts == 0) { | 
					
						
							|  |  |  | 			// the cache is empty before this time, reiterate
 | 
					
						
							|  |  |  | 			if (ikparam->flag & ITASC_INITIAL_REITERATION) | 
					
						
							|  |  |  | 				reiterate = true; | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// can take the cache as a start point.
 | 
					
						
							|  |  |  | 			sts -= cts; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			timestep = sts / 1000.0; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-07-11 12:42:02 +00:00
										 |  |  | 	// don't cache if we are reiterating because we don't want to destroy the cache unnecessarily
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 	ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, false, !reiterate, simulation); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	if (reiterate) { | 
					
						
							|  |  |  | 		// how many times do we reiterate?
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (i = 0; i < ikparam->numiter; i++) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (ikscene->armature->getMaxJointChange() < ikparam->precision || | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			    ikscene->armature->getMaxEndEffectorChange() < ikparam->precision) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2012-04-28 06:31:57 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 			ikscene->scene->update(eval_ctx, timestamp, timestep, numstep, true, false, simulation); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if (simulation) { | 
					
						
							|  |  |  | 			// one more fake iteration to cache
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 			ikscene->scene->update(eval_ctx, timestamp, 0.0, 1, true, true, true); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// compute constraint error
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (i = ikscene->targets.size(); i > 0; --i) { | 
					
						
							|  |  |  | 		IK_Target *iktarget = ikscene->targets[i - 1]; | 
					
						
							| 
									
										
										
										
											2012-12-06 22:23:58 +00:00
										 |  |  | 		if (!(iktarget->blenderConstraint->flag & CONSTRAINT_OFF) && iktarget->constraint) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			unsigned int nvalues; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			const iTaSC::ConstraintValues *values; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			values = iktarget->constraint->getControlParameters(&nvalues); | 
					
						
							|  |  |  | 			iktarget->errorCallback(values, nvalues, iktarget); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Apply result to bone:
 | 
					
						
							|  |  |  | 	// walk the ikscene->channels
 | 
					
						
							|  |  |  | 	// for each, get the Frame of the joint corresponding to the bone relative to its parent
 | 
					
						
							|  |  |  | 	// combine the parent and the joint frame to get the frame relative to armature
 | 
					
						
							|  |  |  | 	// a backward translation of the bone length gives the head
 | 
					
						
							|  |  |  | 	// if TY, compute the scale as the ratio of the joint length with rest pose length
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	iTaSC::Armature *arm = ikscene->armature; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	KDL::Frame frame; | 
					
						
							|  |  |  | 	double q_rest[3], q[3]; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	const KDL::Joint *joint; | 
					
						
							|  |  |  | 	const KDL::Frame *tip; | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	float scale; | 
					
						
							|  |  |  | 	float length; | 
					
						
							|  |  |  | 	float yaxis[3]; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (i = 0, ikchan = ikscene->channels; i < ikscene->numchan; ++i, ++ikchan) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		if (i == 0) { | 
					
						
							|  |  |  | 			if (!arm->getRelativeFrame(frame, ikchan->tail)) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			// this frame is relative to base, make it relative to object
 | 
					
						
							|  |  |  | 			ikchan->frame = ikscene->baseFrame * frame; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			if (!arm->getRelativeFrame(frame, ikchan->tail, ikscene->channels[ikchan->parent].tail)) | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			// combine with parent frame to get frame relative to object
 | 
					
						
							|  |  |  | 			ikchan->frame = ikscene->channels[ikchan->parent].frame * frame; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// ikchan->frame is the tail frame relative to object
 | 
					
						
							|  |  |  | 		// get bone length
 | 
					
						
							|  |  |  | 		if (!arm->getSegment(ikchan->tail, 3, joint, q_rest[0], q[0], tip)) | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		if (joint->getType() == KDL::Joint::TransY) { | 
					
						
							|  |  |  | 			// stretch bones have a TY joint, compute the scale
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			scale = (float)(q[0] / q_rest[0]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			// the length is the joint itself
 | 
					
						
							|  |  |  | 			length = (float)q[0]; | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		else { | 
					
						
							|  |  |  | 			scale = 1.0f; | 
					
						
							|  |  |  | 			// for fixed bone, the length is in the tip (always along Y axis)
 | 
					
						
							|  |  |  | 			length = tip->p(1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// ready to compute the pose mat
 | 
					
						
							|  |  |  | 		pchan = ikchan->pchan; | 
					
						
							|  |  |  | 		// tail mat
 | 
					
						
							|  |  |  | 		ikchan->frame.getValue(&pchan->pose_mat[0][0]); | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		// the scale of the object was included in the ik scene, take it out now
 | 
					
						
							|  |  |  | 		// because the pose channels are relative to the object
 | 
					
						
							|  |  |  | 		mul_v3_fl(pchan->pose_mat[3], ikscene->blInvScale); | 
					
						
							|  |  |  | 		length *= ikscene->blInvScale; | 
					
						
							| 
									
										
										
										
											2011-11-07 01:38:32 +00:00
										 |  |  | 		copy_v3_v3(pchan->pose_tail, pchan->pose_mat[3]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// shift to head
 | 
					
						
							| 
									
										
										
										
											2011-11-07 01:38:32 +00:00
										 |  |  | 		copy_v3_v3(yaxis, pchan->pose_mat[1]); | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mul_v3_fl(yaxis, length); | 
					
						
							|  |  |  | 		sub_v3_v3v3(pchan->pose_mat[3], pchan->pose_mat[3], yaxis); | 
					
						
							| 
									
										
										
										
											2011-11-07 01:38:32 +00:00
										 |  |  | 		copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// add scale
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | 		mul_v3_fl(pchan->pose_mat[0], scale); | 
					
						
							|  |  |  | 		mul_v3_fl(pchan->pose_mat[1], scale); | 
					
						
							|  |  |  | 		mul_v3_fl(pchan->pose_mat[2], scale); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	if (i < ikscene->numchan) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// big problem
 | 
					
						
							|  |  |  | 		; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //---------------------------------------------------
 | 
					
						
							|  |  |  | // plugin interface
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | void itasc_initialize_tree(struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob, float ctime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	bPoseChannel *pchan; | 
					
						
							|  |  |  | 	int count = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ob->pose->ikdata != NULL && !(ob->pose->flag & POSE_WAS_REBUILT)) { | 
					
						
							| 
									
										
										
										
											2012-06-03 12:06:42 +00:00
										 |  |  | 		if (!init_scene(ob)) | 
					
						
							|  |  |  | 			return; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// first remove old scene
 | 
					
						
							|  |  |  | 	itasc_clear_data(ob->pose); | 
					
						
							|  |  |  | 	// we should handle all the constraint and mark them all disabled
 | 
					
						
							|  |  |  | 	// for blender but we'll start with the IK constraint alone
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	for (pchan = (bPoseChannel *)ob->pose->chanbase.first; pchan; pchan = (bPoseChannel *)pchan->next) { | 
					
						
							| 
									
										
										
										
											2012-03-24 07:52:14 +00:00
										 |  |  | 		if (pchan->constflag & PCHAN_HAS_IK) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			count += initialize_scene(ob, pchan); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 	// if at least one tree, create the scenes from the PoseTree stored in the channels
 | 
					
						
							| 
									
										
										
										
											2012-12-29 19:43:08 +00:00
										 |  |  | 	// postpone until execute_tree: this way the pose constraint are included
 | 
					
						
							| 
									
										
										
										
											2016-11-15 16:18:59 +01:00
										 |  |  | 	if (count) | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 		create_scene(eval_ctx, scene, ob, ctime); | 
					
						
							| 
									
										
										
										
											2016-11-15 16:18:59 +01:00
										 |  |  | 	itasc_update_param(ob->pose); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	// make sure we don't rebuilt until the user changes something important
 | 
					
						
							|  |  |  | 	ob->pose->flag &= ~POSE_WAS_REBUILT; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | void itasc_execute_tree(struct EvaluationContext *eval_ctx, struct Scene *scene, Object *ob,  bPoseChannel *pchan_root, float ctime) | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	if (ob->pose->ikdata) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		IK_Data *ikdata = (IK_Data *)ob->pose->ikdata; | 
					
						
							|  |  |  | 		bItasc *ikparam = (bItasc *) ob->pose->ikparam; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 		// we need default parameters
 | 
					
						
							|  |  |  | 		if (!ikparam) ikparam = &DefIKParam; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		for (IK_Scene *ikscene = ikdata->first; ikscene; ikscene = ikscene->next) { | 
					
						
							| 
									
										
										
										
											2016-07-08 21:06:38 +10:00
										 |  |  | 			if (ikscene->channels[0].pchan == pchan_root) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				float timestep = scene->r.frs_sec_base / scene->r.frs_sec; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				if (ob->pose->flag & POSE_GAME_ENGINE) { | 
					
						
							|  |  |  | 					timestep = ob->pose->ctime; | 
					
						
							|  |  |  | 					// limit the timestep to avoid excessive number of iteration
 | 
					
						
							|  |  |  | 					if (timestep > 0.2f) | 
					
						
							|  |  |  | 						timestep = 0.2f; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2017-07-21 11:53:13 +02:00
										 |  |  | 				execute_scene(eval_ctx, scene, ikscene, ikparam, ctime, timestep); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void itasc_release_tree(struct Scene *scene, struct Object *ob,  float ctime) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	// not used for iTaSC
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void itasc_clear_data(struct bPose *pose) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (pose->ikdata) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		IK_Data *ikdata = (IK_Data *)pose->ikdata; | 
					
						
							|  |  |  | 		for (IK_Scene *scene = ikdata->first; scene; scene = ikdata->first) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			ikdata->first = scene->next; | 
					
						
							|  |  |  | 			delete scene; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		MEM_freeN(ikdata); | 
					
						
							|  |  |  | 		pose->ikdata = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void itasc_clear_cache(struct bPose *pose) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (pose->ikdata) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		IK_Data *ikdata = (IK_Data *)pose->ikdata; | 
					
						
							|  |  |  | 		for (IK_Scene *scene = ikdata->first; scene; scene = scene->next) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (scene->cache) | 
					
						
							|  |  |  | 				// clear all cache but leaving the timestamp 0 (=rest pose)
 | 
					
						
							|  |  |  | 				scene->cache->clearCacheFrom(NULL, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void itasc_update_param(struct bPose *pose) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (pose->ikdata && pose->ikparam) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		IK_Data *ikdata = (IK_Data *)pose->ikdata; | 
					
						
							|  |  |  | 		bItasc *ikparam = (bItasc *)pose->ikparam; | 
					
						
							|  |  |  | 		for (IK_Scene *ikscene = ikdata->first; ikscene; ikscene = ikscene->next) { | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			double armlength = ikscene->armature->getArmLength(); | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 			ikscene->solver->setParam(iTaSC::Solver::DLS_LAMBDA_MAX, ikparam->dampmax * armlength); | 
					
						
							|  |  |  | 			ikscene->solver->setParam(iTaSC::Solver::DLS_EPSILON, ikparam->dampeps * armlength); | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 			if (ikparam->flag & ITASC_SIMULATION) { | 
					
						
							|  |  |  | 				ikscene->scene->setParam(iTaSC::Scene::MIN_TIMESTEP, ikparam->minstep); | 
					
						
							|  |  |  | 				ikscene->scene->setParam(iTaSC::Scene::MAX_TIMESTEP, ikparam->maxstep); | 
					
						
							|  |  |  | 				ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, ikparam->maxvel); | 
					
						
							|  |  |  | 				ikscene->armature->setControlParameter(CONSTRAINT_ID_ALL, iTaSC::Armature::ID_JOINT, iTaSC::ACT_FEEDBACK, ikparam->feedback); | 
					
						
							| 
									
										
										
										
											2012-03-24 06:24:53 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 				// in animation mode timestep is 1s by convention =>
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 				// qmax becomes radiant and feedback becomes fraction of error gap corrected in one iteration
 | 
					
						
							|  |  |  | 				ikscene->scene->setParam(iTaSC::Scene::MIN_TIMESTEP, 1.0); | 
					
						
							|  |  |  | 				ikscene->scene->setParam(iTaSC::Scene::MAX_TIMESTEP, 1.0); | 
					
						
							|  |  |  | 				ikscene->solver->setParam(iTaSC::Solver::DLS_QMAX, 0.52); | 
					
						
							|  |  |  | 				ikscene->armature->setControlParameter(CONSTRAINT_ID_ALL, iTaSC::Armature::ID_JOINT, iTaSC::ACT_FEEDBACK, 0.8); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void itasc_test_constraint(struct Object *ob, struct bConstraint *cons) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct bKinematicConstraint *data = (struct bKinematicConstraint *)cons->data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* only for IK constraint */ | 
					
						
							|  |  |  | 	if (cons->type != CONSTRAINT_TYPE_KINEMATIC || data == NULL) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (data->type) { | 
					
						
							| 
									
										
										
										
											2012-07-01 09:54:44 +00:00
										 |  |  | 		case CONSTRAINT_IK_COPYPOSE: | 
					
						
							|  |  |  | 		case CONSTRAINT_IK_DISTANCE: | 
					
						
							|  |  |  | 			/* cartesian space constraint */ | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |