IK.C

Go to the documentation of this file.
00001 /* file IK.C    for IK animation   */
00002 
00003 #define MODULE_IK 1
00004 
00005 #include "animate.h"
00006 
00007 
00008 void AssignIKchain(node *Np, long frame){
00009   return;
00010 }
00011 
00012 void RemoveIKchain(node *Np, long frame){
00013   return;
00014 }
00015 
00016 void RemoveAllIKchains(node *Np, long frame){
00017   return;
00018 }
00019 
00020 
00021 #if 0
00022 static void IterateTowardsGoal(HWND hWnd,int xi, int yi){
00023  double *J,*Jt,*dTheta,*I,*dI,*Ji;
00024  double x[3],dx[3];
00025  long Nv1,Nv2,n=0;
00026  if(Lv < 0)return;
00027  if(debug != NULL)fprintf(debug,"Test No. %ld\n",++version);
00028  Nv1=Nv-1;
00029  Nv1=Lv; 
00030  Nv2=Nv1-Sv;
00031  SaveLast();
00032  // Define the goal point for the end of the linkage
00033  x[0]=TVlist[Nv1].p[0]+(double)xi;
00034  x[1]=TVlist[Nv1].p[1]+(double)yi;
00035  x[2]=TVlist[Nv1].p[2]+(double)0.0;
00036  VECSUB(x,TVlist[Nv1].p,dx)
00037  if(debug != NULL)fprintf(debug,"Initial |dx| = %lf\n",Length(dx,3));
00038  if((dTheta=(double *)malloc((3*Nv2)*sizeof(double))) == NULL)return;
00039  if((J=(double *)malloc(3*(3*Nv2)*sizeof(double))) == NULL)return;
00040  if((Jt=(double *)malloc((3*Nv2)*3*sizeof(double))) == NULL)return;
00041  if((Ji=(double *)malloc((3*Nv2)*3*sizeof(double))) == NULL)return;
00042  if((dI=(double *)malloc(3*3*sizeof(double))) == NULL)return;
00043  if((I=(double *)malloc(3*3*sizeof(double))) == NULL)return;
00044 
00045  while(1){
00046    VECSUB(x,TVlist[Nv1].p,dx)
00047    if(++n > 50){
00048      if(debug != NULL)fprintf(debug,"*********** Out of iteration ******\n");
00049      // revert to last position (TODO)
00050      RevertToLast();
00051      MessageBeep(MB_OK);
00052      break;
00053    }
00054    CalculateJacobian(J,Nv2,Sv);
00055    CalculateTranspose(J,Jt,3,3*Nv2);
00056    MultiplyMatrix(J,3,3*Nv2,Jt,3*Nv2,3,I);
00057    if(InvertMatrix(I,3,dI)){
00058      // calculate the generalised inverse of the jacobian J (i.e. Ji)
00059      MultiplyMatrix(Jt,3*Nv2,3,dI,3,3,Ji);
00060      // StepOK returns a reduced dx so that the product [J][Ji] is
00061      // close to the identity matrix [I] and therefore can be used to
00062      // determine incremental angular rotations.
00063      if(debug != NULL)fprintf(debug,"Iteration %ld ",n);
00064      if(!StepOK(J,Ji,dx,3,3*Nv2,1.e-2,1.e-6)){
00065        MessageBox(NULL,"Dx too small",NULL,MB_OK);
00066        break;
00067      }
00068      else{
00069        // calculate the incremental rotations
00070        MultiplyMatrix(Ji,3*Nv2,3,dx,3,1,dTheta);
00071        // determine the new position of the linkage
00072        UpdateTheLinkage(Nv1,Nv,Sv,dTheta);
00073        if(Dist(TVlist[Nv1].p,x,3) < 3.0){ //
00074          if(debug != NULL)
00075            fprintf(debug,"converged in %ld iterations with |dx| = %lf\n",
00076                    n,Length(dx,3));
00077          break;   // converged to solution
00078        }
00079        else{
00080          if(debug != NULL)fprintf(debug,"linkage not yet at end point\n");
00081        }
00082      }
00083    }
00084    else{
00085      MessageBox(NULL,"Singular matrix",NULL,MB_OK);
00086    }
00087  }
00088 
00089  free(dTheta);
00090  free(Ji);
00091  free(I);
00092  free(dI);
00093  free(Jt);
00094  free(J);
00095  InvalidateRect(hWnd,NULL,FALSE);
00096  return;
00097 }
00098 
00099 static void CalculateJacobian(double *J,
00100                               long n,
00101                               long ns
00102                              ){
00103  long k,l;
00104  vector ax,ay,az,dp,Jx,Jy,Jz;
00105  for(l=0,k=0;k<n;k++){
00106    VECCOPY(TVlist[k+ns].ax,ax)
00107    VECCOPY(TVlist[k+ns].ay,ay)
00108    VECCOPY(TVlist[k+ns].az,az)
00109    VECSUB(TVlist[n+ns].p,TVlist[k+ns].p,dp)
00110    CROSS(ax,dp,Jx)
00111    CROSS(ay,dp,Jy)
00112    CROSS(az,dp,Jz)
00113    J[l]       = Jx[0];
00114    J[l+n*3]   = Jx[1];
00115    J[l+n*3*2] = Jx[2];
00116    l++;
00117    J[l]       = Jy[0];
00118    J[l+n*3]   = Jy[1];
00119    J[l+n*3*2] = Jy[2];
00120    l++;
00121    J[l]       = Jz[0];
00122    J[l+n*3]   = Jz[1];
00123    J[l+n*3*2] = Jz[2];
00124    l++;
00125  }
00126 #if 0
00127  l=3*2;  // lock link 2
00128  for(k=l;k<l+3;k++){
00129    J[k]=0.0;
00130    J[k+n*3]=0.0;
00131    J[k+n*3*2]=0.0;
00132  }
00133 #endif
00134 #if 0
00135  for(l=0,k=0;k<n;k++){ // damping
00136    J[l]        *= (1.0+2.0*(double)(k));
00137    J[l+n*3]    *= (1.0+2.0*(double)(k));
00138    J[l+n*3*2]  *= (1.0+2.0*(double)(k));
00139    l++;
00140    J[l]        *= (1.0+2.0*(double)(k));
00141    J[l+n*3]    *= (1.0+2.0*(double)(k));
00142    J[l+n*3*2]  *= (1.0+2.0*(double)(k));
00143    l++;
00144    J[l]        *= (1.0+2.0*(double)(k));
00145    J[l+n*3]    *= (1.0+2.0*(double)(k));
00146    J[l+n*3*2]  *= (1.0+2.0*(double)(k));
00147    l++;
00148  }
00149 #endif
00150  return;
00151 }
00152 
00153 static void UpdateTheLinkage(long Nv1, long Nv, long Ns, double *dTheta){
00154  long i,j,l;
00155  double thetaX,thetaY,thetaZ;
00156  vector ax,ay,az,baseZero={0.0,0.0,0.0};
00157  for(i=Ns,l=0;i<Nv1;i++,l+=3){
00158    // extract the incremental rotations and axis vectors around which
00159    // they are to be applied.
00160    thetaX = *(dTheta+l);
00161    thetaY = *(dTheta+l+1);
00162    thetaZ = *(dTheta+l+2);
00163    VECCOPY(TVlist[i].ax,ax)
00164    VECCOPY(TVlist[i].ay,ay)
00165    VECCOPY(TVlist[i].az,az)
00166    // apply the rotation to all the vertex locations and base vectors
00167    // further down the linkage (including the end point)
00168    for(j=i+1;j<Nv;j++){
00169      RotateVectorRound(TVlist[j].p,TVlist[i].p,ax,thetaX);
00170      RotateVectorRound(TVlist[j].p,TVlist[i].p,ay,thetaY);
00171      RotateVectorRound(TVlist[j].p,TVlist[i].p,az,thetaZ);
00172      RotateVectorRound(TVlist[j].ax,baseZero,ax,thetaX);
00173      RotateVectorRound(TVlist[j].ax,baseZero,ay,thetaY);
00174      RotateVectorRound(TVlist[j].ax,baseZero,az,thetaZ);
00175      RotateVectorRound(TVlist[j].ay,baseZero,ax,thetaX);
00176      RotateVectorRound(TVlist[j].ay,baseZero,ay,thetaY);
00177      RotateVectorRound(TVlist[j].ay,baseZero,az,thetaZ);
00178      RotateVectorRound(TVlist[j].az,baseZero,ax,thetaX);
00179      RotateVectorRound(TVlist[j].az,baseZero,ay,thetaY);
00180      RotateVectorRound(TVlist[j].az,baseZero,az,thetaZ);
00181      TVlist[j].x=(int)TVlist[j].p[0];
00182      TVlist[j].y=(int)TVlist[j].p[1];
00183      TVlist[j].z=(int)TVlist[j].p[2]; // should be 0 in case of pseudo 2D
00184    }
00185  }
00186  return;
00187 }
00188 
00189 static BOOL StepOK(double *J, double *Ji, double *dx,
00190                    long n, long m,
00191                    double e, double dmin){
00192  // n=3 for 3D Jacobian, m=(# linkages - 1)*3 (no angular constraints apply)
00193  BOOL result=TRUE;
00194  long i;
00195  double *I,*N,norm=0.0;
00196  if((I=(double *)malloc(n*n*sizeof(double))) == NULL)return FALSE;
00197  if((N=(double *)malloc(n*sizeof(double))) == NULL)return FALSE;
00198  MultiplyMatrix(J,n,m,Ji,m,n,I);
00199  if(debug != NULL){
00200    fprintf(debug,"\nInverse matrix\n");
00201    for(i=0;i<n;i++){
00202      long j;
00203      for(j=0;j<3;j++){
00204        fprintf(debug,"%lf ",I[i*n+j]);
00205      }
00206      fprintf(debug,"\n");
00207    }
00208  }
00209  for(i=0;i<n;i++){
00210    I[i*n+i] -= 1.0;
00211  }
00212  while(1){
00213    MultiplyMatrix(I,n,n,dx,n,1,N);
00214    norm=0.0;
00215    for(i=0;i<n;i++){
00216      norm += N[i] * N[i];
00217    }
00218    if(debug != NULL)fprintf(debug,"Norm = %lf\n",norm);
00219    if(norm < e)break;
00220    for(i=0;i<n;i++)dx[i] *= 0.5;
00221    if(Length(dx,n) < dmin){
00222       result=FALSE;
00223       break;
00224    }
00225  }
00226  free(N);
00227  free(I);
00228  return result;
00229 }
00230 
00231 static void SaveLast(void){
00232  long i;
00233  for(i=0;i<Nv;i++){ // make record of last positions
00234    TVlist[i].lx=TVlist[i].x;
00235    TVlist[i].ly=TVlist[i].y;
00236    TVlist[i].lz=TVlist[i].z;
00237    VECCOPY(TVlist[i].p,TVlist[i].lp)
00238    VECCOPY(TVlist[i].ax,TVlist[i].lax)
00239    VECCOPY(TVlist[i].ay,TVlist[i].lay)
00240    VECCOPY(TVlist[i].az,TVlist[i].laz)
00241  }
00242  return;
00243 }
00244 
00245 static void RevertToLast(void){
00246  long i;
00247  for(i=0;i<Nv;i++){ // make record of last positions
00248    TVlist[i].x=TVlist[i].lx;
00249    TVlist[i].y=TVlist[i].ly;
00250    TVlist[i].z=TVlist[i].lz;
00251    VECCOPY(TVlist[i].lp,TVlist[i].p)
00252    VECCOPY(TVlist[i].lax,TVlist[i].ax)
00253    VECCOPY(TVlist[i].lay,TVlist[i].ay)
00254    VECCOPY(TVlist[i].laz,TVlist[i].az)
00255  }
00256  return;
00257 }
00258 
00259 static void SetupStart(void){
00260  int i;
00261  vector x0={1.0,0.0,0.0},y0={0.0,1.0,0.0},z0={0.0,0.0,1.0};
00262  if(Nv < 2)return;
00263  for(i=0;i<Nv;i++){
00264    TVlist[i].p[0]=(double)TVlist[i].x;
00265    TVlist[i].p[1]=(double)TVlist[i].y;
00266    TVlist[i].p[2]=0.0;
00267    VECCOPY(x0,TVlist[i].ax)
00268    VECCOPY(y0,TVlist[i].ay)
00269    VECCOPY(z0,TVlist[i].az)
00270  }
00271 }
00272 
00273 static void RotateVectorRound(vector v,
00274                               vector BaseOfRotation,
00275                               vector AxisOfRotation,
00276                               double theta){
00277  // modify the input vector to apply the rotational transformation
00278  double t[4][4];
00279  vector lv,lvv;
00280  VECSUB(v,BaseOfRotation,lv) // remove
00281  rotate_round_vector(theta,AxisOfRotation,t);  // get rotational transform
00282  mv4by1(t,lv,lvv);  // apply it
00283  VECSUM(lvv,BaseOfRotation,v)
00284  return;
00285 }
00286 
00287 static void rotz(double tr[4][4], double ang){
00288  short i,j;
00289  for(i=0;i<4;i++)
00290  for(j=0;j<4;j++){
00291   tr[i][j]=0.0;
00292   if(i == j)tr[i][j]=1.0;
00293  }
00294   tr[0][0]= cos(ang);
00295   tr[0][1]=-sin(ang);
00296   tr[1][0]= sin(ang);
00297   tr[1][1]= cos(ang);
00298   return;
00299 }
00300 
00301 static void roty(double tr[4][4], double ang){
00302  short i,j;
00303  for(i=0;i<4;i++)
00304  for(j=0;j<4;j++){
00305   tr[i][j]=0.0;
00306   if(i == j)tr[i][j]=1.0;
00307  }
00308   tr[0][0]= cos(ang);
00309   tr[0][2]=-sin(ang);
00310   tr[2][0]= sin(ang);
00311   tr[2][2]= cos(ang);
00312   return;
00313 }
00314 
00315 static void rotx(double tr[4][4], double ang){
00316  long i,j;
00317  for(i=0;i<4;i++)
00318  for(j=0;j<4;j++){
00319   tr[i][j]=0.0;
00320   if(i == j)tr[i][j]=1.0;
00321  }
00322   tr[1][1]= cos(ang);
00323   tr[1][2]=-sin(ang);
00324   tr[2][1]= sin(ang);
00325   tr[2][2]= cos(ang);
00326   return;
00327 }
00328 
00329 static void mv4by1(double t4[4][4], vector v1, vector v2){
00330  double xx,yy,zz;
00331  xx=t4[0][0]*v1[0]+t4[0][1]*v1[1]+t4[0][2]*v1[2]+t4[0][3];
00332  yy=t4[1][0]*v1[0]+t4[1][1]*v1[1]+t4[1][2]*v1[2]+t4[1][3];
00333  zz=t4[2][0]*v1[0]+t4[2][1]*v1[1]+t4[2][2]*v1[2]+t4[2][3];
00334  v2[0]=xx; v2[1]=yy; v2[2]=zz;
00335  return;
00336 }
00337 
00338 static void m4by4(double t1[4][4], double t2[4][4], double tr[4][4]){
00339  short n=4,i,j,k;
00340  for(i=0;i<4;i++)
00341  for(j=0;j<4;j++){
00342   tr[i][j]=0.0;
00343   for(k=0;k<4;k++)tr[i][j]=tr[i][j]+t1[i][k]*t2[k][j];
00344  }
00345  return;
00346 }
00347 
00348 static void rotate_round_vector(double angle, vector v, double t[4][4]){
00349   double dx,dy,dz,phi,theta,dxy;
00350   double t1[4][4],t2[4][4],t3[4][4];
00351   dx=v[0]; dy=v[1]; dz=v[2];
00352   dxy=dx*dx+dy*dy;
00353   if(dxy < 0.00001){ /* vertical so just rotate about z  and return */
00354     if(dz > 0.0)rotz(t, angle);
00355     else        rotz(t,-angle);
00356     return;
00357   }
00358   dxy=sqrt(dxy);
00359   if     (dx == 0.0 && dy > 0.0)phi =  PI2;
00360   else if(dx == 0.0 && dy < 0.0)phi = -PI2;
00361   else phi = atan2(dy,dx);
00362   theta = atan2(dz,dxy);
00363   rotz(t3, -phi);
00364   roty(t2, -theta);
00365   m4by4(t2,t3,t1);
00366   rotx(t2, angle);
00367   m4by4(t2,t1,t3);
00368   roty(t2,theta);
00369   m4by4(t2,t3,t1);
00370   rotz(t2,phi);
00371   m4by4(t2,t1,t);
00372 }
00373 
00374 static double Length(double *dx, long n){
00375  long i;
00376  double l=0.0;
00377  for(i=0;i<n;i++)l += dx[i]*dx[i];
00378  return sqrt(l);
00379 }
00380 
00381 static double Dist(double *x, double *y, long n){
00382  long i;
00383  double d=0.0;
00384  for(i=0;i<n;i++)d += (x[i]-y[i])*(x[i]-y[i]);
00385  return sqrt(d);
00386 }
00387 
00388 static void CalculateTranspose(double *M, double *Mt, long n, long m){
00389  long i,j;                       // M  is "n" rows "m" columns  [n x m]
00390  for(i=0;i<n;i++){
00391    for(j=0;j<m;j++){
00392      *(Mt+j*n+i) = *(M+i*m+j);   // Mt[j*n+i] = M[i*m+j];
00393    }
00394  }
00395  return;
00396 }
00397 
00398 static void MultiplyMatrix(double *M1, long n1, long m1,
00399                            double *M2, long n2, long m2,
00400                            double *I){
00401  long   i,j,k,c;           // [n1 x m2][n2 x m2] result is [n1 x m2]
00402  double s;
00403  if(m1 != n2){MessageBox(NULL,"Bad Multiply",NULL,MB_OK); return;}
00404  c=n2;
00405  for(i=0;i<n1;i++){
00406    for(j=0;j<m2;j++){
00407      for(s=0.0,k=0;k<c;k++){
00408        s += (*(M1+i*m1+k)) * (*(M2+k*m2+j));
00409        //  s += M1[i*m1+k]*M2[k*m2+j];  //  M1[i][k] * M2[k][j]
00410      }
00411      *(I+i*m2+j) = s;                   //  I[i*m2+j]=s;   // I[i][j]
00412    }
00413  }
00414  return;
00415 }
00416 
00417 static BOOL InvertMatrix(double *A, long n, double *B){
00418  int i,j,k,imax,kp1;
00419  double del,amax,atmp,btmp,div,amult,eps=1.e-6;
00420  for(i=0;i<n;i++)for(j=0;j<n;j++){
00421    if(i == j)B[i*n+j]=1.0;
00422    else      B[i*n+j]=0.0;
00423  }
00424  del=1.0;
00425  for(k=0;k<n;k++){
00426    if(k < n-1){
00427      imax=k;
00428      amax=fabs(A[k*n+k]);
00429      kp1=k+1;
00430      for(i=kp1;i<n;i++){
00431        if(amax-fabs(A[i*n+k]) < 0.0){
00432          imax=i;
00433          amax=fabs(A[i*n+k]);
00434        }
00435      }
00436      if(imax != k){
00437        for(j=0;j<n;j++){
00438          atmp=A[imax*n+j];
00439          A[imax*n+j]=A[k*n+j];
00440          A[k*n+j]=atmp;
00441          btmp=B[imax*n+j];
00442          B[imax*n+j]=B[k*n+j];
00443          B[k*n+j]=btmp;
00444        }
00445        del = -del;
00446      }
00447    }
00448    if(fabs(A[k*n+k]) < eps)return FALSE;
00449    del=A[k*n+k]*del;
00450    div=1.0/A[k*n+k];
00451    for(j=0;j<n;j++){
00452      A[k*n+j]=A[k*n+j]*div;
00453      B[k*n+j]=B[k*n+j]*div;
00454    }
00455    for(i=0;i<n;i++){
00456      amult=A[i*n+k];
00457      if(i != k){
00458        for(j=0;j<n;j++){
00459          A[i*n+j]=A[i*n+j]-amult*A[k*n+j];
00460          B[i*n+j]=B[i*n+j]-amult*B[k*n+j];
00461        }
00462      }
00463    }
00464  }
00465  return TRUE;
00466 }
00467 
00468 #endif

Generated on Sun Apr 27 14:20:09 2014 for OpenFX by  doxygen 1.5.6