Merging r49300 through r49333 from trunk into soc-2011-tomato
This commit is contained in:
@@ -705,11 +705,23 @@ def UnixPyBundle(target=None, source=None, env=None):
|
||||
run("rm -r '%s/turtle.py'" % py_target)
|
||||
run("rm -f '%s/lib-dynload/_tkinter.so'" % py_target)
|
||||
|
||||
if env['WITH_BF_PYTHON_INSTALL_NUMPY']:
|
||||
numpy_src = py_src + "/site-packages/numpy"
|
||||
numpy_target = py_target + "/site-packages/numpy"
|
||||
|
||||
if os.path.exists(numpy_src):
|
||||
print 'Install numpy from:'
|
||||
print '\t"%s" into...' % numpy_src
|
||||
print '\t"%s"\n' % numpy_target
|
||||
|
||||
run("cp -R '%s' '%s'" % (numpy_src, os.path.dirname(numpy_target)))
|
||||
else:
|
||||
print 'Failed to find numpy at %s, skipping copying' % numpy_src
|
||||
|
||||
run("find '%s' -type d -name 'test' -prune -exec rm -rf {} ';'" % py_target)
|
||||
run("find '%s' -type d -name '__pycache__' -exec rm -rf {} ';'" % py_target)
|
||||
run("find '%s' -name '*.py[co]' -exec rm -rf {} ';'" % py_target)
|
||||
run("find '%s' -name '*.so' -exec strip -s {} ';'" % py_target)
|
||||
|
||||
|
||||
#### END ACTION STUFF #########
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ def validate_arguments(args, bc):
|
||||
'BF_CXX', 'WITH_BF_STATICCXX', 'BF_CXX_LIB_STATIC',
|
||||
'BF_TWEAK_MODE', 'BF_SPLIT_SRC',
|
||||
'WITHOUT_BF_INSTALL',
|
||||
'WITHOUT_BF_PYTHON_INSTALL', 'WITHOUT_BF_PYTHON_UNPACK',
|
||||
'WITHOUT_BF_PYTHON_INSTALL', 'WITHOUT_BF_PYTHON_UNPACK', 'WITH_BF_PYTHON_INSTALL_NUMPY'
|
||||
'WITHOUT_BF_OVERWRITE_INSTALL',
|
||||
'WITH_BF_OPENMP', 'BF_OPENMP', 'BF_OPENMP_LIBPATH',
|
||||
'WITH_GHOST_COCOA',
|
||||
@@ -521,6 +521,7 @@ def read_opts(env, cfg, args):
|
||||
(BoolVariable('BF_SPLIT_SRC', 'Split src lib into several chunks if true', False)),
|
||||
(BoolVariable('WITHOUT_BF_INSTALL', 'dont install if true', False)),
|
||||
(BoolVariable('WITHOUT_BF_PYTHON_INSTALL', 'dont install Python modules if true', False)),
|
||||
(BoolVariable('WITH_BF_PYTHON_INSTALL_NUMPY', 'install Python mumpy module', False)),
|
||||
(BoolVariable('WITHOUT_BF_PYTHON_UNPACK', 'dont remove and unpack Python modules everytime if true', False)),
|
||||
(BoolVariable('WITHOUT_BF_OVERWRITE_INSTALL', 'dont remove existing files before breating the new install directory (set to False when making packages for others)', False)),
|
||||
(BoolVariable('BF_FANCY', 'Enable fancy output if true', True)),
|
||||
|
||||
@@ -163,8 +163,8 @@
|
||||
|
||||
#include "Eigen/Core"
|
||||
|
||||
// Visual Studio 2010 or older version
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1600
|
||||
// Visual Studio 2012 or older version
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
namespace std {
|
||||
inline bool isfinite(double x) { return _finite(x); }
|
||||
inline bool isinf (double x) { return !_finite(x) && !_isnan(x); }
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef CERES_INTERNAL_COLLECTIONS_PORT_H_
|
||||
#define CERES_INTERNAL_COLLECTIONS_PORT_H_
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1600
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#else
|
||||
|
||||
@@ -16,6 +16,13 @@
|
||||
|
||||
#include "mvmcoords.h"
|
||||
#include <algorithm>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER > 1600
|
||||
// sdt::greater
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
|
||||
using std::vector;
|
||||
|
||||
void MeanValueMeshCoords::clear()
|
||||
|
||||
3
intern/iksolver/extern/IK_solver.h
vendored
3
intern/iksolver/extern/IK_solver.h
vendored
@@ -163,6 +163,9 @@ float IK_SolverGetPoleAngle(IK_Solver *solver);
|
||||
|
||||
int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations);
|
||||
|
||||
#define IK_STRETCH_STIFF_EPS 0.001f
|
||||
#define IK_STRETCH_STIFF_MIN 0.001f
|
||||
#define IK_STRETCH_STIFF_MAX 1e10
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "TNT/svd.h"
|
||||
|
||||
IK_QJacobian::IK_QJacobian()
|
||||
: m_sdls(true), m_min_damp(1.0)
|
||||
: m_sdls(true), m_min_damp(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -106,16 +106,16 @@ void IK_QJacobian::ArmMatrices(int dof, int task_size)
|
||||
|
||||
void IK_QJacobian::SetBetas(int id, int, const MT_Vector3& v)
|
||||
{
|
||||
m_beta[id] = v.x();
|
||||
m_beta[id+1] = v.y();
|
||||
m_beta[id+2] = v.z();
|
||||
m_beta[id + 0] = v.x();
|
||||
m_beta[id + 1] = v.y();
|
||||
m_beta[id + 2] = v.z();
|
||||
}
|
||||
|
||||
void IK_QJacobian::SetDerivatives(int id, int dof_id, const MT_Vector3& v, MT_Scalar norm_weight)
|
||||
{
|
||||
m_jacobian[id][dof_id] = v.x()*m_weight_sqrt[dof_id];
|
||||
m_jacobian[id+1][dof_id] = v.y()*m_weight_sqrt[dof_id];
|
||||
m_jacobian[id+2][dof_id] = v.z()*m_weight_sqrt[dof_id];
|
||||
m_jacobian[id + 0][dof_id] = v.x() * m_weight_sqrt[dof_id];
|
||||
m_jacobian[id + 1][dof_id] = v.y() * m_weight_sqrt[dof_id];
|
||||
m_jacobian[id + 2][dof_id] = v.z() * m_weight_sqrt[dof_id];
|
||||
|
||||
m_d_norm_weight[dof_id] = norm_weight;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ void IK_QJacobian::SubTask(IK_QJacobian& jacobian)
|
||||
// doesn't work well at all
|
||||
int i;
|
||||
for (i = 0; i < m_d_theta.size(); i++)
|
||||
m_d_theta[i] = m_d_theta[i] + /*m_min_damp**/jacobian.AngleUpdate(i);
|
||||
m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
|
||||
}
|
||||
|
||||
void IK_QJacobian::Restrict(TVector& d_theta, TMatrix& null)
|
||||
@@ -230,7 +230,7 @@ void IK_QJacobian::InvertSDLS()
|
||||
// DLS. The SDLS damps individual singular values, instead of using a single
|
||||
// damping term.
|
||||
|
||||
MT_Scalar max_angle_change = MT_PI/4.0;
|
||||
MT_Scalar max_angle_change = MT_PI / 4.0;
|
||||
MT_Scalar epsilon = 1e-10;
|
||||
int i, j;
|
||||
|
||||
@@ -239,35 +239,35 @@ void IK_QJacobian::InvertSDLS()
|
||||
|
||||
for (i = 0; i < m_dof; i++) {
|
||||
m_norm[i] = 0.0;
|
||||
for (j = 0; j < m_task_size; j+=3) {
|
||||
for (j = 0; j < m_task_size; j += 3) {
|
||||
MT_Scalar n = 0.0;
|
||||
n += m_jacobian[j][i]*m_jacobian[j][i];
|
||||
n += m_jacobian[j+1][i]*m_jacobian[j+1][i];
|
||||
n += m_jacobian[j+2][i]*m_jacobian[j+2][i];
|
||||
n += m_jacobian[j][i] * m_jacobian[j][i];
|
||||
n += m_jacobian[j + 1][i] * m_jacobian[j + 1][i];
|
||||
n += m_jacobian[j + 2][i] * m_jacobian[j + 2][i];
|
||||
m_norm[i] += sqrt(n);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i<m_svd_w.size(); i++) {
|
||||
for (i = 0; i < m_svd_w.size(); i++) {
|
||||
if (m_svd_w[i] <= epsilon)
|
||||
continue;
|
||||
|
||||
MT_Scalar wInv = 1.0/m_svd_w[i];
|
||||
MT_Scalar wInv = 1.0 / m_svd_w[i];
|
||||
MT_Scalar alpha = 0.0;
|
||||
MT_Scalar N = 0.0;
|
||||
|
||||
// compute alpha and N
|
||||
for (j=0; j<m_svd_u.num_rows(); j+=3) {
|
||||
alpha += m_svd_u[j][i]*m_beta[j];
|
||||
alpha += m_svd_u[j+1][i]*m_beta[j+1];
|
||||
alpha += m_svd_u[j+2][i]*m_beta[j+2];
|
||||
for (j = 0; j < m_svd_u.num_rows(); j += 3) {
|
||||
alpha += m_svd_u[j][i] * m_beta[j];
|
||||
alpha += m_svd_u[j + 1][i] * m_beta[j + 1];
|
||||
alpha += m_svd_u[j + 2][i] * m_beta[j + 2];
|
||||
|
||||
// note: for 1 end effector, N will always be 1, since U is
|
||||
// orthogonal, .. so could be optimized
|
||||
MT_Scalar tmp;
|
||||
tmp = m_svd_u[j][i]*m_svd_u[j][i];
|
||||
tmp += m_svd_u[j+1][i]*m_svd_u[j+1][i];
|
||||
tmp += m_svd_u[j+2][i]*m_svd_u[j+2][i];
|
||||
tmp = m_svd_u[j][i] * m_svd_u[j][i];
|
||||
tmp += m_svd_u[j + 1][i] * m_svd_u[j + 1][i];
|
||||
tmp += m_svd_u[j + 2][i] * m_svd_u[j + 2][i];
|
||||
N += sqrt(tmp);
|
||||
}
|
||||
alpha *= wInv;
|
||||
@@ -278,14 +278,14 @@ void IK_QJacobian::InvertSDLS()
|
||||
|
||||
for (j = 0; j < m_d_theta.size(); j++) {
|
||||
MT_Scalar v = m_svd_v[j][i];
|
||||
M += MT_abs(v)*m_norm[j];
|
||||
M += MT_abs(v) * m_norm[j];
|
||||
|
||||
// compute tmporary dTheta's
|
||||
m_d_theta_tmp[j] = v*alpha;
|
||||
m_d_theta_tmp[j] = v * alpha;
|
||||
|
||||
// find largest absolute dTheta
|
||||
// multiply with weight to prevent unnecessary damping
|
||||
abs_dtheta = MT_abs(m_d_theta_tmp[j])*m_weight_sqrt[j];
|
||||
abs_dtheta = MT_abs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
|
||||
if (abs_dtheta > max_dtheta)
|
||||
max_dtheta = abs_dtheta;
|
||||
}
|
||||
@@ -295,19 +295,19 @@ void IK_QJacobian::InvertSDLS()
|
||||
// compute damping term and damp the dTheta's
|
||||
MT_Scalar gamma = max_angle_change;
|
||||
if (N < M)
|
||||
gamma *= N/M;
|
||||
gamma *= N / M;
|
||||
|
||||
MT_Scalar damp = (gamma < max_dtheta)? gamma/max_dtheta: 1.0;
|
||||
MT_Scalar damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
|
||||
|
||||
for (j = 0; j < m_d_theta.size(); j++) {
|
||||
// slight hack: we do 0.80*, so that if there is some oscillation,
|
||||
// the system can still converge (for joint limits). also, it's
|
||||
// better to go a little to slow than to far
|
||||
|
||||
MT_Scalar dofdamp = damp/m_weight[j];
|
||||
MT_Scalar dofdamp = damp / m_weight[j];
|
||||
if (dofdamp > 1.0) dofdamp = 1.0;
|
||||
|
||||
m_d_theta[j] += 0.80*dofdamp*m_d_theta_tmp[j];
|
||||
m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
|
||||
}
|
||||
|
||||
if (damp < m_min_damp)
|
||||
@@ -317,7 +317,7 @@ void IK_QJacobian::InvertSDLS()
|
||||
// weight + prevent from doing angle updates with angles > max_angle_change
|
||||
MT_Scalar max_angle = 0.0, abs_angle;
|
||||
|
||||
for (j = 0; j<m_dof; j++) {
|
||||
for (j = 0; j < m_dof; j++) {
|
||||
m_d_theta[j] *= m_weight[j];
|
||||
|
||||
abs_angle = MT_abs(m_d_theta[j]);
|
||||
@@ -327,9 +327,9 @@ void IK_QJacobian::InvertSDLS()
|
||||
}
|
||||
|
||||
if (max_angle > max_angle_change) {
|
||||
MT_Scalar damp = (max_angle_change)/(max_angle_change + max_angle);
|
||||
MT_Scalar damp = (max_angle_change) / (max_angle_change + max_angle);
|
||||
|
||||
for (j = 0; j<m_dof; j++)
|
||||
for (j = 0; j < m_dof; j++)
|
||||
m_d_theta[j] *= damp;
|
||||
}
|
||||
}
|
||||
@@ -360,20 +360,20 @@ void IK_QJacobian::InvertDLS()
|
||||
int i, j;
|
||||
MT_Scalar w_min = MT_INFINITY;
|
||||
|
||||
for (i = 0; i <m_svd_w.size() ; i++) {
|
||||
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];
|
||||
}
|
||||
|
||||
// compute lambda damping term
|
||||
|
||||
MT_Scalar d = x_length/max_angle_change;
|
||||
MT_Scalar d = x_length / max_angle_change;
|
||||
MT_Scalar lambda;
|
||||
|
||||
if (w_min <= d/2)
|
||||
lambda = d/2;
|
||||
if (w_min <= d / 2)
|
||||
lambda = d / 2;
|
||||
else if (w_min < d)
|
||||
lambda = sqrt(w_min*(d - w_min));
|
||||
lambda = sqrt(w_min * (d - w_min));
|
||||
else
|
||||
lambda = 0.0;
|
||||
|
||||
@@ -393,17 +393,17 @@ void IK_QJacobian::InvertDLS()
|
||||
|
||||
for (i = 0; i < m_svd_w.size(); i++) {
|
||||
if (m_svd_w[i] > epsilon) {
|
||||
MT_Scalar wInv = m_svd_w[i]/(m_svd_w[i]*m_svd_w[i] + lambda);
|
||||
MT_Scalar wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
|
||||
|
||||
// compute V*Winv*Ut*Beta
|
||||
m_svd_u_beta[i] *= wInv;
|
||||
|
||||
for (j = 0; j<m_d_theta.size(); j++)
|
||||
m_d_theta[j] += m_svd_v[j][i]*m_svd_u_beta[i];
|
||||
for (j = 0; j < m_d_theta.size(); j++)
|
||||
m_d_theta[j] += m_svd_v[j][i] * m_svd_u_beta[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j<m_d_theta.size(); j++)
|
||||
for (j = 0; j < m_d_theta.size(); j++)
|
||||
m_d_theta[j] *= m_weight[j];
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ void IK_QJacobian::Lock(int dof_id, MT_Scalar delta)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < m_task_size; i++) {
|
||||
m_beta[i] -= m_jacobian[i][dof_id]*delta;
|
||||
m_beta[i] -= m_jacobian[i][dof_id] * delta;
|
||||
m_jacobian[i][dof_id] = 0.0;
|
||||
}
|
||||
|
||||
@@ -431,7 +431,7 @@ MT_Scalar IK_QJacobian::AngleUpdateNorm() const
|
||||
MT_Scalar mx = 0.0, dtheta_abs;
|
||||
|
||||
for (i = 0; i < m_d_theta.size(); i++) {
|
||||
dtheta_abs = MT_abs(m_d_theta[i]*m_d_norm_weight[i]);
|
||||
dtheta_abs = MT_abs(m_d_theta[i] * m_d_norm_weight[i]);
|
||||
if (dtheta_abs > mx)
|
||||
mx = dtheta_abs;
|
||||
}
|
||||
|
||||
@@ -45,22 +45,22 @@ IK_QJacobianSolver::IK_QJacobianSolver()
|
||||
|
||||
MT_Scalar IK_QJacobianSolver::ComputeScale()
|
||||
{
|
||||
std::vector<IK_QSegment*>::iterator seg;
|
||||
float length = 0.0f;
|
||||
std::vector<IK_QSegment *>::iterator seg;
|
||||
MT_Scalar length = 0.0f;
|
||||
|
||||
for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
|
||||
length += (*seg)->MaxExtension();
|
||||
|
||||
if(length == 0.0f)
|
||||
return 1.0f;
|
||||
if (length == 0.0)
|
||||
return 1.0;
|
||||
else
|
||||
return 1.0f/length;
|
||||
return 1.0 / length;
|
||||
}
|
||||
|
||||
void IK_QJacobianSolver::Scale(float scale, std::list<IK_QTask*>& tasks)
|
||||
void IK_QJacobianSolver::Scale(MT_Scalar scale, std::list<IK_QTask *>& tasks)
|
||||
{
|
||||
std::list<IK_QTask*>::iterator task;
|
||||
std::vector<IK_QSegment*>::iterator seg;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
std::vector<IK_QSegment *>::iterator seg;
|
||||
|
||||
for (task = tasks.begin(); task != tasks.end(); task++)
|
||||
(*task)->Scale(scale);
|
||||
@@ -82,13 +82,13 @@ void IK_QJacobianSolver::AddSegmentList(IK_QSegment *seg)
|
||||
AddSegmentList(child);
|
||||
}
|
||||
|
||||
bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks)
|
||||
bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask *>& tasks)
|
||||
{
|
||||
m_segments.clear();
|
||||
AddSegmentList(root);
|
||||
|
||||
// assign each segment a unique id for the jacobian
|
||||
std::vector<IK_QSegment*>::iterator seg;
|
||||
std::vector<IK_QSegment *>::iterator seg;
|
||||
int num_dof = 0;
|
||||
|
||||
for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
|
||||
@@ -103,7 +103,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks)
|
||||
int primary_size = 0, primary = 0;
|
||||
int secondary_size = 0, secondary = 0;
|
||||
MT_Scalar primary_weight = 0.0, secondary_weight = 0.0;
|
||||
std::list<IK_QTask*>::iterator task;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
|
||||
for (task = tasks.begin(); task != tasks.end(); task++) {
|
||||
IK_QTask *qtask = *task;
|
||||
@@ -128,20 +128,20 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks)
|
||||
m_secondary_enabled = (secondary > 0);
|
||||
|
||||
// rescale weights of tasks to sum up to 1
|
||||
MT_Scalar primary_rescale = 1.0/primary_weight;
|
||||
MT_Scalar primary_rescale = 1.0 / primary_weight;
|
||||
MT_Scalar secondary_rescale;
|
||||
if (MT_fuzzyZero(secondary_weight))
|
||||
secondary_rescale = 0.0;
|
||||
else
|
||||
secondary_rescale = 1.0/secondary_weight;
|
||||
secondary_rescale = 1.0 / secondary_weight;
|
||||
|
||||
for (task = tasks.begin(); task != tasks.end(); task++) {
|
||||
IK_QTask *qtask = *task;
|
||||
|
||||
if (qtask->Primary())
|
||||
qtask->SetWeight(qtask->Weight()*primary_rescale);
|
||||
qtask->SetWeight(qtask->Weight() * primary_rescale);
|
||||
else
|
||||
qtask->SetWeight(qtask->Weight()*secondary_rescale);
|
||||
qtask->SetWeight(qtask->Weight() * secondary_rescale);
|
||||
}
|
||||
|
||||
// set matrix sizes
|
||||
@@ -154,7 +154,7 @@ bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks)
|
||||
|
||||
for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
|
||||
for (i = 0; i < (*seg)->NumberOfDoF(); i++)
|
||||
m_jacobian.SetDoFWeight((*seg)->DoFId()+i, (*seg)->Weight(i));
|
||||
m_jacobian.SetDoFWeight((*seg)->DoFId() + i, (*seg)->Weight(i));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -165,15 +165,15 @@ void IK_QJacobianSolver::SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& g
|
||||
m_poletip = tip;
|
||||
m_goal = goal;
|
||||
m_polegoal = polegoal;
|
||||
m_poleangle = (getangle)? 0.0f: poleangle;
|
||||
m_poleangle = (getangle) ? 0.0f : poleangle;
|
||||
m_getpoleangle = getangle;
|
||||
}
|
||||
|
||||
static MT_Scalar safe_acos(MT_Scalar f)
|
||||
{
|
||||
// acos that does not return NaN with rounding errors
|
||||
if (f <= -1.0f) return MT_PI;
|
||||
else if (f >= 1.0f) return 0.0;
|
||||
if (f <= -1.0) return MT_PI;
|
||||
else if (f >= 1.0) return 0.0;
|
||||
else return acos(f);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ static MT_Vector3 normalize(const MT_Vector3& v)
|
||||
// a sane normalize function that doesn't give (1, 0, 0) in case
|
||||
// of a zero length vector, like MT_Vector3.normalize
|
||||
MT_Scalar len = v.length();
|
||||
return MT_fuzzyZero(len)? MT_Vector3(0, 0, 0): v/len;
|
||||
return MT_fuzzyZero(len) ? MT_Vector3(0, 0, 0) : v / len;
|
||||
}
|
||||
|
||||
static float angle(const MT_Vector3& v1, const MT_Vector3& v2)
|
||||
@@ -190,21 +190,21 @@ static float angle(const MT_Vector3& v1, const MT_Vector3& v2)
|
||||
return safe_acos(v1.dot(v2));
|
||||
}
|
||||
|
||||
void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask*>& tasks)
|
||||
void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask *>& tasks)
|
||||
{
|
||||
// this function will be called before and after solving. calling it before
|
||||
// solving gives predictable solutions by rotating towards the solution,
|
||||
// and calling it afterwards ensures the solution is exact.
|
||||
|
||||
if(!m_poleconstraint)
|
||||
if (!m_poleconstraint)
|
||||
return;
|
||||
|
||||
// disable pole vector constraint in case of multiple position tasks
|
||||
std::list<IK_QTask*>::iterator task;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
int positiontasks = 0;
|
||||
|
||||
for (task = tasks.begin(); task != tasks.end(); task++)
|
||||
if((*task)->PositionTask())
|
||||
if ((*task)->PositionTask())
|
||||
positiontasks++;
|
||||
|
||||
if (positiontasks >= 2) {
|
||||
@@ -223,12 +223,12 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
|
||||
// an up vector, with the direction going from the root to the end effector
|
||||
// and the up vector going from the root to the pole constraint position.
|
||||
MT_Vector3 dir = normalize(endpos - rootpos);
|
||||
MT_Vector3 rootx= rootbasis.getColumn(0);
|
||||
MT_Vector3 rootz= rootbasis.getColumn(2);
|
||||
MT_Vector3 up = rootx*cos(m_poleangle) + rootz*sin(m_poleangle);
|
||||
MT_Vector3 rootx = rootbasis.getColumn(0);
|
||||
MT_Vector3 rootz = rootbasis.getColumn(2);
|
||||
MT_Vector3 up = rootx * cos(m_poleangle) + rootz *sin(m_poleangle);
|
||||
|
||||
// in post, don't rotate towards the goal but only correct the pole up
|
||||
MT_Vector3 poledir = (m_getpoleangle)? dir: normalize(m_goal - rootpos);
|
||||
MT_Vector3 poledir = (m_getpoleangle) ? dir : normalize(m_goal - rootpos);
|
||||
MT_Vector3 poleup = normalize(m_polegoal - rootpos);
|
||||
|
||||
MT_Matrix3x3 mat, polemat;
|
||||
@@ -241,11 +241,11 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
|
||||
polemat[1] = MT_cross(polemat[0], poledir);
|
||||
polemat[2] = -poledir;
|
||||
|
||||
if(m_getpoleangle) {
|
||||
if (m_getpoleangle) {
|
||||
// we compute the pole angle that to rotate towards the target
|
||||
m_poleangle = angle(mat[1], polemat[1]);
|
||||
|
||||
if(rootz.dot(mat[1]*cos(m_poleangle) + mat[0]*sin(m_poleangle)) > 0.0f)
|
||||
if (rootz.dot(mat[1] * cos(m_poleangle) + mat[0] * sin(m_poleangle)) > 0.0)
|
||||
m_poleangle = -m_poleangle;
|
||||
|
||||
// solve again, with the pole angle we just computed
|
||||
@@ -257,15 +257,15 @@ void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTa
|
||||
// desired rotation based on the pole vector constraint. we use
|
||||
// transpose instead of inverse because we have orthogonal matrices
|
||||
// anyway, and in case of a singular matrix we don't get NaN's.
|
||||
MT_Transform trans(MT_Point3(0, 0, 0), polemat.transposed()*mat);
|
||||
m_rootmatrix = trans*m_rootmatrix;
|
||||
MT_Transform trans(MT_Point3(0, 0, 0), polemat.transposed() * mat);
|
||||
m_rootmatrix = trans * m_rootmatrix;
|
||||
}
|
||||
}
|
||||
|
||||
bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
|
||||
{
|
||||
// assing each segment a unique id for the jacobian
|
||||
std::vector<IK_QSegment*>::iterator seg;
|
||||
std::vector<IK_QSegment *>::iterator seg;
|
||||
IK_QSegment *qseg, *minseg = NULL;
|
||||
MT_Scalar minabsdelta = 1e10, absdelta;
|
||||
MT_Vector3 delta, mindelta;
|
||||
@@ -318,11 +318,11 @@ bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
|
||||
}
|
||||
|
||||
bool IK_QJacobianSolver::Solve(
|
||||
IK_QSegment *root,
|
||||
std::list<IK_QTask*> tasks,
|
||||
const MT_Scalar,
|
||||
const int max_iterations
|
||||
)
|
||||
IK_QSegment *root,
|
||||
std::list<IK_QTask *> tasks,
|
||||
const MT_Scalar,
|
||||
const int max_iterations
|
||||
)
|
||||
{
|
||||
float scale = ComputeScale();
|
||||
bool solved = false;
|
||||
@@ -339,7 +339,7 @@ bool IK_QJacobianSolver::Solve(
|
||||
// update transform
|
||||
root->UpdateTransform(m_rootmatrix);
|
||||
|
||||
std::list<IK_QTask*>::iterator task;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
|
||||
// compute jacobian
|
||||
for (task = tasks.begin(); task != tasks.end(); task++) {
|
||||
@@ -367,7 +367,7 @@ bool IK_QJacobianSolver::Solve(
|
||||
} while (UpdateAngles(norm));
|
||||
|
||||
// unlock segments again after locking in clamping loop
|
||||
std::vector<IK_QSegment*>::iterator seg;
|
||||
std::vector<IK_QSegment *>::iterator seg;
|
||||
for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
|
||||
(*seg)->UnLock();
|
||||
|
||||
@@ -383,10 +383,10 @@ bool IK_QJacobianSolver::Solve(
|
||||
}
|
||||
}
|
||||
|
||||
if(m_poleconstraint)
|
||||
if (m_poleconstraint)
|
||||
root->PrependBasis(m_rootmatrix.getBasis());
|
||||
|
||||
Scale(1.0f/scale, tasks);
|
||||
Scale(1.0f / scale, tasks);
|
||||
|
||||
//analyze_add_run(max_iterations, analyze_time()-dt);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ private:
|
||||
void ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask*>& tasks);
|
||||
|
||||
MT_Scalar ComputeScale();
|
||||
void Scale(float scale, std::list<IK_QTask*>& tasks);
|
||||
void Scale(MT_Scalar scale, std::list<IK_QTask*>& tasks);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -60,24 +60,25 @@ static MT_Matrix3x3 RotationMatrix(MT_Scalar angle, int axis)
|
||||
|
||||
static MT_Scalar EulerAngleFromMatrix(const MT_Matrix3x3& R, int axis)
|
||||
{
|
||||
MT_Scalar t = sqrt(R[0][0]*R[0][0] + R[0][1]*R[0][1]);
|
||||
MT_Scalar t = sqrt(R[0][0] * R[0][0] + R[0][1] * R[0][1]);
|
||||
|
||||
if (t > 16.0*MT_EPSILON) {
|
||||
if (axis == 0) return -atan2(R[1][2], R[2][2]);
|
||||
else if(axis == 1) return atan2(-R[0][2], t);
|
||||
else return -atan2(R[0][1], R[0][0]);
|
||||
} else {
|
||||
if (axis == 0) return -atan2(-R[2][1], R[1][1]);
|
||||
else if(axis == 1) return atan2(-R[0][2], t);
|
||||
else return 0.0f;
|
||||
}
|
||||
if (t > 16.0 * MT_EPSILON) {
|
||||
if (axis == 0) return -atan2(R[1][2], R[2][2]);
|
||||
else if (axis == 1) return atan2(-R[0][2], t);
|
||||
else return -atan2(R[0][1], R[0][0]);
|
||||
}
|
||||
else {
|
||||
if (axis == 0) return -atan2(-R[2][1], R[1][1]);
|
||||
else if (axis == 1) return atan2(-R[0][2], t);
|
||||
else return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static MT_Scalar safe_acos(MT_Scalar f)
|
||||
{
|
||||
if (f <= -1.0f)
|
||||
if (f <= -1.0)
|
||||
return MT_PI;
|
||||
else if (f >= 1.0f)
|
||||
else if (f >= 1.0)
|
||||
return 0.0;
|
||||
else
|
||||
return acos(f);
|
||||
@@ -89,7 +90,7 @@ static MT_Scalar ComputeTwist(const MT_Matrix3x3& R)
|
||||
MT_Scalar qy = R[0][2] - R[2][0];
|
||||
MT_Scalar qw = R[0][0] + R[1][1] + R[2][2] + 1;
|
||||
|
||||
MT_Scalar tau = 2*atan2(qy, qw);
|
||||
MT_Scalar tau = 2.0 * atan2(qy, qw);
|
||||
|
||||
return tau;
|
||||
}
|
||||
@@ -108,7 +109,7 @@ static void RemoveTwist(MT_Matrix3x3& R)
|
||||
MT_Matrix3x3 T = ComputeTwistMatrix(tau);
|
||||
|
||||
// remove twist
|
||||
R = R*T.transposed();
|
||||
R = R * T.transposed();
|
||||
}
|
||||
|
||||
static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
|
||||
@@ -117,7 +118,7 @@ static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
|
||||
MT_Scalar tau = ComputeTwist(R);
|
||||
|
||||
// compute swing parameters
|
||||
MT_Scalar num = 2.0*(1.0 + R[1][1]);
|
||||
MT_Scalar num = 2.0 * (1.0 + R[1][1]);
|
||||
|
||||
// singularity at pi
|
||||
if (MT_abs(num) < MT_EPSILON)
|
||||
@@ -126,9 +127,9 @@ static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
|
||||
// enforce limits at all then
|
||||
return MT_Vector3(0.0, tau, 1.0);
|
||||
|
||||
num = 1.0/sqrt(num);
|
||||
MT_Scalar ax = -R[2][1]*num;
|
||||
MT_Scalar az = R[0][1]*num;
|
||||
num = 1.0 / sqrt(num);
|
||||
MT_Scalar ax = -R[2][1] * num;
|
||||
MT_Scalar az = R[0][1] * num;
|
||||
|
||||
return MT_Vector3(ax, tau, az);
|
||||
}
|
||||
@@ -136,8 +137,8 @@ static MT_Vector3 SphericalRangeParameters(const MT_Matrix3x3& R)
|
||||
static MT_Matrix3x3 ComputeSwingMatrix(MT_Scalar ax, MT_Scalar az)
|
||||
{
|
||||
// length of (ax, 0, az) = sin(theta/2)
|
||||
MT_Scalar sine2 = ax*ax + az*az;
|
||||
MT_Scalar cosine2 = sqrt((sine2 >= 1.0)? 0.0: 1.0-sine2);
|
||||
MT_Scalar sine2 = ax * ax + az * az;
|
||||
MT_Scalar cosine2 = sqrt((sine2 >= 1.0) ? 0.0 : 1.0 - sine2);
|
||||
|
||||
// compute swing matrix
|
||||
MT_Matrix3x3 S(MT_Quaternion(ax, 0.0, az, -cosine2));
|
||||
@@ -151,11 +152,11 @@ static MT_Vector3 MatrixToAxisAngle(const MT_Matrix3x3& R)
|
||||
R[0][2] - R[2][0],
|
||||
R[1][0] - R[0][1]);
|
||||
|
||||
MT_Scalar c = safe_acos((R[0][0] + R[1][1] + R[2][2] - 1)/2);
|
||||
MT_Scalar c = safe_acos((R[0][0] + R[1][1] + R[2][2] - 1) / 2);
|
||||
MT_Scalar l = delta.length();
|
||||
|
||||
if (!MT_fuzzyZero(l))
|
||||
delta *= c/l;
|
||||
delta *= c / l;
|
||||
|
||||
return delta;
|
||||
}
|
||||
@@ -192,10 +193,10 @@ static bool EllipseClamp(MT_Scalar& ax, MT_Scalar& az, MT_Scalar *amin, MT_Scala
|
||||
z = zlim;
|
||||
}
|
||||
else {
|
||||
MT_Scalar invx = 1.0/(xlim*xlim);
|
||||
MT_Scalar invz = 1.0/(zlim*zlim);
|
||||
MT_Scalar invx = 1.0 / (xlim * xlim);
|
||||
MT_Scalar invz = 1.0 / (zlim * zlim);
|
||||
|
||||
if ((x*x*invx + z*z*invz) <= 1.0)
|
||||
if ((x * x * invx + z * z * invz) <= 1.0)
|
||||
return false;
|
||||
|
||||
if (MT_fuzzyZero(x)) {
|
||||
@@ -203,17 +204,17 @@ static bool EllipseClamp(MT_Scalar& ax, MT_Scalar& az, MT_Scalar *amin, MT_Scala
|
||||
z = zlim;
|
||||
}
|
||||
else {
|
||||
MT_Scalar rico = z/x;
|
||||
MT_Scalar rico = z / x;
|
||||
MT_Scalar old_x = x;
|
||||
x = sqrt(1.0/(invx + invz*rico*rico));
|
||||
x = sqrt(1.0 / (invx + invz * rico * rico));
|
||||
if (old_x < 0.0)
|
||||
x = -x;
|
||||
z = rico*x;
|
||||
z = rico * x;
|
||||
}
|
||||
}
|
||||
|
||||
ax = (ax < 0.0)? -x: x;
|
||||
az = (az < 0.0)? -z: z;
|
||||
ax = (ax < 0.0) ? -x : x;
|
||||
az = (az < 0.0) ? -z : z;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -221,8 +222,8 @@ static bool EllipseClamp(MT_Scalar& ax, MT_Scalar& az, MT_Scalar *amin, MT_Scala
|
||||
// IK_QSegment
|
||||
|
||||
IK_QSegment::IK_QSegment(int num_DoF, bool translational)
|
||||
: m_parent(NULL), m_child(NULL), m_sibling(NULL), m_composite(NULL),
|
||||
m_num_DoF(num_DoF), m_translational(translational)
|
||||
: m_parent(NULL), m_child(NULL), m_sibling(NULL), m_composite(NULL),
|
||||
m_num_DoF(num_DoF), m_translational(translational)
|
||||
{
|
||||
m_locked[0] = m_locked[1] = m_locked[2] = false;
|
||||
m_weight[0] = m_weight[1] = m_weight[2] = 1.0;
|
||||
@@ -251,11 +252,11 @@ void IK_QSegment::Reset()
|
||||
}
|
||||
|
||||
void IK_QSegment::SetTransform(
|
||||
const MT_Vector3& start,
|
||||
const MT_Matrix3x3& rest_basis,
|
||||
const MT_Matrix3x3& basis,
|
||||
const MT_Scalar length
|
||||
)
|
||||
const MT_Vector3& start,
|
||||
const MT_Matrix3x3& rest_basis,
|
||||
const MT_Matrix3x3& basis,
|
||||
const MT_Scalar length
|
||||
)
|
||||
{
|
||||
m_max_extension = start.length() + length;
|
||||
|
||||
@@ -271,7 +272,7 @@ void IK_QSegment::SetTransform(
|
||||
|
||||
MT_Matrix3x3 IK_QSegment::BasisChange() const
|
||||
{
|
||||
return m_orig_basis.transposed()*m_basis;
|
||||
return m_orig_basis.transposed() * m_basis;
|
||||
}
|
||||
|
||||
MT_Vector3 IK_QSegment::TranslationChange() const
|
||||
@@ -329,7 +330,7 @@ void IK_QSegment::RemoveChild(IK_QSegment *child)
|
||||
void IK_QSegment::UpdateTransform(const MT_Transform& global)
|
||||
{
|
||||
// compute the global transform at the end of the segment
|
||||
m_global_start = global.getOrigin() + global.getBasis()*m_start;
|
||||
m_global_start = global.getOrigin() + global.getBasis() * m_start;
|
||||
|
||||
m_global_transform.setOrigin(m_global_start);
|
||||
m_global_transform.setBasis(global.getBasis() * m_rest_basis * m_basis);
|
||||
@@ -345,7 +346,7 @@ void IK_QSegment::PrependBasis(const MT_Matrix3x3& mat)
|
||||
m_basis = m_rest_basis.inverse() * mat * m_rest_basis * m_basis;
|
||||
}
|
||||
|
||||
void IK_QSegment::Scale(float scale)
|
||||
void IK_QSegment::Scale(MT_Scalar scale)
|
||||
{
|
||||
m_start *= scale;
|
||||
m_translation *= scale;
|
||||
@@ -358,7 +359,7 @@ void IK_QSegment::Scale(float scale)
|
||||
// IK_QSphericalSegment
|
||||
|
||||
IK_QSphericalSegment::IK_QSphericalSegment()
|
||||
: IK_QSegment(3, false), m_limit_x(false), m_limit_y(false), m_limit_z(false)
|
||||
: IK_QSegment(3, false), m_limit_x(false), m_limit_y(false), m_limit_z(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -386,8 +387,8 @@ void IK_QSphericalSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
|
||||
lmin = MT_clamp(lmin, -MT_PI, MT_PI);
|
||||
lmax = MT_clamp(lmax, -MT_PI, MT_PI);
|
||||
|
||||
lmin = sin(lmin*0.5);
|
||||
lmax = sin(lmax*0.5);
|
||||
lmin = sin(lmin * 0.5);
|
||||
lmax = sin(lmax * 0.5);
|
||||
|
||||
if (axis == 0) {
|
||||
m_min[0] = -lmax;
|
||||
@@ -414,8 +415,8 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
|
||||
|
||||
MT_Vector3 dq;
|
||||
dq.x() = jacobian.AngleUpdate(m_DoF_id);
|
||||
dq.y() = jacobian.AngleUpdate(m_DoF_id+1);
|
||||
dq.z() = jacobian.AngleUpdate(m_DoF_id+2);
|
||||
dq.y() = jacobian.AngleUpdate(m_DoF_id + 1);
|
||||
dq.z() = jacobian.AngleUpdate(m_DoF_id + 2);
|
||||
|
||||
// Directly update the rotation matrix, with Rodrigues' rotation formula,
|
||||
// to avoid singularities and allow smooth integration.
|
||||
@@ -423,29 +424,29 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
|
||||
MT_Scalar theta = dq.length();
|
||||
|
||||
if (!MT_fuzzyZero(theta)) {
|
||||
MT_Vector3 w = dq*(1.0/theta);
|
||||
MT_Vector3 w = dq * (1.0 / theta);
|
||||
|
||||
MT_Scalar sine = sin(theta);
|
||||
MT_Scalar cosine = cos(theta);
|
||||
MT_Scalar cosineInv = 1-cosine;
|
||||
MT_Scalar cosineInv = 1 - cosine;
|
||||
|
||||
MT_Scalar xsine = w.x()*sine;
|
||||
MT_Scalar ysine = w.y()*sine;
|
||||
MT_Scalar zsine = w.z()*sine;
|
||||
MT_Scalar xsine = w.x() * sine;
|
||||
MT_Scalar ysine = w.y() * sine;
|
||||
MT_Scalar zsine = w.z() * sine;
|
||||
|
||||
MT_Scalar xxcosine = w.x()*w.x()*cosineInv;
|
||||
MT_Scalar xycosine = w.x()*w.y()*cosineInv;
|
||||
MT_Scalar xzcosine = w.x()*w.z()*cosineInv;
|
||||
MT_Scalar yycosine = w.y()*w.y()*cosineInv;
|
||||
MT_Scalar yzcosine = w.y()*w.z()*cosineInv;
|
||||
MT_Scalar zzcosine = w.z()*w.z()*cosineInv;
|
||||
MT_Scalar xxcosine = w.x() * w.x() * cosineInv;
|
||||
MT_Scalar xycosine = w.x() * w.y() * cosineInv;
|
||||
MT_Scalar xzcosine = w.x() * w.z() * cosineInv;
|
||||
MT_Scalar yycosine = w.y() * w.y() * cosineInv;
|
||||
MT_Scalar yzcosine = w.y() * w.z() * cosineInv;
|
||||
MT_Scalar zzcosine = w.z() * w.z() * cosineInv;
|
||||
|
||||
MT_Matrix3x3 M(
|
||||
cosine + xxcosine, -zsine + xycosine, ysine + xzcosine,
|
||||
zsine + xycosine, cosine + yycosine, -xsine + yzcosine,
|
||||
-ysine + xzcosine, xsine + yzcosine, cosine + zzcosine);
|
||||
cosine + xxcosine, -zsine + xycosine, ysine + xzcosine,
|
||||
zsine + xycosine, cosine + yycosine, -xsine + yzcosine,
|
||||
-ysine + xzcosine, xsine + yzcosine, cosine + zzcosine);
|
||||
|
||||
m_new_basis = m_basis*M;
|
||||
m_new_basis = m_basis * M;
|
||||
}
|
||||
else
|
||||
m_new_basis = m_basis;
|
||||
@@ -505,13 +506,13 @@ bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3&
|
||||
|
||||
if (clamp[0] == false && clamp[1] == false && clamp[2] == false) {
|
||||
if (m_locked[0] || m_locked[1] || m_locked[2])
|
||||
m_new_basis = ComputeSwingMatrix(ax, az)*ComputeTwistMatrix(ay);
|
||||
m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_new_basis = ComputeSwingMatrix(ax, az)*ComputeTwistMatrix(ay);
|
||||
m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
|
||||
|
||||
delta = MatrixToAxisAngle(m_basis.transposed()*m_new_basis);
|
||||
delta = MatrixToAxisAngle(m_basis.transposed() * m_new_basis);
|
||||
|
||||
if (!(m_locked[0] || m_locked[2]) && (clamp[0] || clamp[2])) {
|
||||
m_locked_ax = ax;
|
||||
@@ -528,12 +529,12 @@ void IK_QSphericalSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& del
|
||||
{
|
||||
if (dof == 1) {
|
||||
m_locked[1] = true;
|
||||
jacobian.Lock(m_DoF_id+1, delta[1]);
|
||||
jacobian.Lock(m_DoF_id + 1, delta[1]);
|
||||
}
|
||||
else {
|
||||
m_locked[0] = m_locked[2] = true;
|
||||
jacobian.Lock(m_DoF_id, delta[0]);
|
||||
jacobian.Lock(m_DoF_id+2, delta[2]);
|
||||
jacobian.Lock(m_DoF_id + 2, delta[2]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,14 +546,14 @@ void IK_QSphericalSegment::UpdateAngleApply()
|
||||
// IK_QNullSegment
|
||||
|
||||
IK_QNullSegment::IK_QNullSegment()
|
||||
: IK_QSegment(0, false)
|
||||
: IK_QSegment(0, false)
|
||||
{
|
||||
}
|
||||
|
||||
// IK_QRevoluteSegment
|
||||
|
||||
IK_QRevoluteSegment::IK_QRevoluteSegment(int axis)
|
||||
: IK_QSegment(1, false), m_axis(axis), m_angle(0.0), m_limit(false)
|
||||
: IK_QSegment(1, false), m_axis(axis), m_angle(0.0), m_limit(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -634,7 +635,7 @@ void IK_QRevoluteSegment::SetWeight(int axis, MT_Scalar weight)
|
||||
// IK_QSwingSegment
|
||||
|
||||
IK_QSwingSegment::IK_QSwingSegment()
|
||||
: IK_QSegment(2, false), m_limit_x(false), m_limit_z(false)
|
||||
: IK_QSegment(2, false), m_limit_x(false), m_limit_z(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -646,7 +647,7 @@ void IK_QSwingSegment::SetBasis(const MT_Matrix3x3& basis)
|
||||
|
||||
MT_Vector3 IK_QSwingSegment::Axis(int dof) const
|
||||
{
|
||||
return m_global_transform.getBasis().getColumn((dof==0)? 0: 2);
|
||||
return m_global_transform.getBasis().getColumn((dof == 0) ? 0 : 2);
|
||||
}
|
||||
|
||||
bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& delta, bool *clamp)
|
||||
@@ -657,7 +658,7 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
|
||||
MT_Vector3 dq;
|
||||
dq.x() = jacobian.AngleUpdate(m_DoF_id);
|
||||
dq.y() = 0.0;
|
||||
dq.z() = jacobian.AngleUpdate(m_DoF_id+1);
|
||||
dq.z() = jacobian.AngleUpdate(m_DoF_id + 1);
|
||||
|
||||
// Directly update the rotation matrix, with Rodrigues' rotation formula,
|
||||
// to avoid singularities and allow smooth integration.
|
||||
@@ -665,25 +666,25 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
|
||||
MT_Scalar theta = dq.length();
|
||||
|
||||
if (!MT_fuzzyZero(theta)) {
|
||||
MT_Vector3 w = dq*(1.0/theta);
|
||||
MT_Vector3 w = dq * (1.0 / theta);
|
||||
|
||||
MT_Scalar sine = sin(theta);
|
||||
MT_Scalar cosine = cos(theta);
|
||||
MT_Scalar cosineInv = 1-cosine;
|
||||
MT_Scalar cosineInv = 1 - cosine;
|
||||
|
||||
MT_Scalar xsine = w.x()*sine;
|
||||
MT_Scalar zsine = w.z()*sine;
|
||||
MT_Scalar xsine = w.x() * sine;
|
||||
MT_Scalar zsine = w.z() * sine;
|
||||
|
||||
MT_Scalar xxcosine = w.x()*w.x()*cosineInv;
|
||||
MT_Scalar xzcosine = w.x()*w.z()*cosineInv;
|
||||
MT_Scalar zzcosine = w.z()*w.z()*cosineInv;
|
||||
MT_Scalar xxcosine = w.x() * w.x() * cosineInv;
|
||||
MT_Scalar xzcosine = w.x() * w.z() * cosineInv;
|
||||
MT_Scalar zzcosine = w.z() * w.z() * cosineInv;
|
||||
|
||||
MT_Matrix3x3 M(
|
||||
cosine + xxcosine, -zsine, xzcosine,
|
||||
zsine, cosine, -xsine,
|
||||
xzcosine, xsine, cosine + zzcosine);
|
||||
cosine + xxcosine, -zsine, xzcosine,
|
||||
zsine, cosine, -xsine,
|
||||
xzcosine, xsine, cosine + zzcosine);
|
||||
|
||||
m_new_basis = m_basis*M;
|
||||
m_new_basis = m_basis * M;
|
||||
|
||||
RemoveTwist(m_new_basis);
|
||||
}
|
||||
@@ -731,7 +732,7 @@ bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
|
||||
|
||||
m_new_basis = ComputeSwingMatrix(ax, az);
|
||||
|
||||
delta = MatrixToAxisAngle(m_basis.transposed()*m_new_basis);
|
||||
delta = MatrixToAxisAngle(m_basis.transposed() * m_new_basis);
|
||||
delta[1] = delta[2]; delta[2] = 0.0;
|
||||
|
||||
return true;
|
||||
@@ -741,7 +742,7 @@ void IK_QSwingSegment::Lock(int, IK_QJacobian& jacobian, MT_Vector3& delta)
|
||||
{
|
||||
m_locked[0] = m_locked[1] = true;
|
||||
jacobian.Lock(m_DoF_id, delta[0]);
|
||||
jacobian.Lock(m_DoF_id+1, delta[1]);
|
||||
jacobian.Lock(m_DoF_id + 1, delta[1]);
|
||||
}
|
||||
|
||||
void IK_QSwingSegment::UpdateAngleApply()
|
||||
@@ -758,11 +759,11 @@ void IK_QSwingSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
|
||||
lmin = MT_clamp(lmin, -MT_PI, MT_PI);
|
||||
lmax = MT_clamp(lmax, -MT_PI, MT_PI);
|
||||
|
||||
lmin = sin(lmin*0.5);
|
||||
lmax = sin(lmax*0.5);
|
||||
lmin = sin(lmin * 0.5);
|
||||
lmax = sin(lmax * 0.5);
|
||||
|
||||
// put center of ellispe in the middle between min and max
|
||||
MT_Scalar offset = 0.5*(lmin + lmax);
|
||||
MT_Scalar offset = 0.5 * (lmin + lmax);
|
||||
//lmax = lmax - offset;
|
||||
|
||||
if (axis == 0) {
|
||||
@@ -794,8 +795,8 @@ void IK_QSwingSegment::SetWeight(int axis, MT_Scalar weight)
|
||||
// IK_QElbowSegment
|
||||
|
||||
IK_QElbowSegment::IK_QElbowSegment(int axis)
|
||||
: IK_QSegment(2, false), m_axis(axis), m_twist(0.0), m_angle(0.0),
|
||||
m_cos_twist(1.0), m_sin_twist(0.0), m_limit(false), m_limit_twist(false)
|
||||
: IK_QSegment(2, false), m_axis(axis), m_twist(0.0), m_angle(0.0),
|
||||
m_cos_twist(1.0), m_sin_twist(0.0), m_limit(false), m_limit_twist(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -807,7 +808,7 @@ void IK_QElbowSegment::SetBasis(const MT_Matrix3x3& basis)
|
||||
RemoveTwist(m_basis);
|
||||
m_angle = EulerAngleFromMatrix(basis, m_axis);
|
||||
|
||||
m_basis = RotationMatrix(m_angle, m_axis)*ComputeTwistMatrix(m_twist);
|
||||
m_basis = RotationMatrix(m_angle, m_axis) * ComputeTwistMatrix(m_twist);
|
||||
}
|
||||
|
||||
MT_Vector3 IK_QElbowSegment::Axis(int dof) const
|
||||
@@ -850,7 +851,7 @@ bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, MT_Vector3& del
|
||||
}
|
||||
|
||||
if (!m_locked[1]) {
|
||||
m_new_twist = m_twist + jacobian.AngleUpdate(m_DoF_id+1);
|
||||
m_new_twist = m_twist + jacobian.AngleUpdate(m_DoF_id + 1);
|
||||
|
||||
if (m_limit_twist) {
|
||||
if (m_new_twist > m_max_twist) {
|
||||
@@ -877,7 +878,7 @@ void IK_QElbowSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta)
|
||||
}
|
||||
else {
|
||||
m_locked[1] = true;
|
||||
jacobian.Lock(m_DoF_id+1, delta[1]);
|
||||
jacobian.Lock(m_DoF_id + 1, delta[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,7 +893,7 @@ void IK_QElbowSegment::UpdateAngleApply()
|
||||
MT_Matrix3x3 A = RotationMatrix(m_angle, m_axis);
|
||||
MT_Matrix3x3 T = RotationMatrix(m_sin_twist, m_cos_twist, 1);
|
||||
|
||||
m_basis = A*T;
|
||||
m_basis = A * T;
|
||||
}
|
||||
|
||||
void IK_QElbowSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
|
||||
@@ -927,7 +928,7 @@ void IK_QElbowSegment::SetWeight(int axis, MT_Scalar weight)
|
||||
// IK_QTranslateSegment
|
||||
|
||||
IK_QTranslateSegment::IK_QTranslateSegment(int axis1)
|
||||
: IK_QSegment(1, true)
|
||||
: IK_QSegment(1, true)
|
||||
{
|
||||
m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
|
||||
m_axis_enabled[axis1] = true;
|
||||
@@ -938,7 +939,7 @@ IK_QTranslateSegment::IK_QTranslateSegment(int axis1)
|
||||
}
|
||||
|
||||
IK_QTranslateSegment::IK_QTranslateSegment(int axis1, int axis2)
|
||||
: IK_QSegment(2, true)
|
||||
: IK_QSegment(2, true)
|
||||
{
|
||||
m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
|
||||
m_axis_enabled[axis1] = true;
|
||||
@@ -951,7 +952,7 @@ IK_QTranslateSegment::IK_QTranslateSegment(int axis1, int axis2)
|
||||
}
|
||||
|
||||
IK_QTranslateSegment::IK_QTranslateSegment()
|
||||
: IK_QSegment(3, true)
|
||||
: IK_QSegment(3, true)
|
||||
{
|
||||
m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = true;
|
||||
|
||||
@@ -1013,7 +1014,7 @@ void IK_QTranslateSegment::UpdateAngleApply()
|
||||
void IK_QTranslateSegment::Lock(int dof, IK_QJacobian& jacobian, MT_Vector3& delta)
|
||||
{
|
||||
m_locked[dof] = true;
|
||||
jacobian.Lock(m_DoF_id+dof, delta[dof]);
|
||||
jacobian.Lock(m_DoF_id + dof, delta[dof]);
|
||||
}
|
||||
|
||||
void IK_QTranslateSegment::SetWeight(int axis, MT_Scalar weight)
|
||||
@@ -1030,12 +1031,12 @@ void IK_QTranslateSegment::SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax)
|
||||
if (lmax < lmin)
|
||||
return;
|
||||
|
||||
m_min[axis]= lmin;
|
||||
m_max[axis]= lmax;
|
||||
m_limit[axis]= true;
|
||||
m_min[axis] = lmin;
|
||||
m_max[axis] = lmax;
|
||||
m_limit[axis] = true;
|
||||
}
|
||||
|
||||
void IK_QTranslateSegment::Scale(float scale)
|
||||
void IK_QTranslateSegment::Scale(MT_Scalar scale)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
void Reset();
|
||||
|
||||
// scale
|
||||
virtual void Scale(float scale);
|
||||
virtual void Scale(MT_Scalar scale);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -338,7 +338,7 @@ public:
|
||||
void SetWeight(int axis, MT_Scalar weight);
|
||||
void SetLimit(int axis, MT_Scalar lmin, MT_Scalar lmax);
|
||||
|
||||
void Scale(float scale);
|
||||
void Scale(MT_Scalar scale);
|
||||
|
||||
private:
|
||||
int m_axis[3];
|
||||
|
||||
@@ -36,11 +36,11 @@
|
||||
// IK_QTask
|
||||
|
||||
IK_QTask::IK_QTask(
|
||||
int size,
|
||||
bool primary,
|
||||
bool active,
|
||||
const IK_QSegment *segment
|
||||
) :
|
||||
int size,
|
||||
bool primary,
|
||||
bool active,
|
||||
const IK_QSegment *segment
|
||||
) :
|
||||
m_size(size), m_primary(primary), m_active(active), m_segment(segment),
|
||||
m_weight(1.0)
|
||||
{
|
||||
@@ -49,10 +49,10 @@ IK_QTask::IK_QTask(
|
||||
// IK_QPositionTask
|
||||
|
||||
IK_QPositionTask::IK_QPositionTask(
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Vector3& goal
|
||||
) :
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Vector3& goal
|
||||
) :
|
||||
IK_QTask(3, primary, true, segment), m_goal(goal)
|
||||
{
|
||||
// computing clamping length
|
||||
@@ -67,7 +67,7 @@ IK_QPositionTask::IK_QPositionTask(
|
||||
num++;
|
||||
}
|
||||
|
||||
m_clamp_length /= 2*num;
|
||||
m_clamp_length /= 2 * num;
|
||||
}
|
||||
|
||||
void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
@@ -79,9 +79,9 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
MT_Scalar length = d_pos.length();
|
||||
|
||||
if (length > m_clamp_length)
|
||||
d_pos = (m_clamp_length/length)*d_pos;
|
||||
d_pos = (m_clamp_length / length) * d_pos;
|
||||
|
||||
jacobian.SetBetas(m_id, m_size, m_weight*d_pos);
|
||||
jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
|
||||
|
||||
// compute derivatives
|
||||
int i;
|
||||
@@ -91,13 +91,13 @@ void IK_QPositionTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
MT_Vector3 p = seg->GlobalStart() - pos;
|
||||
|
||||
for (i = 0; i < seg->NumberOfDoF(); i++) {
|
||||
MT_Vector3 axis = seg->Axis(i)*m_weight;
|
||||
MT_Vector3 axis = seg->Axis(i) * m_weight;
|
||||
|
||||
if (seg->Translational())
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e2);
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2);
|
||||
else {
|
||||
MT_Vector3 pa = p.cross(axis);
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId()+i, pa, 1e0);
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,10 +113,10 @@ MT_Scalar IK_QPositionTask::Distance() const
|
||||
// IK_QOrientationTask
|
||||
|
||||
IK_QOrientationTask::IK_QOrientationTask(
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Matrix3x3& goal
|
||||
) :
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Matrix3x3& goal
|
||||
) :
|
||||
IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0)
|
||||
{
|
||||
}
|
||||
@@ -126,17 +126,17 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
// compute betas
|
||||
const MT_Matrix3x3& rot = m_segment->GlobalTransform().getBasis();
|
||||
|
||||
MT_Matrix3x3 d_rotm = m_goal*rot.transposed();
|
||||
MT_Matrix3x3 d_rotm = m_goal * rot.transposed();
|
||||
d_rotm.transpose();
|
||||
|
||||
MT_Vector3 d_rot;
|
||||
d_rot = -0.5*MT_Vector3(d_rotm[2][1] - d_rotm[1][2],
|
||||
d_rotm[0][2] - d_rotm[2][0],
|
||||
d_rotm[1][0] - d_rotm[0][1]);
|
||||
d_rot = -0.5 * MT_Vector3(d_rotm[2][1] - d_rotm[1][2],
|
||||
d_rotm[0][2] - d_rotm[2][0],
|
||||
d_rotm[1][0] - d_rotm[0][1]);
|
||||
|
||||
m_distance = d_rot.length();
|
||||
|
||||
jacobian.SetBetas(m_id, m_size, m_weight*d_rot);
|
||||
jacobian.SetBetas(m_id, m_size, m_weight * d_rot);
|
||||
|
||||
// compute derivatives
|
||||
int i;
|
||||
@@ -146,10 +146,10 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
for (i = 0; i < seg->NumberOfDoF(); i++) {
|
||||
|
||||
if (seg->Translational())
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId()+i, MT_Vector3(0, 0, 0), 1e2);
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId() + i, MT_Vector3(0, 0, 0), 1e2);
|
||||
else {
|
||||
MT_Vector3 axis = seg->Axis(i)*m_weight;
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId()+i, axis, 1e0);
|
||||
MT_Vector3 axis = seg->Axis(i) * m_weight;
|
||||
jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,15 +158,15 @@ void IK_QOrientationTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
// Note: implementation not finished!
|
||||
|
||||
IK_QCenterOfMassTask::IK_QCenterOfMassTask(
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Vector3& goal_center
|
||||
) :
|
||||
bool primary,
|
||||
const IK_QSegment *segment,
|
||||
const MT_Vector3& goal_center
|
||||
) :
|
||||
IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
|
||||
{
|
||||
m_total_mass_inv = ComputeTotalMass(m_segment);
|
||||
if (!MT_fuzzyZero(m_total_mass_inv))
|
||||
m_total_mass_inv = 1.0/m_total_mass_inv;
|
||||
m_total_mass_inv = 1.0 / m_total_mass_inv;
|
||||
}
|
||||
|
||||
MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
|
||||
@@ -182,7 +182,7 @@ MT_Scalar IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
|
||||
|
||||
MT_Vector3 IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
|
||||
{
|
||||
MT_Vector3 center = /*seg->Mass()**/segment->GlobalStart();
|
||||
MT_Vector3 center = /*seg->Mass()**/ segment->GlobalStart();
|
||||
|
||||
const IK_QSegment *seg;
|
||||
for (seg = segment->Child(); seg; seg = seg->Sibling())
|
||||
@@ -197,14 +197,14 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& c
|
||||
MT_Vector3 p = center - segment->GlobalStart();
|
||||
|
||||
for (i = 0; i < segment->NumberOfDoF(); i++) {
|
||||
MT_Vector3 axis = segment->Axis(i)*m_weight;
|
||||
axis *= /*segment->Mass()**/m_total_mass_inv;
|
||||
MT_Vector3 axis = segment->Axis(i) * m_weight;
|
||||
axis *= /*segment->Mass()**/ m_total_mass_inv;
|
||||
|
||||
if (segment->Translational())
|
||||
jacobian.SetDerivatives(m_id, segment->DoFId()+i, axis, 1e2);
|
||||
jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2);
|
||||
else {
|
||||
MT_Vector3 pa = axis.cross(p);
|
||||
jacobian.SetDerivatives(m_id, segment->DoFId()+i, pa, 1e0);
|
||||
jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian& jacobian, MT_Vector3& c
|
||||
|
||||
void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
{
|
||||
MT_Vector3 center = ComputeCenter(m_segment)*m_total_mass_inv;
|
||||
MT_Vector3 center = ComputeCenter(m_segment) * m_total_mass_inv;
|
||||
|
||||
// compute beta
|
||||
MT_Vector3 d_pos = m_goal_center - center;
|
||||
@@ -224,10 +224,10 @@ void IK_QCenterOfMassTask::ComputeJacobian(IK_QJacobian& jacobian)
|
||||
|
||||
#if 0
|
||||
if (m_distance > m_clamp_length)
|
||||
d_pos = (m_clamp_length/m_distance)*d_pos;
|
||||
d_pos = (m_clamp_length / m_distance) * d_pos;
|
||||
#endif
|
||||
|
||||
jacobian.SetBetas(m_id, m_size, m_weight*d_pos);
|
||||
jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
|
||||
|
||||
// compute derivatives
|
||||
JacobianSegment(jacobian, center, m_segment);
|
||||
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
|
||||
virtual bool PositionTask() const { return false; }
|
||||
|
||||
virtual void Scale(float) {}
|
||||
virtual void Scale(MT_Scalar) {}
|
||||
|
||||
protected:
|
||||
int m_id;
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
MT_Scalar Distance() const;
|
||||
|
||||
bool PositionTask() const { return true; }
|
||||
void Scale(float scale) { m_goal *= scale; m_clamp_length *= scale; }
|
||||
void Scale(MT_Scalar scale) { m_goal *= scale; m_clamp_length *= scale; }
|
||||
|
||||
private:
|
||||
MT_Vector3 m_goal;
|
||||
@@ -141,7 +141,7 @@ public:
|
||||
|
||||
MT_Scalar Distance() const;
|
||||
|
||||
void Scale(float scale) { m_goal_center *= scale; m_distance *= scale; }
|
||||
void Scale(MT_Scalar scale) { m_goal_center *= scale; m_distance *= scale; }
|
||||
|
||||
private:
|
||||
MT_Scalar ComputeTotalMass(const IK_QSegment *segment);
|
||||
|
||||
@@ -42,20 +42,21 @@ using namespace std;
|
||||
|
||||
class IK_QSolver {
|
||||
public:
|
||||
IK_QSolver() : root(NULL) {};
|
||||
IK_QSolver() : root(NULL) {
|
||||
};
|
||||
|
||||
IK_QJacobianSolver solver;
|
||||
IK_QSegment *root;
|
||||
std::list<IK_QTask*> tasks;
|
||||
std::list<IK_QTask *> tasks;
|
||||
};
|
||||
|
||||
// FIXME: locks still result in small "residual" changes to the locked axes...
|
||||
IK_QSegment *CreateSegment(int flag, bool translate)
|
||||
{
|
||||
int ndof = 0;
|
||||
ndof += (flag & IK_XDOF)? 1: 0;
|
||||
ndof += (flag & IK_YDOF)? 1: 0;
|
||||
ndof += (flag & IK_ZDOF)? 1: 0;
|
||||
ndof += (flag & IK_XDOF) ? 1 : 0;
|
||||
ndof += (flag & IK_YDOF) ? 1 : 0;
|
||||
ndof += (flag & IK_ZDOF) ? 1 : 0;
|
||||
|
||||
IK_QSegment *seg;
|
||||
|
||||
@@ -78,7 +79,7 @@ IK_QSegment *CreateSegment(int flag, bool translate)
|
||||
|
||||
if (flag & IK_XDOF) {
|
||||
axis1 = 0;
|
||||
axis2 = (flag & IK_YDOF)? 1: 2;
|
||||
axis2 = (flag & IK_YDOF) ? 1 : 2;
|
||||
}
|
||||
else {
|
||||
axis1 = 1;
|
||||
@@ -91,7 +92,7 @@ IK_QSegment *CreateSegment(int flag, bool translate)
|
||||
if (axis1 + axis2 == 2)
|
||||
seg = new IK_QSwingSegment();
|
||||
else
|
||||
seg = new IK_QElbowSegment((axis1 == 0)? 0: 2);
|
||||
seg = new IK_QElbowSegment((axis1 == 0) ? 0 : 2);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -131,7 +132,7 @@ IK_Segment *IK_CreateSegment(int flag)
|
||||
|
||||
void IK_FreeSegment(IK_Segment *seg)
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
|
||||
if (qseg->Composite())
|
||||
delete qseg->Composite();
|
||||
@@ -140,8 +141,8 @@ void IK_FreeSegment(IK_Segment *seg)
|
||||
|
||||
void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qparent = (IK_QSegment*)parent;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
IK_QSegment *qparent = (IK_QSegment *)parent;
|
||||
|
||||
if (qparent && qparent->Composite())
|
||||
qseg->SetParent(qparent->Composite());
|
||||
@@ -151,7 +152,7 @@ void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
|
||||
|
||||
void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float basis[][3], float length)
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
|
||||
MT_Vector3 mstart(start);
|
||||
// convert from blender column major to moto row major
|
||||
@@ -177,19 +178,19 @@ void IK_SetTransform(IK_Segment *seg, float start[3], float rest[][3], float bas
|
||||
|
||||
void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
|
||||
if (axis >= IK_TRANS_X) {
|
||||
if(!qseg->Translational()) {
|
||||
if(qseg->Composite() && qseg->Composite()->Translational())
|
||||
if (!qseg->Translational()) {
|
||||
if (qseg->Composite() && qseg->Composite()->Translational())
|
||||
qseg = qseg->Composite();
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if(axis == IK_TRANS_X) axis = IK_X;
|
||||
else if(axis == IK_TRANS_Y) axis = IK_Y;
|
||||
else axis = IK_Z;
|
||||
if (axis == IK_TRANS_X) axis = IK_X;
|
||||
else if (axis == IK_TRANS_Y) axis = IK_Y;
|
||||
else axis = IK_Z;
|
||||
}
|
||||
|
||||
qseg->SetLimit(axis, lmin, lmax);
|
||||
@@ -197,25 +198,25 @@ void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
|
||||
|
||||
void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
|
||||
{
|
||||
if (stiffness < 0.0)
|
||||
if (stiffness < 0.0f)
|
||||
return;
|
||||
|
||||
if (stiffness > 0.999)
|
||||
stiffness = 0.999;
|
||||
if (stiffness > (1.0 - IK_STRETCH_STIFF_EPS))
|
||||
stiffness = (1.0 - IK_STRETCH_STIFF_EPS);
|
||||
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
MT_Scalar weight = 1.0-stiffness;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
MT_Scalar weight = 1.0f - stiffness;
|
||||
|
||||
if (axis >= IK_TRANS_X) {
|
||||
if(!qseg->Translational()) {
|
||||
if(qseg->Composite() && qseg->Composite()->Translational())
|
||||
if (!qseg->Translational()) {
|
||||
if (qseg->Composite() && qseg->Composite()->Translational())
|
||||
qseg = qseg->Composite();
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
if(axis == IK_TRANS_X) axis = IK_X;
|
||||
else if(axis == IK_TRANS_Y) axis = IK_Y;
|
||||
if (axis == IK_TRANS_X) axis = IK_X;
|
||||
else if (axis == IK_TRANS_Y) axis = IK_Y;
|
||||
else axis = IK_Z;
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
|
||||
|
||||
void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
|
||||
if (qseg->Translational() && qseg->Composite())
|
||||
qseg = qseg->Composite();
|
||||
@@ -245,7 +246,7 @@ void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
|
||||
|
||||
void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
|
||||
{
|
||||
IK_QSegment *qseg = (IK_QSegment*)seg;
|
||||
IK_QSegment *qseg = (IK_QSegment *)seg;
|
||||
|
||||
if (!qseg->Translational() && qseg->Composite())
|
||||
qseg = qseg->Composite();
|
||||
@@ -263,9 +264,9 @@ IK_Solver *IK_CreateSolver(IK_Segment *root)
|
||||
return NULL;
|
||||
|
||||
IK_QSolver *solver = new IK_QSolver();
|
||||
solver->root = (IK_QSegment*)root;
|
||||
solver->root = (IK_QSegment *)root;
|
||||
|
||||
return (IK_Solver*)solver;
|
||||
return (IK_Solver *)solver;
|
||||
}
|
||||
|
||||
void IK_FreeSolver(IK_Solver *solver)
|
||||
@@ -273,9 +274,9 @@ void IK_FreeSolver(IK_Solver *solver)
|
||||
if (solver == NULL)
|
||||
return;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
std::list<IK_QTask*>& tasks = qsolver->tasks;
|
||||
std::list<IK_QTask*>::iterator task;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
std::list<IK_QTask *>& tasks = qsolver->tasks;
|
||||
std::list<IK_QTask *>::iterator task;
|
||||
|
||||
for (task = tasks.begin(); task != tasks.end(); task++)
|
||||
delete (*task);
|
||||
@@ -288,8 +289,8 @@ void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float w
|
||||
if (solver == NULL || tip == NULL)
|
||||
return;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment*)tip;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment *)tip;
|
||||
|
||||
if (qtip->Composite())
|
||||
qtip = qtip->Composite();
|
||||
@@ -306,8 +307,8 @@ void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[
|
||||
if (solver == NULL || tip == NULL)
|
||||
return;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment*)tip;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment *)tip;
|
||||
|
||||
if (qtip->Composite())
|
||||
qtip = qtip->Composite();
|
||||
@@ -327,14 +328,14 @@ void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float
|
||||
if (solver == NULL || tip == NULL)
|
||||
return;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment*)tip;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
IK_QSegment *qtip = (IK_QSegment *)tip;
|
||||
|
||||
MT_Vector3 qgoal(goal);
|
||||
MT_Vector3 qpolegoal(polegoal);
|
||||
|
||||
qsolver->solver.SetPoleVectorConstraint(
|
||||
qtip, qgoal, qpolegoal, poleangle, getangle);
|
||||
qtip, qgoal, qpolegoal, poleangle, getangle);
|
||||
}
|
||||
|
||||
float IK_SolverGetPoleAngle(IK_Solver *solver)
|
||||
@@ -342,7 +343,7 @@ float IK_SolverGetPoleAngle(IK_Solver *solver)
|
||||
if (solver == NULL)
|
||||
return 0.0f;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
|
||||
return qsolver->solver.GetPoleAngle();
|
||||
}
|
||||
@@ -352,8 +353,8 @@ void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3]
|
||||
if (solver == NULL || root == NULL)
|
||||
return;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSegment *qroot = (IK_QSegment*)root;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
IK_QSegment *qroot = (IK_QSegment *)root;
|
||||
|
||||
// convert from blender column major to moto row major
|
||||
MT_Vector3 center(goal);
|
||||
@@ -368,18 +369,18 @@ int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
|
||||
if (solver == NULL)
|
||||
return 0;
|
||||
|
||||
IK_QSolver *qsolver = (IK_QSolver*)solver;
|
||||
IK_QSolver *qsolver = (IK_QSolver *)solver;
|
||||
|
||||
IK_QSegment *root = qsolver->root;
|
||||
IK_QJacobianSolver& jacobian = qsolver->solver;
|
||||
std::list<IK_QTask*>& tasks = qsolver->tasks;
|
||||
std::list<IK_QTask *>& tasks = qsolver->tasks;
|
||||
MT_Scalar tol = tolerance;
|
||||
|
||||
if(!jacobian.Setup(root, tasks))
|
||||
if (!jacobian.Setup(root, tasks))
|
||||
return 0;
|
||||
|
||||
bool result = jacobian.Solve(root, tasks, tol, max_iterations);
|
||||
|
||||
return ((result)? 1: 0);
|
||||
return ((result) ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@
|
||||
* Set the exponential map from a quaternion. The quaternion must be non-zero.
|
||||
*/
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
setRotation(
|
||||
const MT_Quaternion &q
|
||||
) {
|
||||
const MT_Quaternion &q)
|
||||
{
|
||||
// ok first normalize the quaternion
|
||||
// then compute theta the axis-angle and the normalized axis v
|
||||
// scale v by theta and that's it hopefully!
|
||||
@@ -53,7 +53,7 @@ setRotation(
|
||||
m_sinp = m_v.length();
|
||||
m_v /= m_sinp;
|
||||
|
||||
m_theta = atan2(double(m_sinp),double(cosp));
|
||||
m_theta = atan2(double(m_sinp), double(cosp));
|
||||
m_v *= m_theta;
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ setRotation(
|
||||
* representation
|
||||
*/
|
||||
|
||||
const MT_Quaternion&
|
||||
const MT_Quaternion&
|
||||
MT_ExpMap::
|
||||
getRotation(
|
||||
) const {
|
||||
getRotation() const
|
||||
{
|
||||
return m_q;
|
||||
}
|
||||
|
||||
@@ -73,10 +73,10 @@ getRotation(
|
||||
* Convert the exponential map to a 3x3 matrix
|
||||
*/
|
||||
|
||||
MT_Matrix3x3
|
||||
MT_Matrix3x3
|
||||
MT_ExpMap::
|
||||
getMatrix(
|
||||
) const {
|
||||
getMatrix() const
|
||||
{
|
||||
return MT_Matrix3x3(m_q);
|
||||
}
|
||||
|
||||
@@ -84,11 +84,11 @@ getMatrix(
|
||||
* Update & reparameterizate the exponential map
|
||||
*/
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
update(
|
||||
const MT_Vector3& dv
|
||||
){
|
||||
const MT_Vector3& dv)
|
||||
{
|
||||
m_v += dv;
|
||||
|
||||
angleUpdated();
|
||||
@@ -100,14 +100,13 @@ update(
|
||||
* from the map) and return them as a 3x3 matrix
|
||||
*/
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
partialDerivatives(
|
||||
MT_Matrix3x3& dRdx,
|
||||
MT_Matrix3x3& dRdy,
|
||||
MT_Matrix3x3& dRdz
|
||||
) const {
|
||||
|
||||
MT_Matrix3x3& dRdx,
|
||||
MT_Matrix3x3& dRdy,
|
||||
MT_Matrix3x3& dRdz) const
|
||||
{
|
||||
MT_Quaternion dQdx[3];
|
||||
|
||||
compute_dQdVi(dQdx);
|
||||
@@ -117,29 +116,28 @@ partialDerivatives(
|
||||
compute_dRdVi(dQdx[2], dRdz);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
compute_dRdVi(
|
||||
const MT_Quaternion &dQdvi,
|
||||
MT_Matrix3x3 & dRdvi
|
||||
) const {
|
||||
|
||||
MT_Scalar prod[9];
|
||||
const MT_Quaternion &dQdvi,
|
||||
MT_Matrix3x3 & 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)*m_q.x()*dQdvi.x();
|
||||
prod[1] = -MT_Scalar(4)*m_q.y()*dQdvi.y();
|
||||
prod[2] = -MT_Scalar(4)*m_q.z()*dQdvi.z();
|
||||
prod[3] = MT_Scalar(2)*(m_q.y()*dQdvi.x() + m_q.x()*dQdvi.y());
|
||||
prod[4] = MT_Scalar(2)*(m_q.w()*dQdvi.z() + m_q.z()*dQdvi.w());
|
||||
prod[5] = MT_Scalar(2)*(m_q.z()*dQdvi.x() + m_q.x()*dQdvi.z());
|
||||
prod[6] = MT_Scalar(2)*(m_q.w()*dQdvi.y() + m_q.y()*dQdvi.w());
|
||||
prod[7] = MT_Scalar(2)*(m_q.z()*dQdvi.y() + m_q.y()*dQdvi.z());
|
||||
prod[8] = MT_Scalar(2)*(m_q.w()*dQdvi.x() + m_q.x()*dQdvi.w());
|
||||
prod[0] = -MT_Scalar(4) * m_q.x() * dQdvi.x();
|
||||
prod[1] = -MT_Scalar(4) * m_q.y() * dQdvi.y();
|
||||
prod[2] = -MT_Scalar(4) * m_q.z() * dQdvi.z();
|
||||
prod[3] = MT_Scalar(2) * (m_q.y() * dQdvi.x() + m_q.x() * dQdvi.y());
|
||||
prod[4] = MT_Scalar(2) * (m_q.w() * dQdvi.z() + m_q.z() * dQdvi.w());
|
||||
prod[5] = MT_Scalar(2) * (m_q.z() * dQdvi.x() + m_q.x() * dQdvi.z());
|
||||
prod[6] = MT_Scalar(2) * (m_q.w() * dQdvi.y() + m_q.y() * dQdvi.w());
|
||||
prod[7] = MT_Scalar(2) * (m_q.z() * dQdvi.y() + m_q.y() * dQdvi.z());
|
||||
prod[8] = MT_Scalar(2) * (m_q.w() * dQdvi.x() + m_q.x() * dQdvi.w());
|
||||
|
||||
/* first row, followed by second and third */
|
||||
dRdvi[0][0] = prod[1] + prod[2];
|
||||
@@ -157,61 +155,60 @@ compute_dRdVi(
|
||||
|
||||
// compute partial derivatives dQ/dVi
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
compute_dQdVi(
|
||||
MT_Quaternion *dQdX
|
||||
) const {
|
||||
|
||||
MT_Quaternion *dQdX) const
|
||||
{
|
||||
/* This is an efficient implementation of the derivatives given
|
||||
* in Appendix A of the paper with common subexpressions factored out */
|
||||
|
||||
MT_Scalar sinc, termCoeff;
|
||||
|
||||
if (m_theta < MT_EXPMAP_MINANGLE) {
|
||||
sinc = 0.5 - m_theta*m_theta/48.0;
|
||||
termCoeff = (m_theta*m_theta/40.0 - 1.0)/24.0;
|
||||
sinc = 0.5 - m_theta * m_theta / 48.0;
|
||||
termCoeff = (m_theta * m_theta / 40.0 - 1.0) / 24.0;
|
||||
}
|
||||
else {
|
||||
MT_Scalar cosp = m_q.w();
|
||||
MT_Scalar ang = 1.0/m_theta;
|
||||
MT_Scalar ang = 1.0 / m_theta;
|
||||
|
||||
sinc = m_sinp*ang;
|
||||
termCoeff = ang*ang*(0.5*cosp - sinc);
|
||||
sinc = m_sinp * ang;
|
||||
termCoeff = ang * ang * (0.5 * cosp - sinc);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
MT_Quaternion& dQdx = dQdX[i];
|
||||
int i2 = (i+1)%3;
|
||||
int i3 = (i+2)%3;
|
||||
int i2 = (i + 1) % 3;
|
||||
int i3 = (i + 2) % 3;
|
||||
|
||||
MT_Scalar term = m_v[i]*termCoeff;
|
||||
MT_Scalar term = m_v[i] * termCoeff;
|
||||
|
||||
dQdx[i] = term*m_v[i] + sinc;
|
||||
dQdx[i2] = term*m_v[i2];
|
||||
dQdx[i3] = term*m_v[i3];
|
||||
dQdx.w() = -0.5*m_v[i]*sinc;
|
||||
dQdx[i] = term * m_v[i] + sinc;
|
||||
dQdx[i2] = term * m_v[i2];
|
||||
dQdx[i3] = term * m_v[i3];
|
||||
dQdx.w() = -0.5 * m_v[i] * sinc;
|
||||
}
|
||||
}
|
||||
|
||||
// reParametize away from singularity, updating
|
||||
// m_v and m_theta
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
reParametrize(
|
||||
){
|
||||
reParametrize()
|
||||
{
|
||||
if (m_theta > MT_PI) {
|
||||
MT_Scalar scl = m_theta;
|
||||
if (m_theta > MT_2_PI){ /* first get theta into range 0..2PI */
|
||||
if (m_theta > MT_2_PI) { /* first get theta into range 0..2PI */
|
||||
m_theta = MT_Scalar(fmod(m_theta, MT_2_PI));
|
||||
scl = m_theta/scl;
|
||||
scl = m_theta / scl;
|
||||
m_v *= scl;
|
||||
}
|
||||
if (m_theta > MT_PI){
|
||||
if (m_theta > MT_PI) {
|
||||
scl = m_theta;
|
||||
m_theta = MT_2_PI - m_theta;
|
||||
scl = MT_Scalar(1.0) - MT_2_PI/scl;
|
||||
scl = MT_Scalar(1.0) - MT_2_PI / scl;
|
||||
m_v *= scl;
|
||||
}
|
||||
}
|
||||
@@ -219,10 +216,10 @@ reParametrize(
|
||||
|
||||
// compute cached variables
|
||||
|
||||
void
|
||||
void
|
||||
MT_ExpMap::
|
||||
angleUpdated(
|
||||
){
|
||||
angleUpdated()
|
||||
{
|
||||
m_theta = m_v.length();
|
||||
|
||||
reParametrize();
|
||||
@@ -233,20 +230,21 @@ angleUpdated(
|
||||
m_sinp = MT_Scalar(0.0);
|
||||
|
||||
/* Taylor Series for sinc */
|
||||
MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - m_theta*m_theta/MT_Scalar(48.0));
|
||||
MT_Vector3 temp = m_v * MT_Scalar(MT_Scalar(.5) - m_theta * m_theta / MT_Scalar(48.0));
|
||||
m_q.x() = temp.x();
|
||||
m_q.y() = temp.y();
|
||||
m_q.z() = temp.z();
|
||||
m_q.w() = MT_Scalar(1.0);
|
||||
} else {
|
||||
m_sinp = MT_Scalar(sin(.5*m_theta));
|
||||
}
|
||||
else {
|
||||
m_sinp = MT_Scalar(sin(.5 * m_theta));
|
||||
|
||||
/* Taylor Series for sinc */
|
||||
MT_Vector3 temp = m_v * (m_sinp/m_theta);
|
||||
MT_Vector3 temp = m_v * (m_sinp / m_theta);
|
||||
m_q.x() = temp.x();
|
||||
m_q.y() = temp.y();
|
||||
m_q.z() = temp.z();
|
||||
m_q.w() = MT_Scalar(cos(.5*m_theta));
|
||||
m_q.w() = MT_Scalar(cos(0.5 * m_theta));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
#endif
|
||||
|
||||
|
||||
// this is needed for inlining behavior
|
||||
#if defined _WIN32
|
||||
# define DO_INLINE __inline
|
||||
#elif defined (__sun) || defined (__sun__)
|
||||
# define DO_INLINE
|
||||
#else
|
||||
# define DO_INLINE static inline
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Sort all the edges of the input polygon by Y, then by X, of the "first" vertex encountered.
|
||||
@@ -814,14 +823,14 @@ int get_range_expanded_pixel_coord(float normalized_value, int max_value) {
|
||||
return (int)((normalized_value * (float)(max_value)) + 0.5f);
|
||||
}
|
||||
|
||||
__inline float get_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y) {
|
||||
DO_INLINE float get_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y) {
|
||||
if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
|
||||
return 0.0f;
|
||||
}
|
||||
return buf[(pos_y * buf_x) + pos_x];
|
||||
}
|
||||
|
||||
__inline float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) {
|
||||
DO_INLINE float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, float u, float v) {
|
||||
int a;
|
||||
int b;
|
||||
int a_plus_1;
|
||||
@@ -847,7 +856,7 @@ __inline float get_pixel_intensity_bilinear(float *buf, int buf_x, int buf_y, fl
|
||||
|
||||
}
|
||||
|
||||
__inline void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) {
|
||||
DO_INLINE void set_pixel_intensity(float *buf, int buf_x, int buf_y, int pos_x, int pos_y, float intensity) {
|
||||
if(pos_x < 0 || pos_x >= buf_x || pos_y < 0 || pos_y >= buf_y) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -171,6 +171,7 @@ MaskLayer *BKE_mask_layer_new(Mask *mask, const char *name)
|
||||
|
||||
mask->masklay_tot++;
|
||||
|
||||
masklay->blend = MASK_BLEND_MERGE;
|
||||
masklay->alpha = 1.0f;
|
||||
|
||||
return masklay;
|
||||
|
||||
@@ -1251,6 +1251,9 @@ float BKE_maskrasterize_handle_sample(MaskRasterHandle *mr_handle, const float x
|
||||
}
|
||||
|
||||
switch (layer->blend) {
|
||||
case MASK_BLEND_MERGE:
|
||||
value += value_layer * (1.0f - value);
|
||||
break;
|
||||
case MASK_BLEND_ADD:
|
||||
value += value_layer;
|
||||
break;
|
||||
|
||||
@@ -505,7 +505,9 @@ static void movieclip_load_get_szie(MovieClip *clip)
|
||||
if (width && height) {
|
||||
clip->tracking.camera.principal[0] = ((float)width) / 2.0f;
|
||||
clip->tracking.camera.principal[1] = ((float)height) / 2.0f;
|
||||
|
||||
}
|
||||
else {
|
||||
clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1080,7 +1082,7 @@ void BKE_movieclip_reload(MovieClip *clip)
|
||||
else
|
||||
clip->source = MCLIP_SRC_SEQUENCE;
|
||||
|
||||
clip->lastsize[0] = clip->lastsize[1] = IMG_SIZE_FALLBACK;
|
||||
clip->lastsize[0] = clip->lastsize[1] = 0;
|
||||
movieclip_load_get_szie(clip);
|
||||
|
||||
movieclip_calc_length(clip);
|
||||
|
||||
@@ -104,6 +104,9 @@ static BMOpDefine bmo_smooth_vert_def = {
|
||||
{BMO_OP_SLOT_BOOL, "mirror_clip_y"}, /* set vertices close to the y axis before the operation to 0 */
|
||||
{BMO_OP_SLOT_BOOL, "mirror_clip_z"}, /* set vertices close to the z axis before the operation to 0 */
|
||||
{BMO_OP_SLOT_FLT, "clipdist"}, /* clipping threshod for the above three slots */
|
||||
{BMO_OP_SLOT_BOOL, "use_axis_x"}, /* smooth vertices along X axis */
|
||||
{BMO_OP_SLOT_BOOL, "use_axis_y"}, /* smooth vertices along Y axis */
|
||||
{BMO_OP_SLOT_BOOL, "use_axis_z"}, /* smooth vertices along Z axis */
|
||||
{0} /* null-terminating sentinel */,
|
||||
},
|
||||
bmo_smooth_vert_exec,
|
||||
|
||||
@@ -413,11 +413,16 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op)
|
||||
float (*cos)[3] = NULL;
|
||||
float *co, *co2, clipdist = BMO_slot_float_get(op, "clipdist");
|
||||
int i, j, clipx, clipy, clipz;
|
||||
int xaxis, yaxis, zaxis;
|
||||
|
||||
clipx = BMO_slot_bool_get(op, "mirror_clip_x");
|
||||
clipy = BMO_slot_bool_get(op, "mirror_clip_y");
|
||||
clipz = BMO_slot_bool_get(op, "mirror_clip_z");
|
||||
|
||||
xaxis = BMO_slot_bool_get(op, "use_axis_x");
|
||||
yaxis = BMO_slot_bool_get(op, "use_axis_y");
|
||||
zaxis = BMO_slot_bool_get(op, "use_axis_z");
|
||||
|
||||
i = 0;
|
||||
BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
|
||||
BLI_array_grow_one(cos);
|
||||
@@ -451,7 +456,13 @@ void bmo_smooth_vert_exec(BMesh *bm, BMOperator *op)
|
||||
|
||||
i = 0;
|
||||
BMO_ITER (v, &siter, bm, op, "verts", BM_VERT) {
|
||||
copy_v3_v3(v->co, cos[i]);
|
||||
if (xaxis)
|
||||
v->co[0] = cos[i][0];
|
||||
if (yaxis)
|
||||
v->co[1] = cos[i][1];
|
||||
if (zaxis)
|
||||
v->co[2] = cos[i][2];
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
|
||||
break;
|
||||
|
||||
case CMP_SCALE_RENDERPERCENT: {
|
||||
const RenderData *data = context->getRenderData();
|
||||
const RenderData *rd = context->getRenderData();
|
||||
ScaleFixedSizeOperation *operation = new ScaleFixedSizeOperation();
|
||||
|
||||
/* framing options */
|
||||
@@ -72,8 +72,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c
|
||||
operation->setIsCrop((bnode->custom2 & CMP_SCALE_RENDERSIZE_FRAME_CROP) != 0);
|
||||
operation->setOffset(bnode->custom3, bnode->custom4);
|
||||
|
||||
operation->setNewWidth(data->xsch * data->size / 100.0f);
|
||||
operation->setNewHeight(data->ysch * data->size / 100.0f);
|
||||
operation->setNewWidth(rd->xsch * rd->size / 100.0f);
|
||||
operation->setNewHeight(rd->ysch * rd->size / 100.0f);
|
||||
inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph);
|
||||
outputSocket->relinkConnections(operation->getOutputSocket(0));
|
||||
operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true);
|
||||
|
||||
@@ -39,7 +39,6 @@ struct Main;
|
||||
struct Mask;
|
||||
struct MovieClip;
|
||||
struct SpaceClip;
|
||||
struct wmEvent;
|
||||
|
||||
/* ** clip_editor.c ** */
|
||||
|
||||
@@ -69,7 +68,7 @@ int ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, int fit
|
||||
void ED_clip_point_undistorted_pos(struct SpaceClip *sc, const float co[2], float r_co[2]);
|
||||
void ED_clip_point_stable_pos(struct SpaceClip *sc, struct ARegion *ar, float x, float y, float *xr, float *yr);
|
||||
void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc, struct ARegion *ar, const float co[2], float r_co[2]);
|
||||
void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, struct wmEvent *event, float co[2]);
|
||||
void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, const int mval[2], float co[2]);
|
||||
|
||||
int ED_space_clip_check_show_trackedit(struct SpaceClip *sc);
|
||||
int ED_space_clip_check_show_maskedit(struct SpaceClip *sc);
|
||||
|
||||
@@ -39,7 +39,6 @@ struct ToolSettings;
|
||||
struct uiBlock;
|
||||
struct wmWindowManager;
|
||||
struct ARegion;
|
||||
struct wmEvent;
|
||||
|
||||
/* image_edit.c, exported for transform */
|
||||
struct Image *ED_space_image(struct SpaceImage *sima);
|
||||
@@ -63,7 +62,7 @@ void ED_space_image_uv_sculpt_update(struct wmWindowManager *wm, struct ToolSett
|
||||
void ED_image_get_size(struct Image *ima, int *width, int *height);
|
||||
void ED_image_get_aspect(struct Image *ima, float *aspx, float *aspy);
|
||||
void ED_image_get_uv_aspect(struct Image *ima, float *aspx, float *aspy);
|
||||
void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, struct wmEvent *event, float co[2]);
|
||||
void ED_image_mouse_pos(struct SpaceImage *sima, struct ARegion *ar, const int mval[2], float co[2]);
|
||||
void ED_image_point_pos(struct SpaceImage *sima, struct ARegion *ar, float x, float y, float *xr, float *yr);
|
||||
void ED_image_point_pos__reverse(struct SpaceImage *sima, struct ARegion *ar, const float co[2], float r_co[2]);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ void ED_mask_zoom(struct ScrArea *sa, struct ARegion *ar, float *zoomx, float *z
|
||||
void ED_mask_get_aspect(struct ScrArea *sa, struct ARegion *ar, float *aspx, float *aspy);
|
||||
|
||||
void ED_mask_pixelspace_factor(struct ScrArea *sa, struct ARegion *ar, float *scalex, float *scaley);
|
||||
void ED_mask_mouse_pos(struct ScrArea *sa, struct ARegion *ar, struct wmEvent *event, float co[2]);
|
||||
void ED_mask_mouse_pos(struct ScrArea *sa, struct ARegion *ar, const int mval[2], float co[2]);
|
||||
|
||||
void ED_mask_point_pos(struct ScrArea *sa, struct ARegion *ar, float x, float y, float *xr, float *yr);
|
||||
void ED_mask_point_pos__reverse(struct ScrArea *sa, struct ARegion *ar,
|
||||
|
||||
@@ -621,7 +621,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
float co[2];
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
|
||||
RNA_float_set_array(op->ptr, "location", co);
|
||||
|
||||
@@ -695,7 +695,7 @@ static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event
|
||||
|
||||
float co[2];
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
|
||||
RNA_float_set_array(op->ptr, "location", co);
|
||||
|
||||
|
||||
@@ -90,20 +90,21 @@ int ED_maskedit_mask_poll(bContext *C)
|
||||
|
||||
/********************** registration *********************/
|
||||
|
||||
void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, wmEvent *event, float co[2])
|
||||
/* takes event->mval */
|
||||
void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, const int mval[2], float co[2])
|
||||
{
|
||||
if (sa) {
|
||||
switch (sa->spacetype) {
|
||||
case SPACE_CLIP:
|
||||
{
|
||||
SpaceClip *sc = sa->spacedata.first;
|
||||
ED_clip_mouse_pos(sc, ar, event, co);
|
||||
ED_clip_mouse_pos(sc, ar, mval, co);
|
||||
BKE_mask_coord_from_movieclip(sc->clip, &sc->user, co, co);
|
||||
break;
|
||||
}
|
||||
case SPACE_SEQ:
|
||||
{
|
||||
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &co[0], &co[1]);
|
||||
break;
|
||||
}
|
||||
case SPACE_IMAGE:
|
||||
@@ -111,7 +112,7 @@ void ED_mask_mouse_pos(ScrArea *sa, ARegion *ar, wmEvent *event, float co[2])
|
||||
float frame_size[2];
|
||||
SpaceImage *sima = sa->spacedata.first;
|
||||
ED_space_image_get_size_fl(sima, frame_size);
|
||||
ED_image_mouse_pos(sima, ar, event, co);
|
||||
ED_image_mouse_pos(sima, ar, mval, co);
|
||||
BKE_mask_coord_from_frame(co, co, frame_size);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
|
||||
float co[2], cv_score, feather_score;
|
||||
const float threshold = 19;
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
ED_mask_get_size(sa, &width, &height);
|
||||
|
||||
cv_point = ED_mask_point_find_nearest(C, mask, co, threshold, &cv_masklay, &cv_spline, &is_handle, &cv_score);
|
||||
@@ -511,7 +511,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event)
|
||||
copy_m3_m3(customdata->vec, point->bezt.vec);
|
||||
if (BKE_mask_point_has_handle(point))
|
||||
BKE_mask_point_handle(point, customdata->handle);
|
||||
ED_mask_mouse_pos(sa, ar, event, customdata->co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, customdata->co);
|
||||
}
|
||||
|
||||
return customdata;
|
||||
@@ -652,7 +652,7 @@ static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event)
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
sub_v2_v2v2(dco, co, data->co);
|
||||
|
||||
if (data->action == SLIDE_ACTION_HANDLE) {
|
||||
|
||||
@@ -348,7 +348,7 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
float co[2];
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
|
||||
RNA_float_set_array(op->ptr, "location", co);
|
||||
|
||||
@@ -688,7 +688,7 @@ static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *
|
||||
const float threshold = 19;
|
||||
int change = FALSE;
|
||||
|
||||
ED_mask_mouse_pos(sa, ar, event, co);
|
||||
ED_mask_mouse_pos(sa, ar, event->mval, co);
|
||||
|
||||
point = ED_mask_point_find_nearest(C, mask, co, threshold, &masklay, &spline, &is_handle, NULL);
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ typedef struct KnifeColors {
|
||||
typedef struct KnifeVert {
|
||||
BMVert *v; /* non-NULL if this is an original vert */
|
||||
ListBase edges;
|
||||
ListBase faces;
|
||||
|
||||
float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */
|
||||
short flag, draw, isface, inspace;
|
||||
@@ -277,6 +278,32 @@ static void knife_add_to_vert_edges(KnifeTool_OpData *kcd, KnifeEdge *kfe)
|
||||
knife_append_list(kcd, &kfe->v2->edges, kfe);
|
||||
}
|
||||
|
||||
/* Add faces of an edge to a KnifeVert's faces list. No checks for dups. */
|
||||
static void knife_add_edge_faces_to_vert(KnifeTool_OpData *kcd, KnifeVert *kfv, BMEdge *e)
|
||||
{
|
||||
BMIter bmiter;
|
||||
BMFace *f;
|
||||
|
||||
BM_ITER_ELEM(f, &bmiter, e, BM_FACES_OF_EDGE) {
|
||||
knife_append_list(kcd, &kfv->faces, f);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find a face in common in the two faces lists.
|
||||
If more than one, return the first; if none, return NULL */
|
||||
static BMFace* knife_find_common_face(ListBase *faces1, ListBase *faces2)
|
||||
{
|
||||
Ref *ref1, *ref2;
|
||||
|
||||
for (ref1 = faces1->first; ref1; ref1 = ref1->next) {
|
||||
for (ref2 = faces2->first; ref2; ref2 = ref2->next) {
|
||||
if (ref1->ref == ref2->ref)
|
||||
return (BMFace*)(ref1->ref);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], float *cageco)
|
||||
{
|
||||
KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
|
||||
@@ -298,9 +325,15 @@ static KnifeVert *get_bm_knife_vert(KnifeTool_OpData *kcd, BMVert *v)
|
||||
KnifeVert *kfv = BLI_ghash_lookup(kcd->origvertmap, v);
|
||||
|
||||
if (!kfv) {
|
||||
BMIter bmiter;
|
||||
BMFace *f;
|
||||
|
||||
kfv = new_knife_vert(kcd, v->co, kcd->cagecos[BM_elem_index_get(v)]);
|
||||
kfv->v = v;
|
||||
BLI_ghash_insert(kcd->origvertmap, v, kfv);
|
||||
BM_ITER_ELEM(f, &bmiter, v, BM_FACES_OF_VERT) {
|
||||
knife_append_list(kcd, &kfv->faces, f);
|
||||
}
|
||||
}
|
||||
|
||||
return kfv;
|
||||
@@ -389,35 +422,9 @@ static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f)
|
||||
}
|
||||
|
||||
/* finds the proper face to restrict face fill to */
|
||||
static void knife_find_basef(KnifeTool_OpData *kcd, KnifeEdge *kfe)
|
||||
static void knife_find_basef(KnifeEdge *kfe)
|
||||
{
|
||||
if (!kfe->basef) {
|
||||
Ref *r1, *r2, *r3, *r4;
|
||||
|
||||
if (kfe->v1->isface || kfe->v2->isface) {
|
||||
if (kfe->v2->isface)
|
||||
kfe->basef = kcd->cur.bmface;
|
||||
else
|
||||
kfe->basef = kcd->prev.bmface;
|
||||
}
|
||||
else {
|
||||
for (r1 = kfe->v1->edges.first; r1 && !kfe->basef; r1 = r1->next) {
|
||||
KnifeEdge *ke1 = r1->ref;
|
||||
for (r2 = ke1->faces.first; r2 && !kfe->basef; r2 = r2->next) {
|
||||
for (r3 = kfe->v2->edges.first; r3 && !kfe->basef; r3 = r3->next) {
|
||||
KnifeEdge *ke2 = r3->ref;
|
||||
|
||||
for (r4 = ke2->faces.first; r4 && !kfe->basef; r4 = r4->next) {
|
||||
if (r2->ref == r4->ref) {
|
||||
kfe->basef = r2->ref;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ok, at this point kfe->basef should be set if any valid possibility exists */
|
||||
}
|
||||
kfe->basef = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
|
||||
}
|
||||
|
||||
static void knife_edge_append_face(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMFace *f)
|
||||
@@ -430,6 +437,7 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float
|
||||
{
|
||||
KnifeEdge *newkfe = new_knife_edge(kcd);
|
||||
Ref *ref;
|
||||
BMFace *f;
|
||||
float perc, cageco[3], l12;
|
||||
|
||||
l12 = len_v3v3(kfe->v1->co, kfe->v2->co);
|
||||
@@ -444,6 +452,16 @@ static KnifeVert *knife_split_edge(KnifeTool_OpData *kcd, KnifeEdge *kfe, float
|
||||
newkfe->v1 = kfe->v1;
|
||||
newkfe->v2 = new_knife_vert(kcd, co, cageco);
|
||||
newkfe->v2->draw = 1;
|
||||
if (kfe->e) {
|
||||
knife_add_edge_faces_to_vert(kcd, newkfe->v2, kfe->e);
|
||||
} else {
|
||||
/* kfe cuts across an existing face.
|
||||
If v1 and v2 are in multiple faces together (e.g., if they
|
||||
are in doubled polys) then this arbitrarily chooses one of them */
|
||||
f = knife_find_common_face(&kfe->v1->faces, &kfe->v2->faces);
|
||||
if (f)
|
||||
knife_append_list(kcd, &newkfe->v2->faces, f);
|
||||
}
|
||||
newkfe->basef = kfe->basef;
|
||||
|
||||
ref = find_ref(&kfe->v1->edges, kfe);
|
||||
@@ -490,6 +508,8 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
|
||||
kfe->v1->inspace = kcd->prev.is_space;
|
||||
kfe->draw = !kcd->prev.is_space;
|
||||
kfe->v1->isface = 1;
|
||||
if (kfe->v1->draw && kcd->prev.bmface)
|
||||
knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface);
|
||||
}
|
||||
|
||||
if (kcd->cur.vert) {
|
||||
@@ -504,6 +524,8 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
|
||||
kfe->v2->draw = !kcd->cur.is_space;
|
||||
kfe->v2->isface = 1;
|
||||
kfe->v2->inspace = kcd->cur.is_space;
|
||||
if (kfe->v2->draw && kcd->cur.bmface)
|
||||
knife_append_list(kcd, &kfe->v2->faces, kcd->cur.bmface);
|
||||
|
||||
if (kcd->cur.is_space)
|
||||
kfe->draw = 0;
|
||||
@@ -511,7 +533,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd)
|
||||
kcd->cur.vert = kfe->v2;
|
||||
}
|
||||
|
||||
knife_find_basef(kcd, kfe);
|
||||
knife_find_basef(kfe);
|
||||
|
||||
knife_add_to_vert_edges(kcd, kfe);
|
||||
|
||||
@@ -716,6 +738,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd)
|
||||
BMEdgeHit *lh, *lastlh, *firstlh;
|
||||
int i;
|
||||
|
||||
/* TODO: not a stable sort! need to figure out what to do for equal lambdas */
|
||||
qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit);
|
||||
|
||||
lh = kcd->linehits;
|
||||
@@ -1153,7 +1176,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree,
|
||||
hit.kfe = kfe;
|
||||
hit.v = NULL;
|
||||
|
||||
knife_find_basef(kcd, kfe);
|
||||
knife_find_basef(kfe);
|
||||
hit.f = kfe->basef;
|
||||
hit.perc = len_v3v3(p, kfe->v1->cageco) / len_v3v3(kfe->v1->cageco, kfe->v2->cageco);
|
||||
copy_v3_v3(hit.cagehit, p);
|
||||
|
||||
@@ -1533,6 +1533,10 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
|
||||
int i, repeat;
|
||||
float clipdist = 0.0f;
|
||||
|
||||
int xaxis = RNA_boolean_get(op->ptr, "xaxis");
|
||||
int yaxis = RNA_boolean_get(op->ptr, "yaxis");
|
||||
int zaxis = RNA_boolean_get(op->ptr, "zaxis");
|
||||
|
||||
/* mirror before smooth */
|
||||
if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
|
||||
EDBM_verts_mirror_cache_begin(em, TRUE);
|
||||
@@ -1564,8 +1568,9 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
|
||||
|
||||
for (i = 0; i < repeat; i++) {
|
||||
if (!EDBM_op_callf(em, op,
|
||||
"smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f",
|
||||
BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist))
|
||||
"smooth_vert verts=%hv mirror_clip_x=%b mirror_clip_y=%b mirror_clip_z=%b clipdist=%f "
|
||||
"use_axis_x=%b use_axis_y=%b use_axis_z=%b",
|
||||
BM_ELEM_SELECT, mirrx, mirry, mirrz, clipdist, xaxis, yaxis, zaxis))
|
||||
{
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
@@ -1597,6 +1602,9 @@ void MESH_OT_vertices_smooth(wmOperatorType *ot)
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
RNA_def_int(ot->srna, "repeat", 1, 1, 100, "Number of times to smooth the mesh", "", 1, INT_MAX);
|
||||
RNA_def_boolean(ot->srna, "xaxis", 1, "X-Axis", "Smooth along the X axis");
|
||||
RNA_def_boolean(ot->srna, "yaxis", 1, "Y-Axis", "Smooth along the Y axis");
|
||||
RNA_def_boolean(ot->srna, "zaxis", 1, "Z-Axis", "Smooth along the Z axis");
|
||||
}
|
||||
|
||||
/********************** Smooth/Solid Operators *************************/
|
||||
|
||||
@@ -439,9 +439,10 @@ void ED_clip_point_stable_pos__reverse(SpaceClip *sc, ARegion *ar, const float c
|
||||
r_co[1] = (pos[1] * height * zoomy) + (float)sy;
|
||||
}
|
||||
|
||||
void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, wmEvent *event, float co[2])
|
||||
/* takes event->mval */
|
||||
void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2])
|
||||
{
|
||||
ED_clip_point_stable_pos(sc, ar, event->mval[0], event->mval[1], &co[0], &co[1]);
|
||||
ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]);
|
||||
}
|
||||
|
||||
int ED_space_clip_check_show_trackedit(SpaceClip *sc)
|
||||
|
||||
@@ -119,7 +119,7 @@ static void sclip_zoom_set_factor_exec(bContext *C, wmEvent *event, float factor
|
||||
if (event) {
|
||||
SpaceClip *sc = CTX_wm_space_clip(C);
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, location);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, location);
|
||||
mpos = location;
|
||||
}
|
||||
|
||||
@@ -483,7 +483,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event)
|
||||
vpd->zoom = sc->zoom;
|
||||
vpd->event_type = event->type;
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, vpd->location);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, vpd->location);
|
||||
|
||||
WM_event_add_modal_handler(C, op);
|
||||
}
|
||||
@@ -605,7 +605,7 @@ static int view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
float location[2];
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, location);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, location);
|
||||
RNA_float_set_array(op->ptr, "location", location);
|
||||
|
||||
return view_zoom_in_exec(C, op);
|
||||
@@ -648,7 +648,7 @@ static int view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
float location[2];
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, location);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, location);
|
||||
RNA_float_set_array(op->ptr, "location", location);
|
||||
|
||||
return view_zoom_out_exec(C, op);
|
||||
|
||||
@@ -132,7 +132,7 @@ static int add_marker_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
|
||||
float co[2];
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, co);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, co);
|
||||
|
||||
RNA_float_set_array(op->ptr, "location", co);
|
||||
|
||||
@@ -543,7 +543,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, wmEvent *event, int
|
||||
if (width == 0 || height == 0)
|
||||
return NULL;
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, co);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, co);
|
||||
|
||||
track = tracksbase->first;
|
||||
while (track) {
|
||||
@@ -641,7 +641,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event)
|
||||
if (width == 0 || height == 0)
|
||||
return NULL;
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, co);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, co);
|
||||
|
||||
track = tracking_marker_check_slide(C, event, &area, &action, &corner);
|
||||
if (track) {
|
||||
|
||||
@@ -302,7 +302,7 @@ static int select_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
ED_clip_mouse_pos(sc, ar, event, co);
|
||||
ED_clip_mouse_pos(sc, ar, event->mval, co);
|
||||
RNA_float_set_array(op->ptr, "location", co);
|
||||
|
||||
return select_exec(C, op);
|
||||
|
||||
@@ -260,7 +260,8 @@ void ED_image_get_uv_aspect(Image *ima, float *aspx, float *aspy)
|
||||
*aspy *= (float)h;
|
||||
}
|
||||
|
||||
void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, wmEvent *event, float co[2])
|
||||
/* takes event->mval */
|
||||
void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, const int mval[2], float co[2])
|
||||
{
|
||||
int sx, sy, width, height;
|
||||
float zoomx, zoomy;
|
||||
@@ -270,8 +271,8 @@ void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, wmEvent *event, float co[
|
||||
|
||||
UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &sx, &sy);
|
||||
|
||||
co[0] = ((event->mval[0] - sx) / zoomx) / width;
|
||||
co[1] = ((event->mval[1] - sy) / zoomy) / height;
|
||||
co[0] = ((mval[0] - sx) / zoomx) / width;
|
||||
co[1] = ((mval[1] - sy) / zoomy) / height;
|
||||
}
|
||||
|
||||
void ED_image_point_pos(SpaceImage *sima, ARegion *ar, float x, float y, float *xr, float *yr)
|
||||
|
||||
@@ -2140,13 +2140,13 @@ void SEQUENCER_OT_view_all_preview(wmOperatorType *ot)
|
||||
|
||||
static int sequencer_view_zoom_ratio_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
RenderData *r = &CTX_data_scene(C)->r;
|
||||
RenderData *rd = &CTX_data_scene(C)->r;
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
float ratio = RNA_float_get(op->ptr, "ratio");
|
||||
|
||||
float winx = (int)(r->size * r->xsch) / 100;
|
||||
float winy = (int)(r->size * r->ysch) / 100;
|
||||
float winx = (int)(rd->size * rd->xsch) / 100;
|
||||
float winy = (int)(rd->size * rd->ysch) / 100;
|
||||
|
||||
float facx = (v2d->mask.xmax - v2d->mask.xmin) / winx;
|
||||
float facy = (v2d->mask.ymax - v2d->mask.ymin) / winy;
|
||||
|
||||
@@ -334,9 +334,9 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
|
||||
IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]);
|
||||
|
||||
if (tree->stretch && (pchan->ikstretch > 0.0f)) {
|
||||
float ikstretch = pchan->ikstretch * pchan->ikstretch;
|
||||
IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f - ikstretch, 0.99f));
|
||||
IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10);
|
||||
double ikstretch = (double)pchan->ikstretch * (double)pchan->ikstretch;
|
||||
IK_SetStiffness(seg, IK_TRANS_Y, 1.0f - ikstretch);
|
||||
IK_SetLimit(seg, IK_TRANS_Y, IK_STRETCH_STIFF_MIN, IK_STRETCH_STIFF_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,7 +178,8 @@ enum {
|
||||
MASK_BLEND_DARKEN = 3,
|
||||
MASK_BLEND_MUL = 4,
|
||||
MASK_BLEND_REPLACE = 5,
|
||||
MASK_BLEND_DIFFERENCE = 6
|
||||
MASK_BLEND_DIFFERENCE = 6,
|
||||
MASK_BLEND_MERGE = 7
|
||||
};
|
||||
|
||||
/* masklay->blend_flag */
|
||||
|
||||
@@ -573,6 +573,7 @@ static void rna_def_maskSpline(BlenderRNA *brna)
|
||||
static void rna_def_mask_layer(BlenderRNA *brna)
|
||||
{
|
||||
static EnumPropertyItem masklay_blend_mode_items[] = {
|
||||
{MASK_BLEND_MERGE, "MERGE", 0, "Merge", ""},
|
||||
{MASK_BLEND_ADD, "ADD", 0, "Add", ""},
|
||||
{MASK_BLEND_SUBTRACT, "SUBTRACT", 0, "Subtract", ""},
|
||||
{MASK_BLEND_LIGHTEN, "LIGHTEN", 0, "Lighten", ""},
|
||||
|
||||
@@ -137,6 +137,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
|
||||
if (bmd->object != ob) {
|
||||
dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_MESH);
|
||||
}
|
||||
else {
|
||||
dm = NULL;
|
||||
}
|
||||
|
||||
if (dm) {
|
||||
DerivedMesh *result;
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
|
||||
RAS_2DFilterManager::RAS_2DFilterManager():
|
||||
texturewidth(-1), textureheight(-1),
|
||||
canvaswidth(-1), canvasheight(-1),
|
||||
/* numberoffilters(0), */ /* UNUSED */ need_tex_update(true)
|
||||
{
|
||||
isshadersupported = GLEW_ARB_shader_objects &&
|
||||
@@ -404,7 +403,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas)
|
||||
RAS_Rect rect = canvas->GetWindowArea();
|
||||
int rect_width = rect.GetWidth()+1, rect_height = rect.GetHeight()+1;
|
||||
|
||||
if (canvaswidth != canvas->GetWidth() || canvasheight != canvas->GetHeight())
|
||||
if (texturewidth != rect_width || textureheight != rect_height)
|
||||
{
|
||||
UpdateOffsetMatrix(canvas);
|
||||
UpdateCanvasTextureCoord((unsigned int*)viewport);
|
||||
|
||||
@@ -62,8 +62,6 @@ private:
|
||||
unsigned int texname[3];
|
||||
int texturewidth;
|
||||
int textureheight;
|
||||
int canvaswidth;
|
||||
int canvasheight;
|
||||
/* int numberoffilters; */ /* UNUSED */
|
||||
/* bit 0: enable/disable depth texture
|
||||
* bit 1: enable/disable luminance texture*/
|
||||
|
||||
@@ -15,7 +15,7 @@ incs += ' #source/blender/gpu #intern/string #intern/moto/include'
|
||||
incs += ' #intern/guardedalloc #intern/container #extern/glew/include'
|
||||
incs += ' #intern/ffmpeg'
|
||||
|
||||
defs = []
|
||||
defs = ['GLEW_STATIC']
|
||||
if env['OURPLATFORM'] in ('win32-vc', 'win64-vc','win32-mingw', 'win64-mingw'):
|
||||
if env['BF_DEBUG']:
|
||||
defs.append('_DEBUG')
|
||||
|
||||
Reference in New Issue
Block a user