| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * 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 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup bke | 
					
						
							| 
									
										
										
										
											2011-02-27 20:40:57 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-08-13 19:41:45 +00:00
										 |  |  | #include <ctype.h>
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2008-01-28 00:53:54 +00:00
										 |  |  | #include <float.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | #include "BLI_listbase.h"
 | 
					
						
							|  |  |  | #include "BLI_string.h"
 | 
					
						
							|  |  |  | #include "BLI_ghash.h"
 | 
					
						
							| 
									
										
										
										
											2016-05-13 11:05:12 +02:00
										 |  |  | #include "BLI_task.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 18:36:47 +00:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | #include "BLI_alloca.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-26 03:43:39 +00:00
										 |  |  | #include "DNA_anim_types.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "DNA_armature_types.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "DNA_constraint_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-30 12:22:55 +02:00
										 |  |  | #include "DNA_gpencil_types.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_lattice_types.h"
 | 
					
						
							| 
									
										
										
										
											2016-05-13 11:05:12 +02:00
										 |  |  | #include "DNA_listBase.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "DNA_scene_types.h"
 | 
					
						
							| 
									
										
										
										
											2010-08-04 04:01:27 +00:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-26 03:43:39 +00:00
										 |  |  | #include "BKE_animsys.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "BKE_armature.h"
 | 
					
						
							|  |  |  | #include "BKE_action.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-01 11:29:40 +00:00
										 |  |  | #include "BKE_anim.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "BKE_constraint.h"
 | 
					
						
							| 
									
										
										
										
											2005-07-16 19:07:02 +00:00
										 |  |  | #include "BKE_curve.h"
 | 
					
						
							| 
									
										
										
										
											2010-04-20 21:38:55 +00:00
										 |  |  | #include "BKE_deform.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "BKE_displist.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-28 15:33:45 +00:00
										 |  |  | #include "BKE_idprop.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "BKE_library.h"
 | 
					
						
							| 
									
										
											  
											
												Two wonderful new NLA & Armature editing features!
- FORWARD CYCLING & MATCHING
Up to no now, adding multiple actions in NLA with walkcycles required to
animate them standing still, as if walking on a conveyor belt. The stride
option then makes the object itself move forward, trying to keep the foot
stuck on the floor (with poor results!).
This option now allows to make walk cycles moving forward. By
indicating a reference Offset Bone, the NLA system will use that bone to
detect the correct offset for the Armature Pose to make it seamlessly going
forward.
Best of all, this option works as for cyclic Action Strips as well as for
individual Action Strips. Note that for individual strips, you have to set
the strip on "Hold". (Might become automatic detected later).
Here's an example edit image for NLA:
http://www.blender.org/bf/nla_match-cycle.jpg
And the animation for it:
http://download.blender.org/demo/test/2.43/0001_0150_match.avi
Blender file:
http://download.blender.org/demo/test/2.43/mancandy_matching.blend
Using this kind of cycling works pretty straightforward, and is a lot
easier to setup than Stride Bones.
To be further tested:
- Blending cycles
- matching rotation for the bones as well.
- ACTION MODIFIERS (motion deformors)
The above option was actually required for this feature. Typically walk
cycles are constructed with certain Bones to be the handles, controlling
for example the torso or feet.
An Action Modifier allows you to use a Curve Path to deform the motion of
these controlling bones. This uses the existing Curve Deformation option.
Modifiers can be added per Action Strip, each controlling a channel (bone)
by choice, and even allows to layer multiple modifiers on top of each other
(several paths deforming motion). This option is using the dependency graph,
so editing the Curve will give realtime changes in the Armature.
The previous walkcycle, controlled by two curves:
http://download.blender.org/demo/test/2.43/0001_0150_deform.avi
Blender file:
http://download.blender.org/demo/test/2.43/mancandy_actiondeform.blend
Action Modifiers can be added in the NLA Properties Panel. Per Modifier you
have to indicate the channel and a Curve Object. You can copy modifiers from
one strip to another using CTRL+C (only copies to active Object strips).
Setting up a correct Curve Path has to be carefully done:
- Use SHIFT+A "Curve Path" in top view, or ensure the path is not rotated.
- make sure the center point of the Curve Object is at the center of the
  Armature (or above)
- move the first point of the curve to the center point as well.
- check if the path starts from this first point, you can change it using
  (in Curve EditMode) the option Wkey -> "Switch Direction"
- Make sure alignment uses the correct axis; if the Armature walks into
  the negative Y direction, you have to set in Object Buttons, "Anim settings"
  Panel, the correct Track option. (Note; option will probably move to the
  Modifier later).
This is a good reason to make such paths automatic (on a command). Is on the
todo list.
Also note this:
- the Curve Path extends in beginning and ending, that's (for now) the default,
  and allows to use multiple paths. Make sure paths begin and end horizontal.
- Moving the Curve in Object Mode will change the "mapping" (as if the landscape
  a character walks over moves). Moving the Curve in Edit Mode will change the
  actual position of the deformation.
- Speed (Ipos) on paths is not supported yet, will be done.
- The Curve "Stretch" deform option doesn't work.
- Modifiers are executed *after* all actions in NLA are evaluated, there's no
  support yet for blending multiple strips with Modifiers.
- This doesn't work yet for time-mapping...
This commit is mostly for review by character animators... some details or
working methods might change.
This feature can also be used for other modifiers, such as noise (Perlin) or
the mythical "Oomph" (frequency control) and of course Python.
Special thanks to Bassam & Matt for research & design help. Have fun!
											
										 
											2006-10-31 15:51:57 +00:00
										 |  |  | #include "BKE_lattice.h"
 | 
					
						
							| 
									
										
										
										
											2006-09-03 12:16:14 +00:00
										 |  |  | #include "BKE_main.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | #include "BKE_object.h"
 | 
					
						
							| 
									
										
										
										
											2011-11-06 06:08:18 +00:00
										 |  |  | #include "BKE_scene.h"
 | 
					
						
							| 
									
										
										
										
											2011-01-07 19:18:31 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-19 16:48:21 +02:00
										 |  |  | #include "DEG_depsgraph_build.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:22:24 +00:00
										 |  |  | #include "BIK_api.h"
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-20 15:42:37 +01:00
										 |  |  | #include "atomic_ops.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-01 12:44:19 +11:00
										 |  |  | #include "CLG_log.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static CLG_LogRef LOG = {"bke.armature"}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* **************** Generic Functions, data level *************** */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-05 12:46:15 +00:00
										 |  |  | bArmature *BKE_armature_add(Main *bmain, const char *name) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bArmature *arm; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   arm = BKE_libblock_alloc(bmain, ID_AR, name, 0); | 
					
						
							|  |  |  |   arm->deformflag = ARM_DEF_VGROUP | ARM_DEF_ENVELOPE; | 
					
						
							|  |  |  |   arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */ | 
					
						
							|  |  |  |   arm->layer = 1; | 
					
						
							|  |  |  |   return arm; | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | bArmature *BKE_armature_from_object(Object *ob) | 
					
						
							| 
									
										
										
										
											2009-01-10 19:34:23 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (ob->type == OB_ARMATURE) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return (bArmature *)ob->data; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return NULL; | 
					
						
							| 
									
										
										
										
											2009-01-10 19:34:23 +00:00
										 |  |  | } | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | int BKE_armature_bonelist_count(ListBase *lb) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int i = 0; | 
					
						
							|  |  |  |   for (Bone *bone = lb->first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     i += 1 + BKE_armature_bonelist_count(&bone->childbase); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return i; | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_armature_bonelist_free(ListBase *lb) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *bone; | 
					
						
							| 
									
										
										
										
											2009-10-28 15:33:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (bone = lb->first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     if (bone->prop) { | 
					
						
							|  |  |  |       IDP_FreeProperty(bone->prop); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     BKE_armature_bonelist_free(&bone->childbase); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_freelistN(lb); | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												ID-Remap - Step one: core work (cleanup and rework of generic ID datablock handling).
This commit changes a lot of how IDs are handled internally, especially the unlinking/freeing
processes. So far, this was very fuzy, to summarize cleanly deleting or replacing a datablock
was pretty much impossible, except for a few special cases.
Also, unlinking was handled by each datatype, in a rather messy and prone-to-errors way (quite
a few ID usages were missed or wrongly handled that way).
One of the main goal of id-remap branch was to cleanup this, and fatorize ID links handling
by using library_query utils to allow generic handling of those, which is now the case
(now, generic ID links handling is only "knwon" from readfile.c and library_query.c).
This commit also adds backends to allow live replacement and deletion of datablocks in Blender
(so-called 'remapping' process, where we replace all usages of a given ID pointer by a new one,
or NULL one in case of unlinking).
This will allow nice new features, like ability to easily reload or relocate libraries, real immediate
deletion of datablocks in blender, replacement of one datablock by another, etc.
Some of those are for next commits.
A word of warning: this commit is highly risky, because it affects potentially a lot in Blender core.
Though it was tested rather deeply, being totally impossible to check all possible ID usage cases,
it's likely there are some remaining issues and bugs in new code... Please report them! ;)
Review task: D2027 (https://developer.blender.org/D2027).
Reviewed by campbellbarton, thanks a bunch.
											
										 
											2016-06-22 17:29:38 +02:00
										 |  |  | /** Free (or release) any data used by this armature (does not free the armature itself). */ | 
					
						
							| 
									
										
										
										
											2012-05-05 14:03:12 +00:00
										 |  |  | void BKE_armature_free(bArmature *arm) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_animdata_free(&arm->id, false); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |   BKE_armature_bone_hash_free(arm); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_armature_bonelist_free(&arm->bonebase); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* free editmode data */ | 
					
						
							|  |  |  |   if (arm->edbo) { | 
					
						
							|  |  |  |     BLI_freelistN(arm->edbo); | 
					
						
							| 
									
										
										
										
											2009-07-19 02:26:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MEM_freeN(arm->edbo); | 
					
						
							|  |  |  |     arm->edbo = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-20 19:49:45 +02:00
										 |  |  | void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_id_make_local_generic(bmain, &arm->id, true, lib_local); | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void copy_bonechildren(Bone *bone_dst, | 
					
						
							|  |  |  |                               const Bone *bone_src, | 
					
						
							|  |  |  |                               const Bone *bone_src_act, | 
					
						
							|  |  |  |                               Bone **r_bone_dst_act, | 
					
						
							|  |  |  |                               const int flag) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *bone_src_child, *bone_dst_child; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (bone_src == bone_src_act) { | 
					
						
							|  |  |  |     *r_bone_dst_act = bone_dst; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-11-09 21:03:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (bone_src->prop) { | 
					
						
							|  |  |  |     bone_dst->prop = IDP_CopyProperty_ex(bone_src->prop, flag); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-12-07 15:54:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Copy this bone's list */ | 
					
						
							|  |  |  |   BLI_duplicatelist(&bone_dst->childbase, &bone_src->childbase); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* For each child in the list, update it's children */ | 
					
						
							|  |  |  |   for (bone_src_child = bone_src->childbase.first, bone_dst_child = bone_dst->childbase.first; | 
					
						
							|  |  |  |        bone_src_child; | 
					
						
							|  |  |  |        bone_src_child = bone_src_child->next, bone_dst_child = bone_dst_child->next) { | 
					
						
							|  |  |  |     bone_dst_child->parent = bone_dst; | 
					
						
							|  |  |  |     copy_bonechildren(bone_dst_child, bone_src_child, bone_src_act, r_bone_dst_act, flag); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  | static void copy_bonechildren_custom_handles(Bone *bone_dst, bArmature *arm_dst) | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  | { | 
					
						
							|  |  |  |   Bone *bone_dst_child; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (bone_dst->bbone_prev) { | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |     bone_dst->bbone_prev = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_prev->name); | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  |   } | 
					
						
							|  |  |  |   if (bone_dst->bbone_next) { | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |     bone_dst->bbone_next = BKE_armature_find_bone_name(arm_dst, bone_dst->bbone_next->name); | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (bone_dst_child = bone_dst->childbase.first; bone_dst_child; | 
					
						
							|  |  |  |        bone_dst_child = bone_dst_child->next) { | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |     copy_bonechildren_custom_handles(bone_dst_child, arm_dst); | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Only copy internal data of Armature ID from source | 
					
						
							|  |  |  |  * to already allocated/initialized destination. | 
					
						
							|  |  |  |  * You probably never want to use that directly, | 
					
						
							|  |  |  |  * use #BKE_id_copy or #BKE_id_copy_ex for typical needs. | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * WARNING! This function will not handle ID user count! | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-12 12:50:58 +11:00
										 |  |  |  * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_armature_copy_data(Main *UNUSED(bmain), | 
					
						
							|  |  |  |                             bArmature *arm_dst, | 
					
						
							|  |  |  |                             const bArmature *arm_src, | 
					
						
							|  |  |  |                             const int flag) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *bone_src, *bone_dst; | 
					
						
							|  |  |  |   Bone *bone_dst_act = NULL; | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* We never handle usercount here for own data. */ | 
					
						
							|  |  |  |   const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |   arm_dst->bonehash = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_duplicatelist(&arm_dst->bonebase, &arm_src->bonebase); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Duplicate the childrens' lists */ | 
					
						
							|  |  |  |   bone_dst = arm_dst->bonebase.first; | 
					
						
							|  |  |  |   for (bone_src = arm_src->bonebase.first; bone_src; bone_src = bone_src->next) { | 
					
						
							|  |  |  |     bone_dst->parent = NULL; | 
					
						
							|  |  |  |     copy_bonechildren(bone_dst, bone_src, arm_src->act_bone, &bone_dst_act, flag_subdata); | 
					
						
							|  |  |  |     bone_dst = bone_dst->next; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   arm_dst->act_bone = bone_dst_act; | 
					
						
							| 
									
										
										
										
											2011-04-21 09:38:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |   BKE_armature_bone_hash_make(arm_dst); | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |   /* Fix custom handle references. */ | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  |   for (bone_dst = arm_dst->bonebase.first; bone_dst; bone_dst = bone_dst->next) { | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |     copy_bonechildren_custom_handles(bone_dst, arm_dst); | 
					
						
							| 
									
										
										
										
											2019-04-28 16:19:45 +03:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   arm_dst->edbo = NULL; | 
					
						
							|  |  |  |   arm_dst->act_edbone = NULL; | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-09 09:52:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Refactor ID copying (and to some extent, ID freeing).
This will allow much finer controll over how we copy data-blocks, from
full copy in Main database, to "lighter" ones (out of Main, inside an
already allocated datablock, etc.).
This commit also transfers a llot of what was previously handled by
per-ID-type custom code to generic ID handling code in BKE_library.
Hopefully will avoid in future inconsistencies and missing bits we had
all over the codebase in the past.
It also adds missing copying handling for a few types, most notably
Scene (which where using a fully customized handling previously).
Note that the type of allocation used during copying (regular in Main,
allocated but outside of Main, or not allocated by ID handling code at
all) is stored in ID's, which allows to handle them correctly when
freeing. This needs to be taken care of with caution when doing 'weird'
unusual things with ID copying and/or allocation!
As a final note, while rather noisy, this commit will hopefully not
break too much existing branches, old 'API' has been kept for the main
part, as a wrapper around new code. Cleaning it up will happen later.
Design task : T51804
Phab Diff: D2714
											
										 
											2017-08-07 16:39:55 +02:00
										 |  |  | bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bArmature *arm_copy; | 
					
						
							|  |  |  |   BKE_id_copy(bmain, &arm->id, (ID **)&arm_copy); | 
					
						
							|  |  |  |   return arm_copy; | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-24 10:08:42 +02:00
										 |  |  | static void copy_bone_transform(Bone *bone_dst, const Bone *bone_src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bone_dst->roll = bone_src->roll; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_v3_v3(bone_dst->head, bone_src->head); | 
					
						
							|  |  |  |   copy_v3_v3(bone_dst->tail, bone_src->tail); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_m3_m3(bone_dst->bone_mat, bone_src->bone_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_v3_v3(bone_dst->arm_head, bone_src->arm_head); | 
					
						
							|  |  |  |   copy_v3_v3(bone_dst->arm_tail, bone_src->arm_tail); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_m4_m4(bone_dst->arm_mat, bone_src->arm_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bone_dst->arm_roll = bone_src->arm_roll; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Bone *bone_dst = armature_dst->bonebase.first; | 
					
						
							|  |  |  |   const Bone *bone_src = armature_src->bonebase.first; | 
					
						
							|  |  |  |   while (bone_dst != NULL) { | 
					
						
							|  |  |  |     BLI_assert(bone_src != NULL); | 
					
						
							|  |  |  |     copy_bone_transform(bone_dst, bone_src); | 
					
						
							|  |  |  |     bone_dst = bone_dst->next; | 
					
						
							|  |  |  |     bone_src = bone_src->next; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 10:38:30 +10:00
										 |  |  | /** Helper for #ED_armature_transform */ | 
					
						
							|  |  |  | static void armature_transform_recurse(ListBase *bonebase, | 
					
						
							|  |  |  |                                        const float mat[4][4], | 
					
						
							|  |  |  |                                        const bool do_props, | 
					
						
							|  |  |  |                                        /* Cached from 'mat'. */ | 
					
						
							|  |  |  |                                        const float mat3[3][3], | 
					
						
							|  |  |  |                                        const float scale, | 
					
						
							|  |  |  |                                        /* Child bones. */ | 
					
						
							|  |  |  |                                        const Bone *bone_parent, | 
					
						
							|  |  |  |                                        const float arm_mat_parent_inv[4][4]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (Bone *bone = bonebase->first; bone; bone = bone->next) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Transform the bone's roll. */ | 
					
						
							|  |  |  |     if (bone_parent == NULL) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       float roll_mat[3][3]; | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         float delta[3]; | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, bone->tail, bone->head); | 
					
						
							|  |  |  |         vec_roll_to_mat3(delta, bone->roll, roll_mat); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Transform the roll matrix. */ | 
					
						
							|  |  |  |       mul_m3_m3m3(roll_mat, mat3, roll_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Apply the transformed roll back. */ | 
					
						
							|  |  |  |       mat3_to_vec_roll(roll_mat, NULL, &bone->roll); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mul_m4_v3(mat, bone->arm_head); | 
					
						
							|  |  |  |     mul_m4_v3(mat, bone->arm_tail); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Get the new head and tail */ | 
					
						
							|  |  |  |     if (bone_parent) { | 
					
						
							|  |  |  |       sub_v3_v3v3(bone->head, bone->arm_head, bone_parent->arm_tail); | 
					
						
							|  |  |  |       sub_v3_v3v3(bone->tail, bone->arm_tail, bone_parent->arm_tail); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mul_mat3_m4_v3(arm_mat_parent_inv, bone->head); | 
					
						
							|  |  |  |       mul_mat3_m4_v3(arm_mat_parent_inv, bone->tail); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       copy_v3_v3(bone->head, bone->arm_head); | 
					
						
							|  |  |  |       copy_v3_v3(bone->tail, bone->arm_tail); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BKE_armature_where_is_bone(bone, bone_parent, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       float arm_mat3[3][3]; | 
					
						
							|  |  |  |       copy_m3_m4(arm_mat3, bone->arm_mat); | 
					
						
							|  |  |  |       mat3_to_vec_roll(arm_mat3, NULL, &bone->arm_roll); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (do_props) { | 
					
						
							|  |  |  |       bone->rad_head *= scale; | 
					
						
							|  |  |  |       bone->rad_tail *= scale; | 
					
						
							|  |  |  |       bone->dist *= scale; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* we could be smarter and scale by the matrix along the x & z axis */ | 
					
						
							|  |  |  |       bone->xwidth *= scale; | 
					
						
							|  |  |  |       bone->zwidth *= scale; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!BLI_listbase_is_empty(&bone->childbase)) { | 
					
						
							|  |  |  |       float arm_mat_inv[4][4]; | 
					
						
							|  |  |  |       invert_m4_m4(arm_mat_inv, bone->arm_mat); | 
					
						
							|  |  |  |       armature_transform_recurse(&bone->childbase, mat, do_props, mat3, scale, bone, arm_mat_inv); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* Store the scale of the matrix here to use on envelopes. */ | 
					
						
							|  |  |  |   float scale = mat4_to_scale(mat); | 
					
						
							|  |  |  |   float mat3[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_m3_m4(mat3, mat); | 
					
						
							|  |  |  |   normalize_m3(mat3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *curBone, *rbone; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (curBone = lb->first; curBone; curBone = curBone->next) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (STREQ(curBone->name, name)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return curBone; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     rbone = get_named_bone_bonechildren(&curBone->childbase, name); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (rbone) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return rbone; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return NULL; | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Walk the list until the bone is found (slow!), | 
					
						
							|  |  |  |  * use #BKE_armature_bone_from_name_map for multiple lookups. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (!arm) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return NULL; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |   if (arm->bonehash) { | 
					
						
							|  |  |  |     return BLI_ghash_lookup(arm->bonehash, name); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return get_named_bone_bonechildren(&arm->bonebase, name); | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void armature_bone_from_name_insert_recursive(GHash *bone_hash, ListBase *lb) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (Bone *bone = lb->first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     BLI_ghash_insert(bone_hash, bone->name, bone); | 
					
						
							|  |  |  |     armature_bone_from_name_insert_recursive(bone_hash, &bone->childbase); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Create a (name -> bone) map. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note typically #bPose.chanhash us used via #BKE_pose_channel_find_name | 
					
						
							|  |  |  |  * this is for the cases we can't use pose channels. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  | static GHash *armature_bone_from_name_map(bArmature *arm) | 
					
						
							| 
									
										
										
										
											2016-01-09 09:12:06 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const int bones_count = BKE_armature_bonelist_count(&arm->bonebase); | 
					
						
							|  |  |  |   GHash *bone_hash = BLI_ghash_str_new_ex(__func__, bones_count); | 
					
						
							|  |  |  |   armature_bone_from_name_insert_recursive(bone_hash, &arm->bonebase); | 
					
						
							|  |  |  |   return bone_hash; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  | void BKE_armature_bone_hash_make(bArmature *arm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!arm->bonehash) { | 
					
						
							|  |  |  |     arm->bonehash = armature_bone_from_name_map(arm); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BKE_armature_bone_hash_free(bArmature *arm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (arm->bonehash) { | 
					
						
							|  |  |  |     BLI_ghash_free(arm->bonehash, NULL, NULL); | 
					
						
							|  |  |  |     arm->bonehash = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-04 14:38:16 +11:00
										 |  |  | bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (bone->flag & flag) { | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (bone->parent) { | 
					
						
							|  |  |  |     return BKE_armature_bone_flag_test_recursive(bone->parent, flag); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-03-04 14:38:16 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-17 14:17:16 -03:00
										 |  |  | static void armature_refresh_layer_used_recursive(bArmature *arm, ListBase *bones) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   for (Bone *bone = bones->first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     arm->layer_used |= bone->layer; | 
					
						
							|  |  |  |     armature_refresh_layer_used_recursive(arm, &bone->childbase); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Update the layers_used variable after bones are moved between layer
 | 
					
						
							|  |  |  |  * NOTE: Used to be done in drawing code in 2.7, but that won't work with | 
					
						
							|  |  |  |  *       Copy-on-Write, as drawing uses evaluated copies. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void BKE_armature_refresh_layer_used(bArmature *arm) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   arm->layer_used = 0; | 
					
						
							|  |  |  |   armature_refresh_layer_used_recursive(arm, &arm->bonebase); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* Finds the best possible extension to the name on a particular axis. (For renaming, check for
 | 
					
						
							|  |  |  |  * unique names afterwards) strip_number: removes number extensions  (TODO: not used) | 
					
						
							|  |  |  |  * axis: the axis to name on | 
					
						
							|  |  |  |  * head/tail: the head/tail co-ordinate of the bone on the specified axis */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | int bone_autoside_name( | 
					
						
							|  |  |  |     char name[MAXBONENAME], int UNUSED(strip_number), short axis, float head, float tail) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   unsigned int len; | 
					
						
							|  |  |  |   char basename[MAXBONENAME] = ""; | 
					
						
							|  |  |  |   char extension[5] = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   len = strlen(name); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (len == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_strncpy(basename, name, sizeof(basename)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Figure out extension to append:
 | 
					
						
							|  |  |  |    * - The extension to append is based upon the axis that we are working on. | 
					
						
							|  |  |  |    * - If head happens to be on 0, then we must consider the tail position as well to decide | 
					
						
							|  |  |  |    *   which side the bone is on | 
					
						
							|  |  |  |    *   -> If tail is 0, then it's bone is considered to be on axis, so no extension should be added | 
					
						
							|  |  |  |    *   -> Otherwise, extension is added from perspective of object based on which side tail goes to | 
					
						
							|  |  |  |    * - If head is non-zero, extension is added from perspective of object based on side head is on | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   if (axis == 2) { | 
					
						
							|  |  |  |     /* z-axis - vertical (top/bottom) */ | 
					
						
							|  |  |  |     if (IS_EQF(head, 0.0f)) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (tail < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Bot"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else if (tail > 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Top"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (head < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Bot"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Top"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (axis == 1) { | 
					
						
							|  |  |  |     /* y-axis - depth (front/back) */ | 
					
						
							|  |  |  |     if (IS_EQF(head, 0.0f)) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (tail < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Fr"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else if (tail > 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Bk"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (head < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Fr"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "Bk"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* x-axis - horizontal (left/right) */ | 
					
						
							|  |  |  |     if (IS_EQF(head, 0.0f)) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (tail < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "R"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else if (tail > 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "L"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (head < 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "R"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |         /* XXX Shouldn't this be simple else, as for z and y axes? */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (head > 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         strcpy(extension, "L"); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Simple name truncation
 | 
					
						
							|  |  |  |    * - truncate if there is an extension and it wouldn't be able to fit | 
					
						
							|  |  |  |    * - otherwise, just append to end | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   if (extension[0]) { | 
					
						
							|  |  |  |     bool changed = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (changed) { /* remove extensions */ | 
					
						
							|  |  |  |       changed = false; | 
					
						
							|  |  |  |       if (len > 2 && basename[len - 2] == '.') { | 
					
						
							|  |  |  |         if (basename[len - 1] == 'L' || basename[len - 1] == 'R') { /* L R */ | 
					
						
							|  |  |  |           basename[len - 2] = '\0'; | 
					
						
							|  |  |  |           len -= 2; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (len > 3 && basename[len - 3] == '.') { | 
					
						
							|  |  |  |         if ((basename[len - 2] == 'F' && basename[len - 1] == 'r') || /* Fr */ | 
					
						
							|  |  |  |             (basename[len - 2] == 'B' && basename[len - 1] == 'k'))   /* Bk */ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           basename[len - 3] = '\0'; | 
					
						
							|  |  |  |           len -= 3; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (len > 4 && basename[len - 4] == '.') { | 
					
						
							|  |  |  |         if ((basename[len - 3] == 'T' && basename[len - 2] == 'o' && | 
					
						
							|  |  |  |              basename[len - 1] == 'p') || /* Top */ | 
					
						
							|  |  |  |             (basename[len - 3] == 'B' && basename[len - 2] == 'o' && | 
					
						
							|  |  |  |              basename[len - 1] == 't')) /* Bot */ | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           basename[len - 4] = '\0'; | 
					
						
							|  |  |  |           len -= 4; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((MAXBONENAME - len) < strlen(extension) + 1) { /* add 1 for the '.' */ | 
					
						
							|  |  |  |       strncpy(name, basename, len - strlen(extension)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BLI_snprintf(name, MAXBONENAME, "%s.%s", basename, extension); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-01-28 00:53:54 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-08-13 19:41:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-16 19:07:02 +00:00
										 |  |  | /* ************* B-Bone support ******************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | /* Compute a set of bezier parameter values that produce approximately equally spaced points. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void equalize_cubic_bezier(const float control[4][3], | 
					
						
							|  |  |  |                                   int temp_segments, | 
					
						
							|  |  |  |                                   int final_segments, | 
					
						
							|  |  |  |                                   float *r_t_points) | 
					
						
							| 
									
										
										
										
											2005-07-17 08:58:42 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float(*coords)[3] = BLI_array_alloca(coords, temp_segments + 1); | 
					
						
							|  |  |  |   float *pdist = BLI_array_alloca(pdist, temp_segments + 1); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Compute the first pass of bezier point coordinates. */ | 
					
						
							|  |  |  |   for (int i = 0; i < 3; i++) { | 
					
						
							|  |  |  |     BKE_curve_forward_diff_bezier(control[0][i], | 
					
						
							|  |  |  |                                   control[1][i], | 
					
						
							|  |  |  |                                   control[2][i], | 
					
						
							|  |  |  |                                   control[3][i], | 
					
						
							|  |  |  |                                   &coords[0][i], | 
					
						
							|  |  |  |                                   temp_segments, | 
					
						
							|  |  |  |                                   sizeof(*coords)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Calculate the length of the polyline at each point. */ | 
					
						
							|  |  |  |   pdist[0] = 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   for (int i = 0; i < temp_segments; i++) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     pdist[i + 1] = pdist[i] + len_v3v3(coords[i], coords[i + 1]); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Go over distances and calculate new parameter values. */ | 
					
						
							|  |  |  |   float dist_step = pdist[temp_segments] / final_segments; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   r_t_points[0] = 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (int i = 1, nr = 1; i <= final_segments; i++) { | 
					
						
							|  |  |  |     float dist = i * dist_step; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* We're looking for location (distance) 'dist' in the array. */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     while ((nr < temp_segments) && (dist >= pdist[nr])) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       nr++; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float fac = (pdist[nr] - dist) / (pdist[nr] - pdist[nr - 1]); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     r_t_points[i] = (nr - fac) / temp_segments; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   r_t_points[final_segments] = 1.0f; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  | /* Evaluate bezier position and tangent at a specific parameter value
 | 
					
						
							|  |  |  |  * using the De Casteljau algorithm. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void evaluate_cubic_bezier(const float control[4][3], | 
					
						
							|  |  |  |                                   float t, | 
					
						
							|  |  |  |                                   float r_pos[3], | 
					
						
							|  |  |  |                                   float r_tangent[3]) | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float layer1[3][3]; | 
					
						
							|  |  |  |   interp_v3_v3v3(layer1[0], control[0], control[1], t); | 
					
						
							|  |  |  |   interp_v3_v3v3(layer1[1], control[1], control[2], t); | 
					
						
							|  |  |  |   interp_v3_v3v3(layer1[2], control[2], control[3], t); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float layer2[2][3]; | 
					
						
							|  |  |  |   interp_v3_v3v3(layer2[0], layer1[0], layer1[1], t); | 
					
						
							|  |  |  |   interp_v3_v3v3(layer2[1], layer1[1], layer1[2], t); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   sub_v3_v3v3(r_tangent, layer2[1], layer2[0]); | 
					
						
							|  |  |  |   madd_v3_v3v3fl(r_pos, layer2[0], r_tangent, t); | 
					
						
							| 
									
										
										
										
											2005-07-17 08:58:42 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-05 18:48:05 +03:00
										 |  |  | /* Get "next" and "prev" bones - these are used for handle calculations. */ | 
					
						
							| 
									
										
										
										
											2018-12-02 14:32:31 +11:00
										 |  |  | void BKE_pchan_bbone_handles_get(bPoseChannel *pchan, bPoseChannel **r_prev, bPoseChannel **r_next) | 
					
						
							| 
									
										
										
										
											2018-08-09 17:17:40 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (pchan->bone->bbone_prev_type == BBONE_HANDLE_AUTO) { | 
					
						
							|  |  |  |     /* Use connected parent. */ | 
					
						
							|  |  |  |     if (pchan->bone->flag & BONE_CONNECTED) { | 
					
						
							|  |  |  |       *r_prev = pchan->parent; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       *r_prev = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* Use the provided bone as prev - leave blank to eliminate this effect altogether. */ | 
					
						
							|  |  |  |     *r_prev = pchan->bbone_prev; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (pchan->bone->bbone_next_type == BBONE_HANDLE_AUTO) { | 
					
						
							|  |  |  |     /* Use connected child. */ | 
					
						
							|  |  |  |     *r_next = pchan->child; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* Use the provided bone as next - leave blank to eliminate this effect altogether. */ | 
					
						
							|  |  |  |     *r_next = pchan->bbone_next; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-08-09 17:17:40 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | /* Compute B-Bone spline parameters for the given channel. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan, | 
					
						
							|  |  |  |                                        const bool rest, | 
					
						
							|  |  |  |                                        struct BBoneSplineParameters *param) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bPoseChannel *next, *prev; | 
					
						
							|  |  |  |   Bone *bone = pchan->bone; | 
					
						
							|  |  |  |   float imat[4][4], posemat[4][4]; | 
					
						
							|  |  |  |   float delta[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   memset(param, 0, sizeof(*param)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   param->segments = bone->segments; | 
					
						
							|  |  |  |   param->length = bone->length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!rest) { | 
					
						
							|  |  |  |     float scale[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Check if we need to take non-uniform bone scaling into account. */ | 
					
						
							|  |  |  |     mat4_to_size(scale, pchan->pose_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - scale[2]) > 1e-6f) { | 
					
						
							|  |  |  |       param->do_scale = true; | 
					
						
							|  |  |  |       copy_v3_v3(param->scale, scale); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BKE_pchan_bbone_handles_get(pchan, &prev, &next); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Find the handle points, since this is inside bone space, the
 | 
					
						
							|  |  |  |    * first point = (0, 0, 0) | 
					
						
							|  |  |  |    * last point =  (0, length, 0) */ | 
					
						
							|  |  |  |   if (rest) { | 
					
						
							|  |  |  |     invert_m4_m4(imat, pchan->bone->arm_mat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (param->do_scale) { | 
					
						
							|  |  |  |     copy_m4_m4(posemat, pchan->pose_mat); | 
					
						
							|  |  |  |     normalize_m4(posemat); | 
					
						
							|  |  |  |     invert_m4_m4(imat, posemat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     invert_m4_m4(imat, pchan->pose_mat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (prev) { | 
					
						
							|  |  |  |     float h1[3]; | 
					
						
							|  |  |  |     bool done = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     param->use_prev = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Transform previous point inside this bone space. */ | 
					
						
							|  |  |  |     if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) { | 
					
						
							|  |  |  |       /* Use delta movement (from restpose), and apply this relative to the current bone's head. */ | 
					
						
							|  |  |  |       if (rest) { | 
					
						
							|  |  |  |         /* In restpose, arm_head == pose_head */ | 
					
						
							|  |  |  |         zero_v3(param->prev_h); | 
					
						
							|  |  |  |         done = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, prev->pose_head, prev->bone->arm_head); | 
					
						
							|  |  |  |         sub_v3_v3v3(h1, pchan->pose_head, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (bone->bbone_prev_type == BBONE_HANDLE_TANGENT) { | 
					
						
							|  |  |  |       /* Use bone direction by offsetting so that its tail meets current bone's head */ | 
					
						
							|  |  |  |       if (rest) { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, prev->bone->arm_tail, prev->bone->arm_head); | 
					
						
							|  |  |  |         sub_v3_v3v3(h1, bone->arm_head, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, prev->pose_tail, prev->pose_head); | 
					
						
							|  |  |  |         sub_v3_v3v3(h1, pchan->pose_head, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* Apply special handling for smoothly joining B-Bone chains */ | 
					
						
							|  |  |  |       param->prev_bbone = (prev->bone->segments > 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Use bone head as absolute position. */ | 
					
						
							|  |  |  |       copy_v3_v3(h1, rest ? prev->bone->arm_head : prev->pose_head); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!done) { | 
					
						
							|  |  |  |       mul_v3_m4v3(param->prev_h, imat, h1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!param->prev_bbone) { | 
					
						
							|  |  |  |       /* Find the previous roll to interpolate. */ | 
					
						
							|  |  |  |       mul_m4_m4m4(param->prev_mat, imat, rest ? prev->bone->arm_mat : prev->pose_mat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (next) { | 
					
						
							|  |  |  |     float h2[3]; | 
					
						
							|  |  |  |     bool done = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     param->use_next = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Transform next point inside this bone space. */ | 
					
						
							|  |  |  |     if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) { | 
					
						
							|  |  |  |       /* Use delta movement (from restpose), and apply this relative to the current bone's tail. */ | 
					
						
							|  |  |  |       if (rest) { | 
					
						
							|  |  |  |         /* In restpose, arm_head == pose_head */ | 
					
						
							|  |  |  |         copy_v3_fl3(param->next_h, 0.0f, param->length, 0.0); | 
					
						
							|  |  |  |         done = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, next->pose_head, next->bone->arm_head); | 
					
						
							|  |  |  |         add_v3_v3v3(h2, pchan->pose_tail, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (bone->bbone_next_type == BBONE_HANDLE_TANGENT) { | 
					
						
							|  |  |  |       /* Use bone direction by offsetting so that its head meets current bone's tail */ | 
					
						
							|  |  |  |       if (rest) { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, next->bone->arm_tail, next->bone->arm_head); | 
					
						
							|  |  |  |         add_v3_v3v3(h2, bone->arm_tail, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         sub_v3_v3v3(delta, next->pose_tail, next->pose_head); | 
					
						
							|  |  |  |         add_v3_v3v3(h2, pchan->pose_tail, delta); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* Apply special handling for smoothly joining B-Bone chains */ | 
					
						
							|  |  |  |       param->next_bbone = (next->bone->segments > 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Use bone tail as absolute position. */ | 
					
						
							|  |  |  |       copy_v3_v3(h2, rest ? next->bone->arm_tail : next->pose_tail); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!done) { | 
					
						
							|  |  |  |       mul_v3_m4v3(param->next_h, imat, h2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Find the next roll to interpolate as well. */ | 
					
						
							|  |  |  |     mul_m4_m4m4(param->next_mat, imat, rest ? next->bone->arm_mat : next->pose_mat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Add effects from bbone properties over the top
 | 
					
						
							|  |  |  |    * - These properties allow users to hand-animate the | 
					
						
							|  |  |  |    *   bone curve/shape, without having to resort to using | 
					
						
							|  |  |  |    *   extra bones | 
					
						
							|  |  |  |    * - The "bone" level offsets are for defining the restpose | 
					
						
							|  |  |  |    *   shape of the bone (e.g. for curved eyebrows for example). | 
					
						
							|  |  |  |    *   -> In the viewport, it's needed to define what the rest pose | 
					
						
							|  |  |  |    *      looks like | 
					
						
							|  |  |  |    *   -> For "rest == 0", we also still need to have it present | 
					
						
							|  |  |  |    *      so that we can "cancel out" this restpose when it comes | 
					
						
							|  |  |  |    *      time to deform some geometry, it won't cause double transforms. | 
					
						
							|  |  |  |    * - The "pchan" level offsets are the ones that animators actually | 
					
						
							|  |  |  |    *   end up animating | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     param->ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f); | 
					
						
							|  |  |  |     param->ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     param->roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f); | 
					
						
							|  |  |  |     param->roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bone->flag & BONE_ADD_PARENT_END_ROLL) { | 
					
						
							|  |  |  |       if (prev) { | 
					
						
							|  |  |  |         if (prev->bone) { | 
					
						
							|  |  |  |           param->roll1 += prev->bone->roll2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!rest) { | 
					
						
							|  |  |  |           param->roll1 += prev->roll2; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |     param->scale_in_x = bone->scale_in_x * (!rest ? pchan->scale_in_x : 1.0f); | 
					
						
							|  |  |  |     param->scale_in_y = bone->scale_in_y * (!rest ? pchan->scale_in_y : 1.0f); | 
					
						
							|  |  |  |     param->scale_out_x = bone->scale_out_x * (!rest ? pchan->scale_out_x : 1.0f); | 
					
						
							|  |  |  |     param->scale_out_y = bone->scale_out_y * (!rest ? pchan->scale_out_y : 1.0f); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Extra curve x / y */ | 
					
						
							| 
									
										
										
										
											2019-04-23 13:15:30 +03:00
										 |  |  |     param->curve_in_x = bone->curve_in_x + (!rest ? pchan->curve_in_x : 0.0f); | 
					
						
							|  |  |  |     param->curve_in_y = bone->curve_in_y + (!rest ? pchan->curve_in_y : 0.0f); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 13:15:30 +03:00
										 |  |  |     param->curve_out_x = bone->curve_out_x + (!rest ? pchan->curve_out_x : 0.0f); | 
					
						
							|  |  |  |     param->curve_out_y = bone->curve_out_y + (!rest ? pchan->curve_out_y : 0.0f); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-08-07 21:08:16 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fills the array with the desired amount of bone->segments elements.
 | 
					
						
							|  |  |  |  * This calculation is done within unit bone space. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_pchan_bbone_spline_setup(bPoseChannel *pchan, | 
					
						
							|  |  |  |                                   const bool rest, | 
					
						
							|  |  |  |                                   const bool for_deform, | 
					
						
							|  |  |  |                                   Mat4 *result_array) | 
					
						
							| 
									
										
										
										
											2018-08-07 21:08:16 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BBoneSplineParameters param; | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_pchan_bbone_spline_params_get(pchan, rest, ¶m); | 
					
						
							| 
									
										
										
										
											2018-08-07 21:08:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   pchan->bone->segments = BKE_pchan_bbone_spline_compute(¶m, for_deform, result_array); | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Computes the bezier handle vectors and rolls coming from custom handles. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param, | 
					
						
							|  |  |  |                                      float h1[3], | 
					
						
							|  |  |  |                                      float *r_roll1, | 
					
						
							|  |  |  |                                      float h2[3], | 
					
						
							|  |  |  |                                      float *r_roll2, | 
					
						
							|  |  |  |                                      bool ease, | 
					
						
							|  |  |  |                                      bool offsets) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float mat3[3][3]; | 
					
						
							|  |  |  |   float length = param->length; | 
					
						
							|  |  |  |   float epsilon = 1e-5 * length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (param->do_scale) { | 
					
						
							|  |  |  |     length *= param->scale[1]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *r_roll1 = *r_roll2 = 0.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (param->use_prev) { | 
					
						
							|  |  |  |     copy_v3_v3(h1, param->prev_h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (param->prev_bbone) { | 
					
						
							|  |  |  |       /* If previous bone is B-bone too, use average handle direction. */ | 
					
						
							|  |  |  |       h1[1] -= length; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (normalize_v3(h1) < epsilon) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       copy_v3_fl3(h1, 0.0f, -1.0f, 0.0f); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     negate_v3(h1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!param->prev_bbone) { | 
					
						
							|  |  |  |       /* Find the previous roll to interpolate. */ | 
					
						
							|  |  |  |       copy_m3_m4(mat3, param->prev_mat); | 
					
						
							|  |  |  |       mat3_vec_to_roll(mat3, h1, r_roll1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     h1[0] = 0.0f; | 
					
						
							|  |  |  |     h1[1] = 1.0; | 
					
						
							|  |  |  |     h1[2] = 0.0f; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (param->use_next) { | 
					
						
							|  |  |  |     copy_v3_v3(h2, param->next_h); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If next bone is B-bone too, use average handle direction. */ | 
					
						
							|  |  |  |     if (param->next_bbone) { | 
					
						
							|  |  |  |       /* pass */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       h2[1] -= length; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (normalize_v3(h2) < epsilon) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       copy_v3_fl3(h2, 0.0f, 1.0f, 0.0f); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Find the next roll to interpolate as well. */ | 
					
						
							|  |  |  |     copy_m3_m4(mat3, param->next_mat); | 
					
						
							|  |  |  |     mat3_vec_to_roll(mat3, h2, r_roll2); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     h2[0] = 0.0f; | 
					
						
							|  |  |  |     h2[1] = 1.0f; | 
					
						
							|  |  |  |     h2[2] = 0.0f; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ease) { | 
					
						
							|  |  |  |     const float circle_factor = length * (cubic_tangent_factor_circle_v3(h1, h2) / 0.75f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const float hlength1 = param->ease1 * circle_factor; | 
					
						
							|  |  |  |     const float hlength2 = param->ease2 * circle_factor; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* and only now negate h2 */ | 
					
						
							|  |  |  |     mul_v3_fl(h1, hlength1); | 
					
						
							|  |  |  |     mul_v3_fl(h2, -hlength2); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Add effects from bbone properties over the top
 | 
					
						
							|  |  |  |    * - These properties allow users to hand-animate the | 
					
						
							|  |  |  |    *   bone curve/shape, without having to resort to using | 
					
						
							|  |  |  |    *   extra bones | 
					
						
							|  |  |  |    * - The "bone" level offsets are for defining the restpose | 
					
						
							|  |  |  |    *   shape of the bone (e.g. for curved eyebrows for example). | 
					
						
							|  |  |  |    *   -> In the viewport, it's needed to define what the rest pose | 
					
						
							|  |  |  |    *      looks like | 
					
						
							|  |  |  |    *   -> For "rest == 0", we also still need to have it present | 
					
						
							|  |  |  |    *      so that we can "cancel out" this restpose when it comes | 
					
						
							|  |  |  |    *      time to deform some geometry, it won't cause double transforms. | 
					
						
							|  |  |  |    * - The "pchan" level offsets are the ones that animators actually | 
					
						
							|  |  |  |    *   end up animating | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   if (offsets) { | 
					
						
							|  |  |  |     /* Add extra rolls. */ | 
					
						
							|  |  |  |     *r_roll1 += param->roll1; | 
					
						
							|  |  |  |     *r_roll2 += param->roll2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Extra curve x / y */ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |     /* NOTE:
 | 
					
						
							|  |  |  |      * Scale correction factors here are to compensate for some random floating-point glitches | 
					
						
							|  |  |  |      * when scaling up the bone or it's parent by a factor of approximately 8.15/6, which results | 
					
						
							|  |  |  |      * in the bone length getting scaled up too (from 1 to 8), causing the curve to flatten out. | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |      */ | 
					
						
							|  |  |  |     const float xscale_correction = (param->do_scale) ? param->scale[0] : 1.0f; | 
					
						
							|  |  |  |     const float yscale_correction = (param->do_scale) ? param->scale[2] : 1.0f; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 13:15:30 +03:00
										 |  |  |     h1[0] += param->curve_in_x * xscale_correction; | 
					
						
							|  |  |  |     h1[2] += param->curve_in_y * yscale_correction; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-23 13:15:30 +03:00
										 |  |  |     h2[0] += param->curve_out_x * xscale_correction; | 
					
						
							|  |  |  |     h2[2] += param->curve_out_y * yscale_correction; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void make_bbone_spline_matrix(BBoneSplineParameters *param, | 
					
						
							| 
									
										
										
										
											2019-09-14 08:10:50 +10:00
										 |  |  |                                      const float scalemats[2][4][4], | 
					
						
							|  |  |  |                                      const float pos[3], | 
					
						
							|  |  |  |                                      const float axis[3], | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                      float roll, | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |                                      float scalex, | 
					
						
							|  |  |  |                                      float scaley, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                      float result[4][4]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float mat3[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   vec_roll_to_mat3(axis, roll, mat3); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_m4_m3(result, mat3); | 
					
						
							|  |  |  |   copy_v3_v3(result[3], pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (param->do_scale) { | 
					
						
							|  |  |  |     /* Correct for scaling when this matrix is used in scaled space. */ | 
					
						
							|  |  |  |     mul_m4_series(result, scalemats[0], result, scalemats[1]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* BBone scale... */ | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |   mul_v3_fl(result[0], scalex); | 
					
						
							|  |  |  |   mul_v3_fl(result[2], scaley); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Fade from first to second derivative when the handle is very short. */ | 
					
						
							|  |  |  | static void ease_handle_axis(const float deriv1[3], const float deriv2[3], float r_axis[3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const float gap = 0.1f; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_v3_v3(r_axis, deriv1); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float len1 = len_squared_v3(deriv1), len2 = len_squared_v3(deriv2); | 
					
						
							|  |  |  |   float ratio = len1 / len2; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (ratio < gap * gap) { | 
					
						
							|  |  |  |     madd_v3_v3fl(r_axis, deriv2, gap - sqrtf(ratio)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | /* Fills the array with the desired amount of bone->segments elements.
 | 
					
						
							|  |  |  |  * This calculation is done within unit bone space. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param, | 
					
						
							|  |  |  |                                    const bool for_deform, | 
					
						
							|  |  |  |                                    Mat4 *result_array) | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float scalemats[2][4][4]; | 
					
						
							|  |  |  |   float bezt_controls[4][3]; | 
					
						
							|  |  |  |   float h1[3], roll1, h2[3], roll2, prev[3], cur[3], axis[3]; | 
					
						
							|  |  |  |   float length = param->length; | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (param->do_scale) { | 
					
						
							|  |  |  |     size_to_mat4(scalemats[1], param->scale); | 
					
						
							|  |  |  |     invert_m4_m4(scalemats[0], scalemats[1]); | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     length *= param->scale[1]; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-11-24 15:12:24 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_pchan_bbone_handles_compute(param, h1, &roll1, h2, &roll2, true, true); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Make curve. */ | 
					
						
							|  |  |  |   CLAMP_MAX(param->segments, MAX_BBONE_SUBDIV); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_v3_fl3(bezt_controls[3], 0.0f, length, 0.0f); | 
					
						
							|  |  |  |   add_v3_v3v3(bezt_controls[2], bezt_controls[3], h2); | 
					
						
							|  |  |  |   copy_v3_v3(bezt_controls[1], h1); | 
					
						
							|  |  |  |   zero_v3(bezt_controls[0]); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float bezt_points[MAX_BBONE_SUBDIV + 1]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   equalize_cubic_bezier(bezt_controls, MAX_BBONE_SUBDIV, param->segments, bezt_points); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Deformation uses N+1 matrices computed at points between the segments. */ | 
					
						
							|  |  |  |   if (for_deform) { | 
					
						
							|  |  |  |     /* Bezier derivatives. */ | 
					
						
							|  |  |  |     float bezt_deriv1[3][3], bezt_deriv2[2][3]; | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (int i = 0; i < 3; i++) { | 
					
						
							|  |  |  |       sub_v3_v3v3(bezt_deriv1[i], bezt_controls[i + 1], bezt_controls[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     for (int i = 0; i < 2; i++) { | 
					
						
							|  |  |  |       sub_v3_v3v3(bezt_deriv2[i], bezt_deriv1[i + 1], bezt_deriv1[i]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* End points require special handling to fix zero length handles. */ | 
					
						
							|  |  |  |     ease_handle_axis(bezt_deriv1[0], bezt_deriv2[0], axis); | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |     make_bbone_spline_matrix(param, | 
					
						
							|  |  |  |                              scalemats, | 
					
						
							|  |  |  |                              bezt_controls[0], | 
					
						
							|  |  |  |                              axis, | 
					
						
							|  |  |  |                              roll1, | 
					
						
							|  |  |  |                              param->scale_in_x, | 
					
						
							|  |  |  |                              param->scale_in_y, | 
					
						
							|  |  |  |                              result_array[0].mat); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (int a = 1; a < param->segments; a++) { | 
					
						
							|  |  |  |       evaluate_cubic_bezier(bezt_controls, bezt_points[a], cur, axis); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       float fac = ((float)a) / param->segments; | 
					
						
							|  |  |  |       float roll = interpf(roll2, roll1, fac); | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |       float scalex = interpf(param->scale_out_x, param->scale_in_x, fac); | 
					
						
							|  |  |  |       float scaley = interpf(param->scale_out_y, param->scale_in_y, fac); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |       make_bbone_spline_matrix( | 
					
						
							|  |  |  |           param, scalemats, cur, axis, roll, scalex, scaley, result_array[a].mat); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     negate_v3(bezt_deriv2[1]); | 
					
						
							|  |  |  |     ease_handle_axis(bezt_deriv1[2], bezt_deriv2[1], axis); | 
					
						
							|  |  |  |     make_bbone_spline_matrix(param, | 
					
						
							|  |  |  |                              scalemats, | 
					
						
							|  |  |  |                              bezt_controls[3], | 
					
						
							|  |  |  |                              axis, | 
					
						
							|  |  |  |                              roll2, | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |                              param->scale_out_x, | 
					
						
							|  |  |  |                              param->scale_out_y, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                              result_array[param->segments].mat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   /* Other code (e.g. display) uses matrices for the segments themselves. */ | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     zero_v3(prev); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (int a = 0; a < param->segments; a++) { | 
					
						
							|  |  |  |       evaluate_cubic_bezier(bezt_controls, bezt_points[a + 1], cur, axis); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       sub_v3_v3v3(axis, cur, prev); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       float fac = (a + 0.5f) / param->segments; | 
					
						
							|  |  |  |       float roll = interpf(roll2, roll1, fac); | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |       float scalex = interpf(param->scale_out_x, param->scale_in_x, fac); | 
					
						
							|  |  |  |       float scaley = interpf(param->scale_out_y, param->scale_in_y, fac); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-20 18:06:31 +03:00
										 |  |  |       make_bbone_spline_matrix( | 
					
						
							|  |  |  |           param, scalemats, prev, axis, roll, scalex, scaley, result_array[a].mat); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       copy_v3_v3(prev, cur); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-08-07 21:08:16 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return param->segments; | 
					
						
							| 
									
										
										
										
											2005-07-16 19:07:02 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* ************ Armature Deform ******************* */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | static void allocate_bbone_cache(bPoseChannel *pchan, int segments) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel_Runtime *runtime = &pchan->runtime; | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (runtime->bbone_segments != segments) { | 
					
						
							| 
									
										
										
										
											2019-04-18 21:19:57 +03:00
										 |  |  |     BKE_pose_channel_free_bbone_cache(runtime); | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     runtime->bbone_segments = segments; | 
					
						
							|  |  |  |     runtime->bbone_rest_mats = MEM_malloc_arrayN( | 
					
						
							|  |  |  |         sizeof(Mat4), 1 + (uint)segments, "bPoseChannel_Runtime::bbone_rest_mats"); | 
					
						
							|  |  |  |     runtime->bbone_pose_mats = MEM_malloc_arrayN( | 
					
						
							|  |  |  |         sizeof(Mat4), 1 + (uint)segments, "bPoseChannel_Runtime::bbone_pose_mats"); | 
					
						
							|  |  |  |     runtime->bbone_deform_mats = MEM_malloc_arrayN( | 
					
						
							|  |  |  |         sizeof(Mat4), 2 + (uint)segments, "bPoseChannel_Runtime::bbone_deform_mats"); | 
					
						
							|  |  |  |     runtime->bbone_dual_quats = MEM_malloc_arrayN( | 
					
						
							|  |  |  |         sizeof(DualQuat), 1 + (uint)segments, "bPoseChannel_Runtime::bbone_dual_quats"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Compute and cache the B-Bone shape in the channel runtime struct. */ | 
					
						
							| 
									
										
										
										
											2018-12-02 14:32:31 +11:00
										 |  |  | void BKE_pchan_bbone_segments_cache_compute(bPoseChannel *pchan) | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel_Runtime *runtime = &pchan->runtime; | 
					
						
							|  |  |  |   Bone *bone = pchan->bone; | 
					
						
							|  |  |  |   int segments = bone->segments; | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_assert(segments > 1); | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Allocate the cache if needed. */ | 
					
						
							|  |  |  |   allocate_bbone_cache(pchan, segments); | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Compute the shape. */ | 
					
						
							|  |  |  |   Mat4 *b_bone = runtime->bbone_pose_mats; | 
					
						
							|  |  |  |   Mat4 *b_bone_rest = runtime->bbone_rest_mats; | 
					
						
							|  |  |  |   Mat4 *b_bone_mats = runtime->bbone_deform_mats; | 
					
						
							|  |  |  |   DualQuat *b_bone_dual_quats = runtime->bbone_dual_quats; | 
					
						
							|  |  |  |   int a; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_pchan_bbone_spline_setup(pchan, false, true, b_bone); | 
					
						
							|  |  |  |   BKE_pchan_bbone_spline_setup(pchan, true, true, b_bone_rest); | 
					
						
							| 
									
										
										
										
											2013-08-19 10:14:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Compute deform matrices. */ | 
					
						
							|  |  |  |   /* first matrix is the inverse arm_mat, to bring points in local bone space
 | 
					
						
							|  |  |  |    * for finding out which segment it belongs to */ | 
					
						
							|  |  |  |   invert_m4_m4(b_bone_mats[0].mat, bone->arm_mat); | 
					
						
							| 
									
										
										
										
											2007-07-28 21:04:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* then we make the b_bone_mats:
 | 
					
						
							|  |  |  |    * - first transform to local bone space | 
					
						
							|  |  |  |    * - translate over the curve to the bbone mat space | 
					
						
							|  |  |  |    * - transform with b_bone matrix | 
					
						
							|  |  |  |    * - transform back into global space */ | 
					
						
							| 
									
										
										
										
											2007-07-28 21:04:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (a = 0; a <= bone->segments; a++) { | 
					
						
							|  |  |  |     float tmat[4][4]; | 
					
						
							| 
									
										
										
										
											2014-04-29 18:12:44 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     invert_m4_m4(tmat, b_bone_rest[a].mat); | 
					
						
							|  |  |  |     mul_m4_series(b_bone_mats[a + 1].mat, | 
					
						
							|  |  |  |                   pchan->chan_mat, | 
					
						
							|  |  |  |                   bone->arm_mat, | 
					
						
							|  |  |  |                   b_bone[a].mat, | 
					
						
							|  |  |  |                   tmat, | 
					
						
							|  |  |  |                   b_bone_mats[0].mat); | 
					
						
							| 
									
										
										
										
											2007-07-31 19:28:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     mat4_to_dquat(&b_bone_dual_quats[a], bone->arm_mat, b_bone_mats[a + 1].mat); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Copy cached B-Bone segments from one channel to another */ | 
					
						
							| 
									
										
										
										
											2018-12-02 14:32:31 +11:00
										 |  |  | void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pchan_from) | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel_Runtime *runtime = &pchan->runtime; | 
					
						
							|  |  |  |   bPoseChannel_Runtime *runtime_from = &pchan_from->runtime; | 
					
						
							|  |  |  |   int segments = runtime_from->bbone_segments; | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (segments <= 1) { | 
					
						
							| 
									
										
										
										
											2019-04-18 21:19:57 +03:00
										 |  |  |     BKE_pose_channel_free_bbone_cache(&pchan->runtime); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     allocate_bbone_cache(pchan, segments); | 
					
						
							| 
									
										
										
										
											2018-11-22 13:38:03 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     memcpy(runtime->bbone_rest_mats, runtime_from->bbone_rest_mats, sizeof(Mat4) * (1 + segments)); | 
					
						
							|  |  |  |     memcpy(runtime->bbone_pose_mats, runtime_from->bbone_pose_mats, sizeof(Mat4) * (1 + segments)); | 
					
						
							|  |  |  |     memcpy(runtime->bbone_deform_mats, | 
					
						
							|  |  |  |            runtime_from->bbone_deform_mats, | 
					
						
							|  |  |  |            sizeof(Mat4) * (2 + segments)); | 
					
						
							|  |  |  |     memcpy(runtime->bbone_dual_quats, | 
					
						
							|  |  |  |            runtime_from->bbone_dual_quats, | 
					
						
							|  |  |  |            sizeof(DualQuat) * (1 + segments)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2005-08-21 11:26:53 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  | /** Calculate index and blend factor for the two B-Bone segment nodes
 | 
					
						
							|  |  |  |  * affecting the point at 0 <= pos <= 1. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_pchan_bbone_deform_segment_index(const bPoseChannel *pchan, | 
					
						
							|  |  |  |                                           float pos, | 
					
						
							|  |  |  |                                           int *r_index, | 
					
						
							|  |  |  |                                           float *r_blend_next) | 
					
						
							| 
									
										
										
										
											2005-08-21 11:26:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int segments = pchan->bone->segments; | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   CLAMP(pos, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Calculate the indices of the 2 affecting b_bone segments.
 | 
					
						
							|  |  |  |    * Integer part is the first segment's index. | 
					
						
							|  |  |  |    * Integer part plus 1 is the second segment's index. | 
					
						
							|  |  |  |    * Fractional part is the blend factor. */ | 
					
						
							|  |  |  |   float pre_blend = pos * (float)segments; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int index = (int)floorf(pre_blend); | 
					
						
							|  |  |  |   float blend = pre_blend - index; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   CLAMP(index, 0, segments); | 
					
						
							|  |  |  |   CLAMP(blend, 0.0f, 1.0f); | 
					
						
							| 
									
										
										
										
											2018-06-17 17:05:51 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *r_index = index; | 
					
						
							|  |  |  |   *r_blend_next = blend; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Add the effect of one bone or B-Bone segment to the accumulated result. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void pchan_deform_accumulate(const DualQuat *deform_dq, | 
					
						
							|  |  |  |                                     const float deform_mat[4][4], | 
					
						
							|  |  |  |                                     const float co_in[3], | 
					
						
							|  |  |  |                                     float weight, | 
					
						
							|  |  |  |                                     float co_accum[3], | 
					
						
							|  |  |  |                                     DualQuat *dq_accum, | 
					
						
							|  |  |  |                                     float mat_accum[3][3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (weight == 0.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (dq_accum) { | 
					
						
							|  |  |  |     BLI_assert(!co_accum); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     add_weighted_dq_dq(dq_accum, deform_dq, weight); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     float tmp[3]; | 
					
						
							|  |  |  |     mul_v3_m4v3(tmp, deform_mat, co_in); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     sub_v3_v3(tmp, co_in); | 
					
						
							|  |  |  |     madd_v3_v3fl(co_accum, tmp, weight); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (mat_accum) { | 
					
						
							|  |  |  |       float tmpmat[3][3]; | 
					
						
							|  |  |  |       copy_m3_m4(tmpmat, deform_mat); | 
					
						
							| 
									
										
										
										
											2007-07-28 21:04:30 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       madd_m3_m3m3fl(mat_accum, mat_accum, tmpmat, weight); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | static void b_bone_deform(const bPoseChannel *pchan, | 
					
						
							|  |  |  |                           const float co[3], | 
					
						
							|  |  |  |                           float weight, | 
					
						
							|  |  |  |                           float vec[3], | 
					
						
							|  |  |  |                           DualQuat *dq, | 
					
						
							|  |  |  |                           float defmat[3][3]) | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const DualQuat *quats = pchan->runtime.bbone_dual_quats; | 
					
						
							|  |  |  |   const Mat4 *mats = pchan->runtime.bbone_deform_mats; | 
					
						
							|  |  |  |   const float(*mat)[4] = mats[0].mat; | 
					
						
							|  |  |  |   float blend, y; | 
					
						
							|  |  |  |   int index; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Transform co to bone space and get its y component. */ | 
					
						
							|  |  |  |   y = mat[0][1] * co[0] + mat[1][1] * co[1] + mat[2][1] * co[2] + mat[3][1]; | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Calculate the indices of the 2 affecting b_bone segments. */ | 
					
						
							|  |  |  |   BKE_pchan_bbone_deform_segment_index(pchan, y / pchan->bone->length, &index, &blend); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   pchan_deform_accumulate( | 
					
						
							|  |  |  |       &quats[index], mats[index + 1].mat, co, weight * (1.0f - blend), vec, dq, defmat); | 
					
						
							|  |  |  |   pchan_deform_accumulate( | 
					
						
							|  |  |  |       &quats[index + 1], mats[index + 2].mat, co, weight * blend, vec, dq, defmat); | 
					
						
							| 
									
										
										
										
											2019-04-05 18:40:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Armature "Envelope" editing.
For defining the deformation distances of Bones, three values are being
used now. The bone tip and root radius define the bone-shape itself and the
"dist" defines the soft area around it. A full (user) doc is in CMS here;
http://www.blender3d.org/cms/Armature_Envelopes.647.0.html
Note: todo still is allowing both Vertex Deform Groups and these Envelopes
together (and or per Bone).
Also part of this commit is:
- New: Hiding bones in EditMode. This is a separate 'hide flag', so you can
  keep the PoseMode hidden Bones separate from EditMode.
  (In the future we should do some kind of bone-grouping or so)
- While transform(), the hotkeys G,R,S only switch mode when the previous
  mode was compatible. Caused conflicts with Crease/BoneDist/etc.
- Deleting the last VertexGroup now also deletes the entire Mesh 'dvert'
  data. Sounds logical, but remember that VertexGroups are partial on a
  Mesh, partial on Object. Weird design decision though...
  Anyhoo, at this moment the only way to have Bone Envelopes deform, is
  by deleting all VertexGroups!
- In PoseMode, the hotkey ALT+S now does both B-Bone size or Envelope,
  depending draw type.
- In EditMode, Extrude now also works when only Root points were selected.
- Weight editing is also symmetrical btw, with the "X-axis Mirror" option
  set.
											
										 
											2005-08-19 12:35:15 +00:00
										 |  |  | /* using vec with dist to bone b1 - b2 */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | float distfactor_to_bone( | 
					
						
							|  |  |  |     const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float dist_sq; | 
					
						
							|  |  |  |   float bdelta[3]; | 
					
						
							|  |  |  |   float pdelta[3]; | 
					
						
							|  |  |  |   float hsqr, a, l, rad; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sub_v3_v3v3(bdelta, b2, b1); | 
					
						
							|  |  |  |   l = normalize_v3(bdelta); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   sub_v3_v3v3(pdelta, vec, b1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   a = dot_v3v3(bdelta, pdelta); | 
					
						
							|  |  |  |   hsqr = len_squared_v3(pdelta); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (a < 0.0f) { | 
					
						
							|  |  |  |     /* If we're past the end of the bone, do a spherical field attenuation thing */ | 
					
						
							|  |  |  |     dist_sq = len_squared_v3v3(b1, vec); | 
					
						
							|  |  |  |     rad = rad1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (a > l) { | 
					
						
							|  |  |  |     /* If we're past the end of the bone, do a spherical field attenuation thing */ | 
					
						
							|  |  |  |     dist_sq = len_squared_v3v3(b2, vec); | 
					
						
							|  |  |  |     rad = rad2; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     dist_sq = (hsqr - (a * a)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (l != 0.0f) { | 
					
						
							|  |  |  |       rad = a / l; | 
					
						
							|  |  |  |       rad = rad * rad2 + (1.0f - rad) * rad1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       rad = rad1; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   a = rad * rad; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (dist_sq < a) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return 1.0f; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   else { | 
					
						
							|  |  |  |     l = rad + rdist; | 
					
						
							|  |  |  |     l *= l; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (rdist == 0.0f || dist_sq >= l) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     else { | 
					
						
							|  |  |  |       a = sqrtf(dist_sq) - rad; | 
					
						
							|  |  |  |       return 1.0f - (a * a) / (rdist * rdist); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-18 23:17:04 +03:00
										 |  |  | static float dist_bone_deform( | 
					
						
							|  |  |  |     bPoseChannel *pchan, float vec[3], DualQuat *dq, float mat[3][3], const float co[3]) | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   Bone *bone = pchan->bone; | 
					
						
							|  |  |  |   float fac, contrib = 0.0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (bone == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return 0.0f; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   fac = distfactor_to_bone( | 
					
						
							|  |  |  |       co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fac > 0.0f) { | 
					
						
							|  |  |  |     fac *= bone->weight; | 
					
						
							|  |  |  |     contrib = fac; | 
					
						
							|  |  |  |     if (contrib > 0.0f) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         b_bone_deform(pchan, co, fac, vec, dq, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-18 23:17:04 +03:00
										 |  |  |         pchan_deform_accumulate( | 
					
						
							|  |  |  |             &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, fac, vec, dq, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return contrib; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void pchan_bone_deform(bPoseChannel *pchan, | 
					
						
							|  |  |  |                               float weight, | 
					
						
							|  |  |  |                               float vec[3], | 
					
						
							|  |  |  |                               DualQuat *dq, | 
					
						
							|  |  |  |                               float mat[3][3], | 
					
						
							|  |  |  |                               const float co[3], | 
					
						
							|  |  |  |                               float *contrib) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Bone *bone = pchan->bone; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (!weight) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (bone->segments > 1 && pchan->runtime.bbone_segments == bone->segments) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     b_bone_deform(pchan, co, weight, vec, dq, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2019-04-18 23:17:04 +03:00
										 |  |  |     pchan_deform_accumulate( | 
					
						
							|  |  |  |         &pchan->runtime.deform_dual_quat, pchan->chan_mat, co, weight, vec, dq, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   (*contrib) += weight; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  | typedef struct ArmatureUserdata { | 
					
						
							|  |  |  |   Object *armOb; | 
					
						
							|  |  |  |   Object *target; | 
					
						
							|  |  |  |   const Mesh *mesh; | 
					
						
							|  |  |  |   float (*vertexCos)[3]; | 
					
						
							|  |  |  |   float (*defMats)[3][3]; | 
					
						
							|  |  |  |   float (*prevCos)[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool use_envelope; | 
					
						
							|  |  |  |   bool use_quaternion; | 
					
						
							|  |  |  |   bool invert_vgroup; | 
					
						
							|  |  |  |   bool use_dverts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int armature_def_nr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int target_totvert; | 
					
						
							|  |  |  |   MDeformVert *dverts; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int defbase_tot; | 
					
						
							|  |  |  |   bPoseChannel **defnrToPC; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float premat[4][4]; | 
					
						
							|  |  |  |   float postmat[4][4]; | 
					
						
							|  |  |  | } ArmatureUserdata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void armature_vert_task(void *__restrict userdata, | 
					
						
							|  |  |  |                                const int i, | 
					
						
							| 
									
										
										
										
											2019-07-30 14:56:47 +02:00
										 |  |  |                                const TaskParallelTLS *__restrict UNUSED(tls)) | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  | { | 
					
						
							|  |  |  |   const ArmatureUserdata *data = userdata; | 
					
						
							|  |  |  |   float(*const vertexCos)[3] = data->vertexCos; | 
					
						
							|  |  |  |   float(*const defMats)[3][3] = data->defMats; | 
					
						
							|  |  |  |   float(*const prevCos)[3] = data->prevCos; | 
					
						
							|  |  |  |   const bool use_envelope = data->use_envelope; | 
					
						
							|  |  |  |   const bool use_quaternion = data->use_quaternion; | 
					
						
							|  |  |  |   const bool use_dverts = data->use_dverts; | 
					
						
							|  |  |  |   const int armature_def_nr = data->armature_def_nr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MDeformVert *dvert; | 
					
						
							|  |  |  |   DualQuat sumdq, *dq = NULL; | 
					
						
							|  |  |  |   bPoseChannel *pchan; | 
					
						
							|  |  |  |   float *co, dco[3]; | 
					
						
							|  |  |  |   float sumvec[3], summat[3][3]; | 
					
						
							|  |  |  |   float *vec = NULL, (*smat)[3] = NULL; | 
					
						
							|  |  |  |   float contrib = 0.0f; | 
					
						
							|  |  |  |   float armature_weight = 1.0f; /* default to 1 if no overall def group */ | 
					
						
							|  |  |  |   float prevco_weight = 1.0f;   /* weight for optional cached vertexcos */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (use_quaternion) { | 
					
						
							|  |  |  |     memset(&sumdq, 0, sizeof(DualQuat)); | 
					
						
							|  |  |  |     dq = &sumdq; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     sumvec[0] = sumvec[1] = sumvec[2] = 0.0f; | 
					
						
							|  |  |  |     vec = sumvec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (defMats) { | 
					
						
							|  |  |  |       zero_m3(summat); | 
					
						
							|  |  |  |       smat = summat; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (use_dverts || armature_def_nr != -1) { | 
					
						
							|  |  |  |     if (data->mesh) { | 
					
						
							|  |  |  |       BLI_assert(i < data->mesh->totvert); | 
					
						
							| 
									
										
										
										
											2019-07-10 16:03:19 +02:00
										 |  |  |       if (data->mesh->dvert != NULL) { | 
					
						
							|  |  |  |         dvert = data->mesh->dvert + i; | 
					
						
							| 
									
										
										
										
											2019-07-11 09:14:31 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-07-10 16:03:19 +02:00
										 |  |  |         dvert = NULL; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (data->dverts && i < data->target_totvert) { | 
					
						
							|  |  |  |       dvert = data->dverts + i; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       dvert = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     dvert = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (armature_def_nr != -1 && dvert) { | 
					
						
							|  |  |  |     armature_weight = defvert_find_weight(dvert, armature_def_nr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data->invert_vgroup) { | 
					
						
							|  |  |  |       armature_weight = 1.0f - armature_weight; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* hackish: the blending factor can be used for blending with prevCos too */ | 
					
						
							|  |  |  |     if (prevCos) { | 
					
						
							|  |  |  |       prevco_weight = armature_weight; | 
					
						
							|  |  |  |       armature_weight = 1.0f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* check if there's any  point in calculating for this vert */ | 
					
						
							|  |  |  |   if (armature_weight == 0.0f) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get the coord we work on */ | 
					
						
							|  |  |  |   co = prevCos ? prevCos[i] : vertexCos[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Apply the object's matrix */ | 
					
						
							|  |  |  |   mul_m4_v3(data->premat, co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (use_dverts && dvert && dvert->totweight) { /* use weight groups ? */ | 
					
						
							|  |  |  |     MDeformWeight *dw = dvert->dw; | 
					
						
							|  |  |  |     int deformed = 0; | 
					
						
							|  |  |  |     unsigned int j; | 
					
						
							|  |  |  |     float acum_weight = 0; | 
					
						
							|  |  |  |     for (j = dvert->totweight; j != 0; j--, dw++) { | 
					
						
							|  |  |  |       const int index = dw->def_nr; | 
					
						
							|  |  |  |       if (index >= 0 && index < data->defbase_tot && (pchan = data->defnrToPC[index])) { | 
					
						
							|  |  |  |         float weight = dw->weight; | 
					
						
							|  |  |  |         Bone *bone = pchan->bone; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         deformed = 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (bone && bone->flag & BONE_MULT_VG_ENV) { | 
					
						
							|  |  |  |           weight *= distfactor_to_bone( | 
					
						
							|  |  |  |               co, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* check limit of weight */ | 
					
						
							|  |  |  |         if (data->target->type == OB_GPENCIL) { | 
					
						
							|  |  |  |           if (acum_weight + weight >= 1.0f) { | 
					
						
							|  |  |  |             weight = 1.0f - acum_weight; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           acum_weight += weight; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pchan_bone_deform(pchan, weight, vec, dq, smat, co, &contrib); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* if acumulated weight limit exceed, exit loop */ | 
					
						
							|  |  |  |         if ((data->target->type == OB_GPENCIL) && (acum_weight >= 1.0f)) { | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* if there are vertexgroups but not groups with bones
 | 
					
						
							|  |  |  |      * (like for softbody groups) */ | 
					
						
							|  |  |  |     if (deformed == 0 && use_envelope) { | 
					
						
							|  |  |  |       for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |         if (!(pchan->bone->flag & BONE_NO_DEFORM)) { | 
					
						
							|  |  |  |           contrib += dist_bone_deform(pchan, vec, dq, smat, co); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (use_envelope) { | 
					
						
							|  |  |  |     for (pchan = data->armOb->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |       if (!(pchan->bone->flag & BONE_NO_DEFORM)) { | 
					
						
							|  |  |  |         contrib += dist_bone_deform(pchan, vec, dq, smat, co); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* actually should be EPSILON? weight values and contrib can be like 10e-39 small */ | 
					
						
							|  |  |  |   if (contrib > 0.0001f) { | 
					
						
							|  |  |  |     if (use_quaternion) { | 
					
						
							|  |  |  |       normalize_dq(dq, contrib); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (armature_weight != 1.0f) { | 
					
						
							|  |  |  |         copy_v3_v3(dco, co); | 
					
						
							|  |  |  |         mul_v3m3_dq(dco, (defMats) ? summat : NULL, dq); | 
					
						
							|  |  |  |         sub_v3_v3(dco, co); | 
					
						
							|  |  |  |         mul_v3_fl(dco, armature_weight); | 
					
						
							|  |  |  |         add_v3_v3(co, dco); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         mul_v3m3_dq(co, (defMats) ? summat : NULL, dq); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       smat = summat; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       mul_v3_fl(vec, armature_weight / contrib); | 
					
						
							|  |  |  |       add_v3_v3v3(co, vec, co); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (defMats) { | 
					
						
							|  |  |  |       float pre[3][3], post[3][3], tmpmat[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy_m3_m4(pre, data->premat); | 
					
						
							|  |  |  |       copy_m3_m4(post, data->postmat); | 
					
						
							|  |  |  |       copy_m3_m3(tmpmat, defMats[i]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!use_quaternion) { /* quaternion already is scale corrected */ | 
					
						
							|  |  |  |         mul_m3_fl(smat, armature_weight / contrib); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mul_m3_series(defMats[i], post, smat, pre, tmpmat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* always, check above code */ | 
					
						
							|  |  |  |   mul_m4_v3(data->postmat, co); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* interpolate with previous modifier position using weight group */ | 
					
						
							|  |  |  |   if (prevCos) { | 
					
						
							|  |  |  |     float mw = 1.0f - prevco_weight; | 
					
						
							|  |  |  |     vertexCos[i][0] = prevco_weight * vertexCos[i][0] + mw * co[0]; | 
					
						
							|  |  |  |     vertexCos[i][1] = prevco_weight * vertexCos[i][1] + mw * co[1]; | 
					
						
							|  |  |  |     vertexCos[i][2] = prevco_weight * vertexCos[i][2] + mw * co[2]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void armature_deform_verts(Object *armOb, | 
					
						
							|  |  |  |                            Object *target, | 
					
						
							|  |  |  |                            const Mesh *mesh, | 
					
						
							|  |  |  |                            float (*vertexCos)[3], | 
					
						
							|  |  |  |                            float (*defMats)[3][3], | 
					
						
							|  |  |  |                            int numVerts, | 
					
						
							|  |  |  |                            int deformflag, | 
					
						
							|  |  |  |                            float (*prevCos)[3], | 
					
						
							|  |  |  |                            const char *defgrp_name, | 
					
						
							|  |  |  |                            bGPDstroke *gps) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bArmature *arm = armOb->data; | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  |   bPoseChannel **defnrToPC = NULL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MDeformVert *dverts = NULL; | 
					
						
							|  |  |  |   bDeformGroup *dg; | 
					
						
							|  |  |  |   const bool use_envelope = (deformflag & ARM_DEF_ENVELOPE) != 0; | 
					
						
							|  |  |  |   const bool use_quaternion = (deformflag & ARM_DEF_QUATERNION) != 0; | 
					
						
							|  |  |  |   const bool invert_vgroup = (deformflag & ARM_DEF_INVERT_VGROUP) != 0; | 
					
						
							|  |  |  |   int defbase_tot = 0;       /* safety for vertexgroup index overflow */ | 
					
						
							|  |  |  |   int i, target_totvert = 0; /* safety for vertexgroup overflow */ | 
					
						
							|  |  |  |   bool use_dverts = false; | 
					
						
							|  |  |  |   int armature_def_nr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* in editmode, or not an armature */ | 
					
						
							|  |  |  |   if (arm->edbo || (armOb->pose == NULL)) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((armOb->pose->flag & POSE_RECALC) != 0) { | 
					
						
							|  |  |  |     CLOG_ERROR(&LOG, | 
					
						
							|  |  |  |                "Trying to evaluate influence of armature '%s' which needs Pose recalc!", | 
					
						
							|  |  |  |                armOb->id.name); | 
					
						
							|  |  |  |     BLI_assert(0); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get the def_nr for the overall armature vertex group if present */ | 
					
						
							|  |  |  |   armature_def_nr = defgroup_name_index(target, defgrp_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { | 
					
						
							|  |  |  |     defbase_tot = BLI_listbase_count(&target->defbase); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (target->type == OB_MESH) { | 
					
						
							|  |  |  |       Mesh *me = target->data; | 
					
						
							|  |  |  |       dverts = me->dvert; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (dverts) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         target_totvert = me->totvert; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (target->type == OB_LATTICE) { | 
					
						
							|  |  |  |       Lattice *lt = target->data; | 
					
						
							|  |  |  |       dverts = lt->dvert; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (dverts) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         target_totvert = lt->pntsu * lt->pntsv * lt->pntsw; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     else if (target->type == OB_GPENCIL) { | 
					
						
							|  |  |  |       dverts = gps->dvert; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (dverts) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         target_totvert = gps->totpoints; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get a vertex-deform-index to posechannel array */ | 
					
						
							|  |  |  |   if (deformflag & ARM_DEF_VGROUP) { | 
					
						
							|  |  |  |     if (ELEM(target->type, OB_MESH, OB_LATTICE, OB_GPENCIL)) { | 
					
						
							|  |  |  |       /* if we have a Mesh, only use dverts if it has them */ | 
					
						
							|  |  |  |       if (mesh) { | 
					
						
							|  |  |  |         use_dverts = (mesh->dvert != NULL); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (dverts) { | 
					
						
							|  |  |  |         use_dverts = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (use_dverts) { | 
					
						
							|  |  |  |         defnrToPC = MEM_callocN(sizeof(*defnrToPC) * defbase_tot, "defnrToBone"); | 
					
						
							|  |  |  |         /* TODO(sergey): Some considerations here:
 | 
					
						
							|  |  |  |          * | 
					
						
							|  |  |  |          * - Check whether keeping this consistent across frames gives speedup. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         for (i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) { | 
					
						
							|  |  |  |           defnrToPC[i] = BKE_pose_channel_find_name(armOb->pose, dg->name); | 
					
						
							|  |  |  |           /* exclude non-deforming bones */ | 
					
						
							|  |  |  |           if (defnrToPC[i]) { | 
					
						
							|  |  |  |             if (defnrToPC[i]->bone->flag & BONE_NO_DEFORM) { | 
					
						
							|  |  |  |               defnrToPC[i] = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  |   ArmatureUserdata data = {.armOb = armOb, | 
					
						
							|  |  |  |                            .target = target, | 
					
						
							|  |  |  |                            .mesh = mesh, | 
					
						
							|  |  |  |                            .vertexCos = vertexCos, | 
					
						
							|  |  |  |                            .defMats = defMats, | 
					
						
							|  |  |  |                            .prevCos = prevCos, | 
					
						
							|  |  |  |                            .use_envelope = use_envelope, | 
					
						
							|  |  |  |                            .use_quaternion = use_quaternion, | 
					
						
							|  |  |  |                            .invert_vgroup = invert_vgroup, | 
					
						
							|  |  |  |                            .use_dverts = use_dverts, | 
					
						
							|  |  |  |                            .armature_def_nr = armature_def_nr, | 
					
						
							|  |  |  |                            .target_totvert = target_totvert, | 
					
						
							|  |  |  |                            .dverts = dverts, | 
					
						
							|  |  |  |                            .defbase_tot = defbase_tot, | 
					
						
							|  |  |  |                            .defnrToPC = defnrToPC}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   float obinv[4][4]; | 
					
						
							|  |  |  |   invert_m4_m4(obinv, target->obmat); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  |   mul_m4_m4m4(data.postmat, obinv, armOb->obmat); | 
					
						
							|  |  |  |   invert_m4_m4(data.premat, data.postmat); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 14:56:47 +02:00
										 |  |  |   TaskParallelSettings settings; | 
					
						
							| 
									
										
										
										
											2019-04-28 15:05:13 +03:00
										 |  |  |   BLI_parallel_range_settings_defaults(&settings); | 
					
						
							|  |  |  |   settings.min_iter_per_thread = 32; | 
					
						
							|  |  |  |   BLI_task_parallel_range(0, numVerts, &data, armature_vert_task, &settings); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (defnrToPC) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     MEM_freeN(defnrToPC); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2005-08-11 06:44:32 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* ************ END Armature Deform ******************* */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void get_objectspace_bone_matrix(struct Bone *bone, | 
					
						
							|  |  |  |                                  float M_accumulatedMatrix[4][4], | 
					
						
							|  |  |  |                                  int UNUSED(root), | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  |                                  int UNUSED(posed)) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_m4_m4(M_accumulatedMatrix, bone->arm_mat); | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | /* **************** Space to Space API ****************** */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Convert World-Space Matrix to Pose-Space Matrix */ | 
					
						
							| 
									
										
										
										
											2012-12-11 14:29:01 +00:00
										 |  |  | void BKE_armature_mat_world_to_pose(Object *ob, float inmat[4][4], float outmat[4][4]) | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float obmat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* prevent crashes */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (ob == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* get inverse of (armature) object's matrix  */ | 
					
						
							|  |  |  |   invert_m4_m4(obmat, ob->obmat); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* multiply given matrix by object's-inverse to find pose-space matrix */ | 
					
						
							|  |  |  |   mul_m4_m4m4(outmat, inmat, obmat); | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-04 04:35:12 +00:00
										 |  |  | /* Convert World-Space Location to Pose-Space Location
 | 
					
						
							| 
									
										
										
										
											2007-02-05 01:28:14 +00:00
										 |  |  |  * NOTE: this cannot be used to convert to pose-space location of the supplied | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  |  *       pose-channel into its local space (i.e. 'visual'-keyframing) */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outloc[3]) | 
					
						
							| 
									
										
										
										
											2007-02-05 01:28:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float xLocMat[4][4]; | 
					
						
							|  |  |  |   float nLocMat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* build matrix for location */ | 
					
						
							|  |  |  |   unit_m4(xLocMat); | 
					
						
							|  |  |  |   copy_v3_v3(xLocMat[3], inloc); | 
					
						
							| 
									
										
										
										
											2007-02-05 01:28:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* get bone-space cursor matrix and extract location */ | 
					
						
							|  |  |  |   BKE_armature_mat_world_to_pose(ob, xLocMat, nLocMat); | 
					
						
							|  |  |  |   copy_v3_v3(outloc, nLocMat[3]); | 
					
						
							| 
									
										
										
										
											2007-02-05 01:28:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | /* Simple helper, computes the offset bone matrix.
 | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  |  *     offs_bone = yoffs(b-1) + root(b) + bonemat(b). */ | 
					
						
							| 
									
										
										
										
											2018-12-20 17:30:04 +11:00
										 |  |  | void BKE_bone_offset_matrix_get(const Bone *bone, float offs_bone[4][4]) | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_assert(bone->parent != NULL); | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Bone transform itself. */ | 
					
						
							|  |  |  |   copy_m4_m3(offs_bone, bone->bone_mat); | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* The bone's root offset (is in the parent's coordinate system). */ | 
					
						
							|  |  |  |   copy_v3_v3(offs_bone[3], bone->head); | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* Get the length translation of parent (length along y axis). */ | 
					
						
							|  |  |  |   offs_bone[3][1] += bone->parent->length; | 
					
						
							| 
									
										
											  
											
												Armature pose evaluation: more factorization of code.
Now constraints' space conversion code also uses generic armature_mat_(pose_to_bone/bone_to_pose). Previous own function (constraint_pchan_diff_mat) was somewhat inconsistent too with Hinge/NoScale/LocalLocation options...
As with previous similar changes, this might break some old rigs, in very specific cases (when constraint-evaluating an hinge/noscale/local_location bone in local space).
In the same part of code, removed unnecessary matrices copying, mult_m4_m4m4 can take the same matrix as input and output, nowadays...
Also found a bug-generator weakness in those armature_mat_ functions (if both input and output mat where the same, result was wrong, now systematically copying input mat, as done in LIB's matrix funcs).
Finally, factorized offset bone matrix generation into its own small function too, as it is used in two different places in armature.c (pchan_to_pose_mat itself, and restpose's where_is_armature_bone).
Note: I think all parts of blender's code related to that topic have now been tackled, but yet have to check BGE, it’s probably using that stuff too, one way or the other...
											
										 
											2012-02-22 20:06:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  | /* Construct the matrices (rot/scale and loc)
 | 
					
						
							|  |  |  |  * to apply the PoseChannels into the armature (object) space. | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  |  * I.e. (roughly) the "pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)" in the | 
					
						
							|  |  |  |  *     pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) | 
					
						
							|  |  |  |  * ...function. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * This allows to get the transformations of a bone in its object space, | 
					
						
							|  |  |  |  * *before* constraints (and IK) get applied (used by pose evaluation code). | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  |  * And reverse: to find pchan transformations needed to place a bone at a given loc/rot/scale | 
					
						
							|  |  |  |  * in object space (used by interactive transform, and snapping code). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location matrix | 
					
						
							|  |  |  |  * will differ from the rotation/scale matrix... | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * NOTE: This cannot be used to convert to pose-space transforms of the supplied | 
					
						
							|  |  |  |  *       pose-channel into its local space (i.e. 'visual'-keyframing). | 
					
						
							|  |  |  |  *       (note: I don't understand that, so I keep it :p --mont29). | 
					
						
							| 
									
										
										
										
											2007-01-07 22:30:44 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, | 
					
						
							|  |  |  |                                                BoneParentTransform *r_bpt) | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const Bone *bone, *parbone; | 
					
						
							|  |  |  |   const bPoseChannel *parchan; | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* set up variables for quicker access below */ | 
					
						
							|  |  |  |   bone = pchan->bone; | 
					
						
							|  |  |  |   parbone = bone->parent; | 
					
						
							|  |  |  |   parchan = pchan->parent; | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (parchan) { | 
					
						
							|  |  |  |     float offs_bone[4][4]; | 
					
						
							|  |  |  |     /* yoffs(b-1) + root(b) + bonemat(b). */ | 
					
						
							|  |  |  |     BKE_bone_offset_matrix_get(bone, offs_bone); | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     BKE_bone_parent_transform_calc_from_matrices(bone->flag, | 
					
						
							|  |  |  |                                                  bone->inherit_scale_mode, | 
					
						
							|  |  |  |                                                  offs_bone, | 
					
						
							|  |  |  |                                                  parbone->arm_mat, | 
					
						
							|  |  |  |                                                  parchan->pose_mat, | 
					
						
							|  |  |  |                                                  r_bpt); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     BKE_bone_parent_transform_calc_from_matrices( | 
					
						
							|  |  |  |         bone->flag, bone->inherit_scale_mode, bone->arm_mat, NULL, NULL, r_bpt); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Compute the parent transform using data decoupled from specific data structures.
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * bone_flag: Bone->flag containing settings | 
					
						
							|  |  |  |  * offs_bone: delta from parent to current arm_mat (or just arm_mat if no parent) | 
					
						
							|  |  |  |  * parent_arm_mat, parent_pose_mat: arm_mat and pose_mat of parent, or NULL | 
					
						
							|  |  |  |  * r_bpt: OUTPUT parent transform */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |                                                   int inherit_scale_mode, | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |                                                   const float offs_bone[4][4], | 
					
						
							|  |  |  |                                                   const float parent_arm_mat[4][4], | 
					
						
							|  |  |  |                                                   const float parent_pose_mat[4][4], | 
					
						
							|  |  |  |                                                   BoneParentTransform *r_bpt) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (parent_pose_mat) { | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     const bool use_rotation = (bone_flag & BONE_HINGE) == 0; | 
					
						
							|  |  |  |     const bool full_transform = use_rotation && inherit_scale_mode == BONE_INHERIT_SCALE_FULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* Compose the rotscale matrix for this bone. */ | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     if (full_transform) { | 
					
						
							|  |  |  |       /* Parent pose rotation and scale. */ | 
					
						
							|  |  |  |       mul_m4_m4m4(r_bpt->rotscale_mat, parent_pose_mat, offs_bone); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       float tmat[4][4], tscale[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |       /* If using parent pose rotation: */ | 
					
						
							|  |  |  |       if (use_rotation) { | 
					
						
							|  |  |  |         copy_m4_m4(tmat, parent_pose_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Normalize the matrix when needed. */ | 
					
						
							|  |  |  |         switch (inherit_scale_mode) { | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_FULL: | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_FIX_SHEAR: | 
					
						
							|  |  |  |             /* Keep scale and shear. */ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_NONE: | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_AVERAGE: | 
					
						
							|  |  |  |             /* Remove scale and shear from parent. */ | 
					
						
							|  |  |  |             orthogonalize_m4_stable(tmat, 1, true); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_NONE_LEGACY: | 
					
						
							|  |  |  |             /* Remove only scale - bad legacy way. */ | 
					
						
							|  |  |  |             normalize_m4(tmat); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           default: | 
					
						
							|  |  |  |             BLI_assert(false); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /* If removing parent pose rotation: */ | 
					
						
							|  |  |  |       else { | 
					
						
							|  |  |  |         copy_m4_m4(tmat, parent_arm_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Copy the parent scale when needed. */ | 
					
						
							|  |  |  |         switch (inherit_scale_mode) { | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_FULL: | 
					
						
							|  |  |  |             /* Ignore effects of shear. */ | 
					
						
							|  |  |  |             mat4_to_size(tscale, parent_pose_mat); | 
					
						
							|  |  |  |             rescale_m4(tmat, tscale); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_FIX_SHEAR: | 
					
						
							|  |  |  |             /* Take the effects of parent shear into account to get exact volume. */ | 
					
						
							|  |  |  |             mat4_to_size_fix_shear(tscale, parent_pose_mat); | 
					
						
							|  |  |  |             rescale_m4(tmat, tscale); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_NONE: | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_AVERAGE: | 
					
						
							|  |  |  |           case BONE_INHERIT_SCALE_NONE_LEGACY: | 
					
						
							|  |  |  |             /* Keep unscaled. */ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           default: | 
					
						
							|  |  |  |             BLI_assert(false); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |       /* Apply the average parent scale when needed. */ | 
					
						
							|  |  |  |       if (inherit_scale_mode == BONE_INHERIT_SCALE_AVERAGE) { | 
					
						
							|  |  |  |         mul_mat3_m4_fl(tmat, cbrtf(fabsf(mat4_to_volume_scale(parent_pose_mat)))); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       mul_m4_m4m4(r_bpt->rotscale_mat, tmat, offs_bone); | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* Remove remaining shear when needed, preserving volume. */ | 
					
						
							|  |  |  |       if (inherit_scale_mode == BONE_INHERIT_SCALE_FIX_SHEAR) { | 
					
						
							|  |  |  |         orthogonalize_m4_stable(r_bpt->rotscale_mat, 1, false); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Compose the loc matrix for this bone. */ | 
					
						
							|  |  |  |     /* NOTE: That version does not modify bone's loc when HINGE/NO_SCALE options are set. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* In this case, use the object's space *orientation*. */ | 
					
						
							|  |  |  |     if (bone_flag & BONE_NO_LOCAL_LOCATION) { | 
					
						
							|  |  |  |       /* XXX I'm sure that code can be simplified! */ | 
					
						
							|  |  |  |       float bone_loc[4][4], bone_rotscale[3][3], tmat4[4][4], tmat3[3][3]; | 
					
						
							|  |  |  |       unit_m4(bone_loc); | 
					
						
							|  |  |  |       unit_m4(r_bpt->loc_mat); | 
					
						
							|  |  |  |       unit_m4(tmat4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mul_v3_m4v3(bone_loc[3], parent_pose_mat, offs_bone[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       unit_m3(bone_rotscale); | 
					
						
							|  |  |  |       copy_m3_m4(tmat3, parent_pose_mat); | 
					
						
							|  |  |  |       mul_m3_m3m3(bone_rotscale, tmat3, bone_rotscale); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       copy_m4_m3(tmat4, bone_rotscale); | 
					
						
							|  |  |  |       mul_m4_m4m4(r_bpt->loc_mat, bone_loc, tmat4); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Those flags do not affect position, use plain parent transform space! */ | 
					
						
							| 
									
										
											  
											
												Armature: add Inherit Scale options to remove shear or average the scale.
As an inherent property of matrix-based transformation math, non-
uniform scaling of a parent bone induces shear into the transform
matrix of any rotated child. Such matrices cannot be cleanly
decomposed into a combination of location/rotation/scale, which
causes issues for rigging and animation tools.
Blender bones have options to exclude rotation and/or scale from the
inherited transformation, but don't have any support for removing the
often undesired shear component. That goal requires replacing simple
parenting with a combination of multiple bones and constraints. The
same is true about the goal of inheriting some scale, but completely
avoiding shear.
This patch replaces the old Inherit Scale checkbox with a enum that
supports multiple options:
* Full: inherit all effects of scale, like with enabled Inherit Scale.
* Fix Shear: removes shear from the final inherited transformation.
  The cleanup math is specifically designed to preserve the main
  axis of the bone, its length and total volume, and minimally
  affect roll on average. It however will not prevent reappearance
  of shear due to local rotation of the child or its children.
* Average: inherit uniform scale that represents the parent volume.
  This is the simplest foolproof solution that will inherit some
  scale without ever causing shear.
* None: completely remove scale and shear.
* None (Legacy): old disabled Inherit Scale checkbox.
  This mode does not handle parent shear in any way, so the child
  is likely to end up having both scale and shear. It is retained
  for backward compatibility.
Since many rigging-related addons access the use_inherit_scale
property from Python, it is retained as a backward compatibility
stub that provides the old functionality.
As a side effect of reworking the code, this also fixes a matrix
multiplication order bug in the Inherit Rotation code, which caused
the parent local scale to be applied in world space. In rigger
opinion this option is useless in production rigs, so this fix
should not be a problem.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D5588
											
										 
											2019-09-04 10:10:27 +03:00
										 |  |  |     else if (!full_transform) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       mul_m4_m4m4(r_bpt->loc_mat, parent_pose_mat, offs_bone); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |     /* Else (i.e. default, usual case),
 | 
					
						
							|  |  |  |      * just use the same matrix for rotation/scaling, and location. */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       copy_m4_m4(r_bpt->loc_mat, r_bpt->rotscale_mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   /* Root bones. */ | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* Rotation/scaling. */ | 
					
						
							|  |  |  |     copy_m4_m4(r_bpt->rotscale_mat, offs_bone); | 
					
						
							|  |  |  |     /* Translation. */ | 
					
						
							|  |  |  |     if (bone_flag & BONE_NO_LOCAL_LOCATION) { | 
					
						
							|  |  |  |       /* Translation of arm_mat, without the rotation. */ | 
					
						
							|  |  |  |       unit_m4(r_bpt->loc_mat); | 
					
						
							|  |  |  |       copy_v3_v3(r_bpt->loc_mat[3], offs_bone[3]); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       copy_m4_m4(r_bpt->loc_mat, r_bpt->rotscale_mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-20 17:30:04 +11:00
										 |  |  | void BKE_bone_parent_transform_clear(struct BoneParentTransform *bpt) | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   unit_m4(bpt->rotscale_mat); | 
					
						
							|  |  |  |   unit_m4(bpt->loc_mat); | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-20 17:30:04 +11:00
										 |  |  | void BKE_bone_parent_transform_invert(struct BoneParentTransform *bpt) | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   invert_m4(bpt->rotscale_mat); | 
					
						
							|  |  |  |   invert_m4(bpt->loc_mat); | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_bone_parent_transform_combine(const struct BoneParentTransform *in1, | 
					
						
							|  |  |  |                                        const struct BoneParentTransform *in2, | 
					
						
							|  |  |  |                                        struct BoneParentTransform *result) | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   mul_m4_m4m4(result->rotscale_mat, in1->rotscale_mat, in2->rotscale_mat); | 
					
						
							|  |  |  |   mul_m4_m4m4(result->loc_mat, in1->loc_mat, in2->loc_mat); | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt, | 
					
						
							|  |  |  |                                      const float inmat[4][4], | 
					
						
							|  |  |  |                                      float outmat[4][4]) | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* in case inmat == outmat */ | 
					
						
							|  |  |  |   float tmploc[3]; | 
					
						
							|  |  |  |   copy_v3_v3(tmploc, inmat[3]); | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   mul_m4_m4m4(outmat, bpt->rotscale_mat, inmat); | 
					
						
							|  |  |  |   mul_v3_m4v3(outmat[3], bpt->loc_mat, tmploc); | 
					
						
							| 
									
										
										
										
											2018-12-08 09:17:57 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | /* Convert Pose-Space Matrix to Bone-Space Matrix.
 | 
					
						
							|  |  |  |  * NOTE: this cannot be used to convert to pose-space transforms of the supplied | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  |  *       pose-channel into its local space (i.e. 'visual'-keyframing) */ | 
					
						
							| 
									
										
										
										
											2012-12-11 14:29:01 +00:00
										 |  |  | void BKE_armature_mat_pose_to_bone(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) | 
					
						
							| 
									
										
										
										
											2012-01-17 13:30:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BoneParentTransform bpt; | 
					
						
							| 
									
										
										
										
											2010-10-22 06:25:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt); | 
					
						
							|  |  |  |   BKE_bone_parent_transform_invert(&bpt); | 
					
						
							|  |  |  |   BKE_bone_parent_transform_apply(&bpt, inmat, outmat); | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												More pose armature code factorization:
* New armature_mat_bone_to_pose, which is just the reverse of armature_mat_pose_to_bone (currently used by armature evaluation code only, but might be used by constraints space conversion code too, see note below).
* Found another place where another (a bit erroneous) pose_to_bone code existed (apply_targetless_ik(), in transform_conversion.c, used by "auto ik" option), replaced it by a call to armature_mat_pose_to_bone.
Notes:
* All those changes leave many #if 0 commented code, I will remove those in a few weeks.
* There is at least one other place where generic armature_mat_(pose_to_bone/bone_to_pose) functions should be usable: the space conversion function of constraints (constraint_mat_convertspace(), in BKE's constraint.c), but here I have some problems (old code is also somewhat erroneous, but using new one makes old rigs using bone space constraints wrong, e.g. sintel one, and it’s just impossible to make conversion code...). So I'll wait and investigate more for this one.
											
										 
											2012-02-19 11:09:44 +00:00
										 |  |  | /* Convert Bone-Space Matrix to Pose-Space Matrix. */ | 
					
						
							| 
									
										
										
										
											2012-12-11 14:29:01 +00:00
										 |  |  | void BKE_armature_mat_bone_to_pose(bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) | 
					
						
							| 
									
										
											  
											
												More pose armature code factorization:
* New armature_mat_bone_to_pose, which is just the reverse of armature_mat_pose_to_bone (currently used by armature evaluation code only, but might be used by constraints space conversion code too, see note below).
* Found another place where another (a bit erroneous) pose_to_bone code existed (apply_targetless_ik(), in transform_conversion.c, used by "auto ik" option), replaced it by a call to armature_mat_pose_to_bone.
Notes:
* All those changes leave many #if 0 commented code, I will remove those in a few weeks.
* There is at least one other place where generic armature_mat_(pose_to_bone/bone_to_pose) functions should be usable: the space conversion function of constraints (constraint_mat_convertspace(), in BKE's constraint.c), but here I have some problems (old code is also somewhat erroneous, but using new one makes old rigs using bone space constraints wrong, e.g. sintel one, and it’s just impossible to make conversion code...). So I'll wait and investigate more for this one.
											
										 
											2012-02-19 11:09:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BoneParentTransform bpt; | 
					
						
							| 
									
										
											  
											
												More pose armature code factorization:
* New armature_mat_bone_to_pose, which is just the reverse of armature_mat_pose_to_bone (currently used by armature evaluation code only, but might be used by constraints space conversion code too, see note below).
* Found another place where another (a bit erroneous) pose_to_bone code existed (apply_targetless_ik(), in transform_conversion.c, used by "auto ik" option), replaced it by a call to armature_mat_pose_to_bone.
Notes:
* All those changes leave many #if 0 commented code, I will remove those in a few weeks.
* There is at least one other place where generic armature_mat_(pose_to_bone/bone_to_pose) functions should be usable: the space conversion function of constraints (constraint_mat_convertspace(), in BKE's constraint.c), but here I have some problems (old code is also somewhat erroneous, but using new one makes old rigs using bone space constraints wrong, e.g. sintel one, and it’s just impossible to make conversion code...). So I'll wait and investigate more for this one.
											
										 
											2012-02-19 11:09:44 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt); | 
					
						
							|  |  |  |   BKE_bone_parent_transform_apply(&bpt, inmat, outmat); | 
					
						
							| 
									
										
											  
											
												More pose armature code factorization:
* New armature_mat_bone_to_pose, which is just the reverse of armature_mat_pose_to_bone (currently used by armature evaluation code only, but might be used by constraints space conversion code too, see note below).
* Found another place where another (a bit erroneous) pose_to_bone code existed (apply_targetless_ik(), in transform_conversion.c, used by "auto ik" option), replaced it by a call to armature_mat_pose_to_bone.
Notes:
* All those changes leave many #if 0 commented code, I will remove those in a few weeks.
* There is at least one other place where generic armature_mat_(pose_to_bone/bone_to_pose) functions should be usable: the space conversion function of constraints (constraint_mat_convertspace(), in BKE's constraint.c), but here I have some problems (old code is also somewhat erroneous, but using new one makes old rigs using bone space constraints wrong, e.g. sintel one, and it’s just impossible to make conversion code...). So I'll wait and investigate more for this one.
											
										 
											2012-02-19 11:09:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-01-07 22:30:44 +00:00
										 |  |  | /* Convert Pose-Space Location to Bone-Space Location
 | 
					
						
							|  |  |  |  * NOTE: this cannot be used to convert to pose-space location of the supplied | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  |  *       pose-channel into its local space (i.e. 'visual'-keyframing) */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], float outloc[3]) | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float xLocMat[4][4]; | 
					
						
							|  |  |  |   float nLocMat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* build matrix for location */ | 
					
						
							|  |  |  |   unit_m4(xLocMat); | 
					
						
							|  |  |  |   copy_v3_v3(xLocMat[3], inloc); | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* get bone-space cursor matrix and extract location */ | 
					
						
							|  |  |  |   BKE_armature_mat_pose_to_bone(pchan, xLocMat, nLocMat); | 
					
						
							|  |  |  |   copy_v3_v3(outloc, nLocMat[3]); | 
					
						
							| 
									
										
										
										
											2006-12-22 09:05:37 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph, | 
					
						
							|  |  |  |                                       Object *ob, | 
					
						
							|  |  |  |                                       bPoseChannel *pchan, | 
					
						
							|  |  |  |                                       float inmat[4][4], | 
					
						
							|  |  |  |                                       float outmat[4][4]) | 
					
						
							| 
									
										
										
										
											2012-02-01 05:59:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel work_pchan = *pchan; | 
					
						
							| 
									
										
										
										
											2012-02-01 05:59:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* recalculate pose matrix with only parent transformations,
 | 
					
						
							|  |  |  |    * bone loc/sca/rot is ignored, scene and frame are not used. */ | 
					
						
							|  |  |  |   BKE_pose_where_is_bone(depsgraph, NULL, ob, &work_pchan, 0.0f, false); | 
					
						
							| 
									
										
										
										
											2012-02-01 05:59:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* find the matrix, need to remove the bone transforms first so this is
 | 
					
						
							|  |  |  |    * calculated as a matrix to set rather then a difference ontop of what's | 
					
						
							|  |  |  |    * already there. */ | 
					
						
							|  |  |  |   unit_m4(outmat); | 
					
						
							|  |  |  |   BKE_pchan_apply_mat4(&work_pchan, outmat, false); | 
					
						
							| 
									
										
										
										
											2012-02-01 05:59:50 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_armature_mat_pose_to_bone(&work_pchan, inmat, outmat); | 
					
						
							| 
									
										
										
										
											2012-02-01 05:59:50 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-14 10:48:42 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Same as #BKE_object_mat3_to_rot(). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-04-01 11:34:00 +11:00
										 |  |  | void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, float mat[3][3], bool use_compat) | 
					
						
							| 
									
										
										
										
											2010-10-26 12:48:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BLI_ASSERT_UNIT_M3(mat); | 
					
						
							| 
									
										
										
										
											2015-10-24 07:02:51 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   switch (pchan->rotmode) { | 
					
						
							|  |  |  |     case ROT_MODE_QUAT: | 
					
						
							|  |  |  |       mat3_normalized_to_quat(pchan->quat, mat); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     case ROT_MODE_AXISANGLE: | 
					
						
							|  |  |  |       mat3_normalized_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, mat); | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     default: /* euler */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (use_compat) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         mat3_normalized_to_compatible_eulO(pchan->eul, pchan->eul, pchan->rotmode, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							|  |  |  |       else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         mat3_normalized_to_eulO(pchan->eul, pchan->rotmode, mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       break; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2010-10-26 12:48:07 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-02-19 15:34:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 13:15:44 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Same as #BKE_object_rot_to_mat3(). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float mat[3][3]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */ | 
					
						
							|  |  |  |   if (pchan->rotmode > 0) { | 
					
						
							|  |  |  |     /* euler rotations (will cause gimble lock,
 | 
					
						
							|  |  |  |      * but this can be alleviated a bit with rotation orders) */ | 
					
						
							|  |  |  |     eulO_to_mat3(mat, pchan->eul, pchan->rotmode); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (pchan->rotmode == ROT_MODE_AXISANGLE) { | 
					
						
							|  |  |  |     /* axis-angle - not really that great for 3D-changing orientations */ | 
					
						
							|  |  |  |     axis_angle_to_mat3(mat, pchan->rotAxis, pchan->rotAngle); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* quats are normalized before use to eliminate scaling issues */ | 
					
						
							|  |  |  |     float quat[4]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* NOTE: we now don't normalize the stored values anymore,
 | 
					
						
							|  |  |  |      * since this was kindof evil in some cases but if this proves to be too problematic, | 
					
						
							|  |  |  |      * switch back to the old system of operating directly on the stored copy. */ | 
					
						
							|  |  |  |     normalize_qt_qt(quat, pchan->quat); | 
					
						
							|  |  |  |     quat_to_mat3(mat, quat); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-14 10:48:42 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Apply a 4x4 matrix to the pose bone, | 
					
						
							|  |  |  |  * similar to #BKE_object_apply_mat4(). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-04-01 11:34:00 +11:00
										 |  |  | void BKE_pchan_apply_mat4(bPoseChannel *pchan, float mat[4][4], bool use_compat) | 
					
						
							| 
									
										
										
										
											2010-02-19 15:34:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float rot[3][3]; | 
					
						
							|  |  |  |   mat4_to_loc_rot_size(pchan->loc, rot, pchan->size, mat); | 
					
						
							|  |  |  |   BKE_pchan_mat3_to_rot(pchan, rot, use_compat); | 
					
						
							| 
									
										
										
										
											2010-02-19 15:34:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-14 10:48:42 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Remove rest-position effects from pose-transform for obtaining | 
					
						
							| 
									
										
										
										
											2010-02-19 15:34:26 +00:00
										 |  |  |  * 'visual' transformation of pose-channel. | 
					
						
							| 
									
										
										
										
											2019-04-14 10:48:42 +02:00
										 |  |  |  * (used by the Visual-Keyframing stuff). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], | 
					
						
							|  |  |  |                                     float pose_mat[4][4], | 
					
						
							|  |  |  |                                     float arm_mat[4][4]) | 
					
						
							| 
									
										
										
										
											2007-01-17 05:53:44 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float imat[4][4]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   invert_m4_m4(imat, arm_mat); | 
					
						
							|  |  |  |   mul_m4_m4m4(delta_mat, imat, pose_mat); | 
					
						
							| 
									
										
										
										
											2007-01-17 05:53:44 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-28 10:19:20 +00:00
										 |  |  | /* **************** Rotation Mode Conversions ****************************** */ | 
					
						
							|  |  |  | /* Used for Objects and Pose Channels, since both can have multiple rotation representations */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* Called from RNA when rotation mode changes
 | 
					
						
							|  |  |  |  * - the result should be that the rotations given in the provided pointers have had conversions | 
					
						
							|  |  |  |  *   applied (as appropriate), such that the rotation of the element hasn't 'visually' changed  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_rotMode_change_values( | 
					
						
							|  |  |  |     float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* check if any change - if so, need to convert data */ | 
					
						
							|  |  |  |   if (newMode > 0) { /* to euler */ | 
					
						
							|  |  |  |     if (oldMode == ROT_MODE_AXISANGLE) { | 
					
						
							|  |  |  |       /* axis-angle to euler */ | 
					
						
							|  |  |  |       axis_angle_to_eulO(eul, newMode, axis, *angle); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (oldMode == ROT_MODE_QUAT) { | 
					
						
							|  |  |  |       /* quat to euler */ | 
					
						
							|  |  |  |       normalize_qt(quat); | 
					
						
							|  |  |  |       quat_to_eulO(eul, newMode, quat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* else { no conversion needed } */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (newMode == ROT_MODE_QUAT) { /* to quat */ | 
					
						
							|  |  |  |     if (oldMode == ROT_MODE_AXISANGLE) { | 
					
						
							|  |  |  |       /* axis angle to quat */ | 
					
						
							|  |  |  |       axis_angle_to_quat(quat, axis, *angle); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (oldMode > 0) { | 
					
						
							|  |  |  |       /* euler to quat */ | 
					
						
							|  |  |  |       eulO_to_quat(quat, eul, oldMode); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* else { no conversion needed } */ | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (newMode == ROT_MODE_AXISANGLE) { /* to axis-angle */ | 
					
						
							|  |  |  |     if (oldMode > 0) { | 
					
						
							|  |  |  |       /* euler to axis angle */ | 
					
						
							|  |  |  |       eulO_to_axis_angle(axis, angle, eul, oldMode); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (oldMode == ROT_MODE_QUAT) { | 
					
						
							|  |  |  |       /* quat to axis angle */ | 
					
						
							|  |  |  |       normalize_qt(quat); | 
					
						
							|  |  |  |       quat_to_axis_angle(axis, angle, quat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |     /* When converting to axis-angle,
 | 
					
						
							|  |  |  |      * we need a special exception for the case when there is no axis. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (IS_EQF(axis[0], axis[1]) && IS_EQF(axis[1], axis[2])) { | 
					
						
							|  |  |  |       /* for now, rotate around y-axis then (so that it simply becomes the roll) */ | 
					
						
							|  |  |  |       axis[1] = 1.0f; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2009-09-28 10:19:20 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* **************** The new & simple (but OK!) armature evaluation ********* */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* ****************** And how it works! ****************************************
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is the bone transformation trick; they're hierarchical so each bone(b) | 
					
						
							|  |  |  |  * is in the coord system of bone(b-1): | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * arm_mat(b)= arm_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * -> yoffs is just the y axis translation in parent's coord system | 
					
						
							|  |  |  |  * -> d_root is the translation of the bone root, also in parent's coord system | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * we then - in init deform - store the deform in chan_mat, such that: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * pose_mat(b)= arm_mat(b) * chan_mat(b) | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * *************************************************************************** */ | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* Computes vector and roll based on a rotation.
 | 
					
						
							|  |  |  |  * "mat" must contain only a rotation, and no scaling. */ | 
					
						
							| 
									
										
										
										
											2018-10-05 21:02:57 +03:00
										 |  |  | void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll) | 
					
						
							| 
									
										
										
										
											2006-11-21 10:52:11 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (r_vec) { | 
					
						
							|  |  |  |     copy_v3_v3(r_vec, mat[1]); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (r_roll) { | 
					
						
							|  |  |  |     mat3_vec_to_roll(mat, mat[1], r_roll); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-10-05 21:02:57 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2006-01-11 19:40:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-05 21:02:57 +03:00
										 |  |  | /* Computes roll around the vector that best approximates the matrix.
 | 
					
						
							|  |  |  |  * If vec is the Y vector from purely rotational mat, result should be exact. */ | 
					
						
							|  |  |  | void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float vecmat[3][3], vecmatinv[3][3], rollmat[3][3]; | 
					
						
							| 
									
										
										
										
											2006-01-11 19:40:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   vec_roll_to_mat3(vec, 0.0f, vecmat); | 
					
						
							|  |  |  |   invert_m3_m3(vecmatinv, vecmat); | 
					
						
							|  |  |  |   mul_m3_m3m3(rollmat, vecmatinv, mat); | 
					
						
							| 
									
										
										
										
											2018-10-05 21:02:57 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   *r_roll = atan2f(rollmat[2][0], rollmat[2][2]); | 
					
						
							| 
									
										
										
										
											2006-01-11 19:40:06 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  | /* Calculates the rest matrix of a bone based on its vector and a roll around that vector. */ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Given `v = (v.x, v.y, v.z)` our (normalized) bone vector, we want the rotation matrix M | 
					
						
							|  |  |  |  * from the Y axis (so that `M * (0, 1, 0) = v`). | 
					
						
							|  |  |  |  * - The rotation axis a lays on XZ plane, and it is orthonormal to v, | 
					
						
							|  |  |  |  *   hence to the projection of v onto XZ plane. | 
					
						
							|  |  |  |  * - `a = (v.z, 0, -v.x)` | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * We know a is eigenvector of M (so M * a = a). | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Finally, we have w, such that M * w = (0, 1, 0) | 
					
						
							|  |  |  |  * (i.e. the vector that will be aligned with Y axis once transformed). | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * We know w is symmetric to v by the Y axis. | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * - `w = (-v.x, v.y, -v.z)` | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Solving this, we get (x, y and z being the components of v): | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * <pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  *     ┌ (x^2 * y + z^2) / (x^2 + z^2),   x,   x * z * (y - 1) / (x^2 + z^2) ┐ | 
					
						
							|  |  |  |  * M = │  x * (y^2 - 1)  / (x^2 + z^2),   y,    z * (y^2 - 1)  / (x^2 + z^2) │ | 
					
						
							|  |  |  |  *     └ x * z * (y - 1) / (x^2 + z^2),   z,   (x^2 + z^2 * y) / (x^2 + z^2) ┘ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * </pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This is stable as long as v (the bone) is not too much aligned with +/-Y | 
					
						
							|  |  |  |  * (i.e. x and z components are not too close to 0). | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Since v is normalized, we have `x^2 + y^2 + z^2 = 1`, | 
					
						
							|  |  |  |  * hence `x^2 + z^2 = 1 - y^2 = (1 - y)(1 + y)`. | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This allows to simplifies M like this: | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * <pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  *     ┌ 1 - x^2 / (1 + y),   x,     -x * z / (1 + y) ┐ | 
					
						
							|  |  |  |  * M = │                -x,   y,                   -z │ | 
					
						
							|  |  |  |  *     └  -x * z / (1 + y),   z,    1 - z^2 / (1 + y) ┘ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * </pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Written this way, we see the case v = +Y is no more a singularity. | 
					
						
							|  |  |  |  * The only one | 
					
						
							|  |  |  |  * remaining is the bone being aligned with -Y. | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Let's handle | 
					
						
							|  |  |  |  * the asymptotic behavior when bone vector is reaching the limit of y = -1. | 
					
						
							|  |  |  |  * Each of the four corner elements can vary from -1 to 1, | 
					
						
							|  |  |  |  * depending on the axis a chosen for doing the rotation. | 
					
						
							|  |  |  |  * And the "rotation" here is in fact established by mirroring XZ plane by that given axis, | 
					
						
							|  |  |  |  * then inversing the Y-axis. | 
					
						
							|  |  |  |  * For sufficiently small x and z, and with y approaching -1, | 
					
						
							|  |  |  |  * all elements but the four corner ones of M will degenerate. | 
					
						
							|  |  |  |  * So let's now focus on these corner elements. | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * We rewrite M so that it only contains its four corner elements, | 
					
						
							|  |  |  |  * and combine the `1 / (1 + y)` factor: | 
					
						
							|  |  |  |  * <pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  *                    ┌ 1 + y - x^2,        -x * z ┐ | 
					
						
							|  |  |  |  * M* = 1 / (1 + y) * │                            │ | 
					
						
							|  |  |  |  *                    └      -x * z,   1 + y - z^2 ┘ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * </pre> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * When y is close to -1, computing 1 / (1 + y) will cause severe numerical instability, | 
					
						
							|  |  |  |  * so we ignore it and normalize M instead. | 
					
						
							|  |  |  |  * We know `y^2 = 1 - (x^2 + z^2)`, and `y < 0`, hence `y = -sqrt(1 - (x^2 + z^2))`. | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Since x and z are both close to 0, we apply the binomial expansion to the first order: | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * `y = -sqrt(1 - (x^2 + z^2)) = -1 + (x^2 + z^2) / 2`. Which gives: | 
					
						
							|  |  |  |  * <pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  *                        ┌  z^2 - x^2,  -2 * x * z ┐ | 
					
						
							|  |  |  |  * M* = 1 / (x^2 + z^2) * │                         │ | 
					
						
							|  |  |  |  *                        └ -2 * x * z,   x^2 - z^2 ┘ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * </pre> | 
					
						
							| 
									
										
										
										
											2014-04-06 19:15:17 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-05-21 15:22:31 +02:00
										 |  |  | void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat[3][3]) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-17 10:19:32 +02:00
										 |  |  | #define THETA_THRESHOLD_NEGY 1.0e-9f
 | 
					
						
							|  |  |  | #define THETA_THRESHOLD_NEGY_CLOSE 1.0e-5f
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float theta; | 
					
						
							|  |  |  |   float rMatrix[3][3], bMatrix[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_ASSERT_UNIT_V3(nor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   theta = 1.0f + nor[1]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438,
 | 
					
						
							|  |  |  |    * so using 1.0e-9f as best compromise. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * New algo is supposed much more precise, since less complex computations are performed, | 
					
						
							|  |  |  |    * but it uses two different threshold values... | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * Note: When theta is close to zero, we have to check we do have non-null X/Z components as well | 
					
						
							|  |  |  |    *       (due to float precision errors, we can have nor = (0.0, 0.99999994, 0.0)...). | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   if (theta > THETA_THRESHOLD_NEGY_CLOSE || ((nor[0] || nor[2]) && theta > THETA_THRESHOLD_NEGY)) { | 
					
						
							|  |  |  |     /* nor is *not* -Y.
 | 
					
						
							|  |  |  |      * We got these values for free... so be happy with it... ;) | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     bMatrix[0][1] = -nor[0]; | 
					
						
							|  |  |  |     bMatrix[1][0] = nor[0]; | 
					
						
							|  |  |  |     bMatrix[1][1] = nor[1]; | 
					
						
							|  |  |  |     bMatrix[1][2] = nor[2]; | 
					
						
							|  |  |  |     bMatrix[2][1] = -nor[2]; | 
					
						
							|  |  |  |     if (theta > THETA_THRESHOLD_NEGY_CLOSE) { | 
					
						
							|  |  |  |       /* If nor is far enough from -Y, apply the general case. */ | 
					
						
							|  |  |  |       bMatrix[0][0] = 1 - nor[0] * nor[0] / theta; | 
					
						
							|  |  |  |       bMatrix[2][2] = 1 - nor[2] * nor[2] / theta; | 
					
						
							|  |  |  |       bMatrix[2][0] = bMatrix[0][2] = -nor[0] * nor[2] / theta; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* If nor is too close to -Y, apply the special case. */ | 
					
						
							|  |  |  |       theta = nor[0] * nor[0] + nor[2] * nor[2]; | 
					
						
							|  |  |  |       bMatrix[0][0] = (nor[0] + nor[2]) * (nor[0] - nor[2]) / -theta; | 
					
						
							|  |  |  |       bMatrix[2][2] = -bMatrix[0][0]; | 
					
						
							|  |  |  |       bMatrix[2][0] = bMatrix[0][2] = 2.0f * nor[0] * nor[2] / theta; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* If nor is -Y, simple symmetry by Z axis. */ | 
					
						
							|  |  |  |     unit_m3(bMatrix); | 
					
						
							|  |  |  |     bMatrix[0][0] = bMatrix[1][1] = -1.0; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Make Roll matrix */ | 
					
						
							|  |  |  |   axis_angle_normalized_to_mat3(rMatrix, nor, roll); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Combine and output result */ | 
					
						
							|  |  |  |   mul_m3_m3m3(mat, rMatrix, bMatrix); | 
					
						
							| 
									
										
										
										
											2014-04-17 10:19:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #undef THETA_THRESHOLD_NEGY
 | 
					
						
							|  |  |  | #undef THETA_THRESHOLD_NEGY_CLOSE
 | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-21 15:22:31 +02:00
										 |  |  | void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float nor[3]; | 
					
						
							| 
									
										
										
										
											2014-05-21 15:22:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   normalize_v3_v3(nor, vec); | 
					
						
							|  |  |  |   vec_roll_to_mat3_normalized(nor, roll, mat); | 
					
						
							| 
									
										
										
										
											2014-05-21 15:22:31 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* recursive part, calculates restposition of entire tree of children */ | 
					
						
							|  |  |  | /* used by exiting editmode too */ | 
					
						
							| 
									
										
										
										
											2019-08-23 09:03:57 +10:00
										 |  |  | void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float vec[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Bone Space */ | 
					
						
							|  |  |  |   sub_v3_v3v3(vec, bone->tail, bone->head); | 
					
						
							|  |  |  |   bone->length = len_v3(vec); | 
					
						
							|  |  |  |   vec_roll_to_mat3(vec, bone->roll, bone->bone_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* this is called on old file reading too... */ | 
					
						
							|  |  |  |   if (bone->xwidth == 0.0f) { | 
					
						
							|  |  |  |     bone->xwidth = 0.1f; | 
					
						
							|  |  |  |     bone->zwidth = 0.1f; | 
					
						
							|  |  |  |     bone->segments = 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 09:03:57 +10:00
										 |  |  |   if (bone_parent) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     float offs_bone[4][4]; | 
					
						
							|  |  |  |     /* yoffs(b-1) + root(b) + bonemat(b) */ | 
					
						
							|  |  |  |     BKE_bone_offset_matrix_get(bone, offs_bone); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Compose the matrix for this bone  */ | 
					
						
							| 
									
										
										
										
											2019-08-23 09:03:57 +10:00
										 |  |  |     mul_m4_m4m4(bone->arm_mat, bone_parent->arm_mat, offs_bone); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     copy_m4_m3(bone->arm_mat, bone->bone_mat); | 
					
						
							|  |  |  |     copy_v3_v3(bone->arm_mat[3], bone->head); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* and the kiddies */ | 
					
						
							|  |  |  |   if (use_recursion) { | 
					
						
							| 
									
										
										
										
											2019-08-23 09:03:57 +10:00
										 |  |  |     bone_parent = bone; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     for (bone = bone->childbase.first; bone; bone = bone->next) { | 
					
						
							| 
									
										
										
										
											2019-08-23 09:03:57 +10:00
										 |  |  |       BKE_armature_where_is_bone(bone, bone_parent, use_recursion); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | /* updates vectors and matrices on rest-position level, only needed
 | 
					
						
							| 
									
										
										
										
											2012-03-03 20:19:11 +00:00
										 |  |  |  * after editing armature itself, now only on reading file */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_armature_where_is(bArmature *arm) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *bone; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* hierarchical from root to children */ | 
					
						
							|  |  |  |   for (bone = arm->bonebase.first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     BKE_armature_where_is_bone(bone, NULL, true); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-23 17:56:45 +00:00
										 |  |  | /* if bone layer is protected, copy the data from from->pose
 | 
					
						
							|  |  |  |  * when used with linked libraries this copies from the linked pose into the local pose */ | 
					
						
							| 
									
										
										
										
											2006-11-30 15:54:21 +00:00
										 |  |  | static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected) | 
					
						
							| 
									
										
										
										
											2006-11-11 16:45:17 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPose *pose = ob->pose, *frompose = from->pose; | 
					
						
							|  |  |  |   bPoseChannel *pchan, *pchanp; | 
					
						
							|  |  |  |   bConstraint *con; | 
					
						
							|  |  |  |   int error = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (frompose == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* in some cases when rigs change, we cant synchronize
 | 
					
						
							|  |  |  |    * to avoid crashing check for possible errors here */ | 
					
						
							|  |  |  |   for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     if (pchan->bone->layer & layer_protected) { | 
					
						
							|  |  |  |       if (BKE_pose_channel_find_name(frompose, pchan->name) == NULL) { | 
					
						
							|  |  |  |         CLOG_ERROR(&LOG, | 
					
						
							|  |  |  |                    "failed to sync proxy armature because '%s' is missing pose channel '%s'", | 
					
						
							|  |  |  |                    from->id.name, | 
					
						
							|  |  |  |                    pchan->name); | 
					
						
							|  |  |  |         error = 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (error) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* clear all transformation values from library */ | 
					
						
							|  |  |  |   BKE_pose_rest(frompose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* copy over all of the proxy's bone groups */ | 
					
						
							|  |  |  |   /* TODO for later
 | 
					
						
							|  |  |  |    * - implement 'local' bone groups as for constraints | 
					
						
							|  |  |  |    * Note: this isn't trivial, as bones reference groups by index not by pointer, | 
					
						
							|  |  |  |    *       so syncing things correctly needs careful attention */ | 
					
						
							|  |  |  |   BLI_freelistN(&pose->agroups); | 
					
						
							|  |  |  |   BLI_duplicatelist(&pose->agroups, &frompose->agroups); | 
					
						
							|  |  |  |   pose->active_group = frompose->active_group; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     pchanp = BKE_pose_channel_find_name(frompose, pchan->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (UNLIKELY(pchanp == NULL)) { | 
					
						
							|  |  |  |       /* happens for proxies that become invalid because of a missing link
 | 
					
						
							|  |  |  |        * for regular cases it shouldn't happen at all */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (pchan->bone->layer & layer_protected) { | 
					
						
							|  |  |  |       ListBase proxylocal_constraints = {NULL, NULL}; | 
					
						
							|  |  |  |       bPoseChannel pchanw; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* copy posechannel to temp, but restore important pointers */ | 
					
						
							|  |  |  |       pchanw = *pchanp; | 
					
						
							|  |  |  |       pchanw.bone = pchan->bone; | 
					
						
							|  |  |  |       pchanw.prev = pchan->prev; | 
					
						
							|  |  |  |       pchanw.next = pchan->next; | 
					
						
							|  |  |  |       pchanw.parent = pchan->parent; | 
					
						
							|  |  |  |       pchanw.child = pchan->child; | 
					
						
							|  |  |  |       pchanw.custom_tx = pchan->custom_tx; | 
					
						
							|  |  |  |       pchanw.bbone_prev = pchan->bbone_prev; | 
					
						
							|  |  |  |       pchanw.bbone_next = pchan->bbone_next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       pchanw.mpath = pchan->mpath; | 
					
						
							|  |  |  |       pchan->mpath = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-29 10:54:28 +02:00
										 |  |  |       /* Reset runtime data, we don't want to share that with the proxy. */ | 
					
						
							|  |  |  |       BKE_pose_channel_runtime_reset(&pchanw.runtime); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       /* this is freed so copy a copy, else undo crashes */ | 
					
						
							|  |  |  |       if (pchanw.prop) { | 
					
						
							|  |  |  |         pchanw.prop = IDP_CopyProperty(pchanw.prop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* use the values from the existing props */ | 
					
						
							|  |  |  |         if (pchan->prop) { | 
					
						
							|  |  |  |           IDP_SyncGroupValues(pchanw.prop, pchan->prop); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |       /* Constraints - proxy constraints are flushed... local ones are added after
 | 
					
						
							|  |  |  |        * 1: extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints. | 
					
						
							|  |  |  |        * 2: copy proxy-pchan's constraints on-to new. | 
					
						
							|  |  |  |        * 3: add extracted local constraints back on top. | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |        * | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |        * Note for BKE_constraints_copy: | 
					
						
							|  |  |  |        * When copying constraints, disable 'do_extern' otherwise | 
					
						
							|  |  |  |        * we get the libs direct linked in this blend. | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |        */ | 
					
						
							|  |  |  |       BKE_constraints_proxylocal_extract(&proxylocal_constraints, &pchan->constraints); | 
					
						
							|  |  |  |       BKE_constraints_copy(&pchanw.constraints, &pchanp->constraints, false); | 
					
						
							|  |  |  |       BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* constraints - set target ob pointer to own object */ | 
					
						
							|  |  |  |       for (con = pchanw.constraints.first; con; con = con->next) { | 
					
						
							|  |  |  |         const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); | 
					
						
							|  |  |  |         ListBase targets = {NULL, NULL}; | 
					
						
							|  |  |  |         bConstraintTarget *ct; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (cti && cti->get_constraint_targets) { | 
					
						
							|  |  |  |           cti->get_constraint_targets(con, &targets); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           for (ct = targets.first; ct; ct = ct->next) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |             if (ct->tar == from) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |               ct->tar = ob; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |           if (cti->flush_constraint_targets) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |             cti->flush_constraint_targets(con, &targets, 0); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |           } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* free stuff from current channel */ | 
					
						
							|  |  |  |       BKE_pose_channel_free(pchan); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* copy data in temp back over to the cleaned-out (but still allocated) original channel */ | 
					
						
							|  |  |  |       *pchan = pchanw; | 
					
						
							|  |  |  |       if (pchan->custom) { | 
					
						
							|  |  |  |         id_us_plus(&pchan->custom->id); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       /* always copy custom shape */ | 
					
						
							|  |  |  |       pchan->custom = pchanp->custom; | 
					
						
							|  |  |  |       if (pchan->custom) { | 
					
						
							|  |  |  |         id_us_plus(&pchan->custom->id); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       if (pchanp->custom_tx) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         pchan->custom_tx = BKE_pose_channel_find_name(pose, pchanp->custom_tx->name); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* ID-Property Syncing */ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         IDProperty *prop_orig = pchan->prop; | 
					
						
							|  |  |  |         if (pchanp->prop) { | 
					
						
							|  |  |  |           pchan->prop = IDP_CopyProperty(pchanp->prop); | 
					
						
							|  |  |  |           if (prop_orig) { | 
					
						
							|  |  |  |             /* copy existing values across when types match */ | 
					
						
							|  |  |  |             IDP_SyncGroupValues(pchan->prop, prop_orig); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           pchan->prop = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (prop_orig) { | 
					
						
							|  |  |  |           IDP_FreeProperty(prop_orig); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2006-11-11 16:45:17 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2005-07-16 19:07:02 +00:00
										 |  |  | static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int counter) | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel *pchan = BKE_pose_channel_verify(pose, bone->name); /* verify checks and/or adds */ | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   pchan->bone = bone; | 
					
						
							|  |  |  |   pchan->parent = parchan; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   counter++; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (bone = bone->childbase.first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     counter = rebuild_pose_bone(pose, bone, pchan, counter); | 
					
						
							|  |  |  |     /* for quick detecting of next bone in chain, only b-bone uses it now */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if (bone->flag & BONE_CONNECTED) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       pchan->child = BKE_pose_channel_find_name(pose, bone->name); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return counter; | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-21 16:15:00 +02:00
										 |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |  * Clear pointers of object's pose | 
					
						
							|  |  |  |  * (needed in remap case, since we cannot always wait for a complete pose rebuild). | 
					
						
							| 
									
										
										
										
											2016-07-21 16:15:00 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | void BKE_pose_clear_pointers(bPose *pose) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     pchan->bone = NULL; | 
					
						
							|  |  |  |     pchan->child = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-07-21 16:15:00 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-03 16:10:37 +02:00
										 |  |  | void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							| 
									
										
										
										
											2019-05-14 21:48:22 +03:00
										 |  |  |     pchan->bone = BKE_armature_find_bone_name(armature, pchan->name); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-05-03 16:10:37 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-31 19:12:59 +03:00
										 |  |  | /** Find the matching pose channel using the bone name, if not NULL. */ | 
					
						
							|  |  |  | static bPoseChannel *pose_channel_find_bone(bPose *pose, Bone *bone) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return (bone != NULL) ? BKE_pose_channel_find_name(pose, bone->name) : NULL; | 
					
						
							| 
									
										
										
										
											2018-10-31 19:12:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Update the links for the B-Bone handles from Bone data. */ | 
					
						
							|  |  |  | void BKE_pchan_rebuild_bbone_handles(bPose *pose, bPoseChannel *pchan) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   pchan->bbone_prev = pose_channel_find_bone(pose, pchan->bone->bbone_prev); | 
					
						
							|  |  |  |   pchan->bbone_next = pose_channel_find_bone(pose, pchan->bone->bbone_next); | 
					
						
							| 
									
										
										
										
											2018-10-31 19:12:59 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-19 16:48:21 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * Only after leave editmode, duplicating, validating older files, library syncing. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \note pose->flag is set for it. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2018-12-12 12:55:20 +11:00
										 |  |  |  * \param bmain: May be NULL, only used to tag depsgraph as being dirty... | 
					
						
							| 
									
										
										
										
											2018-07-19 16:48:21 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-07-31 11:38:10 +02:00
										 |  |  | void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_user) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Bone *bone; | 
					
						
							|  |  |  |   bPose *pose; | 
					
						
							|  |  |  |   bPoseChannel *pchan, *next; | 
					
						
							|  |  |  |   int counter = 0; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* only done here */ | 
					
						
							|  |  |  |   if (ob->pose == NULL) { | 
					
						
							|  |  |  |     /* create new pose */ | 
					
						
							|  |  |  |     ob->pose = MEM_callocN(sizeof(bPose), "new pose"); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* set default settings for animviz */ | 
					
						
							|  |  |  |     animviz_settings_init(&ob->pose->avs); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   pose = ob->pose; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* clear */ | 
					
						
							|  |  |  |   BKE_pose_clear_pointers(pose); | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* first step, check if all channels are there */ | 
					
						
							|  |  |  |   for (bone = arm->bonebase.first; bone; bone = bone->next) { | 
					
						
							|  |  |  |     counter = rebuild_pose_bone(pose, bone, NULL, counter); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* and a check for garbage */ | 
					
						
							|  |  |  |   for (pchan = pose->chanbase.first; pchan; pchan = next) { | 
					
						
							|  |  |  |     next = pchan->next; | 
					
						
							|  |  |  |     if (pchan->bone == NULL) { | 
					
						
							|  |  |  |       BKE_pose_channel_free_ex(pchan, do_id_user); | 
					
						
							|  |  |  |       BKE_pose_channels_hash_free(pose); | 
					
						
							|  |  |  |       BLI_freelinkN(&pose->chanbase, pchan); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-08-05 18:48:05 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_pose_channels_hash_make(pose); | 
					
						
							| 
									
										
										
										
											2018-10-31 19:12:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     /* Find the custom B-Bone handles. */ | 
					
						
							|  |  |  |     BKE_pchan_rebuild_bbone_handles(pose, pchan); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-10-31 19:12:59 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* printf("rebuild pose %s, %d bones\n", ob->id.name, counter); */ | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* synchronize protected layers with proxy */ | 
					
						
							|  |  |  |   /* HACK! To preserve 2.7x behavior that you always can pose even locked bones,
 | 
					
						
							|  |  |  |    * do not do any restoration if this is a COW temp copy! */ | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |   /* Switched back to just NO_MAIN tag, for some reasons (c)
 | 
					
						
							|  |  |  |    * using COW tag was working this morning, but not anymore... */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (ob->proxy != NULL && (ob->id.tag & LIB_TAG_NO_MAIN) == 0) { | 
					
						
							|  |  |  |     BKE_object_copy_proxy_drivers(ob, ob->proxy); | 
					
						
							|  |  |  |     pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_pose_update_constraint_flags(pose); /* for IK detection for example */ | 
					
						
							| 
									
										
										
										
											2018-07-19 16:48:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   pose->flag &= ~POSE_RECALC; | 
					
						
							|  |  |  |   pose->flag |= POSE_WAS_REBUILT; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |   /* Rebuilding poses forces us to also rebuild the dependency graph,
 | 
					
						
							|  |  |  |    * since there is one node per pose/bone. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (bmain != NULL) { | 
					
						
							|  |  |  |     DEG_relations_tag_update(bmain); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* ********************** THE POSE SOLVER ******************* */ | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-01 05:19:07 +00:00
										 |  |  | /* loc/rot/size to given mat4 */ | 
					
						
							| 
									
										
										
										
											2019-05-01 13:15:44 +10:00
										 |  |  | void BKE_pchan_to_mat4(const bPoseChannel *pchan, float chan_mat[4][4]) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float smat[3][3]; | 
					
						
							|  |  |  |   float rmat[3][3]; | 
					
						
							|  |  |  |   float tmat[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* get scaling matrix */ | 
					
						
							|  |  |  |   size_to_mat3(smat, pchan->size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-01 13:15:44 +10:00
										 |  |  |   /* get rotation matrix */ | 
					
						
							|  |  |  |   BKE_pchan_rot_to_mat3(pchan, rmat); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */ | 
					
						
							|  |  |  |   mul_m3_m3m3(tmat, rmat, smat); | 
					
						
							|  |  |  |   copy_m4_m3(chan_mat, tmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* prevent action channels breaking chains */ | 
					
						
							|  |  |  |   /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */ | 
					
						
							|  |  |  |   if ((pchan->bone == NULL) || !(pchan->bone->flag & BONE_CONNECTED)) { | 
					
						
							|  |  |  |     copy_v3_v3(chan_mat[3], pchan->loc); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-01 05:19:07 +00:00
										 |  |  | /* loc/rot/size to mat4 */ | 
					
						
							|  |  |  | /* used in constraint.c too */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_pchan_calc_mat(bPoseChannel *pchan) | 
					
						
							| 
									
										
										
										
											2010-03-01 05:19:07 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* this is just a wrapper around the copy of this function which calculates the matrix
 | 
					
						
							|  |  |  |    * and stores the result in any given channel | 
					
						
							|  |  |  |    */ | 
					
						
							|  |  |  |   BKE_pchan_to_mat4(pchan, pchan->chan_mat); | 
					
						
							| 
									
										
										
										
											2010-03-01 05:19:07 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-22 11:38:10 +00:00
										 |  |  | /* calculate tail of posechannel */ | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | void BKE_pose_where_is_bone_tail(bPoseChannel *pchan) | 
					
						
							| 
									
										
										
										
											2010-10-22 11:38:10 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   float vec[3]; | 
					
						
							| 
									
										
										
										
											2012-02-22 15:35:42 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   copy_v3_v3(vec, pchan->pose_mat[1]); | 
					
						
							|  |  |  |   mul_v3_fl(vec, pchan->bone->length); | 
					
						
							|  |  |  |   add_v3_v3v3(pchan->pose_tail, pchan->pose_head, vec); | 
					
						
							| 
									
										
										
										
											2010-10-22 11:38:10 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2005-11-16 14:32:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* The main armature solver, does all constraints excluding IK */ | 
					
						
							| 
									
										
										
										
											2010-02-19 15:34:26 +00:00
										 |  |  | /* pchan is validated, as having bone and parent pointer
 | 
					
						
							|  |  |  |  * 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, | 
					
						
							|  |  |  |                             Scene *scene, | 
					
						
							|  |  |  |                             Object *ob, | 
					
						
							|  |  |  |                             bPoseChannel *pchan, | 
					
						
							|  |  |  |                             float ctime, | 
					
						
							|  |  |  |                             bool do_extra) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* This gives a chan_mat with actions (ipos) results. */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (do_extra) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BKE_pchan_calc_mat(pchan); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     unit_m4(pchan->chan_mat); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Construct the posemat based on PoseChannels, that we do before applying constraints. */ | 
					
						
							|  |  |  |   /* pose_mat(b) = pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */ | 
					
						
							|  |  |  |   BKE_armature_mat_bone_to_pose(pchan, pchan->chan_mat, pchan->pose_mat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Only rootbones get the cyclic offset (unless user doesn't want that). */ | 
					
						
							|  |  |  |   /* XXX That could be a problem for snapping and other "reverse transform" features... */ | 
					
						
							|  |  |  |   if (!pchan->parent) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     if ((pchan->bone->flag & BONE_NO_CYCLICOFFSET) == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       add_v3_v3(pchan->pose_mat[3], ob->pose->cyclic_offset); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (do_extra) { | 
					
						
							|  |  |  |     /* Do constraints */ | 
					
						
							|  |  |  |     if (pchan->constraints.first) { | 
					
						
							|  |  |  |       bConstraintOb *cob; | 
					
						
							|  |  |  |       float vec[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* make a copy of location of PoseChannel for later */ | 
					
						
							|  |  |  |       copy_v3_v3(vec, pchan->pose_mat[3]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* prepare PoseChannel for Constraint solving
 | 
					
						
							|  |  |  |        * - makes a copy of matrix, and creates temporary struct to use | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       cob = BKE_constraints_make_evalob(depsgraph, scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* Solve PoseChannel's Constraints */ | 
					
						
							| 
									
										
										
										
											2019-08-14 23:29:46 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* ctime doesn't alter objects. */ | 
					
						
							|  |  |  |       BKE_constraints_solve(depsgraph, &pchan->constraints, cob, ctime); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* cleanup after Constraint Solving
 | 
					
						
							|  |  |  |        * - applies matrix back to pchan, and frees temporary struct used | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       BKE_constraints_clear_evalob(cob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* prevent constraints breaking a chain */ | 
					
						
							|  |  |  |       if (pchan->bone->flag & BONE_CONNECTED) { | 
					
						
							|  |  |  |         copy_v3_v3(pchan->pose_mat[3], vec); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculate head */ | 
					
						
							|  |  |  |   copy_v3_v3(pchan->pose_head, pchan->pose_mat[3]); | 
					
						
							|  |  |  |   /* calculate tail */ | 
					
						
							|  |  |  |   BKE_pose_where_is_bone_tail(pchan); | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | /* This only reads anim data from channels, and writes to channels */ | 
					
						
							|  |  |  | /* This is the only function adding poses */ | 
					
						
							| 
									
										
										
										
											2018-04-06 12:07:27 +02:00
										 |  |  | void BKE_pose_where_is(struct Depsgraph *depsgraph, Scene *scene, Object *ob) | 
					
						
							| 
									
										
										
										
											2002-10-12 11:37:38 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bArmature *arm; | 
					
						
							|  |  |  |   Bone *bone; | 
					
						
							|  |  |  |   bPoseChannel *pchan; | 
					
						
							|  |  |  |   float imat[4][4]; | 
					
						
							|  |  |  |   float ctime; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (ob->type != OB_ARMATURE) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   arm = ob->data; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   if (ELEM(NULL, arm, scene)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:39:35 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if ((ob->pose == NULL) || (ob->pose->flag & POSE_RECALC)) { | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |     /* WARNING! passing NULL bmain here means we won't tag depsgraph's as dirty -
 | 
					
						
							|  |  |  |      * hopefully this is OK. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BKE_pose_rebuild(NULL, ob, arm, true); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ctime = BKE_scene_frame_get(scene); /* not accurate... */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* In editmode or restposition we read the data from the bones */ | 
					
						
							|  |  |  |   if (arm->edbo || (arm->flag & ARM_RESTPOS)) { | 
					
						
							|  |  |  |     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |       bone = pchan->bone; | 
					
						
							|  |  |  |       if (bone) { | 
					
						
							|  |  |  |         copy_m4_m4(pchan->pose_mat, bone->arm_mat); | 
					
						
							|  |  |  |         copy_v3_v3(pchan->pose_head, bone->arm_head); | 
					
						
							|  |  |  |         copy_v3_v3(pchan->pose_tail, bone->arm_tail); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     invert_m4_m4(ob->imat, ob->obmat); /* imat is needed */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* 1. clear flags */ | 
					
						
							|  |  |  |     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |       pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* 2a. construct the IK tree (standard IK) */ | 
					
						
							|  |  |  |     BIK_initialize_tree(depsgraph, scene, ob, ctime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* 2b. construct the Spline IK trees
 | 
					
						
							|  |  |  |      * - this is not integrated as an IK plugin, since it should be able | 
					
						
							|  |  |  |      *   to function in conjunction with standard IK | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     BKE_pose_splineik_init_tree(scene, ob, ctime); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* 3. the main loop, channels are already hierarchical sorted from root to children */ | 
					
						
							|  |  |  |     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |       /* 4a. if we find an IK root, we handle it separated */ | 
					
						
							|  |  |  |       if (pchan->flag & POSE_IKTREE) { | 
					
						
							|  |  |  |         BIK_execute_tree(depsgraph, scene, ob, pchan, ctime); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /* 4b. if we find a Spline IK root, we handle it separated too */ | 
					
						
							|  |  |  |       else if (pchan->flag & POSE_IKSPLINE) { | 
					
						
							|  |  |  |         BKE_splineik_execute_tree(depsgraph, scene, ob, pchan, ctime); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /* 5. otherwise just call the normal solver */ | 
					
						
							|  |  |  |       else if (!(pchan->flag & POSE_DONE)) { | 
					
						
							|  |  |  |         BKE_pose_where_is_bone(depsgraph, scene, ob, pchan, ctime, 1); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* 6. release the IK tree */ | 
					
						
							|  |  |  |     BIK_release_tree(scene, ob, ctime); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* calculating deform matrices */ | 
					
						
							|  |  |  |   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     if (pchan->bone) { | 
					
						
							|  |  |  |       invert_m4_m4(imat, pchan->bone->arm_mat); | 
					
						
							|  |  |  |       mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
											  
											
												Result of 2 weeks of quiet coding work in Greece :)
Aim was to get a total refresh of the animation system. This
is needed because;
- we need to upgrade it with 21st century features
- current code is spaghetti/hack combo, and hides good design
- it should become lag-free with using dependency graphs
A full log, with complete code API/structure/design explanation
will follow, that's a load of work... so here below the list with
hot changes;
- The entire object update system (matrices, geometry) is now
  centralized. Calls to where_is_object and makeDispList are
  forbidden, instead we tag objects 'changed' and let the
  depgraph code sort it out
- Removed all old "Ika" code
- Depgraph is aware of all relationships, including meta balls,
  constraints, bevelcurve, and so on.
- Made depgraph aware of relation types and layers, to do smart
  flushing of 'changed' events. Nothing gets calculated too often!
- Transform uses depgraph to detect changes
- On frame-advance, depgraph flushes animated changes
Armatures;
Almost all armature related code has been fully built from scratch.
It now reveils the original design much better, with a very clean
implementation, lag free without even calculating each Bone more than
once. Result is quite a speedup yes!
Important to note is;
1) Armature is data containing the 'rest position'
2) Pose is the changes of rest position, and always on object level.
   That way more Objects can use same Pose. Also constraints are in Pose
3) Actions only contain the Ipos to change values in Poses.
- Bones draw unrotated now
- Drawing bones speedup enormously (10-20 times)
- Bone selecting in EditMode, selection state is saved for PoseMode,
  and vice-versa
- Undo in editmode
- Bone renaming does vertexgroups, constraints, posechannels, actions,
  for all users of Armature in entire file
- Added Bone renaming in NKey panel
- Nkey PoseMode shows eulers now
- EditMode and PoseMode now have 'active' bone too (last clicked)
- Parenting in EditMode' CTRL+P, ALT+P, with nice options!
- Pose is added in Outliner now, with showing that constraints are in
  the Pose, not Armature
- Disconnected IK solving from constraints. It's a separate phase now,
  on top of the full Pose calculations
- Pose itself has a dependency graph too, so evaluation order is lag free.
TODO NOW;
- Rotating in Posemode has incorrect inverse transform (Martin will fix)
- Python Bone/Armature/Pose API disabled... needs full recode too
  (wait for my doc!)
- Game engine will need upgrade too
- Depgraph code needs revision, cleanup, can be much faster!
  (But, compliments for Jean-Luc, it works like a charm!)
- IK changed, it now doesnt use previous position to advance to next
  position anymore. That system looks nice (no flips) but is not well
  suited for NLA and background render.
TODO LATER;
We now can do loadsa new nifty features as well; like:
- Kill PoseMode (can be option for armatures itself)
- Make B-Bones (Bezier, Bspline, like for spines)
- Move all silly button level edit to 3d window (like CTRL+I = add
  IK)
- Much better & informative drawing
- Fix action/nla editors
- Put all ipos in Actions (object, mesh key, lamp color)
- Add hooks
- Null bones
- Much more advanced constraints...
Bugfixes;
- OGL render (view3d header) had wrong first frame on anim render
- Ipo 'recording' mode had wrong playback speed
- Vertex-key mode now sticks to show 'active key', until frame change
-Ton-
											
										 
											2005-07-03 17:35:38 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-09-14 02:04:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | /************** Bounding box ********************/ | 
					
						
							| 
									
										
										
										
											2012-05-13 11:05:52 +00:00
										 |  |  | static int minmax_armature(Object *ob, float r_min[3], float r_max[3]) | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bPoseChannel *pchan; | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-27 12:07:07 +10:00
										 |  |  |   /* For now, we assume BKE_pose_where_is has already been called
 | 
					
						
							|  |  |  |    * (hence we have valid data in pachan). */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |     minmax_v3v3_v3(r_min, r_max, pchan->pose_head); | 
					
						
							|  |  |  |     minmax_v3v3_v3(r_min, r_max, pchan->pose_tail); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return (BLI_listbase_is_empty(&ob->pose->chanbase) == false); | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-13 18:12:08 +02:00
										 |  |  | static void boundbox_armature(Object *ob) | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BoundBox *bb; | 
					
						
							|  |  |  |   float min[3], max[3]; | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (ob->runtime.bb == NULL) { | 
					
						
							|  |  |  |     ob->runtime.bb = MEM_callocN(sizeof(BoundBox), "Armature boundbox"); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   bb = ob->runtime.bb; | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   INIT_MINMAX(min, max); | 
					
						
							|  |  |  |   if (!minmax_armature(ob, min, max)) { | 
					
						
							|  |  |  |     min[0] = min[1] = min[2] = -1.0f; | 
					
						
							|  |  |  |     max[0] = max[1] = max[2] = 1.0f; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_boundbox_init_from_minmax(bb, min, max); | 
					
						
							| 
									
										
										
										
											2016-03-04 21:50:54 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bb->flag &= ~BOUNDBOX_DIRTY; | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-05 16:03:57 +00:00
										 |  |  | BoundBox *BKE_armature_boundbox_get(Object *ob) | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   boundbox_armature(ob); | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return ob->runtime.bb; | 
					
						
							| 
									
										
										
										
											2012-03-22 13:27:24 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-05-12 13:57:11 +05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-04 04:18:49 +10:00
										 |  |  | bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bool changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ob->pose) { | 
					
						
							|  |  |  |     bArmature *arm = ob->data; | 
					
						
							|  |  |  |     bPoseChannel *pchan; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { | 
					
						
							|  |  |  |       /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment
 | 
					
						
							|  |  |  |        *     (editarmature.c:2592)... Skip in this case too! */ | 
					
						
							|  |  |  |       if (pchan->bone && (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) && | 
					
						
							|  |  |  |                           !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) { | 
					
						
							|  |  |  |         bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan; | 
					
						
							|  |  |  |         BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ? | 
					
						
							|  |  |  |                                   BKE_object_boundbox_get(pchan->custom) : | 
					
						
							|  |  |  |                                   NULL; | 
					
						
							|  |  |  |         if (bb_custom) { | 
					
						
							|  |  |  |           float mat[4][4], smat[4][4]; | 
					
						
							|  |  |  |           scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan)); | 
					
						
							|  |  |  |           mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat); | 
					
						
							|  |  |  |           BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           float vec[3]; | 
					
						
							|  |  |  |           mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); | 
					
						
							|  |  |  |           minmax_v3v3_v3(r_min, r_max, vec); | 
					
						
							|  |  |  |           mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); | 
					
						
							|  |  |  |           minmax_v3v3_v3(r_min, r_max, vec); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         changed = true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return changed; | 
					
						
							| 
									
										
										
										
											2015-09-04 04:18:49 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-12 13:57:11 +05:00
										 |  |  | /************** Graph evaluation ********************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bPoseChannel *rootchan = pchan; | 
					
						
							|  |  |  |   if (!(data->flag & CONSTRAINT_IK_TIP)) { | 
					
						
							|  |  |  |     /* Exclude tip from chain. */ | 
					
						
							|  |  |  |     rootchan = rootchan->parent; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (rootchan != NULL) { | 
					
						
							|  |  |  |     int segcount = 0; | 
					
						
							|  |  |  |     while (rootchan->parent) { | 
					
						
							|  |  |  |       /* Continue up chain, until we reach target number of items. */ | 
					
						
							|  |  |  |       segcount++; | 
					
						
							|  |  |  |       if (segcount == data->rootbone) { | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       rootchan = rootchan->parent; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return rootchan; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bPoseChannel *BKE_armature_splineik_solver_find_root(bPoseChannel *pchan, | 
					
						
							|  |  |  |                                                      bSplineIKConstraint *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   bPoseChannel *rootchan = pchan; | 
					
						
							|  |  |  |   int segcount = 0; | 
					
						
							|  |  |  |   BLI_assert(rootchan != NULL); | 
					
						
							|  |  |  |   while (rootchan->parent) { | 
					
						
							|  |  |  |     /* Continue up chain, until we reach target number of items. */ | 
					
						
							|  |  |  |     segcount++; | 
					
						
							|  |  |  |     if (segcount == data->chainlen) { | 
					
						
							|  |  |  |       break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     rootchan = rootchan->parent; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return rootchan; | 
					
						
							| 
									
										
										
										
											2015-05-12 13:57:11 +05:00
										 |  |  | } |