Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/iksolver')
-rw-r--r--intern/iksolver/Makefile52
-rw-r--r--intern/iksolver/extern/IK_solver.h207
-rw-r--r--intern/iksolver/intern/IK_CGChainSolver.cpp300
-rw-r--r--intern/iksolver/intern/IK_CGChainSolver.h178
-rw-r--r--intern/iksolver/intern/IK_Chain.cpp208
-rw-r--r--intern/iksolver/intern/IK_Chain.h194
-rw-r--r--intern/iksolver/intern/IK_ConjugateGradientSolver.cpp162
-rw-r--r--intern/iksolver/intern/IK_ConjugateGradientSolver.h195
-rw-r--r--intern/iksolver/intern/IK_JacobianSolver.cpp267
-rw-r--r--intern/iksolver/intern/IK_JacobianSolver.h171
-rw-r--r--intern/iksolver/intern/IK_LineMinimizer.h298
-rw-r--r--intern/iksolver/intern/IK_QChain.cpp280
-rw-r--r--intern/iksolver/intern/IK_QChain.h211
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.cpp327
-rw-r--r--intern/iksolver/intern/IK_QJacobianSolver.h184
-rw-r--r--intern/iksolver/intern/IK_QSegment.cpp363
-rw-r--r--intern/iksolver/intern/IK_QSegment.h290
-rw-r--r--intern/iksolver/intern/IK_QSolver_Class.h107
-rw-r--r--intern/iksolver/intern/IK_Segment.cpp277
-rw-r--r--intern/iksolver/intern/IK_Segment.h217
-rw-r--r--intern/iksolver/intern/IK_Solver.cpp196
-rw-r--r--intern/iksolver/intern/IK_Solver_Class.h93
-rw-r--r--intern/iksolver/intern/MT_ExpMap.cpp268
-rw-r--r--intern/iksolver/intern/MT_ExpMap.h219
-rw-r--r--intern/iksolver/intern/Makefile44
-rw-r--r--intern/iksolver/intern/TNT/cholesky.h128
-rw-r--r--intern/iksolver/intern/TNT/cmat.h661
-rw-r--r--intern/iksolver/intern/TNT/fcscmat.h197
-rw-r--r--intern/iksolver/intern/TNT/fmat.h609
-rw-r--r--intern/iksolver/intern/TNT/fortran.h99
-rw-r--r--intern/iksolver/intern/TNT/fspvec.h200
-rw-r--r--intern/iksolver/intern/TNT/index.h115
-rw-r--r--intern/iksolver/intern/TNT/lapack.h225
-rw-r--r--intern/iksolver/intern/TNT/lu.h236
-rw-r--r--intern/iksolver/intern/TNT/qr.h261
-rw-r--r--intern/iksolver/intern/TNT/region1d.h403
-rw-r--r--intern/iksolver/intern/TNT/region2d.h499
-rw-r--r--intern/iksolver/intern/TNT/stopwatch.h115
-rw-r--r--intern/iksolver/intern/TNT/subscript.h90
-rw-r--r--intern/iksolver/intern/TNT/svd.h507
-rw-r--r--intern/iksolver/intern/TNT/tnt.h127
-rw-r--r--intern/iksolver/intern/TNT/tntmath.h177
-rw-r--r--intern/iksolver/intern/TNT/tntreqs.h102
-rw-r--r--intern/iksolver/intern/TNT/transv.h192
-rw-r--r--intern/iksolver/intern/TNT/triang.h670
-rw-r--r--intern/iksolver/intern/TNT/trisolve.h216
-rw-r--r--intern/iksolver/intern/TNT/vec.h535
-rw-r--r--intern/iksolver/intern/TNT/vecadaptor.h321
-rw-r--r--intern/iksolver/intern/TNT/version.h52
-rw-r--r--intern/iksolver/make/msvc_6_0/iksolver.dsp244
-rw-r--r--intern/iksolver/make/msvc_6_0/iksolver.dsw35
-rw-r--r--intern/iksolver/test/Makefile67
-rw-r--r--intern/iksolver/test/ik_glut_test/Makefile42
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp95
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutDrawer.h100
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp89
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h106
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp104
-rw-r--r--intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h116
-rw-r--r--intern/iksolver/test/ik_glut_test/common/Makefile44
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h387
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/Makefile51
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h84
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h211
-rw-r--r--intern/iksolver/test/ik_glut_test/intern/main.cpp361
-rw-r--r--intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp130
-rw-r--r--intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw49
67 files changed, 14360 insertions, 0 deletions
diff --git a/intern/iksolver/Makefile b/intern/iksolver/Makefile
new file mode 100644
index 00000000000..8cdb81ca780
--- /dev/null
+++ b/intern/iksolver/Makefile
@@ -0,0 +1,52 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver main makefile.
+#
+
+include nan_definitions.mk
+
+LIBNAME = iksolver
+SOURCEDIR = intern/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = intern
+TESTDIRS = test
+
+include nan_subdirs.mk
+
+install: all debug
+ @[ -d $(NAN_IKSOLVER) ] || mkdir $(NAN_IKSOLVER)
+ @[ -d $(NAN_IKSOLVER)/include ] || mkdir $(NAN_IKSOLVER)/include
+ @[ -d $(NAN_IKSOLVER)/lib ] || mkdir $(NAN_IKSOLVER)/lib
+ @[ -d $(NAN_IKSOLVER)/lib/debug ] || mkdir $(NAN_IKSOLVER)/lib/debug
+ cp -f $(DIR)/libiksolver.a $(NAN_IKSOLVER)/lib/
+ cp -f $(DIR)/debug/libiksolver.a $(NAN_IKSOLVER)/lib/debug/
+ cp -f extern/*.h $(NAN_IKSOLVER)/include/
+
diff --git a/intern/iksolver/extern/IK_solver.h b/intern/iksolver/extern/IK_solver.h
new file mode 100644
index 00000000000..57d06a3ba32
--- /dev/null
+++ b/intern/iksolver/extern/IK_solver.h
@@ -0,0 +1,207 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ * @mainpage IK - Blender inverse kinematics module.
+ *
+ * @section about About the IK module
+ *
+ * This module allows you to create segments and form them into
+ * chains. You can then define a goal point that the end of the
+ * chain should attempt to reach - an inverse kinematic problem.
+ * This module will then modify the segments in the chain in
+ * order to get the end of the chain as near as possible to the
+ * goal. This solver uses an inverse jacobian method to find
+ * a solution.
+ *
+ * @section issues Known issues with this IK solver.
+ *
+ * - The current solver works with only one type of segment. These
+ * segments always have 3 degress of freedom (DOF). i.e. the solver
+ * uses all these degrees to solve the IK problem. It would be
+ * nice to allow the user to specify different segment types such
+ * as 1 DOF joints in a given plane. 2 DOF joints about given axis.
+ * - There is currently no support for joint constraints in the
+ * solver. This is within the realms of possibility - please ask
+ * if this functionality is required.
+ * - The solver is slow, inverse jacobian methods in general give
+ * 'smooth' solutions and the method is also very flexible, it
+ * does not rely on specific angle parameterization and can be
+ * extended to deal with different joint types and joint
+ * constraints. However it is not suitable for real time use.
+ * Other algorithms exist which are more suitable for real-time
+ * applications, please ask if this functionality is required.
+ *
+ * @section dependencies Dependencies
+ *
+ * This module only depends on Moto.
+ */
+
+#ifndef NAN_INCLUDED_IK_solver_h
+#define NAN_INCLUDED_IK_solver_h
+
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * External segment structure
+ */
+
+
+/**
+ * This structure defines a single segment of an IK chain.
+ * - Individual segments are always defined in local coordinates.
+ * - The segment is assumed to be oriented in the local
+ * y-direction.
+ * - seg_start is the start of the segment relative to the end
+ * of the parent segment.
+ * - basis is a column major matrix defining the rest position
+ * of the bone.
+ * - length is the simply the length of the bone.
+ * - basis_change is a 3x3 matrix representing the change
+ * from the rest position of the segment to the solved position.
+ * In fact it is the transpose of this matrix because blender
+ * does something weird with quaternion conversion. This is
+ * strictly an ouput variable for returning the results of an
+ * an ik solve back to you.
+ * The local transformation specified as a column major matrix
+ * of a segment is then defined as.
+ * translate(seg_start)*basis*transpose(basis_change)*translate(0,length,0)
+ */
+
+typedef struct IK_Segment_Extern {
+ float seg_start[3];
+ float basis[9];
+ float length;
+ float basis_change[9];
+} IK_Segment_Extern;
+
+typedef IK_Segment_Extern* IK_Segment_ExternPtr;
+
+/**
+ * External chain structure.
+ * This structure is filled when you call IK_LoadChain.
+ * The first segment in the chain is the root segment.
+ * The end of the last segment is the end-effector of the chain
+ * this is the point that tries to move to the goal in the ik
+ * solver.
+ * - num_segments is the number of segments in the array pointed
+ * to by the member segments.
+ * - chain_dof is the number of degrees of freedom of the chain
+ * that is the number of independent ways the chain can be changed
+ * to reach the goal.
+ * - segments points to an array of IK_Segment_Extern structs
+ * containing the segments of this chain.
+ * - intern is pointer used by the module to store information
+ * about the chain. Please do not touch the member in any way.
+ */
+
+typedef struct IK_Chain_Extern {
+ int num_segments;
+ int chain_dof;
+ IK_Segment_ExternPtr segments;
+ void * intern;
+} IK_Chain_Extern;
+
+typedef IK_Chain_Extern* IK_Chain_ExternPtr;
+
+
+/**
+ * Create a clean chain structure.
+ * @return A IK_Chain_Extern structure allocated on the heap.
+ * Do not attempt to delete or free this memory yourself please
+ * use the FreeChain(...) function for this.
+ */
+
+extern IK_Chain_ExternPtr IK_CreateChain(void);
+
+/**
+ * Copy segment information into the chain structure.
+ * @param chain A chain to load the segments into.
+ * @param segments a ptr to an array of IK_Input_Segment_Extern structures
+ * @param num_segs the number of segments to load into the chain
+ * @return 1 if the chain was correctly loaded into the structure.
+ * @return 0 if an error occured loading the chain. This will normally
+ * occur when there is not enough memory to allocate internal chain data.
+ * In this case you should not use the chain structure and should call
+ * IK_FreeChain to free the memory associated with the chain.
+ */
+
+extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs);
+
+/**
+ * Compute the solution of an inverse kinematic problem.
+ * @param chain a ptr to an IK_Segment_Extern loaded with the segments
+ * to solve for.
+ * @param goal the goal of the IK problem
+ * @param tolerance .The distance to the solution within which the chain is deemed
+ * to be solved.
+ * @param max_iterations. The maximum number of iterations to use in solving the
+ * problem.
+ * @param max_angle_change. The maximum allowed angular change. 0.1 is a good value here.
+ * @param output. Results of the solution are written to the segments pointed to by output.
+ * Only the basis and basis_change fields are written. You must make sure that you have
+ * allocated enough room for the output segments.
+ * @return 0 if the solved chain did not reach the goal. This occurs when the
+ * goal was unreachable by the chain end effector.
+ * @return 1 if the chain reached the goal.
+ */
+
+extern int IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+);
+
+/**
+ * Free a chain and all it's internal memory.
+ */
+
+extern void IK_FreeChain(IK_Chain_ExternPtr);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // NAN_INCLUDED_IK_solver_h \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_CGChainSolver.cpp b/intern/iksolver/intern/IK_CGChainSolver.cpp
new file mode 100644
index 00000000000..6af4df2a35b
--- /dev/null
+++ b/intern/iksolver/intern/IK_CGChainSolver.cpp
@@ -0,0 +1,300 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_CGChainSolver.h"
+
+#include "IK_Segment.h"
+
+using namespace std;
+
+ ChainPotential *
+ChainPotential::
+New(
+ IK_Chain &chain
+){
+ return new ChainPotential(chain);
+};
+
+
+
+// End effector goal
+
+ void
+ChainPotential::
+SetGoal(
+ const MT_Vector3 goal
+){
+ m_goal = goal;
+};
+
+// Inherited from DifferentiablePotenialFunctionNd
+//////////////////////////////////////////////////
+
+ MT_Scalar
+ChainPotential::
+Evaluate(
+ MT_Scalar x
+){
+
+ // evaluate the function at postiion x along the line specified
+ // by the vector pair (m_line_pos,m_line_dir)
+
+ m_temp_pos.newsize(m_line_dir.size());
+
+ TNT::vectorscale(m_temp_pos,m_line_dir,x);
+ TNT::vectoradd(m_temp_pos,m_line_pos);
+
+ return Evaluate(m_temp_pos);
+}
+
+ MT_Scalar
+ChainPotential::
+Derivative(
+ MT_Scalar x
+){
+ m_temp_pos.newsize(m_line_dir.size());
+ m_temp_grad.newsize(m_line_dir.size());
+
+ TNT::vectorscale(m_temp_pos,m_line_dir,x);
+ TNT::vectoradd(m_temp_pos,m_line_pos);
+
+ Derivative(m_temp_pos,m_temp_grad);
+
+ return TNT::dot_prod(m_temp_grad,m_line_dir);
+}
+
+
+ MT_Scalar
+ChainPotential::
+Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+){
+
+
+ // set the vector of angles in the backup chain
+
+ vector<IK_Segment> &segs = m_t_chain.Segments();
+ vector<IK_Segment>::iterator seg_it = segs.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin();
+#if 0
+ TNT::Vector<MT_Scalar>::const_iterator a_end = x.end();
+#endif
+ // while we are iterating through the angles and segments
+ // we compute the current angle potenial
+ MT_Scalar angle_potential = 0;
+#if 0
+
+ for (; a_it != a_end; ++a_it, ++seg_it) {
+
+ MT_Scalar dif = (*a_it - seg_it->CentralAngle());
+ dif *= dif * seg_it->Weight();
+ angle_potential += dif;
+ seg_it->SetTheta(*a_it);
+ }
+#endif
+
+ int chain_dof = m_t_chain.DoF();
+ int n;
+
+ for (n=0; n < chain_dof;seg_it ++) {
+ n += seg_it->SetAngles(a_it + n);
+ }
+
+
+ m_t_chain.UpdateGlobalTransformations();
+
+ MT_Scalar output = (DistancePotential(m_t_chain.EndEffector(),m_goal) + angle_potential);
+
+ return output;
+};
+
+ void
+ChainPotential::
+Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+){
+
+ m_distance_grad.newsize(3);
+ // set the vector of angles in the backup chain
+
+ vector<IK_Segment> & segs = m_t_chain.Segments();
+ vector<IK_Segment>::iterator seg_it = segs.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_it = x.begin();
+ TNT::Vector<MT_Scalar>::const_iterator a_end = x.end();
+
+ m_angle_grad.newsize(segs.size());
+ m_angle_grad = 0;
+#if 0
+ // FIXME compute angle gradients
+ TNT::Vector<MT_Scalar>::iterator ag_it = m_angle_grad.begin();
+#endif
+
+ const int chain_dof = m_t_chain.DoF();
+ for (int n=0; n < chain_dof;seg_it ++) {
+ n += seg_it->SetAngles(a_it + n);
+ }
+
+ m_t_chain.UpdateGlobalTransformations();
+ m_t_chain.ComputeJacobian();
+
+ DistanceGradient(m_t_chain.EndEffector(),m_goal);
+
+ // use chain rule for calculating derivative
+ // of potenial function
+ TNT::matmult(dy,m_t_chain.TransposedJacobian(),m_distance_grad);
+#if 0
+ TNT::vectoradd(dy,m_angle_grad);
+#endif
+
+};
+
+
+ MT_Scalar
+ChainPotential::
+DistancePotential(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+) const {
+ return (pos - goal).length2();
+}
+
+// update m_distance_gradient
+
+ void
+ChainPotential::
+DistanceGradient(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+){
+
+ MT_Vector3 output = 2*(pos - goal);
+ m_distance_grad.newsize(3);
+
+ m_distance_grad[0] = output.x();
+ m_distance_grad[1] = output.y();
+ m_distance_grad[2] = output.z();
+}
+
+
+ IK_CGChainSolver *
+IK_CGChainSolver::
+New(
+){
+
+ MEM_SmartPtr<IK_CGChainSolver> output (new IK_CGChainSolver());
+ MEM_SmartPtr<IK_ConjugateGradientSolver>solver (IK_ConjugateGradientSolver::New());
+
+ if (output == NULL || solver == NULL) return NULL;
+
+ output->m_grad_solver = solver.Release();
+ return output.Release();
+};
+
+
+ bool
+IK_CGChainSolver::
+Solve(
+ IK_Chain & chain,
+ MT_Vector3 new_position,
+ MT_Scalar tolerance
+){
+
+ // first build a potenial function for the chain
+
+ m_potential = ChainPotential::New(chain);
+ if (m_potential == NULL) return false;
+
+ m_potential->SetGoal(new_position);
+
+ // make a TNT::vector to describe the current
+ // chain state
+
+ TNT::Vector<MT_Scalar> p;
+ p.newsize(chain.DoF());
+
+ TNT::Vector<MT_Scalar>::iterator p_it = p.begin();
+ vector<IK_Segment>::const_iterator seg_it = chain.Segments().begin();
+ vector<IK_Segment>::const_iterator seg_end = chain.Segments().end();
+
+ for (; seg_it != seg_end; seg_it++) {
+
+ int i;
+ int seg_dof = seg_it->DoF();
+ for (i=0; i < seg_dof; ++i,++p_it) {
+ *p_it = seg_it->ActiveAngle(i);
+ }
+ }
+
+ // solve the thing
+ int iterations(0);
+ MT_Scalar return_value(0);
+
+ m_grad_solver->Solve(
+ p,
+ tolerance,
+ iterations,
+ return_value,
+ m_potential.Ref(),
+ 100
+ );
+
+ // update this chain
+
+ vector<IK_Segment>::iterator out_seg_it = chain.Segments().begin();
+ TNT::Vector<MT_Scalar>::const_iterator p_cit = p.begin();
+
+ const int chain_dof = chain.DoF();
+ int n;
+
+ for (n=0; n < chain_dof;out_seg_it ++) {
+ n += out_seg_it->SetAngles(p_cit + n);
+ }
+
+ chain.UpdateGlobalTransformations();
+ chain.ComputeJacobian();
+
+ return true;
+}
+
+IK_CGChainSolver::
+~IK_CGChainSolver(
+){
+ //nothing to do
+};
+
+
+IK_CGChainSolver::
+IK_CGChainSolver(
+){
+ //nothing to do;
+};
+
diff --git a/intern/iksolver/intern/IK_CGChainSolver.h b/intern/iksolver/intern/IK_CGChainSolver.h
new file mode 100644
index 00000000000..f7aeee090a1
--- /dev/null
+++ b/intern/iksolver/intern/IK_CGChainSolver.h
@@ -0,0 +1,178 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef CGChainSolver_h
+
+#define CGChainSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "IK_ConjugateGradientSolver.h"
+#include "IK_Chain.h"
+#include "MT_Scalar.h"
+#include "TNT/vec.h"
+#include "MEM_SmartPtr.h"
+
+
+/**
+ * This class is a concrete differentiable potenial function for
+ * an IK_Chain representing the distance to the goal.
+ * @warning This method of solving IK problems is not as good
+ * as IK_JacobianSolver. I advise you to use that class instead.
+ */
+
+class ChainPotential :
+public DifferentiablePotenialFunctionNd
+{
+public :
+
+ static
+ ChainPotential *
+ New(
+ IK_Chain &chain
+ );
+
+ // End effector goal
+
+ void
+ SetGoal(
+ const MT_Vector3 goal
+ );
+
+ // Inherited from DifferentiablePotenialFunctionNd
+ //////////////////////////////////////////////////
+
+ MT_Scalar
+ Evaluate(
+ const MT_Scalar x
+ );
+
+ MT_Scalar
+ Derivative(
+ const MT_Scalar x
+ );
+
+ MT_Scalar
+ Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+ );
+
+ void
+ Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+ );
+
+ // return the dimension of the domain of the potenial
+ // function
+
+ int
+ Dimension(
+ ) const {
+ return m_dimension;
+ }
+
+ ~ChainPotential(
+ ){
+ };
+
+private :
+
+ MT_Scalar
+ DistancePotential(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+ ) const;
+
+ void
+ DistanceGradient(
+ MT_Vector3 pos,
+ MT_Vector3 goal
+ );
+
+ ChainPotential(
+ IK_Chain & chain
+ ) :
+ DifferentiablePotenialFunctionNd(),
+ m_chain(chain),
+ m_t_chain(chain),
+ m_dimension (chain.Segments().size())
+ {
+ };
+
+ MT_Vector3 m_goal;
+ TNT::Vector<MT_Scalar> m_distance_grad;
+ TNT::Vector<MT_Scalar> m_angle_grad;
+ TNT::Vector<MT_Scalar> m_temp_pos;
+ TNT::Vector<MT_Scalar> m_temp_grad;
+
+ TNT::Vector<MT_Scalar> m_original_pos;
+ int m_dimension;
+
+ IK_Chain &m_chain;
+ IK_Chain m_t_chain; // deep copy
+
+};
+
+
+class IK_CGChainSolver : public MEM_NonCopyable
+{
+public :
+
+
+ static
+ IK_CGChainSolver *
+ New(
+ );
+
+ bool
+ Solve(
+ IK_Chain & chain,
+ MT_Vector3 new_position,
+ MT_Scalar tolerance
+ );
+
+ ~IK_CGChainSolver();
+
+private :
+
+ IK_CGChainSolver(
+ );
+
+ MEM_SmartPtr<ChainPotential> m_potential;
+ MEM_SmartPtr<IK_ConjugateGradientSolver> m_grad_solver;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_Chain.cpp b/intern/iksolver/intern/IK_Chain.cpp
new file mode 100644
index 00000000000..875b8da1405
--- /dev/null
+++ b/intern/iksolver/intern/IK_Chain.cpp
@@ -0,0 +1,208 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_Chain.h"
+
+
+using namespace std;
+
+IK_Chain::
+IK_Chain(
+)
+{
+ // nothing to do;
+};
+
+const
+ vector<IK_Segment> &
+IK_Chain::
+Segments(
+) const {
+ return m_segments;
+};
+
+ vector<IK_Segment> &
+IK_Chain::
+Segments(
+){
+ return m_segments;
+};
+
+ void
+IK_Chain::
+UpdateGlobalTransformations(
+){
+
+ // now iterate through the segment list
+ // compute their local transformations if needed
+
+ // assign their global transformations
+ // (relative to chain origin)
+
+ vector<IK_Segment>::const_iterator s_end = m_segments.end();
+ vector<IK_Segment>::iterator s_it = m_segments.begin();
+
+ MT_Transform global;
+
+ global.setIdentity();
+
+ for (; s_it != s_end; ++s_it) {
+ s_it->UpdateGlobal(global);
+ global = s_it->GlobalTransform();
+ }
+ // compute the position of the end effector and it's pose
+
+ const MT_Transform &last_t = m_segments.back().GlobalTransform();
+ m_end_effector = last_t.getOrigin();
+
+ MT_Matrix3x3 last_basis = last_t.getBasis();
+ last_basis.transpose();
+ MT_Vector3 m_end_pose = last_basis[2];
+
+
+};
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_Chain::
+Jacobian(
+) const {
+ return m_jacobian;
+} ;
+
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_Chain::
+TransposedJacobian(
+) const {
+ return m_t_jacobian;
+};
+
+ void
+IK_Chain::
+ComputeJacobian(
+){
+ // let's assume that the chain's global transfomations
+ // have already been computed.
+
+ int dof = DoF();
+
+ int num_segs = m_segments.size();
+ vector<IK_Segment>::const_iterator segs = m_segments.begin();
+
+ m_t_jacobian.newsize(dof,3);
+ m_jacobian.newsize(3,dof);
+
+ // compute the transposed jacobian first
+
+ int n;
+ int i = 0;
+
+
+ for (n= 0; n < num_segs; n++) {
+
+ const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis();
+ const MT_Vector3 &origin = segs[n].GlobalSegmentStart();
+
+ MT_Vector3 p = origin-m_end_effector;
+
+ // iterate through the active angle vectors of this segment
+
+ int angle_ind =0;
+ int seg_dof = segs[n].DoF();
+
+ const std::vector<MT_Vector3> & angle_vectors = segs[n].AngleVectors();
+
+ for (angle_ind = 0;angle_ind <seg_dof; angle_ind++,i++) {
+
+ MT_Vector3 angle_axis = angle_vectors[angle_ind];
+
+ MT_Vector3 a = basis * angle_axis;
+ MT_Vector3 pca = p.cross(a);
+
+ m_t_jacobian(i + 1,1) = pca.x();
+ m_t_jacobian(i + 1,2) = pca.y();
+ m_t_jacobian(i + 1,3) = pca.z();
+
+ }
+ }
+
+ // get the origina1 jacobain
+
+ TNT::transpose(m_t_jacobian,m_jacobian);
+};
+
+ MT_Vector3
+IK_Chain::
+EndEffector(
+) const {
+ return m_end_effector;
+};
+
+ MT_Vector3
+IK_Chain::
+EndPose(
+) const {
+ return m_end_pose;
+};
+
+
+ int
+IK_Chain::
+DoF(
+) const {
+
+ // iterate through the segs and compute the DOF
+
+ vector<IK_Segment>::const_iterator s_end = m_segments.end();
+ vector<IK_Segment>::const_iterator s_it = m_segments.begin();
+
+ int dof = 0;
+
+ for (;s_it != s_end; ++s_it) {
+ dof += s_it->DoF();
+ }
+
+ return dof;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Chain.h b/intern/iksolver/intern/IK_Chain.h
new file mode 100644
index 00000000000..40496b6087a
--- /dev/null
+++ b/intern/iksolver/intern/IK_Chain.h
@@ -0,0 +1,194 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_Chain_h
+
+#define NAN_INCLUDED_IK_Chain_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "IK_Segment.h"
+#include <vector>
+#include "MT_Scalar.h"
+#include "TNT/cmat.h"
+
+/**
+ * This class is a collection of ordered segments that are used
+ * in an Inverse Kinematic solving routine. An IK solver operating
+ * on the chain, will in general manipulate all the segments of the
+ * chain in order to solve the IK problem.
+ *
+ * To build a chain use the default constructor. Once built it's
+ * then possible to add IK_Segments to the chain by inserting
+ * them into the vector of IK_Segments. Note that segments will be
+ * copied into the chain so chain's cannot share instances of
+ * IK_Segments.
+ *
+ * You have full control of which segments form the chain via the
+ * the std::vector routines.
+ */
+class IK_Chain{
+
+public :
+
+ /**
+ * Construct a IK_Chain with no segments.
+ */
+
+ IK_Chain(
+ );
+
+ // IK_Chains also have the default copy constructors
+ // available.
+
+ /**
+ * Const access to the array of segments
+ * comprising the IK_Chain. Used for rendering
+ * etc
+ * @return a vector of segments
+ */
+
+ const
+ std::vector<IK_Segment> &
+ Segments(
+ ) const ;
+
+
+ /**
+ * Full access to segments used to initialize
+ * the IK_Chain and manipulate the segments.
+ * Use the push_back() method of std::vector to add
+ * segments in order to the chain
+ */
+
+ std::vector<IK_Segment> &
+ Segments(
+ );
+
+
+ /**
+ * Force the IK_Chain to recompute all the local
+ * segment transformations and composite them
+ * to calculate the global transformation for
+ * each segment. Must be called before
+ * ComputeJacobian()
+ */
+
+ void
+ UpdateGlobalTransformations(
+ );
+
+ /**
+ * Return the global position of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndEffector(
+ ) const;
+
+
+ /**
+ * Return the global pose of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndPose(
+ ) const;
+
+
+ /**
+ * Calculate the jacobian matrix for
+ * the current end effector position.
+ * A jacobian is the set of column vectors
+ * of partial derivatives for each active angle.
+ * This method also computes the transposed jacobian.
+ * @pre You must have updated the global transformations
+ * of the chain's segments before a call to this method. Do this
+ * with UpdateGlobalTransformation()
+ */
+
+ void
+ ComputeJacobian(
+ );
+
+
+ /**
+ * @return A reference to the last computed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ Jacobian(
+ ) const ;
+
+ /**
+ * @return A reference to the last computed transposed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ TransposedJacobian(
+ ) const ;
+
+ /**
+ * Count the degrees of freedom in the IK_Chain
+ * @warning store this value rather than using this function
+ * as the termination value of a for loop etc.
+ */
+
+ int
+ DoF(
+ ) const;
+
+
+private :
+
+ /// The vector of segments comprising the chain
+ std::vector<IK_Segment> m_segments;
+
+ /// The jacobain of the IK_Chain
+ TNT::Matrix<MT_Scalar> m_jacobian;
+
+ /// It's transpose
+ TNT::Matrix<MT_Scalar> m_t_jacobian;
+
+ MT_Vector3 m_end_effector;
+ MT_Vector3 m_end_pose;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp
new file mode 100644
index 00000000000..028b7dfe2b0
--- /dev/null
+++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.cpp
@@ -0,0 +1,162 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_ConjugateGradientSolver.h"
+
+
+#define EPS 1.0e-10
+
+ IK_ConjugateGradientSolver *
+IK_ConjugateGradientSolver::
+New(
+){
+ return new IK_ConjugateGradientSolver();
+};
+
+IK_ConjugateGradientSolver::
+~IK_ConjugateGradientSolver(
+){
+ //nothing to do
+};
+
+// Compute the minimum of the potenial function
+// starting at point p. On return p contains the
+// computed minima, iter the number of iterations performed,
+// fret the potenial value at the minima
+
+ void
+IK_ConjugateGradientSolver::
+Solve(
+ TNT::Vector<MT_Scalar> &p,
+ MT_Scalar ftol,
+ int &iter,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial,
+ int max_its
+){
+
+ int j;
+ MT_Scalar gg,gam,fp,dgg;
+
+ int n = potenial.Dimension();
+ ArmVectors(n);
+
+ // initialize --- FIXME we probably have these
+ // values to hand already.
+
+ fp = potenial.Evaluate(p);
+ potenial.Derivative(p,m_xi);
+
+ for (j = 1; j<=n; j++) {
+ m_g(j) = -m_xi(j);
+ m_xi(j) = m_h(j) = m_g(j);
+ }
+ for (iter =1;iter <= max_its; iter++) {
+ LineMinimize(p,m_xi,fret,potenial);
+
+ if (2 *TNT::abs(fret-fp) <= ftol*(TNT::abs(fret) + TNT::abs(fp) + EPS)) {
+ return;
+ }
+ fp = fret;
+ potenial.Derivative(p,m_xi);
+ dgg = gg = 0.0;
+
+ for (j = 1; j<=n;j++) {
+ gg += m_g(j)*m_g(j);
+ //dgg+= xi(j)*xi(j);
+ dgg += (m_xi(j) + m_g(j))*m_xi(j);
+ }
+ if (gg == 0.0) {
+ return;
+ }
+ gam = dgg/gg;
+
+ for (j = 1; j<=n; j++) {
+ m_g(j) = -m_xi(j);
+ m_xi(j) = m_h(j) = m_g(j) + gam*m_h(j);
+ }
+ }
+ // FIXME throw exception
+ //assert(false);
+};
+
+
+IK_ConjugateGradientSolver::
+IK_ConjugateGradientSolver(
+){
+ //nothing to do
+}
+
+ void
+IK_ConjugateGradientSolver::
+ArmVectors(
+ int dimension
+){
+ m_g.newsize(dimension);
+ m_h.newsize(dimension);
+ m_xi.newsize(dimension);
+ m_xi_temp.newsize(dimension);
+};
+
+ void
+IK_ConjugateGradientSolver::
+LineMinimize(
+ TNT::Vector<MT_Scalar> & p,
+ const TNT::Vector<MT_Scalar> & xi,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial
+){
+ MT_Scalar ax(0),bx(1); // initial bracket guess
+ MT_Scalar cx,fa,fb,fc;
+
+ MT_Scalar xmin(0); // the 1d function minima
+
+ potenial.SetLineVector(p,xi);
+ IK_LineMinimizer::InitialBracket1d(ax,bx,cx,fa,fb,fc,potenial);
+ fret = IK_LineMinimizer::DerivativeBrent1d(ax,bx,cx,potenial,xmin,0.001);
+
+ // x_min in minimum along line and corresponds with
+ // p[] + x_min *xi[]
+
+ TNT::vectorscale(m_xi_temp,xi,xmin);
+ TNT::vectoradd(p,m_xi_temp);
+};
+
+
+#undef EPS
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_ConjugateGradientSolver.h b/intern/iksolver/intern/IK_ConjugateGradientSolver.h
new file mode 100644
index 00000000000..e50799a9fa1
--- /dev/null
+++ b/intern/iksolver/intern/IK_ConjugateGradientSolver.h
@@ -0,0 +1,195 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_ConjugateGradientSolver_h
+
+#define NAN_INCLUDED_IK_ConjugateGradientSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include "MT_Scalar.h"
+#include "IK_LineMinimizer.h"
+
+/**
+ * These classes locally minimize n dimensional potenial functions.
+ * See Numerical Recipes in C www.nr.com for more details.
+ * If a n dimensionable potenial function is
+ * differentiable, then it is diferentiable along
+ * any vector x. This can be found by the dot product
+ * of the gradient operator with x.
+ * The conjugate gradient solver boils down to
+ * a collection of line minimizations along various lines
+ * defined by position,direction pairs. There are
+ * methods in this class to set the lines along which
+ * minimizations via the DiffentiablePotenialFunction1d interface
+ * are to be performed.
+ *
+ * @warning I don't like data inheritance but it is the most efficient
+ * wasy to do this here.
+ */
+
+
+class DifferentiablePotenialFunctionNd
+: public DifferentiablePotenialFunction1d
+{
+public :
+
+ /**
+ * Inherited from DiffentiablePotenialFunction1d
+ *
+ * virtual
+ * MT_Scalar
+ * Evaluate1d(
+ * MT_Scalar x
+ * ) = 0;
+ *
+ * virtual
+ * MT_Scalar
+ * Derivative1d(
+ * MT_Scalar x
+ * ) = 0;
+ */
+
+ /// Methods to set the current line in N dimensions
+
+ void
+ SetLineVector(
+ const TNT::Vector<MT_Scalar> &pos,
+ const TNT::Vector<MT_Scalar> &dir
+ ){
+ m_line_pos = pos;
+ m_line_dir = dir;
+ };
+
+ virtual
+ MT_Scalar
+ Evaluate(
+ const TNT::Vector<MT_Scalar> &x
+ ) = 0;
+
+ virtual
+ void
+ Derivative(
+ const TNT::Vector<MT_Scalar> &x,
+ TNT::Vector<MT_Scalar> &dy
+ ) = 0;
+
+ /// @return The dimension of the domain of the potenial function
+
+ virtual
+ int
+ Dimension(
+ ) const =0;
+
+ virtual
+ ~DifferentiablePotenialFunctionNd(
+ ){
+ };
+
+protected :
+
+ DifferentiablePotenialFunctionNd(){};
+
+ TNT::Vector<MT_Scalar> m_line_pos;
+ TNT::Vector<MT_Scalar> m_line_dir;
+
+};
+
+
+class IK_ConjugateGradientSolver
+: public MEM_NonCopyable
+{
+public :
+
+ /**
+ * This class necessarily needs some (potenially large)
+ * temporary vectors to aid computation. We therefore
+ * insist creation of these objects on the heap.
+ */
+
+ static
+ IK_ConjugateGradientSolver *
+ New(
+ );
+
+ /**
+ * Compute the minimum of the potenial function
+ * starting at point p. On return p contains the
+ * computed minima, iter the number of iterations performed,
+ * fret the potenial value at the minima
+ */
+
+ void
+ Solve(
+ TNT::Vector<MT_Scalar> &p,
+ MT_Scalar ftol,
+ int &iter,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial,
+ int max_its = 200
+ );
+
+ ~IK_ConjugateGradientSolver(
+ );
+
+private :
+ void
+ LineMinimize(
+ TNT::Vector<MT_Scalar> & p,
+ const TNT::Vector<MT_Scalar> & xi,
+ MT_Scalar &fret,
+ DifferentiablePotenialFunctionNd &potenial
+ );
+
+ IK_ConjugateGradientSolver(
+ );
+
+ void
+ ArmVectors(
+ int dimension
+ );
+
+
+ TNT::Vector<MT_Scalar> m_g;
+ TNT::Vector<MT_Scalar> m_h;
+ TNT::Vector<MT_Scalar> m_xi;
+
+ TNT::Vector<MT_Scalar> m_xi_temp;
+
+};
+
+#endif
+
+
diff --git a/intern/iksolver/intern/IK_JacobianSolver.cpp b/intern/iksolver/intern/IK_JacobianSolver.cpp
new file mode 100644
index 00000000000..de4531f1677
--- /dev/null
+++ b/intern/iksolver/intern/IK_JacobianSolver.cpp
@@ -0,0 +1,267 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_JacobianSolver.h"
+
+#include "TNT/svd.h"
+
+using namespace std;
+
+ IK_JacobianSolver *
+IK_JacobianSolver::
+New(
+){
+ return new IK_JacobianSolver();
+}
+
+ bool
+IK_JacobianSolver::
+Solve(
+ IK_Chain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+){
+
+ ArmMatrices(chain.DoF());
+
+ for (int iterations = 0; iterations < max_iterations; iterations++) {
+
+
+ MT_Vector3 end_effector = chain.EndEffector();
+
+ MT_Vector3 d_pos = g_position - end_effector;
+ const MT_Scalar x_length = d_pos.length();
+
+ if (x_length < tolerance) {
+ return true;
+ }
+
+ chain.ComputeJacobian();
+ ComputeInverseJacobian(chain,x_length,max_angle_change);
+
+ ComputeBetas(chain,d_pos);
+ UpdateChain(chain);
+ chain.UpdateGlobalTransformations();
+ }
+
+ return false;
+};
+
+IK_JacobianSolver::
+~IK_JacobianSolver(
+){
+ // nothing to do
+}
+
+
+IK_JacobianSolver::
+IK_JacobianSolver(
+){
+ // nothing to do
+};
+
+ void
+IK_JacobianSolver::
+ComputeBetas(
+ IK_Chain &chain,
+ const MT_Vector3 d_pos
+){
+
+ m_beta = 0;
+
+ m_beta[0] = d_pos.x();
+ m_beta[1] = d_pos.y();
+ m_beta[2] = d_pos.z();
+
+ TNT::matmult(m_d_theta,m_svd_inverse,m_beta);
+
+};
+
+
+ int
+IK_JacobianSolver::
+ComputeInverseJacobian(
+ IK_Chain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+) {
+
+ int dimension = 0;
+
+ m_svd_u = 0;
+
+ // copy first 3 rows of jacobian into m_svd_u
+
+ int row, column;
+
+ for (row = 0; row < 3; row ++) {
+ for (column = 0; column < chain.Jacobian().num_cols(); column ++) {
+ m_svd_u[row][column] = chain.Jacobian()[row][column];
+ }
+ }
+
+ m_svd_w = 0;
+ m_svd_v = 0;
+
+ TNT::SVD(m_svd_u,m_svd_w,m_svd_v);
+
+ // invert the SVD and compute inverse
+
+ TNT::transpose(m_svd_v,m_svd_v_t);
+ TNT::transpose(m_svd_u,m_svd_u_t);
+
+ // Compute damped least squares inverse of pseudo inverse
+ // Compute damping term lambda
+
+ // Note when lambda is zero this is equivalent to the
+ // least squares solution. This is fine when the m_jjt is
+ // of full rank. When m_jjt is near to singular the least squares
+ // inverse tries to minimize |J(dtheta) - dX)| and doesn't
+ // try to minimize dTheta. This results in eratic changes in angle.
+ // Damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
+
+ // We don't want to use the damped solution everywhere so we
+ // only increase lamda from zero as we approach a singularity.
+
+ // find the smallest non-zero m_svd_w value
+
+ int i = 0;
+
+ MT_Scalar w_min = MT_INFINITY;
+
+ // anything below epsilon is treated as zero
+
+ MT_Scalar epsilon = 1e-10;
+
+ for ( i = 0; i <m_svd_w.size() ; i++) {
+
+ if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
+ w_min = m_svd_w[i];
+ }
+ }
+ MT_Scalar lambda = 0;
+
+ MT_Scalar d = x_length/max_angle_change;
+
+ if (w_min <= d/2) {
+ lambda = d/2;
+ } else
+ if (w_min < d) {
+ lambda = sqrt(w_min*(d - w_min));
+ } else {
+ lambda = 0;
+ }
+
+ lambda *= lambda;
+
+ for (i= 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] < epsilon) {
+ m_svd_w[i] = 0;
+ } else {
+ m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ }
+ }
+
+ m_svd_w_diag.diagonal(m_svd_w);
+
+ // FIXME optimize these matrix multiplications
+ // using the fact that m_svd_w_diag is diagonal!
+
+ TNT::matmult(m_svd_temp1,m_svd_w_diag,m_svd_u_t);
+ TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1);
+ return dimension;
+
+}
+
+ void
+IK_JacobianSolver::
+UpdateChain(
+ IK_Chain &chain
+){
+
+ // iterate through the set of angles and
+ // update their values from the d_thetas
+
+ int n;
+ vector<IK_Segment> &segs = chain.Segments();
+
+ int chain_dof = chain.DoF();
+ int seg_ind = 0;
+ for (n=0; n < chain_dof;seg_ind ++) {
+ n += segs[seg_ind].IncrementAngles(m_d_theta.begin() + n);
+ }
+};
+
+ void
+IK_JacobianSolver::
+ArmMatrices(
+ int dof
+){
+
+ m_beta.newsize(dof);
+ m_d_theta.newsize(dof);
+
+ m_svd_u.newsize(dof,dof);
+ m_svd_v.newsize(dof,dof);
+ m_svd_w.newsize(dof);
+
+ m_svd_u = 0;
+ m_svd_v = 0;
+ m_svd_w = 0;
+
+ m_svd_u_t.newsize(dof,dof);
+ m_svd_v_t.newsize(dof,dof);
+ m_svd_w_diag.newsize(dof,dof);
+ m_svd_inverse.newsize(dof,dof);
+ m_svd_temp1.newsize(dof,dof);
+
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_JacobianSolver.h b/intern/iksolver/intern/IK_JacobianSolver.h
new file mode 100644
index 00000000000..3f3372a2cb7
--- /dev/null
+++ b/intern/iksolver/intern/IK_JacobianSolver.h
@@ -0,0 +1,171 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_JacobianSolver_h
+
+#define NAN_INCLUDED_IK_JacobianSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include <vector>
+#include "MT_Vector3.h"
+#include "IK_Chain.h"
+
+class IK_JacobianSolver {
+
+public :
+
+ /**
+ * Create a new IK_JacobianSolver on the heap
+ * @return A newly created IK_JacobianSolver you take ownership of the object
+ * and responsibility for deleting it
+ */
+
+
+ static
+ IK_JacobianSolver *
+ New(
+ );
+
+ /**
+ * Compute a solution for a chain.
+ * @param chain Reference to the chain to modify
+ * @param g_position Reference to the goal position.
+ * @param g_pose -not used- Reference to the goal pose.
+ * @param tolerance The maximum allowed distance between solution
+ * and goal for termination.
+ * @param max_iterations should be in the range (50 - 500)
+ * @param max_angle_change The maximum change in the angle vector
+ * of the chain (0.1 is a good value)
+ *
+ * @return True iff goal position reached.
+ */
+
+ bool
+ Solve(
+ IK_Chain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+ );
+
+ ~IK_JacobianSolver(
+ );
+
+
+private :
+
+ /**
+ * Private constructor to force use of New()
+ */
+
+ IK_JacobianSolver(
+ );
+
+
+ /**
+ * Compute the inverse jacobian matrix of the chain.
+ * Uses a damped least squares solution when the matrix is
+ * is approaching singularity
+ */
+
+ int
+ ComputeInverseJacobian(
+ IK_Chain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+ );
+
+ void
+ ComputeBetas(
+ IK_Chain &chain,
+ const MT_Vector3 d_pos
+ );
+
+ /**
+ * Updates the angles of the chain with the newly
+ * computed values
+ **/
+
+ void
+ UpdateChain(
+ IK_Chain &chain
+ );
+
+ /**
+ * Make sure all the matrices are of the correct size
+ **/
+
+ void
+ ArmMatrices(
+ int dof
+ );
+
+
+private :
+
+ /// the vector of intermediate betas
+ TNT::Vector<MT_Scalar> m_beta;
+
+ /// the vector of computed angle changes
+ TNT::Vector<MT_Scalar> m_d_theta;
+
+ /// the contraint gradients for each angle.
+ TNT::Vector<MT_Scalar> m_dh;
+
+ /// Space required for SVD computation
+
+ TNT::Vector<MT_Scalar> m_svd_w;
+ TNT::Matrix<MT_Scalar> m_svd_v;
+ TNT::Matrix<MT_Scalar> m_svd_u;
+
+ TNT::Matrix<MT_Scalar> m_svd_w_diag;
+ TNT::Matrix<MT_Scalar> m_svd_v_t;
+ TNT::Matrix<MT_Scalar> m_svd_u_t;
+ TNT::Matrix<MT_Scalar> m_svd_inverse;
+ TNT::Matrix<MT_Scalar> m_svd_temp1;
+
+
+};
+
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/IK_LineMinimizer.h b/intern/iksolver/intern/IK_LineMinimizer.h
new file mode 100644
index 00000000000..635a5972c02
--- /dev/null
+++ b/intern/iksolver/intern/IK_LineMinimizer.h
@@ -0,0 +1,298 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_LineMinimizer_h
+
+#define NAN_INCLUDED_IK_LineMinimizer_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "MT_Scalar.h"
+#include <vector>
+#include "TNT/tntmath.h"
+#include "MEM_NonCopyable.h"
+
+
+
+#define GOLD 1.618034
+#define GLIMIT 100.0
+#define TINY 1.0e-20
+#define ZEPS 1.0e-10
+
+/**
+ * Routines for line - minization in n dimensions
+ * these should be templated on the potenial function
+ * p instead of using a virtual class. Please see
+ * numerical recipes in c for more details. www.nr.com
+ */
+
+class DifferentiablePotenialFunction1d {
+public :
+ virtual
+ MT_Scalar
+ Evaluate(
+ const MT_Scalar x
+ ) = 0;
+
+ virtual
+ MT_Scalar
+ Derivative(
+ const MT_Scalar x
+ ) = 0;
+};
+
+
+/**
+ * TODO get rid of this class and make some
+ * template functions in a seperate namespace
+ */
+
+class IK_LineMinimizer : public MEM_NonCopyable {
+
+public :
+
+ /**
+ * Before we proceed with line minimization
+ * we need to construct an initial bracket
+ * of a minima of the PotenialFunction
+ */
+
+ static
+ void
+ InitialBracket1d (
+ MT_Scalar &ax,
+ MT_Scalar &bx,
+ MT_Scalar &cx,
+ MT_Scalar &fa,
+ MT_Scalar &fb,
+ MT_Scalar &fc,
+ DifferentiablePotenialFunction1d &potenial
+ ) {
+ MT_Scalar ulim,u,r,q,fu;
+
+ fa = potenial.Evaluate(ax);
+ fb = potenial.Evaluate(bx);
+
+ if (fb > fa) {
+ std::swap(ax,bx);
+ std::swap(fa,fb);
+ }
+ cx = bx + GOLD*(bx-ax);
+ fc = potenial.Evaluate(cx);
+
+ while (fb > fc) {
+
+ r = (bx - ax) * (fb - fc);
+ q = (bx - cx) * (fb - fa);
+ u = bx - ((bx - cx)*q - (bx - ax) *r)/
+ (2 * TNT::sign(TNT::max(TNT::abs(q-r),TINY),q-r));
+ ulim = bx + GLIMIT*(cx-bx);
+
+ if ((bx-u)*(u-cx) > 0.0) {
+ fu = potenial.Evaluate(u);
+ if (fu < fc) {
+ ax = bx;
+ bx = u;
+ fa = fb;
+ fb = fu;
+ return;
+ } else if (fu > fb) {
+ cx = u;
+ fc = fu;
+ return;
+ }
+ u = cx + GOLD*(cx-bx);
+ fu = potenial.Evaluate(u);
+
+ } else if ((cx - u)*(u - ulim) > 0.0) {
+ fu = potenial.Evaluate(u);
+
+ if (fu < fc) {
+ bx = cx;
+ cx = u;
+ u = cx + GOLD*(cx - bx);
+ fb = fc;
+ fc = fu;
+ fu = potenial.Evaluate(u);
+ }
+ } else if ((u-ulim)*(ulim-cx) >=0.0) {
+ u = ulim;
+ fu = potenial.Evaluate(u);
+ } else {
+ u = cx + GOLD*(cx-bx);
+ fu = potenial.Evaluate(u);
+ }
+ ax = bx;
+ bx = cx;
+ cx = u;
+ fa = fb;
+ fb = fc;
+ fc = fu;
+ }
+ };
+
+ /**
+ * This is a 1 dimensional brent method for
+ * line-minization with derivatives
+ */
+
+
+ static
+ MT_Scalar
+ DerivativeBrent1d(
+ MT_Scalar ax,
+ MT_Scalar bx,
+ MT_Scalar cx,
+ DifferentiablePotenialFunction1d &potenial,
+ MT_Scalar &x_min,
+ const MT_Scalar tol,
+ int max_iter = 100
+ ) {
+ int iter;
+ bool ok1,ok2;
+ MT_Scalar a,b,d,d1,d2,du,dv,dw,dx,e(0);
+ MT_Scalar fu,fv,fw,fx,olde,tol1,tol2,u,u1,u2,v,w,x,xm;
+
+ a = (ax < cx ? ax : cx);
+ b = (ax > cx ? ax : cx);
+ x = w = v = bx;
+ fw = fv = fx = potenial.Evaluate(x);
+ dw = dv = dx = potenial.Derivative(x);
+
+ for (iter = 1; iter <= max_iter; iter++) {
+ xm = 0.5*(a+b);
+ tol1 = tol*fabs(x) + ZEPS;
+ tol2 = 2 * tol1;
+ if (fabs(x - xm) <= (tol2 - 0.5*(b-a))) {
+ x_min = x;
+ return fx;
+ }
+
+ if (fabs(e) > tol1) {
+ d1 = 2*(b-a);
+ d2 = d1;
+ if (dw != dx) {
+ d1 = (w-x)*dx/(dx-dw);
+ }
+ if (dv != dx) {
+ d2 = (v-x)*dx/(dx-dv);
+ }
+
+ u1 = x+d1;
+ u2 = x+d2;
+ ok1 = ((a-u1)*(u1-b) > 0.0) && ((dx*d1) <= 0.0);
+ ok2 = ((a-u2)*(u2-b) > 0.0) && ((dx*d2) <= 0.0);
+ olde = e;
+ e = d;
+
+ if (ok1 || ok2) {
+ if (ok1 && ok2) {
+ d = fabs(d1) < fabs(d2) ? d1 : d2;
+ } else if (ok1) {
+ d = d1;
+ } else {
+ d = d2;
+ }
+ if (fabs(d) <= fabs(0.5*olde)) {
+ u = x+d;
+ if ((u-a < tol2) || (b-u < tol2)) {
+ d = TNT::sign(tol1,xm-x);
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+ } else {
+ d = 0.5*(e = (dx >= 0.0 ? a-x : b-x));
+ }
+
+ if (fabs(d) >= tol1) {
+ u = x+d;
+ fu = potenial.Evaluate(u);
+ } else {
+ u = x + TNT::sign(tol1,d);
+ fu = potenial.Evaluate(u);
+ if (fu > fx) {
+ x_min = x;
+ return fx;
+ }
+ }
+ du = potenial.Derivative(u);
+ if (fu <= fx) {
+ if (u >= x) {
+ a = x;
+ } else {
+ b = x;
+ }
+ v = w; fv = fw; dv = dw;
+ w = x; fw = fx; dw = dx;
+ x = u; fx = fu; dx = du;
+ } else {
+ if (u < x) {
+ a = u;
+ } else {
+ b = u;
+ }
+ if (fu <= fw || w == x) {
+ v = w; fv = fw; dv = dw;
+ w = u; fw = fu; dw = du;
+ } else if ( fu < fv || v == x || v == w) {
+ v = u; fv = fu; dv = du;
+ }
+ }
+ }
+ // FIXME throw exception
+
+ assert(false);
+ return MT_Scalar(0);
+ };
+
+private :
+
+ /// This class just contains static helper methods so no instantiation
+
+ IK_LineMinimizer();
+
+};
+
+#undef GOLD
+#undef GLIMIT
+#undef TINY
+#undef ZEPS
+
+
+
+#endif
diff --git a/intern/iksolver/intern/IK_QChain.cpp b/intern/iksolver/intern/IK_QChain.cpp
new file mode 100644
index 00000000000..438729003a9
--- /dev/null
+++ b/intern/iksolver/intern/IK_QChain.cpp
@@ -0,0 +1,280 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "IK_QChain.h"
+
+using namespace std;
+
+IK_QChain::
+IK_QChain(
+)
+{
+ // nothing to do;
+};
+
+const
+ vector<IK_QSegment> &
+IK_QChain::
+Segments(
+) const {
+ return m_segments;
+};
+
+ vector<IK_QSegment> &
+IK_QChain::
+Segments(
+){
+ return m_segments;
+};
+
+ void
+IK_QChain::
+UpdateGlobalTransformations(
+){
+
+ // now iterate through the segment list
+ // compute their local transformations if needed
+
+ // assign their global transformations
+ // (relative to chain origin)
+
+ vector<IK_QSegment>::const_iterator s_end = m_segments.end();
+ vector<IK_QSegment>::iterator s_it = m_segments.begin();
+
+ MT_Transform global;
+ global.setIdentity();
+
+ for (; s_it != s_end; ++s_it) {
+ global = s_it->UpdateGlobal(global);
+ }
+
+ // we also need to compute the accumulated local transforms
+ // for each segment
+
+ MT_Transform acc_local;
+ acc_local.setIdentity();
+
+ vector<IK_QSegment>::reverse_iterator s_rit = m_segments.rbegin();
+ vector<IK_QSegment>::reverse_iterator s_rend = m_segments.rend();
+
+ for (; s_rit != s_rend; ++s_rit) {
+ acc_local = s_rit->UpdateAccumulatedLocal(acc_local);
+ }
+
+ // compute the position of the end effector and it's pose
+
+ const MT_Transform &last_t = m_segments.back().GlobalTransform();
+ m_end_effector = last_t.getOrigin();
+
+#if 0
+
+ // The end pose is not currently used.
+
+ MT_Matrix3x3 last_basis = last_t.getBasis();
+ last_basis.transpose();
+ MT_Vector3 m_end_pose = last_basis[1];
+
+#endif
+
+};
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_QChain::
+Jacobian(
+) const {
+ return m_jacobian;
+} ;
+
+
+const
+ TNT::Matrix<MT_Scalar> &
+IK_QChain::
+TransposedJacobian(
+) const {
+ return m_t_jacobian;
+};
+
+ void
+IK_QChain::
+ComputeJacobian(
+){
+ // let's assume that the chain's global transfomations
+ // have already been computed.
+
+ int dof = DoF();
+
+ int num_segs = m_segments.size();
+ vector<IK_QSegment>::const_iterator segs = m_segments.begin();
+
+ m_t_jacobian.newsize(dof,3);
+ m_jacobian.newsize(3,dof);
+
+ // compute the transposed jacobian first
+
+ int n;
+ int i = 0;
+
+ for (n= 0; n < num_segs; n++) {
+#if 0
+
+ // For euler angle computation we can use a slightly quicker method.
+
+ const MT_Matrix3x3 &basis = segs[n].GlobalTransform().getBasis();
+ const MT_Vector3 &origin = segs[n].GlobalSegmentStart();
+
+ const MT_Vector3 p = origin-m_end_effector;
+
+ const MT_Vector3 x_axis(1,0,0);
+ const MT_Vector3 y_axis(0,1,0);
+ const MT_Vector3 z_axis(0,0,1);
+
+ MT_Vector3 a = basis * x_axis;
+ MT_Vector3 pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 1,1) = pca.x();
+ m_t_jacobian(n*3 + 1,2) = pca.y();
+ m_t_jacobian(n*3 + 1,3) = pca.z();
+
+ a = basis * y_axis;
+ pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 2,1) = pca.x();
+ m_t_jacobian(n*3 + 2,2) = pca.y();
+ m_t_jacobian(n*3 + 2,3) = pca.z();
+
+ a = basis * z_axis;
+ pca = p.cross(a);
+
+ m_t_jacobian(n*3 + 3,1) = pca.x();
+ m_t_jacobian(n*3 + 3,2) = pca.y();
+ m_t_jacobian(n*3 + 3,3) = pca.z();
+#else
+ // user slower general jacobian computation method
+
+ MT_Vector3 j1 = segs[n].ComputeJacobianColumn(0);
+
+ m_t_jacobian(n*3 + 1,1) = j1.x();
+ m_t_jacobian(n*3 + 1,2) = j1.y();
+ m_t_jacobian(n*3 + 1,3) = j1.z();
+
+ j1 = segs[n].ComputeJacobianColumn(1);
+
+ m_t_jacobian(n*3 + 2,1) = j1.x();
+ m_t_jacobian(n*3 + 2,2) = j1.y();
+ m_t_jacobian(n*3 + 2,3) = j1.z();
+
+ j1 = segs[n].ComputeJacobianColumn(2);
+
+ m_t_jacobian(n*3 + 3,1) = j1.x();
+ m_t_jacobian(n*3 + 3,2) = j1.y();
+ m_t_jacobian(n*3 + 3,3) = j1.z();
+#endif
+
+
+
+ }
+
+
+ // get the origina1 jacobain
+
+ TNT::transpose(m_t_jacobian,m_jacobian);
+};
+
+ MT_Vector3
+IK_QChain::
+EndEffector(
+) const {
+ return m_end_effector;
+};
+
+ MT_Vector3
+IK_QChain::
+EndPose(
+) const {
+ return m_end_pose;
+};
+
+
+ int
+IK_QChain::
+DoF(
+) const {
+ return 3 * m_segments.size();
+}
+
+const
+ MT_Scalar
+IK_QChain::
+MaxExtension(
+) const {
+
+ vector<IK_QSegment>::const_iterator s_end = m_segments.end();
+ vector<IK_QSegment>::const_iterator s_it = m_segments.begin();
+
+ if (m_segments.size() == 0) return MT_Scalar(0);
+
+ MT_Scalar output = s_it->Length();
+
+ ++s_it ;
+ for (; s_it != s_end; ++s_it) {
+ output += s_it->MaxExtension();
+ }
+ return output;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_QChain.h b/intern/iksolver/intern/IK_QChain.h
new file mode 100644
index 00000000000..ed02bcce53e
--- /dev/null
+++ b/intern/iksolver/intern/IK_QChain.h
@@ -0,0 +1,211 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef NAN_INCLUDED_IK_QChain_h
+#define NAN_INCLUDED_IK_QChain_h
+
+
+#include "IK_QSegment.h"
+#include <vector>
+#include "MT_Scalar.h"
+#include "TNT/cmat.h"
+
+/**
+ * This class is a collection of ordered segments that are used
+ * in an Inverse Kinematic solving routine. An IK solver operating
+ * on the chain, will in general manipulate all the segments of the
+ * chain in order to solve the IK problem.
+ *
+ * To build a chain use the default constructor. Once built it's
+ * then possible to add IK_Segments to the chain by inserting
+ * them into the vector of IK_Segments. Note that segments will be
+ * copied into the chain so chains cannot share instances of
+ * IK_Segments.
+ *
+ * You have full control of which segments form the chain via the
+ * the std::vector routines.
+ */
+
+class IK_QChain{
+
+public :
+
+ /**
+ * Construct a IK_QChain with no segments.
+ */
+
+ IK_QChain(
+ );
+
+ // IK_QChains also have the default copy constructors
+ // available.
+
+ /**
+ * Const access to the array of segments
+ * comprising the IK_QChain. Used for rendering
+ * etc
+ * @return a const reference to a vector of segments
+ */
+
+ const
+ std::vector<IK_QSegment> &
+ Segments(
+ ) const ;
+
+
+ /**
+ * Full access to segments used to initialize
+ * the IK_QChain and manipulate the segments.
+ * Use the push_back() method of std::vector to add
+ * segments in order to the chain
+ * @return a reference to a vector of segments
+ */
+
+ std::vector<IK_QSegment> &
+ Segments(
+ );
+
+
+ /**
+ * Force the IK_QChain to recompute all the local
+ * segment transformations and composite them
+ * to calculate the global transformation for
+ * each segment. Must be called before
+ * ComputeJacobian()
+ */
+
+ void
+ UpdateGlobalTransformations(
+ );
+
+ /**
+ * Return the global position of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndEffector(
+ ) const;
+
+
+ /**
+ * Return the global pose of the end
+ * of the last segment.
+ */
+
+ MT_Vector3
+ EndPose(
+ ) const;
+
+
+ /**
+ * Calculate the jacobian matrix for
+ * the current end effector position.
+ * A jacobian is the set of column vectors
+ * of partial derivatives for each active angle.
+ * This method also computes the transposed jacobian.
+ * @pre You must have updated the global transformations
+ * of the chain's segments before a call to this method. Do this
+ * with UpdateGlobalTransformation()
+ */
+
+ void
+ ComputeJacobian(
+ );
+
+
+ /**
+ * @return A const reference to the last computed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ Jacobian(
+ ) const ;
+
+ /**
+ * @return A const reference to the last computed transposed jacobian matrix
+ */
+
+ const
+ TNT::Matrix<MT_Scalar> &
+ TransposedJacobian(
+ ) const ;
+
+ /**
+ * Count the degrees of freedom in the IK_QChain
+ * @warning store this value rather than using this function
+ * as the termination value of a for loop etc.
+ */
+
+ int
+ DoF(
+ ) const;
+
+ /**
+ * Compute the maximum extension of the chain from the
+ * root segment. This is the length of the root segments
+ * + the max extensions of all the other segments
+ */
+
+ const
+ MT_Scalar
+ MaxExtension(
+ ) const;
+
+
+private :
+
+ /// The vector of segments comprising the chain
+ std::vector<IK_QSegment> m_segments;
+
+ /// The jacobain of the IK_QChain
+ TNT::Matrix<MT_Scalar> m_jacobian;
+
+ /// It's transpose
+ TNT::Matrix<MT_Scalar> m_t_jacobian;
+
+ MT_Vector3 m_end_effector;
+ MT_Vector3 m_end_pose;
+
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.cpp b/intern/iksolver/intern/IK_QJacobianSolver.cpp
new file mode 100644
index 00000000000..32a703cb94d
--- /dev/null
+++ b/intern/iksolver/intern/IK_QJacobianSolver.cpp
@@ -0,0 +1,327 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_QJacobianSolver.h"
+
+#include "TNT/svd.h"
+
+using namespace std;
+
+ IK_QJacobianSolver *
+IK_QJacobianSolver::
+New(
+){
+ return new IK_QJacobianSolver();
+}
+
+ bool
+IK_QJacobianSolver::
+Solve(
+ IK_QChain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+){
+
+ const vector<IK_QSegment> & segs = chain.Segments();
+ if (segs.size() == 0) return false;
+
+ // compute the goal direction from the base of the chain
+ // in global coordinates
+
+ MT_Vector3 goal_dir = g_position - segs[0].GlobalSegmentStart();
+
+
+ const MT_Scalar chain_max_extension = chain.MaxExtension();
+
+ bool do_parallel_check(false);
+
+ if (chain_max_extension < goal_dir.length()) {
+ do_parallel_check = true;
+ }
+
+ goal_dir.normalize();
+
+
+ ArmMatrices(chain.DoF());
+
+ for (int iterations = 0; iterations < max_iterations; iterations++) {
+
+ // check to see if the chain is pointing in the right direction
+
+ if (iterations%32 && do_parallel_check && ParallelCheck(chain,goal_dir)) {
+
+ return false;
+ }
+
+ MT_Vector3 end_effector = chain.EndEffector();
+ MT_Vector3 d_pos = g_position - end_effector;
+ const MT_Scalar x_length = d_pos.length();
+
+ if (x_length < tolerance) {
+ return true;
+ }
+
+ chain.ComputeJacobian();
+
+ try {
+ ComputeInverseJacobian(chain,x_length,max_angle_change);
+ }
+ catch(...) {
+ return false;
+ }
+
+ ComputeBetas(chain,d_pos);
+ UpdateChain(chain);
+ chain.UpdateGlobalTransformations();
+ }
+
+
+ return false;
+};
+
+IK_QJacobianSolver::
+~IK_QJacobianSolver(
+){
+ // nothing to do
+}
+
+
+IK_QJacobianSolver::
+IK_QJacobianSolver(
+){
+ // nothing to do
+};
+
+ void
+IK_QJacobianSolver::
+ComputeBetas(
+ IK_QChain &chain,
+ const MT_Vector3 d_pos
+){
+
+ m_beta = 0;
+
+ m_beta[0] = d_pos.x();
+ m_beta[1] = d_pos.y();
+ m_beta[2] = d_pos.z();
+
+ TNT::matmult(m_d_theta,m_svd_inverse,m_beta);
+
+};
+
+
+ int
+IK_QJacobianSolver::
+ComputeInverseJacobian(
+ IK_QChain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+) {
+
+ int dimension = 0;
+
+ m_svd_u = MT_Scalar(0);
+
+ // copy first 3 rows of jacobian into m_svd_u
+
+ int row, column;
+
+ for (row = 0; row < 3; row ++) {
+ for (column = 0; column < chain.Jacobian().num_cols(); column ++) {
+ m_svd_u[row][column] = chain.Jacobian()[row][column];
+ }
+ }
+
+ m_svd_w = MT_Scalar(0);
+ m_svd_v = MT_Scalar(0);
+
+ m_svd_work_space = MT_Scalar(0);
+
+ TNT::SVD(m_svd_u,m_svd_w,m_svd_v,m_svd_work_space);
+
+ // invert the SVD and compute inverse
+
+ TNT::transpose(m_svd_v,m_svd_v_t);
+ TNT::transpose(m_svd_u,m_svd_u_t);
+
+ // Compute damped least squares inverse of pseudo inverse
+ // Compute damping term lambda
+
+ // Note when lambda is zero this is equivalent to the
+ // least squares solution. This is fine when the m_jjt is
+ // of full rank. When m_jjt is near to singular the least squares
+ // inverse tries to minimize |J(dtheta) - dX)| and doesn't
+ // try to minimize dTheta. This results in eratic changes in angle.
+ // Damped least squares minimizes |dtheta| to try and reduce this
+ // erratic behaviour.
+
+ // We don't want to use the damped solution everywhere so we
+ // only increase lamda from zero as we approach a singularity.
+
+ // find the smallest non-zero m_svd_w value
+
+ int i = 0;
+
+ MT_Scalar w_min = MT_INFINITY;
+
+ // anything below epsilon is treated as zero
+
+ MT_Scalar epsilon = MT_Scalar(1e-10);
+
+ for ( i = 0; i <m_svd_w.size() ; i++) {
+
+ if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
+ w_min = m_svd_w[i];
+ }
+ }
+
+ MT_Scalar lambda(0);
+
+ MT_Scalar d = x_length/max_angle_change;
+
+ if (w_min <= d/2) {
+ lambda = d/2;
+ } else
+ if (w_min < d) {
+ lambda = sqrt(w_min*(d - w_min));
+ } else {
+ lambda = MT_Scalar(0);
+ }
+
+
+ lambda *= lambda;
+
+ for (i= 0; i < m_svd_w.size(); i++) {
+ if (m_svd_w[i] < epsilon) {
+ m_svd_w[i] = MT_Scalar(0);
+ } else {
+ m_svd_w[i] = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
+ }
+ }
+
+
+ TNT::matmultdiag(m_svd_temp1,m_svd_w,m_svd_u_t);
+ TNT::matmult(m_svd_inverse,m_svd_v,m_svd_temp1);
+
+ return dimension;
+
+}
+
+ void
+IK_QJacobianSolver::
+UpdateChain(
+ IK_QChain &chain
+){
+
+ // iterate through the set of angles and
+ // update their values from the d_thetas
+
+ vector<IK_QSegment> &segs = chain.Segments();
+
+ int seg_ind = 0;
+ for (seg_ind = 0;seg_ind < segs.size(); seg_ind++) {
+
+ MT_Vector3 dq;
+ dq[0] = m_d_theta[3*seg_ind];
+ dq[1] = m_d_theta[3*seg_ind + 1];
+ dq[2] = m_d_theta[3*seg_ind + 2];
+ segs[seg_ind].IncrementAngle(dq);
+ }
+
+};
+
+ void
+IK_QJacobianSolver::
+ArmMatrices(
+ int dof
+){
+
+ m_beta.newsize(dof);
+ m_d_theta.newsize(dof);
+
+ m_svd_u.newsize(dof,dof);
+ m_svd_v.newsize(dof,dof);
+ m_svd_w.newsize(dof);
+
+ m_svd_work_space.newsize(dof);
+
+ m_svd_u = MT_Scalar(0);
+ m_svd_v = MT_Scalar(0);
+ m_svd_w = MT_Scalar(0);
+
+ m_svd_u_t.newsize(dof,dof);
+ m_svd_v_t.newsize(dof,dof);
+ m_svd_w_diag.newsize(dof,dof);
+ m_svd_inverse.newsize(dof,dof);
+ m_svd_temp1.newsize(dof,dof);
+
+};
+
+ bool
+IK_QJacobianSolver::
+ParallelCheck(
+ const IK_QChain &chain,
+ const MT_Vector3 goal_dir
+) const {
+
+ // compute the start of the chain in global coordinates
+ const vector<IK_QSegment> &segs = chain.Segments();
+
+ int num_segs = segs.size();
+
+ if (num_segs == 0) {
+ return false;
+ }
+
+ MT_Scalar crossp_sum = 0;
+
+ int i;
+ for (i = 0; i < num_segs; i++) {
+ MT_Vector3 global_seg_direction = segs[i].GlobalSegmentEnd() -
+ segs[i].GlobalSegmentStart();
+
+ global_seg_direction.normalize();
+
+ MT_Scalar crossp = (global_seg_direction.cross(goal_dir)).length();
+ crossp_sum += MT_Scalar(fabs(crossp));
+ }
+
+ if (crossp_sum < MT_Scalar(0.01)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
diff --git a/intern/iksolver/intern/IK_QJacobianSolver.h b/intern/iksolver/intern/IK_QJacobianSolver.h
new file mode 100644
index 00000000000..7e2f886d0c4
--- /dev/null
+++ b/intern/iksolver/intern/IK_QJacobianSolver.h
@@ -0,0 +1,184 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_QJacobianSolver_h
+
+#define NAN_INCLUDED_IK_QJacobianSolver_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+#include "TNT/cmat.h"
+#include <vector>
+#include "MT_Vector3.h"
+#include "IK_QChain.h"
+
+class IK_QJacobianSolver {
+
+public :
+
+ /**
+ * Create a new IK_QJacobianSolver on the heap
+ * @return A newly created IK_QJacobianSolver you take ownership of the object
+ * and responsibility for deleting it
+ */
+
+
+ static
+ IK_QJacobianSolver *
+ New(
+ );
+
+ /**
+ * Compute a solution for a chain.
+ * @param chain Reference to the chain to modify
+ * @param g_position Reference to the goal position.
+ * @param g_pose -not used- Reference to the goal pose.
+ * @param tolerance The maximum allowed distance between solution
+ * and goal for termination.
+ * @param max_iterations should be in the range (50 - 500)
+ * @param max_angle_change The maximum change in the angle vector
+ * of the chain (0.1 is a good value)
+ *
+ * @return True iff goal position reached.
+ */
+
+ bool
+ Solve(
+ IK_QChain &chain,
+ const MT_Vector3 &g_position,
+ const MT_Vector3 &g_pose,
+ const MT_Scalar tolerance,
+ const int max_iterations,
+ const MT_Scalar max_angle_change
+ );
+
+ ~IK_QJacobianSolver(
+ );
+
+
+private :
+
+ /**
+ * Private constructor to force use of New()
+ */
+
+ IK_QJacobianSolver(
+ );
+
+
+ /**
+ * Compute the inverse jacobian matrix of the chain.
+ * Uses a damped least squares solution when the matrix is
+ * is approaching singularity
+ */
+
+ int
+ ComputeInverseJacobian(
+ IK_QChain &chain,
+ const MT_Scalar x_length,
+ const MT_Scalar max_angle_change
+ );
+
+ void
+ ComputeBetas(
+ IK_QChain &chain,
+ const MT_Vector3 d_pos
+ );
+
+ /**
+ * Updates the angles of the chain with the newly
+ * computed values
+ */
+
+ void
+ UpdateChain(
+ IK_QChain &chain
+ );
+
+ /**
+ * Make sure all the matrices are of the correct size
+ */
+
+ void
+ ArmMatrices(
+ int dof
+ );
+
+ /**
+ * Quick check to see if all the segments are parallel
+ * to the goal direction.
+ */
+
+ bool
+ ParallelCheck(
+ const IK_QChain &chain,
+ const MT_Vector3 goal
+ ) const;
+
+
+
+private :
+
+ /// the vector of intermediate betas
+ TNT::Vector<MT_Scalar> m_beta;
+
+ /// the vector of computed angle changes
+ TNT::Vector<MT_Scalar> m_d_theta;
+
+ /// the constraint gradients for each angle.
+ TNT::Vector<MT_Scalar> m_dh;
+
+ /// Space required for SVD computation
+
+ TNT::Vector<MT_Scalar> m_svd_w;
+ TNT::Vector<MT_Scalar> m_svd_work_space;
+ TNT::Matrix<MT_Scalar> m_svd_v;
+ TNT::Matrix<MT_Scalar> m_svd_u;
+
+ TNT::Matrix<MT_Scalar> m_svd_w_diag;
+ TNT::Matrix<MT_Scalar> m_svd_v_t;
+ TNT::Matrix<MT_Scalar> m_svd_u_t;
+ TNT::Matrix<MT_Scalar> m_svd_inverse;
+ TNT::Matrix<MT_Scalar> m_svd_temp1;
+
+
+};
+
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/IK_QSegment.cpp b/intern/iksolver/intern/IK_QSegment.cpp
new file mode 100644
index 00000000000..2956dd815e2
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSegment.cpp
@@ -0,0 +1,363 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "IK_QSegment.h"
+#include <iostream.h>
+
+IK_QSegment::
+IK_QSegment (
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const MT_ExpMap q
+) :
+ m_length (length),
+ m_q (q)
+{
+
+ m_max_extension = tr1.length() + length;
+
+ m_transform.setOrigin(tr1);
+ m_transform.setBasis(A);
+
+ UpdateLocalTransform();
+};
+
+
+IK_QSegment::
+IK_QSegment (
+) :
+ m_length(0),
+ m_q (0,0,0),
+ m_max_extension(0)
+{
+ // Intentionally empty
+}
+
+
+
+// accessors
+////////////
+
+// The length of the segment
+
+const
+ MT_Scalar
+IK_QSegment::
+Length(
+) const {
+ return m_length;
+}
+
+const
+ MT_Scalar
+IK_QSegment::
+MaxExtension(
+) const {
+ return m_max_extension;
+}
+
+// This is the transform from adjacent
+// coordinate systems in the chain.
+
+const
+ MT_Transform &
+IK_QSegment::
+LocalTransform(
+) const {
+ return m_local_transform;
+}
+
+const
+ MT_ExpMap &
+IK_QSegment::
+LocalJointParameter(
+) const {
+ return m_q;
+}
+
+ MT_Transform
+IK_QSegment::
+UpdateGlobal(
+ const MT_Transform & global
+){
+ // compute the global transform
+ // and the start of the segment in global coordinates.
+
+ m_seg_start = global * m_transform.getOrigin();
+ m_global_transform = global;
+
+ const MT_Transform new_global = GlobalTransform();
+
+ m_seg_end = new_global.getOrigin();
+
+ return new_global;
+}
+
+ MT_Transform
+IK_QSegment::
+GlobalTransform(
+) const {
+ return m_global_transform * m_local_transform;
+}
+
+
+ MT_Transform
+IK_QSegment::
+UpdateAccumulatedLocal(
+ const MT_Transform & acc_local
+){
+ m_accum_local = acc_local;
+ return m_local_transform * m_accum_local;
+}
+
+const
+ MT_Transform &
+IK_QSegment::
+AccumulatedLocal(
+) const {
+ return m_accum_local;
+}
+
+ MT_Vector3
+IK_QSegment::
+ComputeJacobianColumn(
+ int angle
+) const {
+
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+
+ // we can compute the jacobian for one of the
+ // angles of this joint by first computing
+ // the partial derivative of the local transform dR/da
+ // and then computing
+ // dG/da = m_global_transform * dR/da * m_accum_local (0,0,0)
+
+#if 0
+
+ // use euler angles as a test of the matrices and this method.
+
+ MT_Matrix3x3 dRda;
+
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_q[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_q[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_q[2]);
+
+ MT_Matrix3x3 rotx_m(rotx);
+ MT_Matrix3x3 roty_m(roty);
+ MT_Matrix3x3 rotz_m(rotz);
+
+ if (angle == 0) {
+
+ MT_Scalar ci = cos(m_q[0]);
+ MT_Scalar si = sin(m_q[1]);
+
+ dRda = MT_Matrix3x3(
+ 0, 0, 0,
+ 0,-si,-ci,
+ 0, ci,-si
+ );
+
+ dRda = rotz_m * roty_m * dRda;
+ } else
+
+ if (angle == 1) {
+
+ MT_Scalar cj = cos(m_q[1]);
+ MT_Scalar sj = sin(m_q[1]);
+
+ dRda = MT_Matrix3x3(
+ -sj, 0, cj,
+ 0, 0, 0,
+ -cj, 0,-sj
+ );
+
+ dRda = rotz_m * dRda * rotx_m;
+ } else
+
+ if (angle == 2) {
+
+ MT_Scalar ck = cos(m_q[2]);
+ MT_Scalar sk = sin(m_q[2]);
+
+ dRda = MT_Matrix3x3(
+ -sk,-ck, 0,
+ ck,-sk, 0,
+ 0, 0, 0
+ );
+
+ dRda = dRda * roty_m * rotx_m;
+ }
+
+ MT_Transform dRda_t(MT_Point3(0,0,0),dRda);
+
+ // convert to 4x4 matrices coz dRda is singular.
+ MT_Matrix4x4 dRda_m(dRda_t);
+ dRda_m[3][3] = 0;
+
+#else
+
+ // use exponential map derivatives
+ MT_Matrix4x4 dRda_m = m_q.partialDerivatives(angle);
+
+#endif
+
+
+ // Once we have computed the local derivatives we can compute
+ // derivatives of the end effector.
+
+ // Imagine a chain consisting of 5 segments each with local
+ // transformation Li
+ // Then the global transformation G is L1 *L2 *L3 *L4 *L5
+ // If we want to compute the partial derivatives of this expression
+ // w.r.t one of the angles x of L3 we should then compute
+ // dG/dx = d(L1 *L2 *L3 *L4 *L5)/dx
+ // = L1 *L2 * dL3/dx *L4 *L5
+ // but L1 *L2 is the global transformation of the parent of this
+ // bone and L4 *L5 is the accumulated local transform of the children
+ // of this bone (m_accum_local)
+ // so dG/dx = m_global_transform * dL3/dx * m_accum_local
+ //
+ // so now we need to compute dL3/dx
+ // L3 = m_transform * rotation(m_q) * translate(0,m_length,0)
+ // do using the same procedure we get
+ // dL3/dx = m_transform * dR/dx * translate(0,m_length,0)
+ // dR/dx is the partial derivative of the exponential map w.r.t
+ // one of it's parameters. This is computed in MT_ExpMap
+
+ MT_Matrix4x4 translation_m (translation);
+ MT_Matrix4x4 global_m(m_global_transform);
+ MT_Matrix4x4 accum_local_m(m_accum_local);
+ MT_Matrix4x4 transform_m(m_transform);
+
+
+ MT_Matrix4x4 dFda_m = global_m * transform_m * dRda_m * translation_m * accum_local_m;
+
+ MT_Vector4 result = dFda_m * MT_Vector4(0,0,0,1);
+ return MT_Vector3(result[0],result[1],result[2]);
+};
+
+
+
+const
+ MT_Vector3 &
+IK_QSegment::
+GlobalSegmentStart(
+) const{
+ return m_seg_start;
+}
+
+const
+ MT_Vector3 &
+IK_QSegment::
+GlobalSegmentEnd(
+) const {
+ return m_seg_end;
+}
+
+
+ void
+IK_QSegment::
+IncrementAngle(
+ const MT_Vector3 &dq
+){
+ m_q.vector() += dq;
+ MT_Scalar theta(0);
+ m_q.reParameterize(theta);
+
+ UpdateLocalTransform();
+}
+
+
+ void
+IK_QSegment::
+SetAngle(
+ const MT_ExpMap &dq
+){
+ m_q = dq;
+ UpdateLocalTransform();
+}
+
+
+ void
+IK_QSegment::
+UpdateLocalTransform(
+){
+#if 0
+
+ //use euler angles - test
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_q[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_q[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_q[2]);
+
+ MT_Matrix3x3 rotx_m(rotx);
+ MT_Matrix3x3 roty_m(roty);
+ MT_Matrix3x3 rotz_m(rotz);
+
+ MT_Matrix3x3 rot = rotz_m * roty_m * rotx_m;
+#else
+
+ //use exponential map
+ MT_Matrix3x3 rot = m_q.getMatrix();
+
+
+#endif
+
+ MT_Transform rx(MT_Point3(0,0,0),rot);
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+ m_local_transform = m_transform * rx * translation;
+};
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_QSegment.h b/intern/iksolver/intern/IK_QSegment.h
new file mode 100644
index 00000000000..0c0e3a7f8bc
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSegment.h
@@ -0,0 +1,290 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+#ifndef NAN_INCLUDED_IK_QSegment_h
+#define NAN_INCLUDED_IK_QSegment_h
+
+
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+#include "MT_Matrix4x4.h"
+#include "MT_ExpMap.h"
+
+#include <vector>
+
+/**
+ * An IK_Qsegment encodes information about a segments
+ * local coordinate system.
+ * In these segments exponential maps are used to parameterize
+ * the 3 DOF joints. Please see the file MT_ExpMap.h for more
+ * information on this parameterization.
+ *
+ * These segments always point along the y-axis.
+ *
+ * Here wee define the local coordinates of a joint as
+ * local_transform =
+ * translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0)
+ * We use the standard moto column ordered matrices. You can read
+ * this as:
+ * - first translate by (0,length,0)
+ * - multiply by the rotation matrix derived from the current
+ * angle parameterization q.
+ * - multiply by the user defined matrix representing the rest
+ * position of the bone.
+ * - translate by the used defined translation (tr1)
+ * The ordering of these transformations is vital, you must
+ * use exactly the same transformations when displaying the segments
+ */
+
+class IK_QSegment {
+
+public :
+
+ /**
+ * Constructor.
+ * @param tr1 a user defined translation
+ * @param a used defined rotation matrix representin
+ * the rest position of the bone.
+ * @param the length of the bone.
+ * @param an exponential map can also be used to
+ * define the bone rest position.
+ */
+
+ IK_QSegment(
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const MT_ExpMap q
+ );
+
+ /**
+ * Default constructor
+ * Defines identity local coordinate system,
+ * with a bone length of 1.
+ */
+
+
+ IK_QSegment(
+ );
+
+
+ /**
+ * @return The length of the segment
+ */
+
+ const
+ MT_Scalar
+ Length(
+ ) const ;
+
+ /**
+ * @return the max distance of the end of this
+ * bone from the local origin.
+ */
+
+ const
+ MT_Scalar
+ MaxExtension(
+ ) const ;
+
+ /**
+ * @return The transform from adjacent
+ * coordinate systems in the chain.
+ */
+
+ const
+ MT_Transform &
+ LocalTransform(
+ ) const ;
+
+ const
+ MT_ExpMap &
+ LocalJointParameter(
+ ) const;
+
+ /**
+ * Update the global coordinates of this segment.
+ * @param global the global coordinates of the
+ * previous bone in the chain
+ * @return the global coordinates of this segment.
+ */
+
+ MT_Transform
+ UpdateGlobal(
+ const MT_Transform & global
+ );
+
+ /**
+ * @return The global transformation
+ */
+
+ MT_Transform
+ GlobalTransform(
+ ) const;
+
+
+ /**
+ * Update the accumulated local transform of this segment
+ * The accumulated local transform is the end effector
+ * transform in the local coordinates of this segment.
+ * @param acc_local the accumulated local transform of
+ * the child of this bone.
+ * @return the accumulated local transorm of this segment
+ */
+
+ MT_Transform
+ UpdateAccumulatedLocal(
+ const MT_Transform & acc_local
+ );
+
+ /**
+ * @return A const reference to accumulated local
+ * transform of this segment.
+ */
+
+ const
+ MT_Transform &
+ AccumulatedLocal(
+ ) const;
+
+ /**
+ * @return A const Reference to start of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentStart(
+ ) const;
+
+ /**
+ * @return A const Reference to end of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentEnd(
+ ) const;
+
+
+ /**
+ * @return the partial derivative of the end effector
+ * with respect to one of the degrees of freedom of this
+ * segment.
+ * @param angle the angle parameter you want to compute
+ * the partial derivatives for. For these segments this
+ * must be in the range [0,2]
+ */
+
+ MT_Vector3
+ ComputeJacobianColumn(
+ int angle
+ ) const ;
+
+ /**
+ * Explicitly set the angle parameterization value.
+ */
+
+ void
+ SetAngle(
+ const MT_ExpMap &q
+ );
+
+ /**
+ * Increment the angle parameterization value.
+ */
+
+ void
+ IncrementAngle(
+ const MT_Vector3 &dq
+ );
+
+
+ /**
+ * Return the parameterization of this angle
+ */
+
+ const
+ MT_ExpMap &
+ ExpMap(
+ ) const {
+ return m_q;
+ };
+
+
+private :
+
+ void
+ UpdateLocalTransform(
+ );
+
+
+private :
+
+ /**
+ * m_transform The user defined transformation, composition of the
+ * translation and rotation from constructor.
+ */
+ MT_Transform m_transform;
+
+ /**
+ * The exponential map parameterization of this joint.
+ */
+
+ MT_ExpMap m_q;
+ MT_Scalar m_length;
+
+ /**
+ * The maximum extension of this segment
+ * This is the magnitude of the user offset + the length of the
+ * chain
+ */
+
+ MT_Scalar m_max_extension;
+
+ MT_Transform m_local_transform;
+ MT_Transform m_global_transform;
+ MT_Transform m_accum_local;
+
+ MT_Vector3 m_seg_start;
+ MT_Vector3 m_seg_end;
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_QSolver_Class.h b/intern/iksolver/intern/IK_QSolver_Class.h
new file mode 100644
index 00000000000..91ad9f9c186
--- /dev/null
+++ b/intern/iksolver/intern/IK_QSolver_Class.h
@@ -0,0 +1,107 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef NAN_INCLUDED_IK_Solver_Class
+#define NAN_INCLUDED_IK_Solver_Class
+
+#include "IK_QChain.h"
+#include "IK_QJacobianSolver.h"
+#include "IK_QSegment.h"
+#include "MEM_SmartPtr.h"
+
+/**
+ * This class just contains all instances of internal data
+ * associated with the external chain structure needed for
+ * an ik solve. A pointer to this class gets hidden in the
+ * external structure as a void pointer.
+ */
+
+class IK_QSolver_Class {
+
+public :
+
+ static
+ IK_QSolver_Class *
+ New(
+ ){
+ MEM_SmartPtr<IK_QSolver_Class> output (new IK_QSolver_Class);
+
+ MEM_SmartPtr<IK_QJacobianSolver> solver (IK_QJacobianSolver::New());
+
+ if (output == NULL ||
+ solver == NULL
+ ) {
+ return NULL;
+ }
+
+ output->m_solver = solver.Release();
+
+ return output.Release();
+ };
+
+ IK_QChain &
+ Chain(
+ ) {
+ return m_chain;
+ };
+
+ IK_QJacobianSolver &
+ Solver(
+ ) {
+ return m_solver.Ref();
+ }
+
+ ~IK_QSolver_Class(
+ ) {
+ // nothing to do
+ }
+
+
+private :
+
+ IK_QSolver_Class(
+ ) {
+ };
+
+ IK_QChain m_chain;
+ MEM_SmartPtr<IK_QJacobianSolver> m_solver;
+
+};
+
+#endif
diff --git a/intern/iksolver/intern/IK_Segment.cpp b/intern/iksolver/intern/IK_Segment.cpp
new file mode 100644
index 00000000000..f955a657dae
--- /dev/null
+++ b/intern/iksolver/intern/IK_Segment.cpp
@@ -0,0 +1,277 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "IK_Segment.h"
+
+
+IK_Segment::
+IK_Segment (
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const bool pitch_on,
+ const bool yaw_on,
+ const bool role_on
+){
+ m_transform.setOrigin(tr1);
+ m_transform.setBasis(A);
+ m_angles[0] =MT_Scalar(0);
+ m_angles[1] =MT_Scalar(0);
+ m_angles[2] =MT_Scalar(0);
+
+ m_active_angles[0] = role_on;
+ m_active_angles[1] = yaw_on;
+ m_active_angles[2] = pitch_on;
+ m_length = length;
+
+ if (role_on) {
+ m_angle_vectors.push_back(MT_Vector3(1,0,0));
+ }
+ if (yaw_on) {
+ m_angle_vectors.push_back(MT_Vector3(0,1,0));
+ }
+ if (pitch_on) {
+ m_angle_vectors.push_back(MT_Vector3(0,0,1));
+ }
+ UpdateLocalTransform();
+
+
+};
+
+
+IK_Segment::
+IK_Segment (
+) {
+ m_transform.setIdentity();
+
+ m_angles[0] =MT_Scalar(0);
+ m_angles[1] =MT_Scalar(0);
+ m_angles[2] =MT_Scalar(0);
+
+ m_active_angles[0] = false;
+ m_active_angles[1] = false;
+ m_active_angles[2] = false;
+ m_length = MT_Scalar(1);
+
+ UpdateLocalTransform();
+}
+
+
+
+// accessors
+////////////
+
+// The length of the segment
+
+const
+ MT_Scalar
+IK_Segment::
+Length(
+) const {
+ return m_length;
+}
+
+
+// This is the transform from adjacent
+// coordinate systems in the chain.
+
+const
+ MT_Transform &
+IK_Segment::
+LocalTransform(
+) const {
+ return m_local_transform;
+}
+
+ void
+IK_Segment::
+UpdateGlobal(
+ const MT_Transform & global
+){
+
+ // compute the global transform
+ // and the start of the segment in global coordinates.
+
+ m_seg_start = global * m_transform.getOrigin();
+ m_global_transform = global * m_local_transform;
+}
+
+const
+ MT_Transform &
+IK_Segment::
+GlobalTransform(
+) const {
+ return m_global_transform;
+}
+
+const
+ MT_Vector3 &
+IK_Segment::
+GlobalSegmentStart(
+) const{
+ return m_seg_start;
+}
+
+
+// Return the number of Degrees of Freedom
+// for this segment
+
+ int
+IK_Segment::
+DoF(
+) const {
+ return
+ (m_active_angles[0] == true) +
+ (m_active_angles[1] == true) +
+ (m_active_angles[2] == true);
+}
+
+
+// suspect interface...
+// Increment the active angles (at most 3) by
+// d_theta. Which angles are incremented depends
+// on which are active. It returns DoF
+
+ int
+IK_Segment::
+IncrementAngles(
+ MT_Scalar *d_theta
+){
+ int i =0;
+ if (m_active_angles[0]) {
+ m_angles[0] += d_theta[i];
+ i++;
+ }
+ if (m_active_angles[1]) {
+ m_angles[1] += d_theta[i];
+ i++;
+ }
+ if (m_active_angles[2]) {
+ m_angles[2] += d_theta[i];
+ i++;
+ }
+ UpdateLocalTransform();
+
+ return i;
+}
+
+
+ int
+IK_Segment::
+SetAngles(
+ const MT_Scalar *angles
+){
+ int i =0;
+ if (m_active_angles[0]) {
+ m_angles[0] = angles[i];
+ i++;
+ }
+ if (m_active_angles[1]) {
+ m_angles[1] = angles[i];
+ i++;
+ }
+ if (m_active_angles[2]) {
+ m_angles[2] = angles[i];
+ i++;
+ }
+ UpdateLocalTransform();
+
+ return i;
+}
+
+
+ void
+IK_Segment::
+UpdateLocalTransform(
+){
+ // The local transformation is defined by
+ // a user defined translation and rotation followed by
+ // rotation by (roll,pitch,yaw) followed by
+ // a translation in x of m_length
+
+ MT_Quaternion rotx,roty,rotz;
+
+ rotx.setRotation(MT_Vector3(1,0,0),m_angles[0]);
+ roty.setRotation(MT_Vector3(0,1,0),m_angles[1]);
+ rotz.setRotation(MT_Vector3(0,0,1),m_angles[2]);
+
+ MT_Quaternion rot = rotx * roty *rotz;
+
+ MT_Transform rx(MT_Point3(0,0,0),rot);
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,m_length,0));
+
+ m_local_transform = m_transform * rx * translation;
+};
+
+
+const
+ std::vector<MT_Vector3> &
+IK_Segment::
+AngleVectors(
+) const{
+ return m_angle_vectors;
+};
+
+ MT_Scalar
+IK_Segment::
+ActiveAngle(
+ int i
+) const {
+ MT_assert((i >=0) && (i < DoF()));
+
+ // umm want to return the ith active angle
+ // and not the ith angle
+
+ int j;
+ int angles = -1;
+ for (j=0;j < 3;j++) {
+ if (m_active_angles[j]) angles ++;
+ if (i == angles) return m_angles[j];
+ }
+ return m_angles[0];
+}
+
+ MT_Scalar
+IK_Segment::
+Angle(
+ int i
+) const {
+ MT_assert((i >=0) && (i < 3));
+ return m_angles[i];
+}
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Segment.h b/intern/iksolver/intern/IK_Segment.h
new file mode 100644
index 00000000000..35018df7859
--- /dev/null
+++ b/intern/iksolver/intern/IK_Segment.h
@@ -0,0 +1,217 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_Segment_h
+
+#define NAN_INCLUDED_Segment_h
+
+/**
+ * @author Laurence Bourn
+ * @date 28/6/2001
+ */
+
+
+#include "MT_Vector3.h"
+#include "MT_Transform.h"
+#include <vector>
+
+class IK_Segment {
+
+public :
+
+ /**
+ * Constructor.
+ * @warning This class uses axis angles for it's parameterization.
+ * Axis angles are a poor representation for joints of more than 1 DOF
+ * because they suffer from Gimbal lock. This becomes noticeable in
+ * IK solutions. A better solution is to do use a quaternion to represent
+ * angles with 3 DOF
+ */
+
+ IK_Segment(
+ const MT_Point3 tr1,
+ const MT_Matrix3x3 A,
+ const MT_Scalar length,
+ const bool pitch_on,
+ const bool yaw_on,
+ const bool role_on
+ );
+
+
+ IK_Segment(
+ );
+
+
+ /**
+ * @return The length of the segment
+ */
+
+ const
+ MT_Scalar
+ Length(
+ ) const ;
+
+ /**
+ * @return The transform from adjacent
+ * coordinate systems in the chain.
+ */
+
+ const
+ MT_Transform &
+ LocalTransform(
+ ) const ;
+
+
+ /**
+ * Get the segment to compute it's
+ * global transform given the global transform
+ * of the parent. This method also updtes the
+ * global segment start
+ */
+
+ void
+ UpdateGlobal(
+ const MT_Transform & global
+ );
+
+ /**
+ * @return A const reference to the global trnasformation
+ */
+
+ const
+ MT_Transform &
+ GlobalTransform(
+ ) const;
+
+ /**
+ * @return A const Reference to start of segment in global
+ * coordinates
+ */
+
+ const
+ MT_Vector3 &
+ GlobalSegmentStart(
+ ) const;
+
+ /**
+ * Computes the number of degrees of freedom of this segment
+ */
+
+ int
+ DoF(
+ ) const;
+
+
+ /**
+ * Increment the active angles (at most DoF()) by
+ * d_theta. Which angles are incremented depends
+ * on which are active.
+ * @return DoF()
+ * @warning Bad interface
+ */
+
+ int
+ IncrementAngles(
+ MT_Scalar *d_theta
+ );
+
+
+ // FIXME - interface bloat
+
+ /**
+ * @return the vectors about which the active
+ * angles operate
+ */
+
+ const
+ std::vector<MT_Vector3> &
+ AngleVectors(
+ ) const;
+
+ /**
+ * @return the ith active angle
+ */
+
+ MT_Scalar
+ ActiveAngle(
+ int i
+ ) const;
+
+ /**
+ * @return the ith angle
+ */
+ MT_Scalar
+ Angle(
+ int i
+ ) const;
+
+
+ /**
+ * Set the active angles from the array
+ * @return the number of active angles
+ */
+
+ int
+ SetAngles(
+ const MT_Scalar *angles
+ );
+
+
+private :
+
+ void
+ UpdateLocalTransform(
+ );
+
+
+
+private :
+
+ /** The user defined transformation, composition of the
+ * translation and rotation from constructor.
+ */
+
+ MT_Transform m_transform;
+ MT_Scalar m_angles[3];
+ MT_Scalar m_length;
+
+ MT_Transform m_local_transform;
+ MT_Transform m_global_transform;
+
+ bool m_active_angles[3];
+
+ MT_Vector3 m_seg_start;
+
+ std::vector<MT_Vector3> m_angle_vectors;
+
+};
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/intern/IK_Solver.cpp b/intern/iksolver/intern/IK_Solver.cpp
new file mode 100644
index 00000000000..11646597d6d
--- /dev/null
+++ b/intern/iksolver/intern/IK_Solver.cpp
@@ -0,0 +1,196 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#define IK_USE_EXPMAP
+
+
+
+#ifdef IK_USE_EXPMAP
+# include "IK_QSolver_Class.h"
+#else
+# include "IK_Solver_Class.h"
+#endif
+#include "../extern/IK_solver.h"
+
+#include <iostream.h>
+
+ IK_Chain_ExternPtr
+IK_CreateChain(
+ void
+) {
+
+ MEM_SmartPtr<IK_Chain_Extern> output (new IK_Chain_Extern);
+ MEM_SmartPtr<IK_QSolver_Class> output_void (IK_QSolver_Class::New());
+
+
+ if (output == NULL || output_void == NULL) {
+ return NULL;
+ }
+
+ output->chain_dof = 0;
+ output->num_segments = 0;
+ output->segments = NULL;
+ output->intern = output_void.Release();
+ return output.Release();
+};
+
+
+ int
+IK_LoadChain(
+ IK_Chain_ExternPtr chain,
+ IK_Segment_ExternPtr segments,
+ int num_segs
+) {
+
+ if (chain == NULL || segments == NULL) return 0;
+
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+ if (intern_cpp == NULL) return 0;
+
+ std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments();
+ if (segs.size() != num_segs) {
+ segs = std::vector<IK_QSegment>(num_segs);
+ }
+
+ std::vector<IK_QSegment>::const_iterator seg_end= segs.end();
+ std::vector<IK_QSegment>::iterator seg_begin= segs.begin();
+
+ IK_Segment_ExternPtr extern_seg_it = segments;
+
+
+ for (;seg_begin != seg_end; ++seg_begin,++extern_seg_it) {
+
+ MT_Point3 tr1(extern_seg_it->seg_start);
+
+ MT_Matrix3x3 A(
+ extern_seg_it->basis[0],extern_seg_it->basis[1],extern_seg_it->basis[2],
+ extern_seg_it->basis[3],extern_seg_it->basis[4],extern_seg_it->basis[5],
+ extern_seg_it->basis[6],extern_seg_it->basis[7],extern_seg_it->basis[8]
+ );
+
+ MT_Scalar length(extern_seg_it->length);
+
+
+ *seg_begin = IK_QSegment(
+ tr1,A,length,MT_Vector3(0,0,0)
+ );
+
+ }
+
+
+ intern_cpp->Chain().UpdateGlobalTransformations();
+ intern_cpp->Chain().ComputeJacobian();
+
+ chain->num_segments = num_segs;
+ chain->chain_dof = intern_cpp->Chain().DoF();
+ chain->segments = segments;
+
+ return 1;
+};
+
+ int
+IK_SolveChain(
+ IK_Chain_ExternPtr chain,
+ float goal[3],
+ float tolerance,
+ int max_iterations,
+ float max_angle_change,
+ IK_Segment_ExternPtr output
+){
+ if (chain == NULL || output == NULL) return 0;
+ if (chain->intern == NULL) return 0;
+
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+
+ IK_QJacobianSolver & solver = intern_cpp->Solver();
+
+ bool solve_result = solver.Solve(
+ intern_cpp->Chain(),
+ MT_Vector3(goal),
+ MT_Vector3(0,0,0),
+ MT_Scalar(tolerance),
+ max_iterations,
+ MT_Scalar(max_angle_change)
+ );
+
+ // turn the computed role->pitch->yaw into a quaternion and
+ // return the result in output
+
+ std::vector<IK_QSegment> & segs = intern_cpp->Chain().Segments();
+ std::vector<IK_QSegment>::const_iterator seg_end= segs.end();
+ std::vector<IK_QSegment>::iterator seg_begin= segs.begin();
+
+ for (;seg_begin != seg_end; ++seg_begin, ++output) {
+ MT_Matrix3x3 qrot = seg_begin->ExpMap().getMatrix();
+
+ // don't forget to transpose this qrot for use by blender!
+
+ qrot.transpose(); // blender uses transpose here ????
+
+ output->basis_change[0] = float(qrot[0][0]);
+ output->basis_change[1] = float(qrot[0][1]);
+ output->basis_change[2] = float(qrot[0][2]);
+ output->basis_change[3] = float(qrot[1][0]);
+ output->basis_change[4] = float(qrot[1][1]);
+ output->basis_change[5] = float(qrot[1][2]);
+ output->basis_change[6] = float(qrot[2][0]);
+ output->basis_change[7] = float(qrot[2][1]);
+ output->basis_change[8] = float(qrot[2][2]);
+
+ }
+
+
+ return solve_result ? 1 : 0;
+}
+
+ void
+IK_FreeChain(
+ IK_Chain_ExternPtr chain
+){
+ IK_QSolver_Class *intern_cpp = (IK_QSolver_Class *)chain->intern;
+
+ delete(intern_cpp);
+ delete(chain);
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/IK_Solver_Class.h b/intern/iksolver/intern/IK_Solver_Class.h
new file mode 100644
index 00000000000..1ef6c22f946
--- /dev/null
+++ b/intern/iksolver/intern/IK_Solver_Class.h
@@ -0,0 +1,93 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_IK_Solver_Class
+
+#define NAN_INCLUDED_IK_Solver_Class
+
+#include "IK_Chain.h"
+#include "IK_JacobianSolver.h"
+#include "IK_Segment.h"
+#include "MEM_SmartPtr.h"
+
+class IK_Solver_Class {
+
+public :
+
+ static
+ IK_Solver_Class *
+ New(
+ ){
+ MEM_SmartPtr<IK_Solver_Class> output (new IK_Solver_Class);
+
+ MEM_SmartPtr<IK_JacobianSolver> solver (IK_JacobianSolver::New());
+
+ if (output == NULL ||
+ solver == NULL
+ ) {
+ return NULL;
+ }
+
+ output->m_solver = solver.Release();
+
+ return output.Release();
+ };
+
+ IK_Chain &
+ Chain(
+ ) {
+ return m_chain;
+ };
+
+ IK_JacobianSolver &
+ Solver(
+ ) {
+ return m_solver.Ref();
+ }
+
+ ~IK_Solver_Class(
+ ) {
+ // nothing to do
+ }
+
+
+private :
+
+ IK_Solver_Class(
+ ) {
+ };
+
+ IK_Chain m_chain;
+ MEM_SmartPtr<IK_JacobianSolver> m_solver;
+
+};
+
+#endif
diff --git a/intern/iksolver/intern/MT_ExpMap.cpp b/intern/iksolver/intern/MT_ExpMap.cpp
new file mode 100644
index 00000000000..ea005a42096
--- /dev/null
+++ b/intern/iksolver/intern/MT_ExpMap.cpp
@@ -0,0 +1,268 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#include "MT_ExpMap.h"
+
+/**
+ * Set the exponential map from a quaternion. The quaternion must be non-zero.
+ */
+
+ void
+MT_ExpMap::
+setRotation(
+ const MT_Quaternion &q
+) {
+ // ok first normailize the quaternion
+ // then compute theta the axis-angle and the normalized axis v
+ // scale v by theta and that's it hopefully!
+
+ MT_Quaternion qt = q.normalized();
+
+ MT_Vector3 axis(qt.x(),qt.y(),qt.z());
+ MT_Scalar cosp = qt.w();
+ MT_Scalar sinp = axis.length();
+ axis /= sinp;
+
+ MT_Scalar theta = atan2(double(sinp),double(cosp));
+
+ axis *= theta;
+ m_v = axis;
+}
+
+/**
+ * Convert from an exponential map to a quaternion
+ * representation
+ */
+
+ MT_Quaternion
+MT_ExpMap::
+getRotation(
+) const {
+ bool rep=0;
+ MT_Scalar cosp, sinp, theta;
+
+ MT_Quaternion q;
+
+ theta = m_v.length();
+
+ cosp = MT_Scalar(cos(.5*theta));
+ sinp = MT_Scalar(sin(.5*theta));
+
+ q.w() = cosp;
+
+ if (theta < MT_EXPMAP_MINANGLE) {
+
+ MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - theta*theta/MT_Scalar(48.0)); /* Taylor Series for sinc */
+ q.x() = temp.x();
+ q.y() = temp.y();
+ q.z() = temp.z();
+ } else {
+ MT_Vector3 temp = m_v * (sinp/theta); /* Taylor Series for sinc */
+ q.x() = temp.x();
+ q.y() = temp.y();
+ q.z() = temp.z();
+ }
+
+ return q;
+}
+
+/**
+ * Convert the exponential map to a 3x3 matrix
+ */
+
+ MT_Matrix3x3
+MT_ExpMap::
+getMatrix(
+) const {
+
+ MT_Quaternion q = getRotation();
+ return MT_Matrix3x3(q);
+}
+
+
+
+
+/**
+ * Force a reparameterization of the exponential
+ * map.
+ */
+
+ bool
+MT_ExpMap::
+reParameterize(
+ MT_Scalar &theta
+){
+ bool rep(false);
+ theta = m_v.length();
+
+ if (theta > MT_PI){
+ MT_Scalar scl = theta;
+ if (theta > MT_2_PI){ /* first get theta into range 0..2PI */
+ theta = MT_Scalar(fmod(theta, MT_2_PI));
+ scl = theta/scl;
+ m_v *= scl;
+ rep = true;
+ }
+ if (theta > MT_PI){
+ scl = theta;
+ theta = MT_2_PI - theta;
+ scl = MT_Scalar(1.0) - MT_2_PI/scl;
+ m_v *= scl;
+ rep = true;
+ }
+ }
+ return rep;
+
+}
+
+/**
+ * Compute the partial derivatives of the exponential
+ * map (dR/de - where R is a 4x4 rotation matrix formed
+ * from the map) and return them as a 4x4 matrix
+ */
+
+ MT_Matrix4x4
+MT_ExpMap::
+partialDerivatives(
+ const int i
+) const {
+
+ MT_Quaternion q = getRotation();
+ MT_Quaternion dQdx;
+
+ MT_Matrix4x4 output;
+
+ compute_dQdVi(i,dQdx);
+ compute_dRdVi(q,dQdx,output);
+
+ return output;
+}
+
+ void
+MT_ExpMap::
+compute_dRdVi(
+ const MT_Quaternion &q,
+ const MT_Quaternion &dQdvi,
+ MT_Matrix4x4 & dRdvi
+) const {
+
+ MT_Scalar prod[9];
+
+ /* This efficient formulation is arrived at by writing out the
+ * entire chain rule product dRdq * dqdv in terms of 'q' and
+ * noticing that all the entries are formed from sums of just
+ * nine products of 'q' and 'dqdv' */
+
+ prod[0] = -MT_Scalar(4)*q.x()*dQdvi.x();
+ prod[1] = -MT_Scalar(4)*q.y()*dQdvi.y();
+ prod[2] = -MT_Scalar(4)*q.z()*dQdvi.z();
+ prod[3] = MT_Scalar(2)*(q.y()*dQdvi.x() + q.x()*dQdvi.y());
+ prod[4] = MT_Scalar(2)*(q.w()*dQdvi.z() + q.z()*dQdvi.w());
+ prod[5] = MT_Scalar(2)*(q.z()*dQdvi.x() + q.x()*dQdvi.z());
+ prod[6] = MT_Scalar(2)*(q.w()*dQdvi.y() + q.y()*dQdvi.w());
+ prod[7] = MT_Scalar(2)*(q.z()*dQdvi.y() + q.y()*dQdvi.z());
+ prod[8] = MT_Scalar(2)*(q.w()*dQdvi.x() + q.x()*dQdvi.w());
+
+ /* first row, followed by second and third */
+ dRdvi[0][0] = prod[1] + prod[2];
+ dRdvi[0][1] = prod[3] - prod[4];
+ dRdvi[0][2] = prod[5] + prod[6];
+
+ dRdvi[1][0] = prod[3] + prod[4];
+ dRdvi[1][1] = prod[0] + prod[2];
+ dRdvi[1][2] = prod[7] - prod[8];
+
+ dRdvi[2][0] = prod[5] - prod[6];
+ dRdvi[2][1] = prod[7] + prod[8];
+ dRdvi[2][2] = prod[0] + prod[1];
+
+ /* the 4th row and column are all zero */
+ int i;
+
+ for (i=0; i<3; i++)
+ dRdvi[3][i] = dRdvi[i][3] = MT_Scalar(0);
+ dRdvi[3][3] = 0;
+}
+
+// compute partial derivatives dQ/dVi
+
+ void
+MT_ExpMap::
+compute_dQdVi(
+ const int i,
+ MT_Quaternion & dQdX
+) const {
+
+ MT_Scalar theta = m_v.length();
+ MT_Scalar cosp(cos(MT_Scalar(.5)*theta)), sinp(sin(MT_Scalar(.5)*theta));
+
+ MT_assert(i>=0 && i<3);
+
+ /* This is an efficient implementation of the derivatives given
+ * in Appendix A of the paper with common subexpressions factored out */
+ if (theta < MT_EXPMAP_MINANGLE){
+ const int i2 = (i+1)%3, i3 = (i+2)%3;
+ MT_Scalar Tsinc = MT_Scalar(0.5) - theta*theta/MT_Scalar(48.0);
+ MT_Scalar vTerm = m_v[i] * (theta*theta/MT_Scalar(40.0) - MT_Scalar(1.0)) / MT_Scalar(24.0);
+
+ dQdX.w() = -.5*m_v[i]*Tsinc;
+ dQdX[i] = m_v[i]* vTerm + Tsinc;
+ dQdX[i2] = m_v[i2]*vTerm;
+ dQdX[i3] = m_v[i3]*vTerm;
+ } else {
+ const int i2 = (i+1)%3, i3 = (i+2)%3;
+ const MT_Scalar ang = 1.0/theta, ang2 = ang*ang*m_v[i], sang = sinp*ang;
+ const MT_Scalar cterm = ang2*(.5*cosp - sang);
+
+ dQdX[i] = cterm*m_v[i] + sang;
+ dQdX[i2] = cterm*m_v[i2];
+ dQdX[i3] = cterm*m_v[i3];
+ dQdX.w() = MT_Scalar(-.5)*m_v[i]*sang;
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/MT_ExpMap.h b/intern/iksolver/intern/MT_ExpMap.h
new file mode 100644
index 00000000000..10cacb59b78
--- /dev/null
+++ b/intern/iksolver/intern/MT_ExpMap.h
@@ -0,0 +1,219 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+
+ * $Id$
+ * Copyright (C) 2001 NaN Technologies B.V.
+ *
+ * @author Laurence
+ */
+
+#ifndef MT_ExpMap_H
+#define MT_ExpMap_H
+
+#include <MT_assert.h>
+
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix4x4.h"
+
+const MT_Scalar MT_EXPMAP_MINANGLE (1e-7);
+
+/**
+ * MT_ExpMap an exponential map parameterization of rotations
+ * in 3D. This implementation is derived from the paper
+ * "F. Sebastian Grassia. Practical parameterization of
+ * rotations using the exponential map. Journal of Graphics Tools,
+ * 3(3):29-48, 1998" Please go to http://www.acm.org/jgt/papers/Grassia98/
+ * for a thorough description of the theory and sample code used
+ * to derive this class.
+ *
+ * Basic overview of why this class is used.
+ * In an IK system we need to paramterize the joint angles in some
+ * way. Typically 2 parameterizations are used.
+ * - Euler Angles
+ * These suffer from singularities in the parameterization known
+ * as gimbal lock. They also do not interpolate well. For every
+ * set of euler angles there is exactly 1 corresponding 3d rotation.
+ * - Quaternions.
+ * Great for interpolating. Only unit quaternions are valid rotations
+ * means that in a differential ik solver we often stray outside of
+ * this manifold into invalid rotations. Means we have to do a lot
+ * of nasty normalizations all the time. Does not suffer from
+ * gimbal lock problems. More expensive to compute partial derivatives
+ * as there are 4 of them.
+ *
+ * So exponential map is similar to a quaternion axis/angle
+ * representation but we store the angle as the length of the
+ * axis. So require only 3 parameters. Means that all exponential
+ * maps are valid rotations. Suffers from gimbal lock. But it's
+ * possible to detect when gimbal lock is near and reparameterize
+ * away from it. Also nice for interpolating.
+ * Exponential maps are share some of the useful properties of
+ * euler and quaternion parameterizations. And are very useful
+ * for differential IK solvers.
+ */
+
+class MT_ExpMap {
+public:
+
+ /**
+ * Default constructor
+ * @warning there is no initialization in the
+ * default constructor
+ */
+
+ MT_ExpMap() {}
+ MT_ExpMap(const MT_Vector3& v) : m_v(v) {}
+
+ MT_ExpMap(const float v[3]) : m_v(v) {}
+ MT_ExpMap(const double v[3]) : m_v(v) {}
+
+ MT_ExpMap(MT_Scalar x, MT_Scalar y, MT_Scalar z) :
+ m_v(x, y, z) {}
+
+ /**
+ * Construct an exponential map from a quaternion
+ */
+
+ MT_ExpMap(
+ const MT_Quaternion &q
+ ) {
+ setRotation(q);
+ };
+
+ /**
+ * Accessors
+ * Decided not to inherit from MT_Vector3 but rather
+ * this class contains an MT_Vector3. This is because
+ * it is very dangerous to use MT_Vector3 functions
+ * on this class and some of them have no direct meaning.
+ */
+
+ MT_Vector3 &
+ vector(
+ ) {
+ return m_v;
+ };
+
+ const
+ MT_Vector3 &
+ vector(
+ ) const {
+ return m_v;
+ };
+
+ /**
+ * Set the exponential map from a quaternion
+ */
+
+ void
+ setRotation(
+ const MT_Quaternion &q
+ );
+
+ /**
+ * Convert from an exponential map to a quaternion
+ * representation
+ */
+
+ MT_Quaternion
+ getRotation(
+ ) const;
+
+ /**
+ * Convert the exponential map to a 3x3 matrix
+ */
+
+ MT_Matrix3x3
+ getMatrix(
+ ) const;
+
+ /**
+ * Force a reparameterization check of the exponential
+ * map.
+ * @param theta returns the new axis-angle.
+ * @return true iff a reParameterization took place.
+ * Use this function whenever you adjust the vector
+ * representing the exponential map.
+ */
+
+ bool
+ reParameterize(
+ MT_Scalar &theta
+ );
+
+ /**
+ * Compute the partial derivatives of the exponential
+ * map (dR/de - where R is a 4x4 matrix formed
+ * from the map) and return them as a 4x4 matrix
+ */
+
+ MT_Matrix4x4
+ partialDerivatives(
+ const int i
+ ) const ;
+
+private :
+
+ MT_Vector3 m_v;
+
+ // private methods
+
+ // Compute partial derivatives dR (3x3 rotation matrix) / dVi (EM vector)
+ // given the partial derivative dQ (Quaternion) / dVi (ith element of EM vector)
+
+
+ void
+ compute_dRdVi(
+ const MT_Quaternion &q,
+ const MT_Quaternion &dQdV,
+ MT_Matrix4x4 & dRdVi
+ ) const;
+
+ // compute partial derivatives dQ/dVi
+
+ void
+ compute_dQdVi(
+ int i,
+ MT_Quaternion & dQdX
+ ) const ;
+
+
+};
+
+
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/Makefile b/intern/iksolver/intern/Makefile
new file mode 100644
index 00000000000..af32d816a80
--- /dev/null
+++ b/intern/iksolver/intern/Makefile
@@ -0,0 +1,44 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver intern Makefile
+#
+
+LIBNAME = iksolver
+DIR = $(OCGDIR)/intern/$(LIBNAME)
+CCSRCS = IK_QChain.cpp IK_QJacobianSolver.cpp IK_QSegment.cpp MT_ExpMap.cpp IK_Solver.cpp
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
diff --git a/intern/iksolver/intern/TNT/cholesky.h b/intern/iksolver/intern/TNT/cholesky.h
new file mode 100644
index 00000000000..a3e0118f4e5
--- /dev/null
+++ b/intern/iksolver/intern/TNT/cholesky.h
@@ -0,0 +1,128 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef CHOLESKY_H
+#define CHOLESKY_H
+
+#include <cmath>
+
+// index method
+
+namespace TNT
+{
+
+
+//
+// Only upper part of A is used. Cholesky factor is returned in
+// lower part of L. Returns 0 if successful, 1 otherwise.
+//
+template <class SPDMatrix, class SymmMatrix>
+int Cholesky_upper_factorization(SPDMatrix &A, SymmMatrix &L)
+{
+ Subscript M = A.dim(1);
+ Subscript N = A.dim(2);
+
+ assert(M == N); // make sure A is square
+
+ // readjust size of L, if necessary
+
+ if (M != L.dim(1) || N != L.dim(2))
+ L = SymmMatrix(N,N);
+
+ Subscript i,j,k;
+
+
+ typename SPDMatrix::element_type dot=0;
+
+
+ for (j=1; j<=N; j++) // form column j of L
+ {
+ dot= 0;
+
+ for (i=1; i<j; i++) // for k= 1 TO j-1
+ dot = dot + L(j,i)*L(j,i);
+
+ L(j,j) = A(j,j) - dot;
+
+ for (i=j+1; i<=N; i++)
+ {
+ dot = 0;
+ for (k=1; k<j; k++)
+ dot = dot + L(i,k)*L(j,k);
+ L(i,j) = A(j,i) - dot;
+ }
+
+ if (L(j,j) <= 0.0) return 1;
+
+ L(j,j) = sqrt( L(j,j) );
+
+ for (i=j+1; i<=N; i++)
+ L(i,j) = L(i,j) / L(j,j);
+
+ }
+
+ return 0;
+}
+
+
+
+
+}
+// namespace TNT
+
+#endif
+// CHOLESKY_H
diff --git a/intern/iksolver/intern/TNT/cmat.h b/intern/iksolver/intern/TNT/cmat.h
new file mode 100644
index 00000000000..80a82417e47
--- /dev/null
+++ b/intern/iksolver/intern/TNT/cmat.h
@@ -0,0 +1,661 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
+//
+
+#ifndef CMAT_H
+#define CMAT_H
+
+#include "subscript.h"
+#include "vec.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+#include <strstream>
+#ifdef TNT_USE_REGIONS
+#include "region2d.h"
+#endif
+
+namespace TNT
+{
+
+template <class T>
+class Matrix
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ Subscript m_;
+ Subscript n_;
+ Subscript mn_; // total size
+ T* v_;
+ T** row_;
+ T* vm1_ ; // these point to the same data, but are 1-based
+ T** rowm1_;
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript M, Subscript N)
+ {
+ mn_ = M*N;
+ m_ = M;
+ n_ = N;
+
+ v_ = new T[mn_];
+ row_ = new T*[M];
+ rowm1_ = new T*[M];
+
+ assert(v_ != NULL);
+ assert(row_ != NULL);
+ assert(rowm1_ != NULL);
+
+ T* p = v_;
+ vm1_ = v_ - 1;
+ for (Subscript i=0; i<M; i++)
+ {
+ row_[i] = p;
+ rowm1_[i] = p-1;
+ p += N ;
+
+ }
+
+ rowm1_ -- ; // compensate for 1-based offset
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ if (v_ != NULL) delete [] (v_);
+ if (row_ != NULL) delete [] (row_);
+
+ /* return rowm1_ back to original value */
+ rowm1_ ++;
+ if (rowm1_ != NULL ) delete [] (rowm1_);
+ }
+
+
+ public:
+
+ operator T**(){ return row_; }
+ operator T**() const { return row_; }
+
+
+ Subscript size() const { return mn_; }
+
+ // constructors
+
+ Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
+
+ Matrix(const Matrix<T> &A)
+ {
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ Matrix(Subscript M, Subscript N, const T& value = T())
+ {
+ initialize(M,N);
+ set(value);
+ }
+
+ Matrix(Subscript M, Subscript N, const T* v)
+ {
+ initialize(M,N);
+ copy(v);
+ }
+
+ Matrix(Subscript M, Subscript N, const char *s)
+ {
+ initialize(M,N);
+ std::istrstream ins(s);
+
+ Subscript i, j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ ins >> row_[i][j];
+ }
+
+
+ // destructor
+ //
+ ~Matrix()
+ {
+ destroy();
+ }
+
+
+ // reallocating
+ //
+ Matrix<T>& newsize(Subscript M, Subscript N)
+ {
+ if (num_rows() == M && num_cols() == N)
+ return *this;
+
+ destroy();
+ initialize(M,N);
+
+ return *this;
+ }
+
+ void
+ diagonal(Vector<T> &diag)
+ {
+ int sz = diag.dim();
+ newsize(sz,sz);
+ set(0);
+
+ Subscript i;
+ for (i = 0; i < sz; i++) {
+ row_[i][i] = diag[i];
+ }
+ }
+
+
+
+ // assignments
+ //
+ Matrix<T>& operator=(const Matrix<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Matrix<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+
+ Subscript dim(Subscript d) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( d >= 1);
+ assert( d <= 2);
+#endif
+ return (d==1) ? m_ : ((d==2) ? n_ : 0);
+ }
+
+ Subscript num_rows() const { return m_; }
+ Subscript num_cols() const { return n_; }
+
+
+
+
+ inline T* operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < m_) ;
+#endif
+ return row_[i];
+ }
+
+ inline const T* operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < m_) ;
+#endif
+ return row_[i];
+ }
+
+ inline reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= mn_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline const_reference operator()(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= mn_) ;
+#endif
+ return vm1_[i];
+ }
+
+
+
+ inline reference operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return rowm1_[i][j];
+ }
+
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return rowm1_[i][j];
+ }
+
+
+
+#ifdef TNT_USE_REGIONS
+
+ typedef Region2D<Matrix<T> > Region;
+
+
+ Region operator()(const Index1D &I, const Index1D &J)
+ {
+ return Region(*this, I,J);
+ }
+
+
+ typedef const_Region2D< Matrix<T> > const_Region;
+ const_Region operator()(const Index1D &I, const Index1D &J) const
+ {
+ return const_Region(*this, I,J);
+ }
+
+#endif
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << "\n";
+
+ for (Subscript i=0; i<M; i++)
+ {
+ for (Subscript j=0; j<N; j++)
+ {
+ s << A[i][j] << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class T>
+std::istream& operator>>(std::istream &s, Matrix<T> &A)
+{
+
+ Subscript M, N;
+
+ s >> M >> N;
+
+ if ( !(M == A.num_rows() && N == A.num_cols() ))
+ {
+ A.newsize(M,N);
+ }
+
+
+ for (Subscript i=0; i<M; i++)
+ for (Subscript j=0; j<N; j++)
+ {
+ s >> A[i][j];
+ }
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+template <class T>
+Matrix<T> operator+(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] + B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+Matrix<T> operator-(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] - B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+Matrix<T> mult_element(const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ tmp[i][j] = A[i][j] * B[i][j];
+
+ return tmp;
+}
+
+template <class T>
+void transpose(const Matrix<T> &A, Matrix<T> &S)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==S.num_cols());
+ assert(N==S.num_rows());
+
+ Subscript i, j;
+
+ for (i=0; i<M; i++)
+ for (j=0; j<N; j++)
+ S[j][i] = A[i][j];
+
+}
+
+
+template <class T>
+inline void matmult(Matrix<T>& C, const Matrix<T> &A,
+ const Matrix<T> &B)
+{
+
+ assert(A.num_cols() == B.num_rows());
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ C.newsize(M,K);
+
+ T sum;
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=0; i<M; i++)
+ for (Subscript k=0; k<K; k++)
+ {
+ row_i = &(A[i][0]);
+ col_k = &(B[0][k]);
+ sum = 0;
+ for (Subscript j=0; j<N; j++)
+ {
+ sum += *row_i * *col_k;
+ row_i++;
+ col_k += K;
+ }
+ C[i][k] = sum;
+ }
+
+}
+
+template <class T>
+void matmult(Vector<T> &y, const Matrix<T> &A, const Vector<T> &x)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == x.dim());
+ assert(A.num_rows() == y.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ T sum;
+
+ for (Subscript i=0; i<M; i++)
+ {
+ sum = 0;
+ const T* rowi = A[i];
+ for (Subscript j=0; j<N; j++)
+ sum = sum + rowi[j] * x[j];
+
+ y[i] = sum;
+ }
+}
+
+template <class T>
+inline void matmultdiag(
+ Matrix<T>& C,
+ const Matrix<T> &A,
+ const Vector<T> &diag
+){
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() ==A.num_rows()== diag.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript K = diag.dim();
+
+ C.newsize(M,K);
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=0; i<M; i++) {
+ for (Subscript k=0; k<K; k++)
+ {
+ C[i][k] = A[i,k] * diag[k];
+ }
+ }
+}
+
+
+template <class T>
+inline void matmultdiag(
+ Matrix<T>& C,
+ const Vector<T> &diag,
+ const Matrix<T> &A
+){
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() ==A.num_rows()== diag.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript K = diag.dim();
+
+ C.newsize(M,K);
+
+ for (Subscript i=0; i<M; i++) {
+
+ const T diag_element = diag[i];
+
+ for (Subscript k=0; k<K; k++)
+ {
+ C[i][k] = A[i][k] * diag_element;
+ }
+ }
+}
+
+
+
+
+} // namespace TNT
+
+
+
+
+#endif
+// CMAT_H
diff --git a/intern/iksolver/intern/TNT/fcscmat.h b/intern/iksolver/intern/TNT/fcscmat.h
new file mode 100644
index 00000000000..877364ad38c
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fcscmat.h
@@ -0,0 +1,197 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Templated compressed sparse column matrix (Fortran conventions).
+// uses 1-based offsets in storing row indices.
+// Used primarily to interface with Fortran sparse matrix libaries.
+// (CANNOT BE USED AS AN STL CONTAINER.)
+
+
+#ifndef FCSCMAT_H
+#define FCSCMAT_H
+
+#include <iostream>
+#include <cassert>
+#include "tnt.h"
+#include "vec.h"
+
+using namespace std;
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Sparse_Col_Matrix
+{
+
+ protected:
+
+ Vector<T> val_; // data values (nz_ elements)
+ Vector<Subscript> rowind_; // row_ind (nz_ elements)
+ Vector<Subscript> colptr_; // col_ptr (n_+1 elements)
+
+ int nz_; // number of nonzeros
+ Subscript m_; // global dimensions
+ Subscript n_;
+
+ public:
+
+
+ Fortran_Sparse_Col_Matrix(void);
+ Fortran_Sparse_Col_Matrix(const Fortran_Sparse_Col_Matrix<T> &S)
+ : val_(S.val_), rowind_(S.rowind_), colptr_(S.colptr_), nz_(S.nz_),
+ m_(S.m_), n_(S.n_) {};
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, const T *val, const Subscript *r,
+ const Subscript *c) : val_(nz, val), rowind_(nz, r),
+ colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
+
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, char *val, char *r,
+ char *c) : val_(nz, val), rowind_(nz, r),
+ colptr_(N+1, c), nz_(nz), m_(M), n_(N) {};
+
+ Fortran_Sparse_Col_Matrix(Subscript M, Subscript N,
+ Subscript nz, const T *val, Subscript *r, Subscript *c)
+ : val_(nz, val), rowind_(nz, r), colptr_(N+1, c), nz_(nz),
+ m_(M), n_(N) {};
+
+ ~Fortran_Sparse_Col_Matrix() {};
+
+
+ T & val(Subscript i) { return val_(i); }
+ const T & val(Subscript i) const { return val_(i); }
+
+ Subscript & row_ind(Subscript i) { return rowind_(i); }
+ const Subscript & row_ind(Subscript i) const { return rowind_(i); }
+
+ Subscript col_ptr(Subscript i) { return colptr_(i);}
+ const Subscript col_ptr(Subscript i) const { return colptr_(i);}
+
+
+ Subscript num_cols() const { return m_;}
+ Subscript num_rows() const { return n_; }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( 1 <= i );
+ assert( i <= 2 );
+#endif
+ if (i==1) return m_;
+ else if (i==2) return m_;
+ else return 0;
+ }
+
+ Subscript num_nonzeros() const {return nz_;};
+ Subscript lbound() const {return 1;}
+
+
+
+ Fortran_Sparse_Col_Matrix& operator=(const
+ Fortran_Sparse_Col_Matrix &C)
+ {
+ val_ = C.val_;
+ rowind_ = C.rowind_;
+ colptr_ = C.colptr_;
+ nz_ = C.nz_;
+ m_ = C.m_;
+ n_ = C.n_;
+
+ return *this;
+ }
+
+ Fortran_Sparse_Col_Matrix& newsize(Subscript M, Subscript N,
+ Subscript nz)
+ {
+ val_.newsize(nz);
+ rowind_.newsize(nz);
+ colptr_.newsize(N+1);
+ return *this;
+ }
+};
+
+template <class T>
+ostream& operator<<(ostream &s, const Fortran_Sparse_Col_Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << " " << A.num_nonzeros() << endl;
+
+
+ for (Subscript k=1; k<=N; k++)
+ {
+ Subscript start = A.col_ptr(k);
+ Subscript end = A.col_ptr(k+1);
+
+ for (Subscript i= start; i<end; i++)
+ {
+ s << A.row_ind(i) << " " << k << " " << A.val(i) << endl;
+ }
+ }
+
+ return s;
+}
+
+
+
+} // namespace TNT
+
+#endif
+/* FCSCMAT_H */
+
diff --git a/intern/iksolver/intern/TNT/fmat.h b/intern/iksolver/intern/TNT/fmat.h
new file mode 100644
index 00000000000..5de9a63813e
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fmat.h
@@ -0,0 +1,609 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Fortran-compatible matrix: column oriented, 1-based (i,j) indexing
+
+#ifndef FMAT_H
+#define FMAT_H
+
+#include "subscript.h"
+#include "vec.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+#ifdef TNT_USE_REGIONS
+#include "region2d.h"
+#endif
+
+// simple 1-based, column oriented Matrix class
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Matrix
+{
+
+
+ public:
+
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ T* v_; // these are adjusted to simulate 1-offset
+ Subscript m_;
+ Subscript n_;
+ T** col_; // these are adjusted to simulate 1-offset
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript M, Subscript N)
+ {
+ // adjust col_[] pointers so that they are 1-offset:
+ // col_[j][i] is really col_[j-1][i-1];
+ //
+ // v_[] is the internal contiguous array, it is still 0-offset
+ //
+ v_ = new T[M*N];
+ col_ = new T*[N];
+
+ assert(v_ != NULL);
+ assert(col_ != NULL);
+
+
+ m_ = M;
+ n_ = N;
+ T* p = v_ - 1;
+ for (Subscript i=0; i<N; i++)
+ {
+ col_[i] = p;
+ p += M ;
+
+ }
+ col_ --;
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = m_ * n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ delete [] (v_);
+ col_ ++; // changed back to 0-offset
+ delete [] (col_);
+ }
+
+
+ public:
+
+ T* begin() { return v_; }
+ const T* begin() const { return v_;}
+
+ T* end() { return v_ + m_*n_; }
+ const T* end() const { return v_ + m_*n_; }
+
+
+ // constructors
+
+ Fortran_Matrix() : v_(0), m_(0), n_(0), col_(0) {};
+ Fortran_Matrix(const Fortran_Matrix<T> &A)
+ {
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ Fortran_Matrix(Subscript M, Subscript N, const T& value = T())
+ {
+ initialize(M,N);
+ set(value);
+ }
+
+ Fortran_Matrix(Subscript M, Subscript N, const T* v)
+ {
+ initialize(M,N);
+ copy(v);
+ }
+
+
+ Fortran_Matrix(Subscript M, Subscript N, char *s)
+ {
+ initialize(M,N);
+ std::istrstream ins(s);
+
+ Subscript i, j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ ins >> (*this)(i,j);
+ }
+
+ // destructor
+ ~Fortran_Matrix()
+ {
+ destroy();
+ }
+
+
+ // assignments
+ //
+ Fortran_Matrix<T>& operator=(const Fortran_Matrix<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (m_ == A.m_ && n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.m_, A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Fortran_Matrix<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+
+ Subscript dim(Subscript d) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( d >= 1);
+ assert( d <= 2);
+#endif
+ return (d==1) ? m_ : ((d==2) ? n_ : 0);
+ }
+
+ Subscript num_rows() const { return m_; }
+ Subscript num_cols() const { return n_; }
+
+ Fortran_Matrix<T>& newsize(Subscript M, Subscript N)
+ {
+ if (num_rows() == M && num_cols() == N)
+ return *this;
+
+ destroy();
+ initialize(M,N);
+
+ return *this;
+ }
+
+
+
+ // 1-based element access
+ //
+ inline reference operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return col_[j][i];
+ }
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= m_) ;
+ assert(1<=j);
+ assert(j <= n_);
+#endif
+ return col_[j][i];
+ }
+
+
+#ifdef TNT_USE_REGIONS
+
+ typedef Region2D<Fortran_Matrix<T> > Region;
+ typedef const_Region2D< Fortran_Matrix<T> > const_Region;
+
+ Region operator()(const Index1D &I, const Index1D &J)
+ {
+ return Region(*this, I,J);
+ }
+
+ const_Region operator()(const Index1D &I, const Index1D &J) const
+ {
+ return const_Region(*this, I,J);
+ }
+
+#endif
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Fortran_Matrix<T> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << "\n";
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class T>
+std::istream& operator>>(std::istream &s, Fortran_Matrix<T> &A)
+{
+
+ Subscript M, N;
+
+ s >> M >> N;
+
+ if ( !(M == A.num_rows() && N == A.num_cols()))
+ {
+ A.newsize(M,N);
+ }
+
+
+ for (Subscript i=1; i<=M; i++)
+ for (Subscript j=1; j<=N; j++)
+ {
+ s >> A(i,j);
+ }
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Fortran_Matrix<T> operator+(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) + B(i,j);
+
+ return tmp;
+}
+
+template <class T>
+Fortran_Matrix<T> operator-(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) - B(i,j);
+
+ return tmp;
+}
+
+// element-wise multiplication (use matmult() below for matrix
+// multiplication in the linear algebra sense.)
+//
+//
+template <class T>
+Fortran_Matrix<T> mult_element(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M==B.num_rows());
+ assert(N==B.num_cols());
+
+ Fortran_Matrix<T> tmp(M,N);
+ Subscript i,j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ tmp(i,j) = A(i,j) * B(i,j);
+
+ return tmp;
+}
+
+
+template <class T>
+Fortran_Matrix<T> transpose(const Fortran_Matrix<T> &A)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Fortran_Matrix<T> S(N,M);
+ Subscript i, j;
+
+ for (i=1; i<=M; i++)
+ for (j=1; j<=N; j++)
+ S(j,i) = A(i,j);
+
+ return S;
+}
+
+
+
+template <class T>
+inline Fortran_Matrix<T> matmult(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == B.num_rows());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ Fortran_Matrix<T> tmp(M,K);
+ T sum;
+
+ for (Subscript i=1; i<=M; i++)
+ for (Subscript k=1; k<=K; k++)
+ {
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ sum = sum + A(i,j) * B(j,k);
+
+ tmp(i,k) = sum;
+ }
+
+ return tmp;
+}
+
+template <class T>
+inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+ return matmult(A,B);
+}
+
+template <class T>
+inline int matmult(Fortran_Matrix<T>& C, const Fortran_Matrix<T> &A,
+ const Fortran_Matrix<T> &B)
+{
+
+ assert(A.num_cols() == B.num_rows());
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+ Subscript K = B.num_cols();
+
+ C.newsize(M,K); // adjust shape of C, if necessary
+
+
+ T sum;
+
+ const T* row_i;
+ const T* col_k;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript k=1; k<=K; k++)
+ {
+ row_i = &A(i,1);
+ col_k = &B(1,k);
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ {
+ sum += *row_i * *col_k;
+ row_i += M;
+ col_k ++;
+ }
+
+ C(i,k) = sum;
+ }
+
+ }
+
+ return 0;
+}
+
+
+template <class T>
+Vector<T> matmult(const Fortran_Matrix<T> &A, const Vector<T> &x)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+ assert(A.num_cols() == x.dim());
+#endif
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Vector<T> tmp(M);
+ T sum;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ sum = 0;
+ for (Subscript j=1; j<=N; j++)
+ sum = sum + A(i,j) * x(j);
+
+ tmp(i) = sum;
+ }
+
+ return tmp;
+}
+
+template <class T>
+inline Vector<T> operator*(const Fortran_Matrix<T> &A, const Vector<T> &x)
+{
+ return matmult(A,x);
+}
+
+template <class T>
+inline Fortran_Matrix<T> operator*(const Fortran_Matrix<T> &A, const T &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ Subscript MN = M*N;
+
+ Fortran_Matrix<T> res(M,N);
+ const T* a = A.begin();
+ T* t = res.begin();
+ T* tend = res.end();
+
+ for (t=res.begin(); t < tend; t++, a++)
+ *t = *a * x;
+
+ return res;
+}
+
+} // namespace TNT
+#endif
+// FMAT_H
diff --git a/intern/iksolver/intern/TNT/fortran.h b/intern/iksolver/intern/TNT/fortran.h
new file mode 100644
index 00000000000..4f513300588
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fortran.h
@@ -0,0 +1,99 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file to define C/Fortran conventions (Platform specific)
+
+#ifndef FORTRAN_H
+#define FORTRAN_H
+
+// help map between C/C++ data types and Fortran types
+
+typedef int Fortran_integer;
+typedef float Fortran_float;
+typedef double Fortran_double;
+
+
+typedef Fortran_double *fda_; // (in/out) double precision array
+typedef const Fortran_double *cfda_; // (in) double precsion array
+
+typedef Fortran_double *fd_; // (in/out) single double precision
+typedef const Fortran_double *cfd_; // (in) single double precision
+
+typedef Fortran_float *ffa_; // (in/out) float precision array
+typedef const Fortran_float *cffa_; // (in) float precsion array
+
+typedef Fortran_float *ff_; // (in/out) single float precision
+typedef const Fortran_float *cff_; // (in) single float precision
+
+typedef Fortran_integer *fia_; // (in/out) single integer array
+typedef const Fortran_integer *cfia_; // (in) single integer array
+
+typedef Fortran_integer *fi_; // (in/out) single integer
+typedef const Fortran_integer *cfi_; // (in) single integer
+
+typedef char *fch_; // (in/out) single character
+typedef char *cfch_; // (in) single character
+
+
+
+#ifndef TNT_SUBSCRIPT_TYPE
+#define TNT_SUBSCRIPT_TYPE TNT::Fortran_integer
+#endif
+
+
+#endif
+// FORTRAN_H
diff --git a/intern/iksolver/intern/TNT/fspvec.h b/intern/iksolver/intern/TNT/fspvec.h
new file mode 100644
index 00000000000..b8dde35b6c6
--- /dev/null
+++ b/intern/iksolver/intern/TNT/fspvec.h
@@ -0,0 +1,200 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// Templated sparse vector (Fortran conventions).
+// Used primarily to interface with Fortran sparse matrix libaries.
+// (CANNOT BE USED AS AN STL CONTAINER.)
+
+#ifndef FSPVEC_H
+#define FSPVEC_H
+
+#include "tnt.h"
+#include "vec.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+
+using namespace std;
+
+namespace TNT
+{
+
+template <class T>
+class Fortran_Sparse_Vector
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ Vector<T> val_;
+ Vector<Subscript> index_;
+ Subscript dim_; // prescribed dimension
+
+
+ public:
+
+ // size and shape information
+
+ Subscript dim() const { return dim_; }
+ Subscript num_nonzeros() const { return val_.dim(); }
+
+ // access
+
+ T& val(Subscript i) { return val_(i); }
+ const T& val(Subscript i) const { return val_(i); }
+
+ Subscript &index(Subscript i) { return index_(i); }
+ const Subscript &index(Subscript i) const { return index_(i); }
+
+ // constructors
+
+ Fortran_Sparse_Vector() : val_(), index_(), dim_(0) {};
+ Fortran_Sparse_Vector(Subscript N, Subscript nz) : val_(nz),
+ index_(nz), dim_(N) {};
+ Fortran_Sparse_Vector(Subscript N, Subscript nz, const T *values,
+ const Subscript *indices): val_(nz, values), index_(nz, indices),
+ dim_(N) {}
+
+ Fortran_Sparse_Vector(const Fortran_Sparse_Vector<T> &S):
+ val_(S.val_), index_(S.index_), dim_(S.dim_) {}
+
+ // initialize from string, e.g.
+ //
+ // Fortran_Sparse_Vector<T> A(N, 2, "1.0 2.1", "1 3");
+ //
+ Fortran_Sparse_Vector(Subscript N, Subscript nz, char *v,
+ char *ind) : val_(nz, v), index_(nz, ind), dim_(N) {}
+
+ // assignments
+
+ Fortran_Sparse_Vector<T> & newsize(Subscript N, Subscript nz)
+ {
+ val_.newsize(nz);
+ index_.newsize(nz);
+ dim_ = N;
+ return *this;
+ }
+
+ Fortran_Sparse_Vector<T> & operator=( const Fortran_Sparse_Vector<T> &A)
+ {
+ val_ = A.val_;
+ index_ = A.index_;
+ dim_ = A.dim_;
+
+ return *this;
+ }
+
+ // methods
+
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+ostream& operator<<(ostream &s, const Fortran_Sparse_Vector<T> &A)
+{
+ // output format is : N nz val1 ind1 val2 ind2 ...
+ Subscript nz=A.num_nonzeros();
+
+ s << A.dim() << " " << nz << endl;
+
+ for (Subscript i=1; i<=nz; i++)
+ s << A.val(i) << " " << A.index(i) << endl;
+ s << endl;
+
+ return s;
+}
+
+
+template <class T>
+istream& operator>>(istream &s, Fortran_Sparse_Vector<T> &A)
+{
+ // output format is : N nz val1 ind1 val2 ind2 ...
+
+ Subscript N;
+ Subscript nz;
+
+ s >> N >> nz;
+
+ A.newsize(N, nz);
+
+ for (Subscript i=1; i<=nz; i++)
+ s >> A.val(i) >> A.index(i);
+
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
+// FSPVEC_H
diff --git a/intern/iksolver/intern/TNT/index.h b/intern/iksolver/intern/TNT/index.h
new file mode 100644
index 00000000000..885545d11b5
--- /dev/null
+++ b/intern/iksolver/intern/TNT/index.h
@@ -0,0 +1,115 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Vector/Matrix/Array Index Module
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include "subscript.h"
+
+namespace TNT
+{
+
+class Index1D
+{
+ Subscript lbound_;
+ Subscript ubound_;
+
+ public:
+
+ Subscript lbound() const { return lbound_; }
+ Subscript ubound() const { return ubound_; }
+
+ Index1D(const Index1D &D) : lbound_(D.lbound_), ubound_(D.ubound_) {}
+ Index1D(Subscript i1, Subscript i2) : lbound_(i1), ubound_(i2) {}
+
+ Index1D & operator=(const Index1D &D)
+ {
+ lbound_ = D.lbound_;
+ ubound_ = D.ubound_;
+ return *this;
+ }
+
+};
+
+inline Index1D operator+(const Index1D &D, Subscript i)
+{
+ return Index1D(i+D.lbound(), i+D.ubound());
+}
+
+inline Index1D operator+(Subscript i, const Index1D &D)
+{
+ return Index1D(i+D.lbound(), i+D.ubound());
+}
+
+
+
+inline Index1D operator-(Index1D &D, Subscript i)
+{
+ return Index1D(D.lbound()-i, D.ubound()-i);
+}
+
+inline Index1D operator-(Subscript i, Index1D &D)
+{
+ return Index1D(i-D.lbound(), i-D.ubound());
+}
+
+} // namespace TNT
+
+#endif
+
diff --git a/intern/iksolver/intern/TNT/lapack.h b/intern/iksolver/intern/TNT/lapack.h
new file mode 100644
index 00000000000..d3556a96071
--- /dev/null
+++ b/intern/iksolver/intern/TNT/lapack.h
@@ -0,0 +1,225 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file for Fortran Lapack
+
+#ifndef LAPACK_H
+#define LAPACK_H
+
+// This file incomplete and included here to only demonstrate the
+// basic framework for linking with the Fortran Lapack routines.
+
+#include "fortran.h"
+#include "vec.h"
+#include "fmat.h"
+
+
+#define F77_DGESV dgesv_
+#define F77_DGELS dgels_
+#define F77_DSYEV dsyev_
+#define F77_DGEEV dgeev_
+
+extern "C"
+{
+
+ // linear equations (general) using LU factorizaiton
+ //
+ void F77_DGESV(cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda,
+ fia_ ipiv, fda_ b, cfi_ ldb, fi_ info);
+
+ // solve linear least squares using QR or LU factorization
+ //
+ void F77_DGELS(cfch_ trans, cfi_ M,
+ cfi_ N, cfi_ nrhs, fda_ A, cfi_ lda, fda_ B, cfi_ ldb, fda_ work,
+ cfi_ lwork, fi_ info);
+
+ // solve symmetric eigenvalues
+ //
+ void F77_DSYEV( cfch_ jobz, cfch_ uplo, cfi_ N, fda_ A, cfi_ lda,
+ fda_ W, fda_ work, cfi_ lwork, fi_ info);
+
+ // solve unsymmetric eigenvalues
+ //
+ void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
+ fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
+ cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
+
+}
+
+// solve linear equations using LU factorization
+
+using namespace TNT;
+
+Vector<double> Lapack_LU_linear_solve(const Fortran_Matrix<double> &A,
+ const Vector<double> &b)
+{
+ const Fortran_integer one=1;
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Fortran_Matrix<double> Tmp(A);
+ Vector<double> x(b);
+ Vector<Fortran_integer> index(M);
+ Fortran_integer info = 0;
+
+ F77_DGESV(&N, &one, &Tmp(1,1), &M, &index(1), &x(1), &M, &info);
+
+ if (info != 0) return Vector<double>(0);
+ else
+ return x;
+}
+
+// solve linear least squares problem using QR factorization
+//
+Vector<double> Lapack_LLS_QR_linear_solve(const Fortran_Matrix<double> &A,
+ const Vector<double> &b)
+{
+ const Fortran_integer one=1;
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Fortran_Matrix<double> Tmp(A);
+ Vector<double> x(b);
+ Fortran_integer info = 0;
+
+ char transp = 'N';
+ Fortran_integer lwork = 5 * (M+N); // temporary work space
+ Vector<double> work(lwork);
+
+ F77_DGELS(&transp, &M, &N, &one, &Tmp(1,1), &M, &x(1), &M, &work(1),
+ &lwork, &info);
+
+ if (info != 0) return Vector<double>(0);
+ else
+ return x;
+}
+
+// *********************** Eigenvalue problems *******************
+
+// solve symmetric eigenvalue problem (eigenvalues only)
+//
+Vector<double> Upper_symmetric_eigenvalue_solve(const Fortran_Matrix<double> &A)
+{
+ char jobz = 'N';
+ char uplo = 'U';
+ Subscript N = A.num_rows();
+
+ assert(N == A.num_cols());
+
+ Vector<double> eigvals(N);
+ Fortran_integer worksize = 3*N;
+ Fortran_integer info = 0;
+ Vector<double> work(worksize);
+ Fortran_Matrix<double> Tmp = A;
+
+ F77_DSYEV(&jobz, &uplo, &N, &Tmp(1,1), &N, eigvals.begin(), work.begin(),
+ &worksize, &info);
+
+ if (info != 0) return Vector<double>();
+ else
+ return eigvals;
+}
+
+
+// solve unsymmetric eigenvalue problems
+//
+int eigenvalue_solve(const Fortran_Matrix<double> &A,
+ Vector<double> &wr, Vector<double> &wi)
+{
+ char jobvl = 'N';
+ char jobvr = 'N';
+
+ Fortran_integer N = A.num_rows();
+
+
+ assert(N == A.num_cols());
+
+ if (N<1) return 1;
+
+ Fortran_Matrix<double> vl(1,N); /* should be NxN ? **** */
+ Fortran_Matrix<double> vr(1,N);
+ Fortran_integer one = 1;
+
+ Fortran_integer worksize = 5*N;
+ Fortran_integer info = 0;
+ Vector<double> work(worksize, 0.0);
+ Fortran_Matrix<double> Tmp = A;
+
+ wr.newsize(N);
+ wi.newsize(N);
+
+// void F77_DGEEV(cfch_ jobvl, cfch_ jobvr, cfi_ N, fda_ A, cfi_ lda,
+// fda_ wr, fda_ wi, fda_ vl, cfi_ ldvl, fda_ vr,
+// cfi_ ldvr, fda_ work, cfi_ lwork, fi_ info);
+
+ F77_DGEEV(&jobvl, &jobvr, &N, &Tmp(1,1), &N, &(wr(1)),
+ &(wi(1)), &(vl(1,1)), &one, &(vr(1,1)), &one,
+ &(work(1)), &worksize, &info);
+
+ return (info==0 ? 0: 1);
+}
+
+
+
+
+
+#endif
+// LAPACK_H
+
+
+
+
diff --git a/intern/iksolver/intern/TNT/lu.h b/intern/iksolver/intern/TNT/lu.h
new file mode 100644
index 00000000000..b86027aa386
--- /dev/null
+++ b/intern/iksolver/intern/TNT/lu.h
@@ -0,0 +1,236 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef LU_H
+#define LU_H
+
+// Solve system of linear equations Ax = b.
+//
+// Typical usage:
+//
+// Matrix(double) A;
+// Vector(Subscript) ipiv;
+// Vector(double) b;
+//
+// 1) LU_Factor(A,ipiv);
+// 2) LU_Solve(A,ipiv,b);
+//
+// Now b has the solution x. Note that both A and b
+// are overwritten. If these values need to be preserved,
+// one can make temporary copies, as in
+//
+// O) Matrix(double) T = A;
+// 1) LU_Factor(T,ipiv);
+// 1a) Vector(double) x=b;
+// 2) LU_Solve(T,ipiv,x);
+//
+// See details below.
+//
+
+
+// for fabs()
+//
+#include <cmath>
+
+// right-looking LU factorization algorithm (unblocked)
+//
+// Factors matrix A into lower and upper triangular matrices
+// (L and U respectively) in solving the linear equation Ax=b.
+//
+//
+// Args:
+//
+// A (input/output) Matrix(1:n, 1:n) In input, matrix to be
+// factored. On output, overwritten with lower and
+// upper triangular factors.
+//
+// indx (output) Vector(1:n) Pivot vector. Describes how
+// the rows of A were reordered to increase
+// numerical stability.
+//
+// Return value:
+//
+// int (0 if successful, 1 otherwise)
+//
+//
+
+
+namespace TNT
+{
+
+template <class MaTRiX, class VecToRSubscript>
+int LU_factor( MaTRiX &A, VecToRSubscript &indx)
+{
+ assert(A.lbound() == 1); // currently for 1-offset
+ assert(indx.lbound() == 1); // vectors and matrices
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ if (M == 0 || N==0) return 0;
+ if (indx.dim() != M)
+ indx.newsize(M);
+
+ Subscript i=0,j=0,k=0;
+ Subscript jp=0;
+
+ typename MaTRiX::element_type t;
+
+ Subscript minMN = (M < N ? M : N) ; // min(M,N);
+
+ for (j=1; j<= minMN; j++)
+ {
+
+ // find pivot in column j and test for singularity.
+
+ jp = j;
+ t = fabs(A(j,j));
+ for (i=j+1; i<=M; i++)
+ if ( fabs(A(i,j)) > t)
+ {
+ jp = i;
+ t = fabs(A(i,j));
+ }
+
+ indx(j) = jp;
+
+ // jp now has the index of maximum element
+ // of column j, below the diagonal
+
+ if ( A(jp,j) == 0 )
+ return 1; // factorization failed because of zero pivot
+
+
+ if (jp != j) // swap rows j and jp
+ for (k=1; k<=N; k++)
+ {
+ t = A(j,k);
+ A(j,k) = A(jp,k);
+ A(jp,k) =t;
+ }
+
+ if (j<M) // compute elements j+1:M of jth column
+ {
+ // note A(j,j), was A(jp,p) previously which was
+ // guarranteed not to be zero (Label #1)
+ //
+ typename MaTRiX::element_type recp = 1.0 / A(j,j);
+
+ for (k=j+1; k<=M; k++)
+ A(k,j) *= recp;
+ }
+
+
+ if (j < minMN)
+ {
+ // rank-1 update to trailing submatrix: E = E - x*y;
+ //
+ // E is the region A(j+1:M, j+1:N)
+ // x is the column vector A(j+1:M,j)
+ // y is row vector A(j,j+1:N)
+
+ Subscript ii,jj;
+
+ for (ii=j+1; ii<=M; ii++)
+ for (jj=j+1; jj<=N; jj++)
+ A(ii,jj) -= A(ii,j)*A(j,jj);
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+template <class MaTRiX, class VecToR, class VecToRSubscripts>
+int LU_solve(const MaTRiX &A, const VecToRSubscripts &indx, VecToR &b)
+{
+ assert(A.lbound() == 1); // currently for 1-offset
+ assert(indx.lbound() == 1); // vectors and matrices
+ assert(b.lbound() == 1);
+
+ Subscript i,ii=0,ip,j;
+ Subscript n = b.dim();
+ typename MaTRiX::element_type sum = 0.0;
+
+ for (i=1;i<=n;i++)
+ {
+ ip=indx(i);
+ sum=b(ip);
+ b(ip)=b(i);
+ if (ii)
+ for (j=ii;j<=i-1;j++)
+ sum -= A(i,j)*b(j);
+ else if (sum) ii=i;
+ b(i)=sum;
+ }
+ for (i=n;i>=1;i--)
+ {
+ sum=b(i);
+ for (j=i+1;j<=n;j++)
+ sum -= A(i,j)*b(j);
+ b(i)=sum/A(i,i);
+ }
+
+ return 0;
+}
+
+} // namespace TNT
+
+#endif
+// LU_H
diff --git a/intern/iksolver/intern/TNT/qr.h b/intern/iksolver/intern/TNT/qr.h
new file mode 100644
index 00000000000..074551896b9
--- /dev/null
+++ b/intern/iksolver/intern/TNT/qr.h
@@ -0,0 +1,261 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef QR_H
+#define QR_H
+
+// Classical QR factorization example, based on Stewart[1973].
+//
+//
+// This algorithm computes the factorization of a matrix A
+// into a product of an orthognal matrix (Q) and an upper triangular
+// matrix (R), such that QR = A.
+//
+// Parameters:
+//
+// A (in): Matrix(1:N, 1:N)
+//
+// Q (output): Matrix(1:N, 1:N), collection of Householder
+// column vectors Q1, Q2, ... QN
+//
+// R (output): upper triangular Matrix(1:N, 1:N)
+//
+// Returns:
+//
+// 0 if successful, 1 if A is detected to be singular
+//
+
+
+#include <cmath> //for sqrt() & fabs()
+#include "tntmath.h" // for sign()
+
+// Classical QR factorization, based on Stewart[1973].
+//
+//
+// This algorithm computes the factorization of a matrix A
+// into a product of an orthognal matrix (Q) and an upper triangular
+// matrix (R), such that QR = A.
+//
+// Parameters:
+//
+// A (in/out): On input, A is square, Matrix(1:N, 1:N), that represents
+// the matrix to be factored.
+//
+// On output, Q and R is encoded in the same Matrix(1:N,1:N)
+// in the following manner:
+//
+// R is contained in the upper triangular section of A,
+// except that R's main diagonal is in D. The lower
+// triangular section of A represents Q, where each
+// column j is the vector Qj = I - uj*uj'/pi_j.
+//
+// C (output): vector of Pi[j]
+// D (output): main diagonal of R, i.e. D(i) is R(i,i)
+//
+// Returns:
+//
+// 0 if successful, 1 if A is detected to be singular
+//
+
+namespace TNT
+{
+
+template <class MaTRiX, class Vector>
+int QR_factor(MaTRiX &A, Vector& C, Vector &D)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(C.lbound() == 1); // 1-based arrays and vectors
+ assert(D.lbound() == 1);
+
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(M == N); // make sure A is square
+
+ Subscript i,j,k;
+ typename MaTRiX::element_type eta, sigma, sum;
+
+ // adjust the shape of C and D, if needed...
+
+ if (N != C.size()) C.newsize(N);
+ if (N != D.size()) D.newsize(N);
+
+ for (k=1; k<N; k++)
+ {
+ // eta = max |M(i,k)|, for k <= i <= n
+ //
+ eta = 0;
+ for (i=k; i<=N; i++)
+ {
+ double absA = fabs(A(i,k));
+ eta = ( absA > eta ? absA : eta );
+ }
+
+ if (eta == 0) // matrix is singular
+ {
+ cerr << "QR: k=" << k << "\n";
+ return 1;
+ }
+
+ // form Qk and premiltiply M by it
+ //
+ for(i=k; i<=N; i++)
+ A(i,k) = A(i,k) / eta;
+
+ sum = 0;
+ for (i=k; i<=N; i++)
+ sum = sum + A(i,k)*A(i,k);
+ sigma = sign(A(k,k)) * sqrt(sum);
+
+
+ A(k,k) = A(k,k) + sigma;
+ C(k) = sigma * A(k,k);
+ D(k) = -eta * sigma;
+
+ for (j=k+1; j<=N; j++)
+ {
+ sum = 0;
+ for (i=k; i<=N; i++)
+ sum = sum + A(i,k)*A(i,j);
+ sum = sum / C(k);
+
+ for (i=k; i<=N; i++)
+ A(i,j) = A(i,j) - sum * A(i,k);
+ }
+
+ D(N) = A(N,N);
+ }
+
+ return 0;
+}
+
+// modified form of upper triangular solve, except that the main diagonal
+// of R (upper portion of A) is in D.
+//
+template <class MaTRiX, class Vector>
+int R_solve(const MaTRiX &A, /*const*/ Vector &D, Vector &b)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(D.lbound() == 1); // 1-based arrays and vectors
+ assert(b.lbound() == 1);
+
+ Subscript i,j;
+ Subscript N = A.num_rows();
+
+ assert(N == A.num_cols());
+ assert(N == D.dim());
+ assert(N == b.dim());
+
+ typename MaTRiX::element_type sum;
+
+ if (D(N) == 0)
+ return 1;
+
+ b(N) = b(N) /
+ D(N);
+
+ for (i=N-1; i>=1; i--)
+ {
+ if (D(i) == 0)
+ return 1;
+ sum = 0;
+ for (j=i+1; j<=N; j++)
+ sum = sum + A(i,j)*b(j);
+ b(i) = ( b(i) - sum ) /
+ D(i);
+ }
+
+ return 0;
+}
+
+
+template <class MaTRiX, class Vector>
+int QR_solve(const MaTRiX &A, const Vector &c, /*const*/ Vector &d,
+ Vector &b)
+{
+ assert(A.lbound() == 1); // ensure these are all
+ assert(c.lbound() == 1); // 1-based arrays and vectors
+ assert(d.lbound() == 1);
+
+ Subscript N=A.num_rows();
+
+ assert(N == A.num_cols());
+ assert(N == c.dim());
+ assert(N == d.dim());
+ assert(N == b.dim());
+
+ Subscript i,j;
+ typename MaTRiX::element_type sum, tau;
+
+ for (j=1; j<N; j++)
+ {
+ // form Q'*b
+ sum = 0;
+ for (i=j; i<=N; i++)
+ sum = sum + A(i,j)*b(i);
+ if (c(j) == 0)
+ return 1;
+ tau = sum / c(j);
+ for (i=j; i<=N; i++)
+ b(i) = b(i) - tau * A(i,j);
+ }
+ return R_solve(A, d, b); // solve Rx = Q'b
+}
+
+} // namespace TNT
+
+#endif
+// QR_H
diff --git a/intern/iksolver/intern/TNT/region1d.h b/intern/iksolver/intern/TNT/region1d.h
new file mode 100644
index 00000000000..0307ee02c39
--- /dev/null
+++ b/intern/iksolver/intern/TNT/region1d.h
@@ -0,0 +1,403 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+
+#ifndef REGION1D_H
+#define REGION1D_H
+
+
+#include "subscript.h"
+#include "index.h"
+#include <iostream>
+#include <cassert>
+
+namespace TNT
+{
+
+template <class Array1D>
+class const_Region1D;
+
+template <class Array1D>
+class Region1D
+{
+ protected:
+
+ Array1D & A_;
+ Subscript offset_; // 0-based
+ Subscript dim_;
+
+ typedef typename Array1D::element_type T;
+
+ public:
+ const Array1D & array() const { return A_; }
+
+ Subscript offset() const { return offset_;}
+ Subscript dim() const { return dim_; }
+
+ Subscript offset(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i== TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+
+ Region1D(Array1D &A, Subscript i1, Subscript i2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(i1 <= i2);
+#endif
+ offset_ = i1 - TNT_BASE_OFFSET;
+ dim_ = i2-i1 + 1;
+ }
+
+ Region1D(Array1D &A, const Index1D &I) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <=I.lbound());
+ assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ offset_ = I.lbound() - TNT_BASE_OFFSET;
+ dim_ = I.ubound() - I.lbound() + 1;
+ }
+
+ Region1D(Region1D<Array1D> &A, Subscript i1, Subscript i2) :
+ A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
+ assert(i1 <= i2);
+#endif
+ // (old-offset) (new-offset)
+ //
+ offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
+ dim_ = i2-i1 + 1;
+ }
+
+ Region1D<Array1D> operator()(Subscript i1, Subscript i2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1);
+ assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
+ assert(i1 <= i2);
+#endif
+ // offset_ is 0-based, so no need for
+ // ( - TNT_BASE_OFFSET)
+ //
+ return Region1D<Array1D>(A_, i1+offset_,
+ offset_ + i2);
+ }
+
+
+ Region1D<Array1D> operator()(const Index1D &I)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET<=I.lbound());
+ assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ return Region1D<Array1D>(A_, I.lbound()+offset_,
+ offset_ + I.ubound());
+ }
+
+
+
+
+ T & operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+ const T & operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+
+ Region1D<Array1D> & operator=(const Region1D<Array1D> &R)
+ {
+ // make sure both sides conform
+ assert(dim() == R.dim());
+
+ Subscript N = dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+ }
+
+
+
+ Region1D<Array1D> & operator=(const const_Region1D<Array1D> &R)
+ {
+ // make sure both sides conform
+ assert(dim() == R.dim());
+
+ Subscript N = dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+
+ }
+
+
+ Region1D<Array1D> & operator=(const T& t)
+ {
+ Subscript N=dim();
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<= iend; i++)
+ (*this)(i) = t;
+
+ return *this;
+
+ }
+
+
+ Region1D<Array1D> & operator=(const Array1D &R)
+ {
+ // make sure both sides conform
+ Subscript N = dim();
+ assert(dim() == R.dim());
+
+ Subscript i;
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = istart + N-1;
+
+ for (i=istart; i<=iend; i++)
+ (*this)(i) = R(i);
+
+ return *this;
+
+ }
+
+};
+
+template <class Array1D>
+std::ostream& operator<<(std::ostream &s, Region1D<Array1D> &A)
+{
+ Subscript N=A.dim();
+ Subscript istart = TNT_BASE_OFFSET;
+ Subscript iend = N - 1 + TNT_BASE_OFFSET;
+
+ for (Subscript i=istart; i<=iend; i++)
+ s << A(i) << endl;
+
+ return s;
+}
+
+
+/* --------- class const_Region1D ------------ */
+
+template <class Array1D>
+class const_Region1D
+{
+ protected:
+
+ const Array1D & A_;
+ Subscript offset_; // 0-based
+ Subscript dim_;
+ typedef typename Array1D::element_type T;
+
+ public:
+ const Array1D & array() const { return A_; }
+
+ Subscript offset() const { return offset_;}
+ Subscript dim() const { return dim_; }
+
+ Subscript offset(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i== TNT_BASE_OFFSET);
+#endif
+ return offset_;
+ }
+
+
+ const_Region1D(const Array1D &A, Subscript i1, Subscript i2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(i1 <= i2);
+#endif
+ offset_ = i1 - TNT_BASE_OFFSET;
+ dim_ = i2-i1 + 1;
+ }
+
+ const_Region1D(const Array1D &A, const Index1D &I) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <=I.lbound());
+ assert(I.ubound() <= A.dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ offset_ = I.lbound() - TNT_BASE_OFFSET;
+ dim_ = I.ubound() - I.lbound() + 1;
+ }
+
+ const_Region1D(const_Region1D<Array1D> &A, Subscript i1, Subscript i2) :
+ A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1 );
+ assert(i2 <= A.dim() + (TNT_BASE_OFFSET - 1));
+ assert(i1 <= i2);
+#endif
+ // (old-offset) (new-offset)
+ //
+ offset_ = (i1 - TNT_BASE_OFFSET) + A.offset_;
+ dim_ = i2-i1 + 1;
+ }
+
+ const_Region1D<Array1D> operator()(Subscript i1, Subscript i2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i1);
+ assert(i2 <= dim() + (TNT_BASE_OFFSET -1));
+ assert(i1 <= i2);
+#endif
+ // offset_ is 0-based, so no need for
+ // ( - TNT_BASE_OFFSET)
+ //
+ return const_Region1D<Array1D>(A_, i1+offset_,
+ offset_ + i2);
+ }
+
+
+ const_Region1D<Array1D> operator()(const Index1D &I)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET<=I.lbound());
+ assert(I.ubound() <= dim() + (TNT_BASE_OFFSET-1));
+ assert(I.lbound() <= I.ubound());
+#endif
+ return const_Region1D<Array1D>(A_, I.lbound()+offset_,
+ offset_ + I.ubound());
+ }
+
+
+ const T & operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(TNT_BASE_OFFSET <= i);
+ assert(i <= dim() + (TNT_BASE_OFFSET-1));
+#endif
+ return A_(i+offset_);
+ }
+
+
+
+
+};
+
+template <class Array1D>
+std::ostream& operator<<(std::ostream &s, const_Region1D<Array1D> &A)
+{
+ Subscript N=A.dim();
+
+ for (Subscript i=1; i<=N; i++)
+ s << A(i) << endl;
+
+ return s;
+}
+
+
+} // namespace TNT
+
+#endif
+// const_Region1D_H
diff --git a/intern/iksolver/intern/TNT/region2d.h b/intern/iksolver/intern/TNT/region2d.h
new file mode 100644
index 00000000000..d612dfdaa79
--- /dev/null
+++ b/intern/iksolver/intern/TNT/region2d.h
@@ -0,0 +1,499 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// 2D Regions for arrays and matrices
+
+#ifndef REGION2D_H
+#define REGION2D_H
+
+#include "index.h"
+#include <iostream>
+#include <cassert>
+
+namespace TNT
+{
+
+template <class Array2D>
+class const_Region2D;
+
+
+template <class Array2D>
+class Region2D
+{
+ protected:
+
+ Array2D & A_;
+ Subscript offset_[2]; // 0-offset internally
+ Subscript dim_[2];
+
+ public:
+ typedef typename Array2D::value_type T;
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Array2D & array() { return A_; }
+ const Array2D & array() const { return A_; }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return dim_[0]; }
+ Subscript num_cols() const { return dim_[1]; }
+ Subscript offset(Subscript i) const // 1-offset
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+#endif
+ return offset_[i-A_.lbound()];
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+#endif
+ return dim_[i-A_.lbound()];
+ }
+
+
+
+ Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1,
+ Subscript j2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A.lbound() <= i1);
+ assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= j1);
+ assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+
+
+ offset_[0] = i1-A.lbound();
+ offset_[1] = j1-A.lbound();
+ dim_[0] = i2-i1+1;
+ dim_[1] = j2-j1+1;
+ }
+
+ Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( A.lbound() <= I.lbound());
+ assert( I.ubound()<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= J.lbound());
+ assert( J.ubound() <= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+
+ offset_[0] = I.lbound()-A.lbound();
+ offset_[1] = J.lbound()-A.lbound();
+ dim_[0] = I.ubound() - I.lbound() + 1;
+ dim_[1] = J.ubound() - J.lbound() + 1;
+ }
+
+ Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) : A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A.lbound() <= i1);
+ assert( i2<= A.dim(A.lbound()) + A.lbound()-1);
+ assert( A.lbound() <= j1);
+ assert( j2<= A.dim(A.lbound()+1) + A.lbound()-1 );
+#endif
+ offset_[0] = (i1 - A.lbound()) + A.offset_[0];
+ offset_[1] = (j1 - A.lbound()) + A.offset_[1];
+ dim_[0] = i2-i1 + 1;
+ dim_[1] = j2-j1+1;
+ }
+
+ Region2D<Array2D> operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( A_.lbound() <= i1);
+ assert( i2<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j1);
+ assert( j2<= dim_[1] + A_.lbound()-1 );
+#endif
+ return Region2D<Array2D>(A_,
+ i1+offset_[0], offset_[0] + i2,
+ j1+offset_[1], offset_[1] + j2);
+ }
+
+
+ Region2D<Array2D> operator()(const Index1D &I,
+ const Index1D &J)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( A_.lbound() <= I.lbound());
+ assert( I.ubound()<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= J.lbound());
+ assert( J.ubound() <= dim_[1] + A_.lbound()-1 );
+#endif
+
+ return Region2D<Array2D>(A_, I.lbound()+offset_[0],
+ offset_[0] + I.ubound(), offset_[1]+J.lbound(),
+ offset_[1] + J.ubound());
+ }
+
+ inline T & operator()(Subscript i, Subscript j)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j);
+ assert( j<= dim_[1] + A_.lbound()-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+ inline const T & operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= dim_[0] + A_.lbound()-1);
+ assert( A_.lbound() <= j);
+ assert( j<= dim_[1] + A_.lbound()-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+
+ Region2D<Array2D> & operator=(const Region2D<Array2D> &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const const_Region2D<Array2D> &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const Array2D &R)
+ {
+ Subscript M = num_rows();
+ Subscript N = num_cols();
+
+ // make sure both sides conform
+ assert(M == R.num_rows());
+ assert(N == R.num_cols());
+
+
+ Subscript start = R.lbound();
+ Subscript Mend = start + M - 1;
+ Subscript Nend = start + N - 1;
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = R(i,j);
+
+ return *this;
+ }
+
+ Region2D<Array2D> & operator=(const T &scalar)
+ {
+ Subscript start = lbound();
+ Subscript Mend = lbound() + num_rows() - 1;
+ Subscript Nend = lbound() + num_cols() - 1;
+
+
+ for (Subscript i=start; i<=Mend; i++)
+ for (Subscript j=start; j<=Nend; j++)
+ (*this)(i,j) = scalar;
+
+ return *this;
+ }
+
+};
+
+//************************
+
+template <class Array2D>
+class const_Region2D
+{
+ protected:
+
+ const Array2D & A_;
+ Subscript offset_[2]; // 0-offset internally
+ Subscript dim_[2];
+
+ public:
+ typedef typename Array2D::value_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ const Array2D & array() const { return A_; }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return dim_[0]; }
+ Subscript num_cols() const { return dim_[1]; }
+ Subscript offset(Subscript i) const // 1-offset
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+#endif
+ return offset_[i-TNT_BASE_OFFSET];
+ }
+
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+#endif
+ return dim_[i-TNT_BASE_OFFSET];
+ }
+
+
+ const_Region2D(const Array2D &A, Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+
+ offset_[0] = i1-TNT_BASE_OFFSET;
+ offset_[1] = j1-TNT_BASE_OFFSET;
+ dim_[0] = i2-i1+1;
+ dim_[1] = j2-j1+1;
+ }
+
+ const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J)
+ : A_(A)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( TNT_BASE_OFFSET <= I.lbound());
+ assert( I.ubound()<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= J.lbound());
+ assert( J.ubound() <= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+
+ offset_[0] = I.lbound()-TNT_BASE_OFFSET;
+ offset_[1] = J.lbound()-TNT_BASE_OFFSET;
+ dim_[0] = I.ubound() - I.lbound() + 1;
+ dim_[1] = J.ubound() - J.lbound() + 1;
+ }
+
+
+ const_Region2D(const_Region2D<Array2D> &A, Subscript i1,
+ Subscript i2,
+ Subscript j1, Subscript j2) : A_(A.A_)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= A.dim(TNT_BASE_OFFSET) + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= A.dim(TNT_BASE_OFFSET+1) + TNT_BASE_OFFSET-1 );
+#endif
+ offset_[0] = (i1 - TNT_BASE_OFFSET) + A.offset_[0];
+ offset_[1] = (j1 - TNT_BASE_OFFSET) + A.offset_[1];
+ dim_[0] = i2-i1 + 1;
+ dim_[1] = j2-j1+1;
+ }
+
+ const_Region2D<Array2D> operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( i1 <= i2 );
+ assert( j1 <= j2);
+ assert( TNT_BASE_OFFSET <= i1);
+ assert( i2<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j1);
+ assert( j2<= dim_[0] + TNT_BASE_OFFSET-1 );
+#endif
+ return const_Region2D<Array2D>(A_,
+ i1+offset_[0], offset_[0] + i2,
+ j1+offset_[1], offset_[1] + j2);
+ }
+
+
+ const_Region2D<Array2D> operator()(const Index1D &I,
+ const Index1D &J)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( I.lbound() <= I.ubound() );
+ assert( J.lbound() <= J.ubound() );
+ assert( TNT_BASE_OFFSET <= I.lbound());
+ assert( I.ubound()<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= J.lbound());
+ assert( J.ubound() <= dim_[1] + TNT_BASE_OFFSET-1 );
+#endif
+
+ return const_Region2D<Array2D>(A_, I.lbound()+offset_[0],
+ offset_[0] + I.ubound(), offset_[1]+J.lbound(),
+ offset_[1] + J.ubound());
+ }
+
+
+ inline const T & operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( TNT_BASE_OFFSET <= i);
+ assert( i<= dim_[0] + TNT_BASE_OFFSET-1);
+ assert( TNT_BASE_OFFSET <= j);
+ assert( j<= dim_[1] + TNT_BASE_OFFSET-1 );
+#endif
+ return A_(i+offset_[0], j+offset_[1]);
+ }
+
+};
+
+
+// ************** std::ostream algorithms *******************************
+
+template <class Array2D>
+std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A)
+{
+ Subscript start = A.lbound();
+ Subscript Mend=A.lbound()+ A.num_rows() - 1;
+ Subscript Nend=A.lbound() + A.num_cols() - 1;
+
+
+ s << A.num_rows() << " " << A.num_cols() << "\n";
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+}
+
+template <class Array2D>
+std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A)
+{
+ Subscript start = A.lbound();
+ Subscript Mend=A.lbound()+ A.num_rows() - 1;
+ Subscript Nend=A.lbound() + A.num_cols() - 1;
+
+
+ s << A.num_rows() << " " << A.num_cols() << "\n";
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << "\n";
+ }
+
+
+ return s;
+
+}
+
+} // namespace TNT
+
+#endif
+// REGION2D_H
diff --git a/intern/iksolver/intern/TNT/stopwatch.h b/intern/iksolver/intern/TNT/stopwatch.h
new file mode 100644
index 00000000000..6079ec6f1b1
--- /dev/null
+++ b/intern/iksolver/intern/TNT/stopwatch.h
@@ -0,0 +1,115 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef STPWATCH_H
+#define STPWATCH_H
+
+// for clock() and CLOCKS_PER_SEC
+#include <ctime>
+
+namespace TNT
+{
+
+/* Simple stopwatch object:
+
+ void start() : start timing
+ double stop() : stop timing
+ void reset() : set elapsed time to 0.0
+ double read() : read elapsed time (in seconds)
+
+*/
+
+inline double seconds(void)
+{
+ static const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+ return ( (double) clock() ) * secs_per_tick;
+}
+
+
+class stopwatch {
+ private:
+ int running;
+ double last_time;
+ double total;
+
+ public:
+ stopwatch() : running(0), last_time(0.0), total(0.0) {}
+ void reset() { running = 0; last_time = 0.0; total=0.0; }
+ void start() { if (!running) { last_time = seconds(); running = 1;}}
+ double stop() { if (running)
+ {
+ total += seconds() - last_time;
+ running = 0;
+ }
+ return total;
+ }
+ double read() { if (running)
+ {
+ total+= seconds() - last_time;
+ last_time = seconds();
+ }
+ return total;
+ }
+
+};
+
+} // namespace TNT
+
+#endif
+
+
+
diff --git a/intern/iksolver/intern/TNT/subscript.h b/intern/iksolver/intern/TNT/subscript.h
new file mode 100644
index 00000000000..4728a79a168
--- /dev/null
+++ b/intern/iksolver/intern/TNT/subscript.h
@@ -0,0 +1,90 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef SUBSCRPT_H
+#define SUBSCRPT_H
+
+
+//---------------------------------------------------------------------
+// This definition describes the default TNT data type used for
+// indexing into TNT matrices and vectors. The data type should
+// be wide enough to index into large arrays. It defaults to an
+// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE,
+// e.g.
+//
+// g++ -DTNT_SUBSCRIPT_TYPE='unsigned int' ...
+//
+//---------------------------------------------------------------------
+//
+
+#ifndef TNT_SUBSCRIPT_TYPE
+#define TNT_SUBSCRIPT_TYPE int
+#endif
+
+namespace TNT
+{
+ typedef TNT_SUBSCRIPT_TYPE Subscript;
+}
+
+
+// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the
+// first elements. This offset is left as a macro for future
+// purposes, but should not be changed in the current release.
+//
+//
+#define TNT_BASE_OFFSET (1)
+
+#endif
diff --git a/intern/iksolver/intern/TNT/svd.h b/intern/iksolver/intern/TNT/svd.h
new file mode 100644
index 00000000000..9be2d98bd9f
--- /dev/null
+++ b/intern/iksolver/intern/TNT/svd.h
@@ -0,0 +1,507 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef SVD_H
+
+#define SVD_H
+
+// Compute the Single Value Decomposition of an arbitrary matrix A
+// That is compute the 3 matrices U,W,V with U column orthogonal (m,n)
+// ,W a diagonal matrix and V an orthogonal square matrix s.t.
+// A = U.W.Vt. From this decomposition it is trivial to compute the
+// inverse of A as Ainv = V.Winv.tranpose(U).
+// work_space is a temporary vector used by this class to compute
+// intermediate values during the computation of the SVD. This should
+// be of length a.num_cols. This is not checked
+
+#include "tntmath.h"
+
+namespace TNT
+{
+
+
+template <class MaTRiX, class VecToR >
+void SVD(MaTRiX &a, VecToR &w, MaTRiX &v, VecToR &work_space) {
+
+ int n = a.num_cols();
+ int m = a.num_rows();
+
+ int flag,i,its,j,jj,k,l(0),nm(0);
+ typename MaTRiX::value_type c,f,h,x,y,z;
+ typename MaTRiX::value_type anorm(0),g(0),scale(0);
+ typename MaTRiX::value_type s(0);
+
+ work_space.newsize(n);
+
+ for (i=1;i<=n;i++) {
+ l=i+1;
+ work_space(i)=scale*g;
+
+ g = (typename MaTRiX::value_type)0;
+
+ s = (typename MaTRiX::value_type)0;
+ scale = (typename MaTRiX::value_type)0;
+
+ if (i <= m) {
+ for (k=i;k<=m;k++) scale += TNT::abs(a(k,i));
+ if (scale > (typename MaTRiX::value_type)0) {
+ for (k=i;k<=m;k++) {
+ a(k,i) /= scale;
+ s += a(k,i)*a(k,i);
+ }
+ f=a(i,i);
+ g = -TNT::sign(sqrt(s),f);
+ h=f*g-s;
+ a(i,i)=f-g;
+ if (i != n) {
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=i;k<=m;k++) s += a(k,i)*a(k,j);
+ f=s/h;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ }
+ for (k=i;k<=m;k++) a(k,i) *= scale;
+ }
+ }
+ w(i)=scale*g;
+ g = (typename MaTRiX::value_type)0;
+ s = (typename MaTRiX::value_type)0;
+ scale = (typename MaTRiX::value_type)0;
+ if (i <= m && i != n) {
+ for (k=l;k<=n;k++) scale += TNT::abs(a(i,k));
+ if (scale > (typename MaTRiX::value_type)0) {
+ for (k=l;k<=n;k++) {
+ a(i,k) /= scale;
+ s += a(i,k)*a(i,k);
+ }
+ f=a(i,l);
+ g = -TNT::sign(sqrt(s),f);
+ h=f*g-s;
+ a(i,l)=f-g;
+ for (k=l;k<=n;k++) work_space(k)=a(i,k)/h;
+ if (i != m) {
+ for (j=l;j<=m;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=n;k++) s += a(j,k)*a(i,k);
+ for (k=l;k<=n;k++) a(j,k) += s*work_space(k);
+ }
+ }
+ for (k=l;k<=n;k++) a(i,k) *= scale;
+ }
+ }
+ anorm=TNT::max(anorm,(TNT::abs(w(i))+TNT::abs(work_space(i))));
+ }
+ for (i=n;i>=1;i--) {
+ if (i < n) {
+ if (g != (typename MaTRiX::value_type)0) {
+ for (j=l;j<=n;j++)
+ v(j,i)=(a(i,j)/a(i,l))/g;
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=n;k++) s += a(i,k)*v(k,j);
+ for (k=l;k<=n;k++) v(k,j) += s*v(k,i);
+ }
+ }
+ for (j=l;j<=n;j++) v(i,j)=v(j,i)= (typename MaTRiX::value_type)0;
+ }
+ v(i,i)= (typename MaTRiX::value_type)1;
+ g=work_space(i);
+ l=i;
+ }
+ for (i=n;i>=1;i--) {
+ l=i+1;
+ g=w(i);
+ if (i < n) {
+ for (j=l;j<=n;j++) a(i,j)= (typename MaTRiX::value_type)0;
+ }
+ if (g != (typename MaTRiX::value_type)0) {
+ g= ((typename MaTRiX::value_type)1)/g;
+ if (i != n) {
+ for (j=l;j<=n;j++) {
+ s = (typename MaTRiX::value_type)0;
+ for (k=l;k<=m;k++) s += a(k,i)*a(k,j);
+ f=(s/a(i,i))*g;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ }
+ for (j=i;j<=m;j++) a(j,i) *= g;
+ } else {
+ for (j=i;j<=m;j++) a(j,i)= (typename MaTRiX::value_type)0;
+ }
+ ++a(i,i);
+ }
+ for (k=n;k>=1;k--) {
+ for (its=1;its<=30;its++) {
+ flag=1;
+ for (l=k;l>=1;l--) {
+ nm=l-1;
+ if (TNT::abs(work_space(l))+anorm == anorm) {
+ flag=0;
+ break;
+ }
+ if (TNT::abs(w(nm))+anorm == anorm) break;
+ }
+ if (flag) {
+ c= (typename MaTRiX::value_type)0;
+ s= (typename MaTRiX::value_type)1;
+ for (i=l;i<=k;i++) {
+ f=s*work_space(i);
+ if (TNT::abs(f)+anorm != anorm) {
+ g=w(i);
+ h= (typename MaTRiX::value_type)TNT::pythag(float(f),float(g));
+ w(i)=h;
+ h= ((typename MaTRiX::value_type)1)/h;
+ c=g*h;
+ s=(-f*h);
+ for (j=1;j<=m;j++) {
+ y=a(j,nm);
+ z=a(j,i);
+ a(j,nm)=y*c+z*s;
+ a(j,i)=z*c-y*s;
+ }
+ }
+ }
+ }
+ z=w(k);
+ if (l == k) {
+ if (z < (typename MaTRiX::value_type)0) {
+ w(k) = -z;
+ for (j=1;j<=n;j++) v(j,k)=(-v(j,k));
+ }
+ break;
+ }
+
+
+#if 1
+ if (its == 30)
+ {
+ TNTException an_exception;
+ an_exception.i = 0;
+ throw an_exception;
+
+ return ;
+ assert(false);
+ }
+#endif
+ x=w(l);
+ nm=k-1;
+ y=w(nm);
+ g=work_space(nm);
+ h=work_space(k);
+ f=((y-z)*(y+z)+(g-h)*(g+h))/(((typename MaTRiX::value_type)2)*h*y);
+ g=(typename MaTRiX::value_type)TNT::pythag(float(f), float(1));
+ f=((x-z)*(x+z)+h*((y/(f+TNT::sign(g,f)))-h))/x;
+ c = (typename MaTRiX::value_type)1;
+ s = (typename MaTRiX::value_type)1;
+ for (j=l;j<=nm;j++) {
+ i=j+1;
+ g=work_space(i);
+ y=w(i);
+ h=s*g;
+ g=c*g;
+ z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h));
+ work_space(j)=z;
+ c=f/z;
+ s=h/z;
+ f=x*c+g*s;
+ g=g*c-x*s;
+ h=y*s;
+ y=y*c;
+ for (jj=1;jj<=n;jj++) {
+ x=v(jj,j);
+ z=v(jj,i);
+ v(jj,j)=x*c+z*s;
+ v(jj,i)=z*c-x*s;
+ }
+ z=(typename MaTRiX::value_type)TNT::pythag(float(f),float(h));
+ w(j)=z;
+ if (z != (typename MaTRiX::value_type)0) {
+ z= ((typename MaTRiX::value_type)1)/z;
+ c=f*z;
+ s=h*z;
+ }
+ f=(c*g)+(s*y);
+ x=(c*y)-(s*g);
+ for (jj=1;jj<=m;jj++) {
+ y=a(jj,j);
+ z=a(jj,i);
+ a(jj,j)=y*c+z*s;
+ a(jj,i)=z*c-y*s;
+ }
+ }
+ work_space(l)= (typename MaTRiX::value_type)0;
+ work_space(k)=f;
+ w(k)=x;
+ }
+ }
+};
+
+
+
+// A is replaced by the column orthogonal matrix U
+
+
+template <class MaTRiX, class VecToR >
+void SVD_a( MaTRiX &a, VecToR &w, MaTRiX &v) {
+
+ int n = a.num_cols();
+ int m = a.num_rows();
+
+ int flag,i,its,j,jj,k,l,nm;
+ typename MaTRiX::value_type anorm,c,f,g,h,s,scale,x,y,z;
+
+ VecToR work_space;
+ work_space.newsize(n);
+
+ g = scale = anorm = 0.0;
+
+ for (i=1;i <=n;i++) {
+ l = i+1;
+ work_space(i) = scale*g;
+ g = s=scale=0.0;
+
+ if (i <= m) {
+ for(k=i; k<=m; k++) scale += abs(a(k,i));
+
+ if (scale) {
+ for (k = i; k <=m ; k++) {
+ a(k,i) /= scale;
+ s += a(k,i)*a(k,i);
+ }
+ f = a(i,i);
+ g = -sign(sqrt(s),f);
+ h = f*g -s;
+ a(i,i) = f-g;
+
+ for (j = l; j <=n; j++) {
+ for (s = 0.0,k =i;k<=m;k++) s += a(k,i)*a(k,j);
+ f = s/h;
+ for (k = i; k <= m; k++) a(k,j) += f*a(k,i);
+ }
+ for (k = i; k <=m;k++) a(k,i) *= scale;
+ }
+ }
+
+ w(i) = scale*g;
+ g = s = scale = 0.0;
+
+ if (i <=m && i != n) {
+ for (k = l; k <=n;k++) scale += abs(a(i,k));
+ if (scale) {
+ for(k = l;k <=n;k++) {
+ a(i,k) /= scale;
+ s += a(i,k) * a(i,k);
+ }
+
+ f = a(i,l);
+ g = -sign(sqrt(s),f);
+ h= f*g -s;
+ a(i,l) = f-g;
+ for(k=l;k<=n;k++) work_space(k) = a(i,k)/h;
+ for (j=l;j<=m;j++) {
+ for(s = 0.0,k=l;k<=n;k++) s+= a(j,k)*a(i,k);
+ for(k=l;k<=n;k++) a(j,k) += s*work_space(k);
+ }
+ for(k=l;k<=n;k++) a(i,k)*=scale;
+ }
+ }
+ anorm = max(anorm,(abs(w(i)) + abs(work_space(i))));
+ }
+ for (i=n;i>=1;i--) {
+ if (i <n) {
+ if (g) {
+ for(j=l;j<=n;j++) v(j,i) = (a(i,j)/a(i,l))/g;
+ for(j=l;j<=n;j++) {
+ for(s=0.0,k=l;k<=n;k++) s += a(i,k)*v(k,j);
+ for(k=l; k<=n;k++) v(k,j) +=s*v(k,i);
+ }
+ }
+ for(j=l;j <=n;j++) v(i,j) = v(j,i) = 0.0;
+ }
+ v(i,i) = 1.0;
+ g = work_space(i);
+ l = i;
+ }
+
+ for (i = min(m,n);i>=1;i--) {
+ l = i+1;
+ g = w(i);
+ for (j=l;j <=n;j++) a(i,j) = 0.0;
+ if (g) {
+ g = 1.0/g;
+ for (j=l;j<=n;j++) {
+ for (s = 0.0,k=l;k<=m;k++) s += a(k,i)*a(k,j);
+ f = (s/a(i,i))*g;
+ for (k=i;k<=m;k++) a(k,j) += f*a(k,i);
+ }
+ for (j=i;j<=m;j++) a(j,i)*=g;
+ } else {
+ for (j=i;j<=m;j++) a(j,i) = 0.0;
+ }
+ ++a(i,i);
+ }
+
+ for (k=n;k>=1;k--) {
+ for (its=1;its<=30;its++) {
+ flag=1;
+ for(l=k;l>=1;l--) {
+ nm = l-1;
+ if (abs(work_space(l)) + anorm == anorm) {
+ flag = 0;
+ break;
+ }
+ if (abs(w(nm)) + anorm == anorm) break;
+ }
+ if (flag) {
+ c = 0.0;
+ s = 1.0;
+ for (i=l;i<=k;i++) {
+ f = s*work_space(i);
+ work_space(i) = c*work_space(i);
+ if (abs(f) +anorm == anorm) break;
+ g = w(i);
+ h = pythag(f,g);
+ w(i) = h;
+ h = 1.0/h;
+ c = g*h;
+ s = -f*h;
+ for (j=1;j<=m;j++) {
+ y= a(j,nm);
+ z=a(j,i);
+ a(j,nm) = y*c + z*s;
+ a(j,i) = z*c - y*s;
+ }
+ }
+ }
+ z=w(k);
+ if (l==k) {
+ if (z <0.0) {
+ w(k) = -z;
+ for (j=1;j<=n;j++) v(j,k) = -v(j,k);
+ }
+ break;
+ }
+
+ if (its == 30) assert(false);
+
+ x=w(l);
+ nm=k-1;
+ y=w(nm);
+ g=work_space(nm);
+ h=work_space(k);
+
+ f= ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y);
+ g = pythag(f,1.0);
+ f= ((x-z)*(x+z) + h*((y/(f + sign(g,f)))-h))/x;
+ c=s=1.0;
+
+ for (j=l;j<=nm;j++) {
+ i=j+1;
+ g = work_space(i);
+ y=w(i);
+ h=s*g;
+ g=c*g;
+ z=pythag(f,h);
+ work_space(j) = z;
+ c=f/z;
+ s=h/z;
+ f=x*c + g*s;
+ g= g*c - x*s;
+ h=y*s;
+ y*=c;
+ for(jj=1;jj<=n;jj++) {
+ x=v(jj,j);
+ z=v(jj,i);
+ v(jj,j) = x*c + z*s;
+ v(jj,i) = z*c- x*s;
+ }
+ z=pythag(f,h);
+ w(j)=z;
+ if(z) {
+ z = 1.0/z;
+ c=f*z;
+ s=h*z;
+ }
+ f=c*g + s*y;
+ x= c*y-s*g;
+
+ for(jj=1;jj<=m;jj++) {
+ y=a(jj,j);
+ z=a(jj,i);
+ a(jj,j) = y*c+z*s;
+ a(jj,i) = z*c - y*s;
+ }
+ }
+
+ work_space(l) = 0.0;
+ work_space(k) = f;
+ w(k) = x;
+ }
+ }
+}
+}
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/intern/TNT/tnt.h b/intern/iksolver/intern/TNT/tnt.h
new file mode 100644
index 00000000000..df27079f87a
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tnt.h
@@ -0,0 +1,127 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+#ifndef TNT_H
+#define TNT_H
+
+//---------------------------------------------------------------------
+// tnt.h TNT general header file. Defines default types
+// and conventions.
+//---------------------------------------------------------------------
+
+//---------------------------------------------------------------------
+// Include current version
+//---------------------------------------------------------------------
+#include "version.h"
+
+//---------------------------------------------------------------------
+// Define the data type used for matrix and vector Subscripts.
+// This will default to "int", but it can be overriden at compile time,
+// e.g.
+//
+// g++ -DTNT_SUBSCRIPT_TYPE='unsinged long' ...
+//
+// See subscript.h for details.
+//---------------------------------------------------------------------
+
+#include "subscript.h"
+
+
+
+//---------------------------------------------------------------------
+// Define this macro if you want TNT to ensure all refernces
+// are within the bounds of the array. This encurs a run-time
+// overhead, of course, but is recommended while developing
+// code. It can be turned off for production runs.
+//
+// #define TNT_BOUNDS_CHECK
+//---------------------------------------------------------------------
+//
+#define TNT_BOUNDS_CHECK
+#ifdef TNT_NO_BOUNDS_CHECK
+#undef TNT_BOUNDS_CHECK
+#endif
+
+//---------------------------------------------------------------------
+// Define this macro if you want to utilize matrix and vector
+// regions. This is typically on, but you can save some
+// compilation time by turning it off. If you do this and
+// attempt to use regions you will get an error message.
+//
+// #define TNT_USE_REGIONS
+//---------------------------------------------------------------------
+//
+#define TNT_USE_REGIONS
+
+//---------------------------------------------------------------------
+//
+//---------------------------------------------------------------------
+// if your system doesn't have abs() min(), and max() uncoment the following
+//---------------------------------------------------------------------
+//
+//
+//#define __NEED_ABS_MIN_MAX_
+
+#include "tntmath.h"
+
+
+
+
+
+
+
+#endif
+// TNT_H
diff --git a/intern/iksolver/intern/TNT/tntmath.h b/intern/iksolver/intern/TNT/tntmath.h
new file mode 100644
index 00000000000..3342ff7f5c6
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tntmath.h
@@ -0,0 +1,177 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Header file for scalar math functions
+
+#ifndef TNTMATH_H
+#define TNTMATH_H
+
+// conventional functions required by several matrix algorithms
+
+
+
+namespace TNT
+{
+
+struct TNTException {
+ int i;
+};
+
+
+inline double abs(double t)
+{
+ return ( t > 0 ? t : -t);
+}
+
+inline double min(double a, double b)
+{
+ return (a < b ? a : b);
+}
+
+inline double max(double a, double b)
+{
+ return (a > b ? a : b);
+}
+
+inline float abs(float t)
+{
+ return ( t > 0 ? t : -t);
+}
+
+inline float min(float a, float b)
+{
+ return (a < b ? a : b);
+}
+
+inline int min(int a,int b) {
+ return (a < b ? a : b);
+}
+
+
+inline float max(float a, float b)
+{
+ return (a > b ? a : b);
+}
+
+inline double sign(double a)
+{
+ return (a > 0 ? 1.0 : -1.0);
+}
+
+inline double sign(double a,double b) {
+ return (b >= 0.0 ? TNT::abs(a) : -TNT::abs(a));
+}
+
+inline float sign(float a,float b) {
+ return (b >= 0.0f ? TNT::abs(a) : -TNT::abs(a));
+}
+
+inline float sign(float a)
+{
+ return (a > 0.0 ? 1.0f : -1.0f);
+}
+
+inline float pythag(float a, float b)
+{
+ float absa,absb;
+ absa = abs(a);
+ absb = abs(b);
+
+ if (absa > absb) {
+ float sqr = absb/absa;
+ sqr *= sqr;
+ return absa * float(sqrt(1 + sqr));
+ } else {
+ if (absb > float(0)) {
+ float sqr = absa/absb;
+ sqr *= sqr;
+ return absb * float(sqrt(1 + sqr));
+ } else {
+ return float(0);
+ }
+ }
+}
+
+inline double pythag(double a, double b)
+{
+ double absa,absb;
+ absa = abs(a);
+ absb = abs(b);
+
+ if (absa > absb) {
+ double sqr = absb/absa;
+ sqr *= sqr;
+ return absa * double(sqrt(1 + sqr));
+ } else {
+
+ if (absb > double(0)) {
+ double sqr = absa/absb;
+ sqr *= sqr;
+ return absb * double(sqrt(1 + sqr));
+ } else {
+ return double(0);
+ }
+ }
+}
+
+
+} /* namespace TNT */
+
+
+#endif
+/* TNTMATH_H */
+
diff --git a/intern/iksolver/intern/TNT/tntreqs.h b/intern/iksolver/intern/TNT/tntreqs.h
new file mode 100644
index 00000000000..c935902554e
--- /dev/null
+++ b/intern/iksolver/intern/TNT/tntreqs.h
@@ -0,0 +1,102 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// The requirements for a bare-bones vector class:
+//
+//
+// o) must have 0-based [] indexing for const and
+// non-const objects (i.e. operator[] defined)
+//
+// o) must have size() method to denote the number of
+// elements
+// o) must clean up after itself when destructed
+// (i.e. no memory leaks)
+//
+// -) must have begin() and end() methods (The begin()
+// method is necessary, because relying on
+// &v_[0] may not work on a empty vector (i.e. v_ is NULL.)
+//
+// o) must be templated
+// o) must have X::value_type defined to be the types of elements
+// o) must have X::X(const &x) copy constructor (by *value*)
+// o) must have X::X(int N) constructor to N-length vector
+// (NOTE: this constructor need *NOT* initalize elements)
+//
+// -) must have X::X(int N, T scalar) constructor to initalize
+// elements to value of "scalar".
+//
+// ( removed, because valarray<> class uses (scalar, N) rather
+// than (N, scalar) )
+// -) must have X::X(int N, const T* scalars) constructor to copy from
+// any C linear array
+//
+// ( removed, because of same reverse order of valarray<> )
+//
+// o) must have assignment A=B, by value
+//
+// NOTE: this class is *NOT* meant to be derived from,
+// so its methods (particularly indexing) need not be
+// declared virtual.
+//
+//
+// Some things it *DOES NOT* need to do are
+//
+// o) bounds checking
+// o) array referencing (e.g. reference counting)
+// o) support () indexing
+// o) I/O
+//
diff --git a/intern/iksolver/intern/TNT/transv.h b/intern/iksolver/intern/TNT/transv.h
new file mode 100644
index 00000000000..47730350acc
--- /dev/null
+++ b/intern/iksolver/intern/TNT/transv.h
@@ -0,0 +1,192 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Matrix Transpose Views
+
+#ifndef TRANSV_H
+#define TRANSV_H
+
+#include <iostream>
+#include <cassert>
+#include "vec.h"
+
+namespace TNT
+{
+
+template <class Array2D>
+class Transpose_View
+{
+ protected:
+
+ const Array2D & A_;
+
+ public:
+
+ typedef typename Array2D::element_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+
+ const Array2D & array() const { return A_; }
+ Subscript num_rows() const { return A_.num_cols();}
+ Subscript num_cols() const { return A_.num_rows();}
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript dim(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert( A_.lbound() <= i);
+ assert( i<= A_.lbound()+1);
+#endif
+ if (i== A_.lbound())
+ return num_rows();
+ else
+ return num_cols();
+ }
+
+
+ Transpose_View(const Transpose_View<Array2D> &A) : A_(A.A_) {};
+ Transpose_View(const Array2D &A) : A_(A) {};
+
+
+ inline const typename Array2D::element_type & operator()(
+ Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_cols() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_rows() + lbound() - 1);
+#endif
+
+ return A_(j,i);
+ }
+
+
+};
+
+template <class Matrix>
+Transpose_View<Matrix> Transpose_view(const Matrix &A)
+{
+ return Transpose_View<Matrix>(A);
+}
+
+template <class Matrix, class T>
+Vector<T> matmult(
+ const Transpose_View<Matrix> & A,
+ const Vector<T> &B)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(B.dim() == N);
+
+ Vector<T> x(N);
+
+ Subscript i, j;
+ T tmp = 0;
+
+ for (i=1; i<=M; i++)
+ {
+ tmp = 0;
+ for (j=1; j<=N; j++)
+ tmp += A(i,j) * B(j);
+ x(i) = tmp;
+ }
+
+ return x;
+}
+
+template <class Matrix, class T>
+inline Vector<T> operator*(const Transpose_View<Matrix> & A, const Vector<T> &B)
+{
+ return matmult(A,B);
+}
+
+
+template <class Matrix>
+std::ostream& operator<<(std::ostream &s, const Transpose_View<Matrix> &A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() - 1;
+ Subscript Nend = N + A.lbound() - 1;
+
+ s << M << " " << N << endl;
+ for (Subscript i=start; i<=Mend; i++)
+ {
+ for (Subscript j=start; j<=Nend; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
+// TRANSV_H
diff --git a/intern/iksolver/intern/TNT/triang.h b/intern/iksolver/intern/TNT/triang.h
new file mode 100644
index 00000000000..883caf138f7
--- /dev/null
+++ b/intern/iksolver/intern/TNT/triang.h
@@ -0,0 +1,670 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Triangular Matrices (Views and Adpators)
+
+#ifndef TRIANG_H
+#define TRIANG_H
+
+// default to use lower-triangular portions of arrays
+// for symmetric matrices.
+
+namespace TNT
+{
+
+template <class MaTRiX>
+class LowerTriangularView
+{
+ protected:
+
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero_;
+
+ public:
+
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef const typename MaTRiX::element_type element_type;
+ typedef const typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ LowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i<j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i<j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+#ifdef TNT_USE_REGIONS
+
+ typedef const_Region2D< LowerTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(/*const*/ Index1D &I,
+ /*const*/ Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+
+
+
+#endif
+// TNT_USE_REGIONS
+
+};
+
+
+/* *********** Lower_triangular_view() algorithms ****************** */
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename MaTRiX::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=start; j<=i; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum;
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ LowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+template <class MaTRiX>
+class UnitLowerTriangularView
+{
+ protected:
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero;
+ const typename MaTRiX::element_type one;
+
+ public:
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef typename MaTRiX::element_type element_type;
+ typedef typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript lbound() const { return 1; }
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UnitLowerTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+ assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
+#endif
+ if (i>j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+#endif
+ if (i>j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // These are the "index-aware" features
+
+ typedef const_Region2D< UnitLowerTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(/*const*/ Index1D &I,
+ /*const*/ Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+#endif
+// TNT_USE_REGIONS
+};
+
+template <class MaTRiX>
+LowerTriangularView<MaTRiX> Lower_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return LowerTriangularView<MaTRiX>(A);
+}
+
+
+template <class MaTRiX>
+UnitLowerTriangularView<MaTRiX> Unit_lower_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UnitLowerTriangularView<MaTRiX>(A);
+}
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename MaTRiX::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=start; j<i; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum + x(i);
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UnitLowerTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+
+//********************** Algorithms *************************************
+
+
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s, const LowerTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ const UnitLowerTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+
+
+// ******************* Upper Triangular Section **************************
+
+template <class MaTRiX>
+class UpperTriangularView
+{
+ protected:
+
+
+ /*const*/ MaTRiX &A_;
+ /*const*/ typename MaTRiX::element_type zero_;
+
+ public:
+
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef /*const*/ typename MaTRiX::element_type element_type;
+ typedef /*const*/ typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript lbound() const { return A_.lbound(); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero_(0) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i>j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(lbound()<=i);
+ assert(i<=A_.num_rows() + lbound() - 1);
+ assert(lbound()<=j);
+ assert(j<=A_.num_cols() + lbound() - 1);
+#endif
+ if (i>j)
+ return zero_;
+ else
+ return A_(i,j);
+ }
+
+#ifdef TNT_USE_REGIONS
+
+ typedef const_Region2D< UpperTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(const Index1D &I,
+ const Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+
+
+
+#endif
+// TNT_USE_REGIONS
+
+};
+
+
+/* *********** Upper_triangular_view() algorithms ****************** */
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename VecToR::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = 0.0;
+ for (j=i; j<=N; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum;
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+template <class MaTRiX>
+class UnitUpperTriangularView
+{
+ protected:
+
+ const MaTRiX &A_;
+ const typename MaTRiX::element_type zero;
+ const typename MaTRiX::element_type one;
+
+ public:
+
+ typedef typename MaTRiX::const_reference const_reference;
+ typedef typename MaTRiX::element_type element_type;
+ typedef typename MaTRiX::element_type value_type;
+ typedef element_type T;
+
+ Subscript lbound() const { return 1; }
+ Subscript dim(Subscript d) const { return A_.dim(d); }
+ Subscript num_rows() const { return A_.num_rows(); }
+ Subscript num_cols() const { return A_.num_cols(); }
+
+
+ // constructors
+
+ UnitUpperTriangularView(/*const*/ MaTRiX &A) : A_(A), zero(0), one(1) {}
+
+
+ inline const_reference get(Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+ assert(0<=i && i<A_.dim(0) && 0<=j && j<A_.dim(1));
+#endif
+ if (i<j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+ inline const_reference operator() (Subscript i, Subscript j) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=A_.dim(1));
+ assert(1<=j);
+ assert(j<=A_.dim(2));
+#endif
+ if (i<j)
+ return A_(i,j);
+ else if (i==j)
+ return one;
+ else
+ return zero;
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // These are the "index-aware" features
+
+ typedef const_Region2D< UnitUpperTriangularView<MaTRiX> >
+ const_Region;
+
+ const_Region operator()(const Index1D &I,
+ const Index1D &J) const
+ {
+ return const_Region(*this, I, J);
+ }
+
+ const_Region operator()(Subscript i1, Subscript i2,
+ Subscript j1, Subscript j2) const
+ {
+ return const_Region(*this, i1, i2, j1, j2);
+ }
+#endif
+// TNT_USE_REGIONS
+};
+
+template <class MaTRiX>
+UpperTriangularView<MaTRiX> Upper_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UpperTriangularView<MaTRiX>(A);
+}
+
+
+template <class MaTRiX>
+UnitUpperTriangularView<MaTRiX> Unit_upper_triangular_view(
+ /*const*/ MaTRiX &A)
+{
+ return UnitUpperTriangularView<MaTRiX>(A);
+}
+
+template <class MaTRiX, class VecToR>
+VecToR matmult(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ Subscript M = A.num_rows();
+ Subscript N = A.num_cols();
+
+ assert(N == x.dim());
+
+ Subscript i, j;
+ typename VecToR::element_type sum=0.0;
+ VecToR result(M);
+
+ Subscript start = A.lbound();
+ Subscript Mend = M + A.lbound() -1 ;
+
+ for (i=start; i<=Mend; i++)
+ {
+ sum = x(i);
+ for (j=i+1; j<=N; j++)
+ sum = sum + A(i,j)*x(j);
+ result(i) = sum + x(i);
+ }
+
+ return result;
+}
+
+template <class MaTRiX, class VecToR>
+inline VecToR operator*(/*const*/ UnitUpperTriangularView<MaTRiX> &A, VecToR &x)
+{
+ return matmult(A,x);
+}
+
+
+//********************** Algorithms *************************************
+
+
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ /*const*/ UpperTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+template <class MaTRiX>
+std::ostream& operator<<(std::ostream &s,
+ /*const*/ UnitUpperTriangularView<MaTRiX>&A)
+{
+ Subscript M=A.num_rows();
+ Subscript N=A.num_cols();
+
+ s << M << " " << N << endl;
+
+ for (Subscript i=1; i<=M; i++)
+ {
+ for (Subscript j=1; j<=N; j++)
+ {
+ s << A(i,j) << " ";
+ }
+ s << endl;
+ }
+
+
+ return s;
+}
+
+} // namespace TNT
+
+
+
+
+
+#endif
+//TRIANG_H
+
diff --git a/intern/iksolver/intern/TNT/trisolve.h b/intern/iksolver/intern/TNT/trisolve.h
new file mode 100644
index 00000000000..6a4f6e1a5b3
--- /dev/null
+++ b/intern/iksolver/intern/TNT/trisolve.h
@@ -0,0 +1,216 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+// Triangular Solves
+
+#ifndef TRISLV_H
+#define TRISLV_H
+
+
+#include "triang.h"
+
+namespace TNT
+{
+
+template <class MaTriX, class VecToR>
+VecToR Lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=1; i<=N; i++)
+ {
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = (b(i) - tmp)/ A(i,i);
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR Unit_lower_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=1; i<=N; i++)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = b(i) - tmp;
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ LowerTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Lower_triangular_solve(A, b);
+}
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UnitLowerTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Unit_lower_triangular_solve(A, b);
+}
+
+
+
+//********************** Upper triangular section ****************
+
+template <class MaTriX, class VecToR>
+VecToR Upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=N; i>=1; i--)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=i+1; j<=N; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = (b(i) - tmp)/ A(i,i);
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR Unit_upper_triangular_solve(/*const*/ MaTriX &A, /*const*/ VecToR &b)
+{
+ Subscript N = A.num_rows();
+
+ // make sure matrix sizes agree; A must be square
+
+ assert(A.num_cols() == N);
+ assert(b.dim() == N);
+
+ VecToR x(N);
+
+ Subscript i;
+ for (i=N; i>=1; i--)
+ {
+
+ typename MaTriX::element_type tmp=0;
+
+ for (Subscript j=i+1; j<i; j++)
+ tmp = tmp + A(i,j)*x(j);
+
+ x(i) = b(i) - tmp;
+ }
+
+ return x;
+}
+
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UpperTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Upper_triangular_solve(A, b);
+}
+
+template <class MaTriX, class VecToR>
+VecToR linear_solve(/*const*/ UnitUpperTriangularView<MaTriX> &A,
+ /*const*/ VecToR &b)
+{
+ return Unit_upper_triangular_solve(A, b);
+}
+
+
+} // namespace TNT
+
+#endif
+// TRISLV_H
diff --git a/intern/iksolver/intern/TNT/vec.h b/intern/iksolver/intern/TNT/vec.h
new file mode 100644
index 00000000000..beb034ce315
--- /dev/null
+++ b/intern/iksolver/intern/TNT/vec.h
@@ -0,0 +1,535 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+// Basic TNT numerical vector (0-based [i] AND 1-based (i) indexing )
+//
+
+#ifndef VEC_H
+#define VEC_H
+
+#include "subscript.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <iostream>
+#include <strstream>
+
+namespace TNT
+{
+
+template <class T>
+class Vector
+{
+
+
+ public:
+
+ typedef Subscript size_type;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1;}
+
+ protected:
+ T* v_;
+ T* vm1_; // pointer adjustment for optimzied 1-offset indexing
+ Subscript n_;
+
+ // internal helper function to create the array
+ // of row pointers
+
+ void initialize(Subscript N)
+ {
+ // adjust pointers so that they are 1-offset:
+ // v_[] is the internal contiguous array, it is still 0-offset
+ //
+ assert(v_ == NULL);
+ v_ = new T[N];
+ assert(v_ != NULL);
+ vm1_ = v_-1;
+ n_ = N;
+ }
+
+ void copy(const T* v)
+ {
+ Subscript N = n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = v[i];
+ v_[i+1] = v[i+1];
+ v_[i+2] = v[i+2];
+ v_[i+3] = v[i+3];
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = v[i];
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = v[i];
+#endif
+ }
+
+ void set(const T& val)
+ {
+ Subscript N = n_;
+ Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+ Subscript Nmod4 = N & 3;
+ Subscript N4 = N - Nmod4;
+
+ for (i=0; i<N4; i+=4)
+ {
+ v_[i] = val;
+ v_[i+1] = val;
+ v_[i+2] = val;
+ v_[i+3] = val;
+ }
+
+ for (i=N4; i< N; i++)
+ v_[i] = val;
+#else
+
+ for (i=0; i< N; i++)
+ v_[i] = val;
+
+#endif
+ }
+
+
+
+ void destroy()
+ {
+ /* do nothing, if no memory has been previously allocated */
+ if (v_ == NULL) return ;
+
+ /* if we are here, then matrix was previously allocated */
+ delete [] (v_);
+
+ v_ = NULL;
+ vm1_ = NULL;
+ }
+
+
+ public:
+
+ // access
+
+ iterator begin() { return v_;}
+ iterator end() { return v_ + n_; }
+ const iterator begin() const { return v_;}
+ const iterator end() const { return v_ + n_; }
+
+ // destructor
+
+ ~Vector()
+ {
+ destroy();
+ }
+
+ // constructors
+
+ Vector() : v_(0), vm1_(0), n_(0) {};
+
+ Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(A.n_);
+ copy(A.v_);
+ }
+
+ Vector(Subscript N, const T& value = T()) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ set(value);
+ }
+
+ Vector(Subscript N, const T* v) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ copy(v);
+ }
+
+ Vector(Subscript N, char *s) : v_(0), vm1_(0), n_(0)
+ {
+ initialize(N);
+ std::istrstream ins(s);
+
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ ins >> v_[i];
+ }
+
+
+ // methods
+ //
+ Vector<T>& newsize(Subscript N)
+ {
+ if (n_ == N) return *this;
+
+ destroy();
+ initialize(N);
+
+ return *this;
+ }
+
+
+ // assignments
+ //
+ Vector<T>& operator=(const Vector<T> &A)
+ {
+ if (v_ == A.v_)
+ return *this;
+
+ if (n_ == A.n_) // no need to re-alloc
+ copy(A.v_);
+
+ else
+ {
+ destroy();
+ initialize(A.n_);
+ copy(A.v_);
+ }
+
+ return *this;
+ }
+
+ Vector<T>& operator=(const T& scalar)
+ {
+ set(scalar);
+ return *this;
+ }
+
+ inline Subscript dim() const
+ {
+ return n_;
+ }
+
+ inline Subscript size() const
+ {
+ return n_;
+ }
+
+
+ inline reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= n_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline const_reference operator() (Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i <= n_) ;
+#endif
+ return vm1_[i];
+ }
+
+ inline reference operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i < n_) ;
+#endif
+ return v_[i];
+ }
+
+ inline const_reference operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i) ;
+ assert(i < n_) ;
+#endif
+ return v_[i];
+ }
+
+
+
+};
+
+
+/* *************************** I/O ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Vector<T> &A)
+{
+ Subscript N=A.dim();
+
+ s << N << endl;
+
+ for (Subscript i=0; i<N; i++)
+ s << A[i] << " " << endl;
+ s << endl;
+
+ return s;
+}
+
+template <class T>
+std::istream & operator>>(std::istream &s, Vector<T> &A)
+{
+
+ Subscript N;
+
+ s >> N;
+
+ if ( !(N == A.size() ))
+ {
+ A.newsize(N);
+ }
+
+
+ for (Subscript i=0; i<N; i++)
+ s >> A[i];
+
+
+ return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Vector<T> operator+(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] + B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator-(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] - B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator*(const Vector<T> &A,
+ const Vector<T> &B)
+{
+ Subscript N = A.dim();
+
+ assert(N==B.dim());
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] * B[i];
+
+ return tmp;
+}
+
+template <class T>
+Vector<T> operator*(const Vector<T> &A,
+ const T &B)
+{
+ Subscript N = A.dim();
+
+ Vector<T> tmp(N);
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ tmp[i] = A[i] * B;
+
+ return tmp;
+}
+
+
+template <class T>
+T dot_prod(const Vector<T> &A, const Vector<T> &B)
+{
+ Subscript N = A.dim();
+ assert(N == B.dim());
+
+ Subscript i;
+ T sum = 0;
+
+ for (i=0; i<N; i++)
+ sum += A[i] * B[i];
+
+ return sum;
+}
+
+// inplace versions of the above template functions
+
+// A = A + B
+
+template <class T>
+void vectoradd(
+ Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] += B[i];
+}
+
+// same with seperate output vector
+
+template <class T>
+void vectoradd(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] + B[i];
+}
+
+// A = A - B
+
+template <class T>
+void vectorsub(
+ Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] -= B[i];
+}
+
+template <class T>
+void vectorsub(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const Vector<T> &B)
+{
+ const Subscript N = A.dim();
+ assert(N==B.dim());
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] - B[i];
+}
+
+template <class T>
+void vectorscale(
+ Vector<T> &C,
+ const Vector<T> &A,
+ const T &B)
+{
+ const Subscript N = A.dim();
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ C[i] = A[i] * B;
+}
+
+template <class T>
+void vectorscale(
+ Vector<T> &A,
+ const T &B)
+{
+ const Subscript N = A.dim();
+ Subscript i;
+
+ for (i=0; i<N; i++)
+ A[i] *= B;
+}
+
+
+
+
+
+} /* namespace TNT */
+
+#endif
+// VEC_H
diff --git a/intern/iksolver/intern/TNT/vecadaptor.h b/intern/iksolver/intern/TNT/vecadaptor.h
new file mode 100644
index 00000000000..337748c58bd
--- /dev/null
+++ b/intern/iksolver/intern/TNT/vecadaptor.h
@@ -0,0 +1,321 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/*
+
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. The Template Numerical Toolkit (TNT) is
+* an experimental system. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+* BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+* see http://math.nist.gov/tnt for latest updates.
+*
+*/
+
+
+
+#ifndef VECADAPTOR_H
+#define VECADAPTOR_H
+
+#include <cstdlib>
+#include <iostream>
+#include <strstream>
+#include <cassert>
+
+#include "subscript.h"
+
+#ifdef TNT_USE_REGIONS
+#include "region1d.h"
+#endif
+
+namespace TNT
+{
+
+// see "tntreq.h" for TNT requirements for underlying vector
+// class. This need NOT be the STL vector<> class, but a subset
+// that provides minimal services.
+//
+// This is a container adaptor that provides the following services.
+//
+// o) adds 1-offset operator() access ([] is always 0 offset)
+// o) adds TNT_BOUNDS_CHECK to () and []
+// o) adds initialization from strings, e.g. "1.0 2.0 3.0";
+// o) adds newsize(N) function (does not preserve previous values)
+// o) adds dim() and dim(1)
+// o) adds free() function to release memory used by vector
+// o) adds regions, e.g. A(Index(1,10)) = ...
+// o) add getVector() method to return adapted container
+// o) adds simple I/O for ostreams
+
+template <class BBVec>
+class Vector_Adaptor
+{
+
+ public:
+ typedef typename BBVec::value_type T;
+ typedef T value_type;
+ typedef T element_type;
+ typedef T* pointer;
+ typedef T* iterator;
+ typedef T& reference;
+ typedef const T* const_iterator;
+ typedef const T& const_reference;
+
+ Subscript lbound() const { return 1; }
+
+ protected:
+ BBVec v_;
+ T* vm1_;
+
+ public:
+
+ Subscript size() const { return v_.size(); }
+
+ // These were removed so that the ANSI C++ valarray class
+ // would work as a possible storage container.
+ //
+ //
+ //iterator begin() { return v_.begin();}
+ //iterator begin() { return &v_[0];}
+ //
+ //iterator end() { return v_.end(); }
+ //iterator end() { return &v_[0] + v_.size(); }
+ //
+ //const_iterator begin() const { return v_.begin();}
+ //const_iterator begin() const { return &v_[0];}
+ //
+ //const_iterator end() const { return v_.end(); }
+ //const_iterator end() const { return &v_[0] + v_.size(); }
+
+ BBVec& getVector() { return v_; }
+ Subscript dim() const { return v_.size(); }
+ Subscript dim(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(i==TNT_BASE_OFFSET);
+#endif
+ return (i==TNT_BASE_OFFSET ? v_.size() : 0 );
+ }
+ Vector_Adaptor() : v_() {};
+ Vector_Adaptor(const Vector_Adaptor<BBVec> &A) : v_(A.v_)
+ {
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+
+ }
+
+ Vector_Adaptor(Subscript N, /*const*/ char *s) : v_(N)
+ {
+ istrstream ins(s);
+ for (Subscript i=0; i<N; i++)
+ ins >> v_[i] ;
+
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ };
+
+ Vector_Adaptor(Subscript N, const T& value = T()) : v_(N)
+ {
+ for (Subscript i=0; i<N; i++)
+ v_[i] = value;
+
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+
+ Vector_Adaptor(Subscript N, const T* values) : v_(N)
+ {
+ for (Subscript i=0; i<N; i++)
+ v_[i] = values[i];
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+ Vector_Adaptor(const BBVec & A) : v_(A)
+ {
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ }
+
+ // NOTE: this assumes that BBVec(0) constructor creates an
+ // null vector that does not take up space... It would be
+ // great to require that BBVec have a corresponding free()
+ // function, but in particular STL vectors do not.
+ //
+ Vector_Adaptor<BBVec>& free()
+ {
+ return *this = Vector_Adaptor<BBVec>(0);
+ }
+
+ Vector_Adaptor<BBVec>& operator=(const Vector_Adaptor<BBVec> &A)
+ {
+ v_ = A.v_ ;
+ vm1_ = ( v_.size() > 0 ? &(v_[0]) -1 : NULL);
+ return *this;
+ }
+
+ Vector_Adaptor<BBVec>& newsize(Subscript N)
+ {
+ // NOTE: this is not as efficient as it could be
+ // but to retain compatiblity with STL interface
+ // we cannot assume underlying implementation
+ // has a newsize() function.
+
+ return *this = Vector_Adaptor<BBVec>(N);
+
+ }
+
+ Vector_Adaptor<BBVec>& operator=(const T &a)
+ {
+ Subscript i;
+ Subscript N = v_.size();
+ for (i=0; i<N; i++)
+ v_[i] = a;
+
+ return *this;
+ }
+
+ Vector_Adaptor<BBVec>& resize(Subscript N)
+ {
+ if (N == size()) return *this;
+
+ Vector_Adaptor<BBVec> tmp(N);
+ Subscript n = (N < size() ? N : size()); // min(N, size());
+ Subscript i;
+
+ for (i=0; i<n; i++)
+ tmp[i] = v_[i];
+
+
+ return (*this = tmp);
+
+ }
+
+
+ reference operator()(Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=dim());
+#endif
+ return vm1_[i];
+ }
+
+ const_reference operator()(Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(1<=i);
+ assert(i<=dim());
+#endif
+ return vm1_[i];
+ }
+
+ reference operator[](Subscript i)
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i<dim());
+#endif
+ return v_[i];
+ }
+
+ const_reference operator[](Subscript i) const
+ {
+#ifdef TNT_BOUNDS_CHECK
+ assert(0<=i);
+ assert(i<dim());
+#endif
+ return v_[i];
+ }
+
+
+#ifdef TNT_USE_REGIONS
+ // "index-aware" features, all of these are 1-based offsets
+
+ typedef Region1D<Vector_Adaptor<BBVec> > Region;
+
+ typedef const_Region1D< Vector_Adaptor<BBVec> > const_Region;
+
+ Region operator()(const Index1D &I)
+ { return Region(*this, I); }
+
+ Region operator()(const Subscript i1, Subscript i2)
+ { return Region(*this, i1, i2); }
+
+ const_Region operator()(const Index1D &I) const
+ { return const_Region(*this, I); }
+
+ const_Region operator()(const Subscript i1, Subscript i2) const
+ { return const_Region(*this, i1, i2); }
+#endif
+// TNT_USE_REGIONS
+
+
+};
+
+#include <iostream>
+
+template <class BBVec>
+std::ostream& operator<<(std::ostream &s, const Vector_Adaptor<BBVec> &A)
+{
+ Subscript M=A.size();
+
+ s << M << endl;
+ for (Subscript i=1; i<=M; i++)
+ s << A(i) << endl;
+ return s;
+}
+
+template <class BBVec>
+std::istream& operator>>(std::istream &s, Vector_Adaptor<BBVec> &A)
+{
+ Subscript N;
+
+ s >> N;
+
+ A.resize(N);
+
+ for (Subscript i=1; i<=N; i++)
+ s >> A(i);
+
+ return s;
+}
+
+} // namespace TNT
+
+#endif
diff --git a/intern/iksolver/intern/TNT/version.h b/intern/iksolver/intern/TNT/version.h
new file mode 100644
index 00000000000..c2759e0ce44
--- /dev/null
+++ b/intern/iksolver/intern/TNT/version.h
@@ -0,0 +1,52 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+// Template Numerical Toolkit (TNT) for Linear Algebra
+
+//
+// BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
+// Please see http://math.nist.gov/tnt for updates
+//
+// R. Pozo
+// Mathematical and Computational Sciences Division
+// National Institute of Standards and Technology
+
+
+#ifndef TNT_VERSION_H
+#define TNT_VERSION_H
+
+
+#define TNT_MAJOR_VERSION '0'
+#define TNT_MINOR_VERSION '9'
+#define TNT_SUBMINOR_VERSION '4'
+#define TNT_VERSION_STRING "0.9.4"
+
+#endif
diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsp b/intern/iksolver/make/msvc_6_0/iksolver.dsp
new file mode 100644
index 00000000000..fb12812b7a7
--- /dev/null
+++ b/intern/iksolver/make/msvc_6_0/iksolver.dsp
@@ -0,0 +1,244 @@
+# Microsoft Developer Studio Project File - Name="iksolver" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=iksolver - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "iksolver.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "iksolver.mak" CFG="iksolver - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "iksolver - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "iksolver - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "iksolver - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /Ob2 /I "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\lib\windows\release\iksolver_rmtd.lib"
+
+!ELSEIF "$(CFG)" == "iksolver - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+LINK32=link.exe -lib
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\intern\moto\include" /I "..\..\..\..\intern\memutil" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FD /GZ /c
+# SUBTRACT CPP /YX
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\..\lib\windows\debug\iksolver_dmtd.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "iksolver - Win32 Release"
+# Name "iksolver - Win32 Debug"
+# Begin Group "intern"
+
+# PROP Default_Filter ""
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# End Group
+# Begin Group "TNT"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\cholesky.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\cmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fcscmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fmat.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fortran.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\fspvec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\index.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\lapack.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\lu.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\qr.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\region1d.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\region2d.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\stopwatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\subscript.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\svd.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tnt.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tntmath.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\tntreqs.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\transv.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\triang.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\trisolve.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\vec.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\vecadaptor.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\TNT\version.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QChain.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QChain.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QJacobianSolver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QJacobianSolver.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSegment.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSegment.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_QSolver_Class.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\IK_Solver.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_ExpMap.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MT_ExpMap.h
+# End Source File
+# End Group
+# Begin Group "extern"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\extern\IK_solver.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/intern/iksolver/make/msvc_6_0/iksolver.dsw b/intern/iksolver/make/msvc_6_0/iksolver.dsw
new file mode 100644
index 00000000000..90a123d9ce8
--- /dev/null
+++ b/intern/iksolver/make/msvc_6_0/iksolver.dsw
@@ -0,0 +1,35 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "iksolver"=.\iksolver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
+
+
+
+
+
+
diff --git a/intern/iksolver/test/Makefile b/intern/iksolver/test/Makefile
new file mode 100644
index 00000000000..f59e487add0
--- /dev/null
+++ b/intern/iksolver/test/Makefile
@@ -0,0 +1,67 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver test makefile.
+#
+
+LIBNAME = iksolver
+SOURCEDIR = intern/$(LIBNAME)/test
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+DIRS = ik_glut_test
+
+include nan_subdirs.mk
+
+include nan_link.mk
+
+LIBS = $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/intern/$(DEBUG_DIR)libintern.a
+LIBS += $(OCGDIR)/intern/$(LIBNAME)/test/ik_glut_test/common/$(DEBUG_DIR)libcommon.a
+LIBS += $(OCGDIR)/intern/$(LIBNAME)/$(DEBUG_DIR)libiksolver.a
+
+SLIBS += $(NAN_MOTO)/lib/$(DEBUG_DIR)libmoto.a
+
+ifeq ($(OS),$(findstring $(OS), "beos darwin linux freebsd openbsd"))
+ LLIBS = -L/usr/X11R6/lib -lglut -pthread
+endif
+
+all debug:: $(LIBS) $(DIR)/$(DEBUG_DIR)iksolvertest
+
+$(DIR)/$(DEBUG_DIR)iksolvertest:
+ @echo "****> linking $@ in $(DIR)"
+ $(CCC) $(LDFLAGS) -o $(DIR)/$(DEBUG_DIR)iksolvertest $(LIBS) $(SLIBS) $(LLIBS) $(DADD)
+
+clean::
+ $(RM) $(DIR)/iksolvertest $(DIR)/debug/iksolvertest
+
+test:: all
+ $(DIR)/iksolvertest
+
diff --git a/intern/iksolver/test/ik_glut_test/Makefile b/intern/iksolver/test/ik_glut_test/Makefile
new file mode 100644
index 00000000000..4b47af16599
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/Makefile
@@ -0,0 +1,42 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver subdir bouncer. Pure waste.
+#
+
+include nan_definitions.mk
+
+LIBNAME = ik_glut_test
+SOURCEDIR = intern/iksolver/test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+DIRS = common intern
+
+include nan_subdirs.mk
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
new file mode 100644
index 00000000000..40c6a4a95c9
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.cpp
@@ -0,0 +1,95 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "GlutDrawer.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutDrawManager> GlutDrawManager::m_s_instance = MEM_SmartPtr<GlutDrawManager>();
+
+ GlutDrawManager *
+GlutDrawManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutDrawManager();
+ }
+
+ return m_s_instance;
+}
+
+
+// this is the function you should pass to glut
+
+ void
+GlutDrawManager::
+Draw(
+){
+ GlutDrawManager *manager = GlutDrawManager::Instance();
+
+ if (manager->m_drawer != NULL) {
+ manager->m_drawer->Draw();
+ }
+}
+
+ void
+GlutDrawManager::
+InstallDrawer(
+ GlutDrawer * drawer
+){
+
+ MT_assert(m_drawer == NULL);
+ m_drawer = drawer;
+}
+
+ void
+GlutDrawManager::
+ReleaseDrawer(
+){
+ m_drawer = NULL;
+}
+
+
+GlutDrawManager::
+~GlutDrawManager(
+){
+
+ delete(m_drawer);
+}
+
+
+
+
+
+
+
+
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
new file mode 100644
index 00000000000..7e56a02dd47
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutDrawer.h
@@ -0,0 +1,100 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_GlutDrawer
+
+#define NAN_INCLUDED_GlutDrawer
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+// So pissed off with Glut callback stuff
+// that is impossible to call objects unless they are global
+
+// inherit from GlutDrawer and installl the drawer in the singleton
+// class GlutDrawManager.
+
+class GlutDrawer {
+public :
+
+ virtual
+ void
+ Draw(
+ )= 0;
+
+ virtual
+ ~GlutDrawer(
+ ){};
+};
+
+class GlutDrawManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutDrawManager *
+ Instance(
+ );
+
+ // this is the function you should pass to glut
+
+ static
+ void
+ Draw(
+ );
+
+ void
+ InstallDrawer(
+ GlutDrawer *
+ );
+
+ void
+ ReleaseDrawer(
+ );
+
+ ~GlutDrawManager(
+ );
+
+private :
+
+ GlutDrawManager (
+ ) :
+ m_drawer (0)
+ {
+ };
+
+ GlutDrawer * m_drawer;
+
+ static MEM_SmartPtr<GlutDrawManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
new file mode 100644
index 00000000000..0d1d52b542d
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.cpp
@@ -0,0 +1,89 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "GlutKeyboardManager.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutKeyboardManager> GlutKeyboardManager::m_s_instance = MEM_SmartPtr<GlutKeyboardManager>();
+
+ GlutKeyboardManager *
+GlutKeyboardManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutKeyboardManager();
+ }
+
+ return m_s_instance;
+}
+
+
+// this is the function you should pass to glut
+
+ void
+GlutKeyboardManager::
+HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+){
+ GlutKeyboardManager *manager = GlutKeyboardManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->HandleKeyboard(key,x,y);
+ }
+}
+
+ void
+GlutKeyboardManager::
+InstallHandler(
+ GlutKeyboardHandler * handler
+){
+
+ MT_assert(m_handler == NULL);
+ m_handler = handler;
+}
+
+ void
+GlutKeyboardManager::
+ReleaseHandler(
+){
+ m_handler = NULL;
+}
+
+
+GlutKeyboardManager::
+~GlutKeyboardManager(
+){
+
+ delete(m_handler);
+} \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
new file mode 100644
index 00000000000..39174b5ff1a
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutKeyboardManager.h
@@ -0,0 +1,106 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_GlutKeyboardManager
+
+#define NAN_INCLUDED_GlutKeyboardManager
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+// So pissed off with Glut callback stuff
+// that is impossible to call objects unless they are global
+
+// inherit from GlutKeyboardHandler and installl the drawer in the singleton
+// class GlutKeyboardManager.
+
+class GlutKeyboardHandler : public MEM_NonCopyable {
+public :
+
+ virtual
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ )= 0;
+
+ virtual
+ ~GlutKeyboardHandler(
+ ){};
+};
+
+class GlutKeyboardManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutKeyboardManager *
+ Instance(
+ );
+
+ // this is the function you should pass to glut
+
+ static
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ );
+
+ void
+ InstallHandler(
+ GlutKeyboardHandler *
+ );
+
+ void
+ ReleaseHandler(
+ );
+
+ ~GlutKeyboardManager(
+ );
+
+private :
+
+ GlutKeyboardManager (
+ ) :
+ m_handler (0)
+ {
+ };
+
+ GlutKeyboardHandler * m_handler;
+
+ static MEM_SmartPtr<GlutKeyboardManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
new file mode 100644
index 00000000000..57f4a65327e
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.cpp
@@ -0,0 +1,104 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "GlutMouseManager.h"
+
+#include "MT_assert.h"
+
+MEM_SmartPtr<GlutMouseManager> GlutMouseManager::m_s_instance = MEM_SmartPtr<GlutMouseManager>();
+
+
+ GlutMouseManager *
+GlutMouseManager::
+Instance(
+){
+ if (m_s_instance == NULL) {
+ m_s_instance = new GlutMouseManager();
+ }
+
+ return m_s_instance;
+}
+
+// these are the functions you should pass to GLUT
+
+ void
+GlutMouseManager::
+Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+){
+ GlutMouseManager *manager = GlutMouseManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->Mouse(button,state,x,y);
+ }
+}
+
+ void
+GlutMouseManager::
+Motion(
+ int x,
+ int y
+){
+ GlutMouseManager *manager = GlutMouseManager::Instance();
+
+ if (manager->m_handler != NULL) {
+ manager->m_handler->Motion(x,y);
+ }
+}
+
+ void
+GlutMouseManager::
+InstallHandler(
+ GlutMouseHandler *handler
+){
+
+ MT_assert(m_handler == NULL);
+ m_handler = handler;
+}
+
+ void
+GlutMouseManager::
+ReleaseHandler(
+){
+ m_handler = NULL;
+}
+
+GlutMouseManager::
+~GlutMouseManager(
+){
+
+ delete(m_handler);
+}
+
+
diff --git a/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
new file mode 100644
index 00000000000..95700bc14dd
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/GlutMouseManager.h
@@ -0,0 +1,116 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_GlutMouseManager_h
+
+#define NAN_INCLUDED_GlutMouseManager_h
+
+#include "MEM_NonCopyable.h"
+#include "MEM_SmartPtr.h"
+
+class GlutMouseHandler {
+public :
+
+ virtual
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ ) = 0;
+
+ virtual
+ void
+ Motion(
+ int x,
+ int y
+ ) = 0;
+
+ virtual
+ ~GlutMouseHandler(
+ ){};
+};
+
+class GlutMouseManager : public MEM_NonCopyable{
+
+public :
+
+ static
+ GlutMouseManager *
+ Instance(
+ );
+
+ // these are the functions you should pass to GLUT
+
+ static
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ );
+
+ static
+ void
+ Motion(
+ int x,
+ int y
+ );
+
+ void
+ InstallHandler(
+ GlutMouseHandler *
+ );
+
+ void
+ ReleaseHandler(
+ );
+
+ ~GlutMouseManager(
+ );
+
+private :
+
+ GlutMouseManager (
+ ) :
+ m_handler (0)
+ {
+ };
+
+ GlutMouseHandler * m_handler;
+
+ static MEM_SmartPtr<GlutMouseManager> m_s_instance;
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/common/Makefile b/intern/iksolver/test/ik_glut_test/common/Makefile
new file mode 100644
index 00000000000..07ad1837a7d
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/common/Makefile
@@ -0,0 +1,44 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver test intern Makefile
+#
+
+LIBNAME = common
+SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
new file mode 100644
index 00000000000..a164e686e37
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/ChainDrawer.h
@@ -0,0 +1,387 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_ChainDrawer_h
+
+#define NAN_INCLUDED_ChainDrawer_h
+
+#include "../common/GlutDrawer.h"
+#include "MyGlutMouseHandler.h"
+#include "MyGlutKeyHandler.h"
+#include "MT_Transform.h"
+#ifdef USE_QUATERNIONS
+# include "IK_Qsolver.h"
+# include "../intern/IK_QChain.h"
+# include "../intern/IK_QSolver_Class.h"
+#else
+# include "IK_solver.h"
+# include "../intern/IK_Chain.h"
+# include "../intern/IK_Solver_Class.h"
+#endif
+#include <GL/glut.h>
+
+class ChainDrawer : public GlutDrawer
+{
+public :
+ static
+ ChainDrawer *
+ New(
+ ) {
+ return new ChainDrawer();
+ }
+
+ void
+ SetMouseHandler(
+ MyGlutMouseHandler *mouse_handler
+ ) {
+ m_mouse_handler = mouse_handler;
+ }
+
+ void
+ SetKeyHandler (
+ MyGlutKeyHandler *key_handler
+ ) {
+ m_key_handler = key_handler;
+ }
+
+ void
+ SetChain(
+ IK_Chain_ExternPtr *chains,int chain_num
+ ) {
+ m_chain_num = chain_num;
+ m_chains = chains;
+ }
+
+
+ // inherited from GlutDrawer
+ void
+ Draw(
+ ) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glPopMatrix();
+ glPushMatrix();
+ glRotatef(m_mouse_handler->AngleX(), 0.0, 1.0, 0.0);
+ glRotatef(m_mouse_handler->AngleY(), 1.0, 0.0, 0.0);
+
+ DrawScene();
+ glutSwapBuffers();
+
+ }
+
+ ~ChainDrawer(
+ ){
+ // nothing to do
+ };
+
+private :
+
+ void
+ DrawScene(
+ ){
+
+ // draw a little cross at the position of the key handler
+ // coordinates
+
+ MT_Vector3 line_x(4,0,0);
+ MT_Vector3 line_y(0.0,4,0);
+ MT_Vector3 line_z(0.0,0.0,4);
+
+ MT_Vector3 cross_origin = m_mouse_handler->Position();
+ MT_Vector3 temp;
+
+ glDisable(GL_LIGHTING);
+
+
+ glBegin(GL_LINES);
+
+ glColor3f (1.0f,1.0f,1.0f);
+
+ temp = cross_origin - line_x;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_x;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ temp = cross_origin - line_y;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_y;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ temp = cross_origin - line_z;
+ glVertex3f(temp[0],temp[1],temp[2]);
+ temp = cross_origin + line_z;
+ glVertex3f(temp[0],temp[1],temp[2]);
+
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+
+ IK_Chain_ExternPtr chain;
+
+ int chain_num;
+ for (chain_num = 0; chain_num < m_chain_num; chain_num++) {
+ chain = m_chains[chain_num];
+
+
+ IK_Segment_ExternPtr segs = chain->segments;
+ IK_Segment_ExternPtr seg_start = segs;
+ const IK_Segment_ExternPtr seg_end = segs + chain->num_segments;
+ float ogl_matrix[16];
+
+ glColor3f (0.0f,1.0f,0.0f);
+
+ MT_Vector3 previous_origin(0,0,0);
+
+ MT_Transform global_transform;
+ global_transform.setIdentity();
+
+ for (; seg_start != seg_end; ++seg_start) {
+
+ glPushMatrix();
+
+ // fill ogl_matrix with zeros
+
+ std::fill(ogl_matrix,ogl_matrix + 16,float(0));
+
+ // we have to do a bit of work here to compute the chain's
+ // bone values
+
+ // first compute all the matrices we need
+
+ MT_Transform translation;
+ translation.setIdentity();
+ translation.translate(MT_Vector3(0,seg_start->length,0));
+
+ MT_Matrix3x3 seg_rot(
+ seg_start->basis_change[0],seg_start->basis_change[1],seg_start->basis_change[2],
+ seg_start->basis_change[3],seg_start->basis_change[4],seg_start->basis_change[5],
+ seg_start->basis_change[6],seg_start->basis_change[7],seg_start->basis_change[8]
+ );
+
+ seg_rot.transpose();
+
+ MT_Matrix3x3 seg_pre_rot(
+ seg_start->basis[0],seg_start->basis[1],seg_start->basis[2],
+ seg_start->basis[3],seg_start->basis[4],seg_start->basis[5],
+ seg_start->basis[6],seg_start->basis[7],seg_start->basis[8]
+ );
+
+
+ MT_Transform seg_t_pre_rot(
+ MT_Point3(
+ seg_start->seg_start[0],
+ seg_start->seg_start[1],
+ seg_start->seg_start[2]
+ ),
+ seg_pre_rot
+ );
+ // start of the bone is just the current global transform
+ // multiplied by the seg_start vector
+
+
+
+ MT_Transform seg_t_rot(MT_Point3(0,0,0),seg_rot);
+ MT_Transform seg_local = seg_t_pre_rot * seg_t_rot * translation;
+
+ MT_Vector3 bone_start = global_transform *
+ MT_Point3(
+ seg_start->seg_start[0],
+ seg_start->seg_start[1],
+ seg_start->seg_start[2]
+ );
+
+
+ global_transform = global_transform * seg_local;
+
+ global_transform.getValue(ogl_matrix);
+ MT_Vector3 bone_end = global_transform.getOrigin();
+
+ glMultMatrixf(ogl_matrix);
+// glutSolidSphere(0.5,5,5);
+
+ glPopMatrix();
+
+ glDisable(GL_LIGHTING);
+
+ glBegin(GL_LINES);
+
+ // draw lines of the principle axis of the local transform
+
+ MT_Vector3 x_axis(1,0,0);
+ MT_Vector3 y_axis(0,1,0);
+ MT_Vector3 z_axis(0,0,1);
+
+ x_axis = global_transform.getBasis() * x_axis * 5;
+ y_axis = global_transform.getBasis() * y_axis * 5;
+ z_axis = global_transform.getBasis() * z_axis * 5;
+
+
+ x_axis = x_axis + bone_start;
+ y_axis = y_axis + bone_start;
+ z_axis = z_axis + bone_start;
+
+ glColor3f(1,0,0);
+
+ glVertex3f(x_axis.x(),x_axis.y(),x_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,1,0);
+
+ glVertex3f(y_axis.x(),y_axis.y(),y_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,1,1);
+
+ glVertex3f(z_axis.x(),z_axis.y(),z_axis.z());
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+
+ glColor3f(0,0,1);
+
+ glVertex3f(
+ bone_start.x(),
+ bone_start.y(),
+ bone_start.z()
+ );
+ glVertex3f(bone_end[0],bone_end[1],bone_end[2]);
+
+ glEnd();
+ glEnable(GL_LIGHTING);
+ }
+#if 0
+ // draw jacobian column vectors
+
+ // hack access to internals
+
+ IK_Solver_Class * internals = static_cast<IK_Solver_Class *>(chain->intern);
+
+ glDisable(GL_LIGHTING);
+
+ glBegin(GL_LINES);
+
+ const TNT::Matrix<MT_Scalar> & jac = internals->Chain().TransposedJacobian();
+
+ int i = 0;
+ for (i=0; i < jac.num_rows(); i++) {
+ glColor3f(1,1,1);
+
+ previous_origin = internals->Chain().Segments()[i/3].GlobalSegmentStart();
+
+ glVertex3f(previous_origin[0],previous_origin[1],previous_origin[2]);
+ glVertex3f(jac[i][0] + previous_origin[0],jac[i][1] + previous_origin[1],jac[i][2] + previous_origin[2]);
+
+
+ }
+ glEnd();
+ glEnable(GL_LIGHTING);
+#endif
+
+ }
+
+ glColor3f(1.0,1.0,1.0);
+
+ glDisable(GL_LIGHTING);
+ glBegin(GL_LINES);
+
+ MT_Scalar cube_size = 50;
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,cube_size,cube_size);
+
+ glVertex3f(cube_size,-cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,cube_size);
+
+ glVertex3f(cube_size,cube_size,-cube_size);
+ glVertex3f(-cube_size,cube_size,-cube_size);
+
+ glVertex3f(cube_size,-cube_size,-cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+
+
+ glVertex3f(-cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,cube_size);
+
+ glVertex3f(cube_size,cube_size,-cube_size);
+ glVertex3f(cube_size,-cube_size,-cube_size);
+
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(cube_size,-cube_size,cube_size);
+
+ glVertex3f(-cube_size,cube_size,-cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+
+
+ glVertex3f(cube_size,cube_size,cube_size);
+ glVertex3f(cube_size,cube_size,-cube_size);
+
+ glVertex3f(cube_size,-cube_size,cube_size);
+ glVertex3f(cube_size,-cube_size,-cube_size);
+
+ glVertex3f(-cube_size,cube_size,cube_size);
+ glVertex3f(-cube_size,cube_size,-cube_size);
+
+ glVertex3f(-cube_size,-cube_size,cube_size);
+ glVertex3f(-cube_size,-cube_size,-cube_size);
+ glEnd();
+ glEnable(GL_LIGHTING);
+
+ };
+
+
+
+private :
+
+ MyGlutMouseHandler * m_mouse_handler;
+ MyGlutKeyHandler *m_key_handler;
+ IK_Chain_ExternPtr *m_chains;
+
+ int m_chain_num;
+ ChainDrawer (
+ ) : m_chains (NULL),
+ m_mouse_handler (NULL),
+ m_chain_num (0)
+ {
+ };
+
+};
+
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/intern/Makefile b/intern/iksolver/test/ik_glut_test/intern/Makefile
new file mode 100644
index 00000000000..fe1f4b54182
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/Makefile
@@ -0,0 +1,51 @@
+#
+# $Id$
+#
+# ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License. See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+# iksolver test intern Makefile
+#
+
+LIBNAME = intern
+SOURCEDIR = intern/iksolver/test/ik_glut_test/$(LIBNAME)
+DIR = $(OCGDIR)/$(SOURCEDIR)
+
+include nan_compile.mk
+
+CCFLAGS += $(LEVEL_2_CPP_WARNINGS)
+
+CPPFLAGS += -I$(OPENGL_HEADERS)
+CPPFLAGS += -I../../../extern
+CPPFLAGS += -I../common
+CPPFLAGS += -I$(NAN_MOTO)/include
+CPPFLAGS += -I$(NAN_MEMUTIL)/include
+
+ifeq ($(OS),windows)
+ CPPFLAGS += -I$(NAN_LIBDIR)/windows/glut-3.7/include
+endif
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
new file mode 100644
index 00000000000..5f88bda378c
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutKeyHandler.h
@@ -0,0 +1,84 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_MyGlutKeyHandler_h
+
+#define NAN_INCLUDED_MyGlutKeyHandler_h
+
+#include "../common/GlutKeyboardManager.h"
+
+class MyGlutKeyHandler : public GlutKeyboardHandler
+{
+public :
+ static
+ MyGlutKeyHandler *
+ New(
+ ) {
+ MEM_SmartPtr<MyGlutKeyHandler> output = new MyGlutKeyHandler();
+
+ if (output == NULL
+ ) {
+ return NULL;
+ }
+ return output.Release();
+
+ }
+
+ void
+ HandleKeyboard(
+ unsigned char key,
+ int x,
+ int y
+ ){
+
+ switch (key) {
+
+ case 27 :
+
+ exit(0);
+ }
+ }
+
+ ~MyGlutKeyHandler(
+ )
+ {
+ };
+
+private :
+
+ MyGlutKeyHandler(
+ )
+ {
+ }
+
+};
+#endif
+
diff --git a/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
new file mode 100644
index 00000000000..e7d210beffb
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/MyGlutMouseHandler.h
@@ -0,0 +1,211 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#ifndef NAN_INCLUDED_MyGlutMouseHandler_h
+
+#define NAN_INCLUDED_MyGlutMouseHandler_h
+
+#include "../common/GlutMouseManager.h"
+#include <GL/glut.h>
+#include "IK_solver.h"
+
+class MyGlutMouseHandler : public GlutMouseHandler
+{
+
+public :
+
+ static
+ MyGlutMouseHandler *
+ New(
+ ) {
+ MEM_SmartPtr<MyGlutMouseHandler> output = new MyGlutMouseHandler();
+ if (output == NULL
+ ) {
+ return NULL;
+ }
+ return output.Release();
+
+ }
+
+ void
+ SetChain(
+ IK_Chain_ExternPtr *chains, int num_chains
+ ){
+ m_chains = chains;
+ m_num_chains = num_chains;
+ }
+
+ void
+ Mouse(
+ int button,
+ int state,
+ int x,
+ int y
+ ){
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
+ m_moving = true;
+ m_begin_x = x;
+ m_begin_y = y;
+ }
+ if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
+ m_moving = false;
+ }
+
+ if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
+ m_tracking = true;
+ }
+ if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) {
+ m_tracking = false;
+ }
+
+ if (button == GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) {
+ m_cg_on = true;
+ }
+ if (button == GLUT_MIDDLE_BUTTON && state == GLUT_UP) {
+ m_cg_on = false;
+ }
+
+ }
+
+
+ void
+ Motion(
+ int x,
+ int y
+ ){
+ if (m_moving) {
+ m_angle_x = m_angle_x + (x - m_begin_x);
+ m_begin_x = x;
+
+ m_angle_y = m_angle_y + (y - m_begin_y);
+ m_begin_y = y;
+
+ glutPostRedisplay();
+ }
+ if (m_tracking) {
+
+ int w_h = glutGet((GLenum)GLUT_WINDOW_HEIGHT);
+
+ y = w_h - y;
+
+ double mvmatrix[16];
+ double projmatrix[16];
+ GLint viewport[4];
+
+ double px, py, pz,sz;
+
+ /* Get the matrices needed for gluUnProject */
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);
+
+ // work out the position of the end effector in screen space
+
+ GLdouble ex,ey,ez;
+ ex = m_pos.x();
+ ey = m_pos.y();
+ ez = m_pos.z();
+
+ gluProject(ex, ey, ez, mvmatrix, projmatrix, viewport, &px, &py, &sz);
+ gluUnProject((GLdouble) x, (GLdouble) y, sz, mvmatrix, projmatrix, viewport, &px, &py, &pz);
+
+ m_pos = MT_Vector3(px,py,pz);
+
+ }
+ if (m_tracking || m_cg_on) {
+ float temp[3];
+ m_pos.getValue(temp);
+
+ IK_SolveChain(m_chains[0],temp,0.01,200,0.1,m_chains[1]->segments);
+ IK_LoadChain(m_chains[0],m_chains[0]->segments,m_chains[0]->num_segments);
+
+ glutPostRedisplay();
+ }
+
+
+ }
+
+ const
+ float
+ AngleX(
+ ) const {
+ return m_angle_x;
+ }
+
+ const
+ float
+ AngleY(
+ ) const {
+ return m_angle_y;
+ }
+
+ const
+ MT_Vector3
+ Position(
+ ) const {
+ return m_pos;
+ }
+
+
+private :
+
+ MyGlutMouseHandler (
+ ) :
+ m_angle_x(0),
+ m_angle_y(0),
+ m_begin_x(0),
+ m_begin_y(0),
+ m_moving (false),
+ m_tracking (false),
+ m_pos(0,0,0),
+ m_cg_on (false),
+ m_chains(NULL),
+ m_num_chains(0)
+ {
+ };
+
+ float m_angle_x;
+ float m_angle_y;
+ float m_begin_x;
+ float m_begin_y;
+
+ bool m_moving;
+ bool m_tracking;
+ bool m_cg_on;
+ MT_Vector3 m_pos;
+
+ IK_Chain_ExternPtr *m_chains;
+ int m_num_chains;
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/intern/iksolver/test/ik_glut_test/intern/main.cpp b/intern/iksolver/test/ik_glut_test/intern/main.cpp
new file mode 100644
index 00000000000..137c9bd4470
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/intern/main.cpp
@@ -0,0 +1,361 @@
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+/**
+ * $Id$
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+
+#include "MEM_SmartPtr.h"
+
+#ifdef USE_QUATERNIONS
+#include "IK_Qsolver.h"
+#else
+#include "IK_solver.h"
+#endif
+
+#include <GL/glut.h>
+#include "MT_Vector3.h"
+#include "MT_Quaternion.h"
+#include "MT_Matrix3x3.h"
+#include "MyGlutMouseHandler.h"
+#include "MyGlutKeyHandler.h"
+#include "ChainDrawer.h"
+
+void
+init(MT_Vector3 min,MT_Vector3 max)
+{
+
+ GLfloat light_diffuse0[] = {1.0, 0.0, 0.0, 1.0}; /* Red diffuse light. */
+ GLfloat light_position0[] = {1.0, 1.0, 1.0, 0.0}; /* Infinite light location. */
+
+ GLfloat light_diffuse1[] = {1.0, 1.0, 1.0, 1.0}; /* Red diffuse light. */
+ GLfloat light_position1[] = {1.0, 0, 0, 0.0}; /* Infinite light location. */
+
+ /* Enable a single OpenGL light. */
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse0);
+ glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
+
+ glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse1);
+ glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
+
+ glEnable(GL_LIGHT0);
+ glEnable(GL_LIGHT1);
+ glEnable(GL_LIGHTING);
+
+ /* Use depth buffering for hidden surface elimination. */
+ glEnable(GL_DEPTH_TEST);
+
+ /* Setup the view of the cube. */
+ glMatrixMode(GL_PROJECTION);
+
+ // centre of the box + 3* depth of box
+
+ MT_Vector3 centre = (min + max) * 0.5;
+ MT_Vector3 diag = max - min;
+
+ float depth = diag.length();
+ float distance = 2;
+
+ gluPerspective(
+ /* field of view in degree */ 40.0,
+ /* aspect ratio */ 1.0,
+ /* Z near */ 1.0,
+ /* Z far */ distance * depth * 2
+ );
+ glMatrixMode(GL_MODELVIEW);
+
+
+ gluLookAt(
+ centre.x(), centre.y(), centre.z() + distance*depth, /* eye is at (0,0,5) */
+ centre.x(), centre.y(), centre.z(), /* center is at (0,0,0) */
+ 0.0, 1.0, 0.); /* up is in positive Y direction */
+
+ glPushMatrix();
+
+
+}
+int
+main(int argc, char **argv)
+{
+
+
+ const int seg_num = 5;
+ const MT_Scalar seg_length = 15;
+
+ const float seg_startA[3] = {0,0,0};
+ const float seg_startB[3] = {0,-20,0};
+
+ // create some segments to solve with
+
+ // First chain
+ //////////////
+
+
+ IK_Segment_ExternPtr const segmentsA = new IK_Segment_Extern[seg_num];
+ IK_Segment_ExternPtr const segmentsB = new IK_Segment_Extern[seg_num];
+
+ IK_Segment_ExternPtr seg_it = segmentsA;
+ IK_Segment_ExternPtr seg_itB = segmentsB;
+
+
+ {
+
+// MT_Quaternion qmat(MT_Vector3(0,0,1),-3.141/2);
+ MT_Quaternion qmat(MT_Vector3(0,0,1),0);
+ MT_Matrix3x3 mat(qmat);
+
+ seg_it->seg_start[0] = seg_startA[0];
+ seg_it->seg_start[1] = seg_startA[1];
+ seg_it->seg_start[2] = seg_startA[2];
+
+ float temp[12];
+ mat.getValue(temp);
+
+ seg_it->basis[0] = temp[0];
+ seg_it->basis[1] = temp[1];
+ seg_it->basis[2] = temp[2];
+
+ seg_it->basis[3] = temp[4];
+ seg_it->basis[4] = temp[5];
+ seg_it->basis[5] = temp[6];
+
+ seg_it->basis[6] = temp[8];
+ seg_it->basis[7] = temp[9];
+ seg_it->basis[8] = temp[10];
+
+ seg_it->length = seg_length;
+
+ MT_Quaternion q;
+ q.setEuler(0,0,0);
+
+
+ MT_Matrix3x3 qrot(q);
+
+ seg_it->basis_change[0] = 1;
+ seg_it->basis_change[1] = 0;
+ seg_it->basis_change[2] = 0;
+ seg_it->basis_change[3] = 0;
+ seg_it->basis_change[4] = 1;
+ seg_it->basis_change[5] = 0;
+ seg_it->basis_change[6] = 0;
+ seg_it->basis_change[7] = 0;
+ seg_it->basis_change[8] = 1;
+
+
+ seg_it ++;
+
+ seg_itB->seg_start[0] = seg_startA[0];
+ seg_itB->seg_start[1] = seg_startA[1];
+ seg_itB->seg_start[2] = seg_startA[2];
+
+ seg_itB->basis[0] = temp[0];
+ seg_itB->basis[1] = temp[1];
+ seg_itB->basis[2] = temp[2];
+
+ seg_itB->basis[3] = temp[4];
+ seg_itB->basis[4] = temp[5];
+ seg_itB->basis[5] = temp[6];
+
+ seg_itB->basis[6] = temp[8];
+ seg_itB->basis[7] = temp[9];
+ seg_itB->basis[8] = temp[10];
+
+ seg_itB->length = seg_length;
+
+ seg_itB->basis_change[0] = 1;
+ seg_itB->basis_change[1] = 0;
+ seg_itB->basis_change[2] = 0;
+ seg_itB->basis_change[3] = 0;
+ seg_itB->basis_change[4] = 1;
+ seg_itB->basis_change[5] = 0;
+ seg_itB->basis_change[6] = 0;
+ seg_itB->basis_change[7] = 0;
+ seg_itB->basis_change[8] = 1;
+
+
+ seg_itB ++;
+
+
+ }
+
+
+ int i;
+ for (i=1; i < seg_num; ++i, ++seg_it,++seg_itB) {
+
+ MT_Quaternion qmat(MT_Vector3(0,0,1),0.3);
+ MT_Matrix3x3 mat(qmat);
+
+ seg_it->seg_start[0] = 0;
+ seg_it->seg_start[1] = 0;
+ seg_it->seg_start[2] = 0;
+
+ float temp[12];
+ mat.getValue(temp);
+
+ seg_it->basis[0] = temp[0];
+ seg_it->basis[1] = temp[1];
+ seg_it->basis[2] = temp[2];
+
+ seg_it->basis[3] = temp[4];
+ seg_it->basis[4] = temp[5];
+ seg_it->basis[5] = temp[6];
+
+ seg_it->basis[6] = temp[8];
+ seg_it->basis[7] = temp[9];
+ seg_it->basis[8] = temp[10];
+
+ seg_it->length = seg_length;
+
+ MT_Quaternion q;
+ q.setEuler(0,0,0);
+
+
+ MT_Matrix3x3 qrot(q);
+
+ seg_it->basis_change[0] = 1;
+ seg_it->basis_change[1] = 0;
+ seg_it->basis_change[2] = 0;
+ seg_it->basis_change[3] = 0;
+ seg_it->basis_change[4] = 1;
+ seg_it->basis_change[5] = 0;
+ seg_it->basis_change[6] = 0;
+ seg_it->basis_change[7] = 0;
+ seg_it->basis_change[8] = 1;
+
+
+ ///////////////////////////////
+
+ seg_itB->seg_start[0] = 0;
+ seg_itB->seg_start[1] = 0;
+ seg_itB->seg_start[2] = 0;
+
+ seg_itB->basis[0] = temp[0];
+ seg_itB->basis[1] = temp[1];
+ seg_itB->basis[2] = temp[2];
+
+ seg_itB->basis[3] = temp[4];
+ seg_itB->basis[4] = temp[5];
+ seg_itB->basis[5] = temp[6];
+
+ seg_itB->basis[6] = temp[8];
+ seg_itB->basis[7] = temp[9];
+ seg_itB->basis[8] = temp[10];
+
+ seg_itB->length = seg_length;
+
+ seg_itB->basis_change[0] = 1;
+ seg_itB->basis_change[1] = 0;
+ seg_itB->basis_change[2] = 0;
+ seg_itB->basis_change[3] = 0;
+ seg_itB->basis_change[4] = 1;
+ seg_itB->basis_change[5] = 0;
+ seg_itB->basis_change[6] = 0;
+ seg_itB->basis_change[7] = 0;
+ seg_itB->basis_change[8] = 1;
+
+
+
+ }
+
+ // create the chains
+
+ const int num_chains = 2;
+
+ IK_Chain_ExternPtr chains[num_chains];
+
+ chains[0] = IK_CreateChain();
+ chains[1] = IK_CreateChain();
+
+ // load segments into chain
+
+ IK_LoadChain(chains[0],segmentsA,seg_num);
+ IK_LoadChain(chains[1],segmentsB,seg_num);
+
+ // make and install a mouse handler
+
+ MEM_SmartPtr<MyGlutMouseHandler> mouse_handler (MyGlutMouseHandler::New());
+ GlutMouseManager::Instance()->InstallHandler(mouse_handler);
+
+ mouse_handler->SetChain(chains,num_chains);
+
+ // make and install a keyhandler
+ MEM_SmartPtr<MyGlutKeyHandler> key_handler (MyGlutKeyHandler::New());
+ GlutKeyboardManager::Instance()->InstallHandler(key_handler);
+
+ // instantiate the drawing class
+
+ MEM_SmartPtr<ChainDrawer> drawer (ChainDrawer::New());
+ GlutDrawManager::Instance()->InstallDrawer(drawer);
+
+ drawer->SetMouseHandler(mouse_handler);
+ drawer->SetChain(chains,num_chains);
+ drawer->SetKeyHandler(key_handler);
+
+ glutInit(&argc, argv);
+ glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
+ glutCreateWindow("ik");
+ glutDisplayFunc(GlutDrawManager::Draw);
+ glutMouseFunc(GlutMouseManager::Mouse);
+ glutMotionFunc(GlutMouseManager::Motion);
+ glutKeyboardFunc(GlutKeyboardManager::HandleKeyboard);
+
+ init(MT_Vector3(-50,-50,-50),MT_Vector3(50,50,50));
+ glutMainLoop();
+ return 0; /* ANSI C requires main to return int. */
+}
diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp
new file mode 100644
index 00000000000..8688b2fcc2c
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsp
@@ -0,0 +1,130 @@
+# Microsoft Developer Studio Project File - Name="ik_glut_test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=ik_glut_test - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "ik_glut_test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "ik_glut_test.mak" CFG="ik_glut_test - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "ik_glut_test - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "ik_glut_test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "ik_glut_test - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD BASE RSC /l 0x413 /d "NDEBUG"
+# ADD RSC /l 0x413 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
+# ADD LINK32 iksolver_rmtd.lib libmoto.a /nologo /subsystem:console /machine:I386 /libpath:"..\..\..\..\lib\windows\release" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib"
+
+!ELSEIF "$(CFG)" == "ik_glut_test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\..\..\..\extern" /I "..\..\..\..\..\..\lib\windows\glut-3.7\include" /I "..\..\..\..\..\..\lib\windows\moto\include" /I "..\..\..\..\..\..\lib\windows\memutil\include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x413 /d "_DEBUG"
+# ADD RSC /l 0x413 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 iksolver_dmtd.lib libmoto.a /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"LIBCMTD.lib" /pdbtype:sept /libpath:"..\..\..\..\lib\windows\debug" /libpath:"..\..\..\..\..\..\lib\windows\glut-3.7\lib" /libpath:"..\..\..\..\..\..\lib\windows\moto\lib\debug"
+
+!ENDIF
+
+# Begin Target
+
+# Name "ik_glut_test - Win32 Release"
+# Name "ik_glut_test - Win32 Debug"
+# Begin Group "common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\common\GlutDrawer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutDrawer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutKeyboardManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutKeyboardManager.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutMouseManager.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\common\GlutMouseManager.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\intern\ChainDrawer.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MyGlutKeyHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\intern\MyGlutMouseHandler.h
+# End Source File
+# End Target
+# End Project
diff --git a/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw
new file mode 100644
index 00000000000..09b7094137b
--- /dev/null
+++ b/intern/iksolver/test/ik_glut_test/make/msvc_6_0/ik_glut_test.dsw
@@ -0,0 +1,49 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "ik_glut_test"=.\ik_glut_test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name iksolver
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "iksolver"=..\..\..\..\make\msvc_6_0\iksolver.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
+
+
+
+
+