ROBOT.C

Go to the documentation of this file.
00001 /* file WROBOT.C    for Windows animator                        */
00002 /* assume that of each robot actor the skeletons are consistent */
00003 
00004 #define MODULE_ROBOT 1
00005 
00006 #define TIME_DELAY 30
00007 
00008 #include <io.h>
00009 #include <fcntl.h>
00010 #include "animate.h"
00011 
00012 typedef double quaternion[4];
00013 
00014 static void rotate_round_vector(double angle, vector v, double t[4][4]);
00015 static void TransformAxis(skel *sid, vector v, vector vv);
00016 static void SelectRobotArm(void);
00017 static void NameRobotDirectory(char *script_file, char *robo_dir);
00018 static void EditRobotTransform(int command);
00019 static void RobotSkeletonTreeView(HWND hWndParent);
00020 static void SelectTreeViewItem(void);
00021 static void GetBasisTransform(vector x, vector y, vector z,
00022                               vector u, vector v, vector w,
00023                               double T[4][4]);
00024 
00025 static node   *LastSelectedRobotNode=NULL;
00026 static object *SelectedRobot=NULL;
00027 static long    SelectedRobotArm = -1;
00028 
00029 long GetRobotVolume(long n, skel *sp, vector c){
00030  long i,size=UNIT;
00031  static double xmax=UNIT2,ymax=UNIT2,zmax=UNIT2,
00032                xmin=0,ymin=0,zmin=0;
00033  if(sp != NULL){
00034    xmin=ymin=zmin =  MAXUNIT;
00035    xmax=ymax=zmax = -MAXUNIT;
00036    for(i=0;i<n;i++){
00037      if(sp->p[0]  > xmax)xmax=sp->p[0];
00038      if(sp->pp[0] > xmax)xmax=sp->pp[0];
00039      if(sp->p[0]  < xmin)xmin=sp->p[0];
00040      if(sp->pp[0] < xmin)xmin=sp->pp[0];
00041      if(sp->p[1]  > ymax)ymax=sp->p[1];
00042      if(sp->pp[1] > ymax)ymax=sp->pp[1];
00043      if(sp->p[1]  < ymin)ymin=sp->p[1];
00044      if(sp->pp[1] < ymin)ymin=sp->pp[1];
00045      if(sp->p[2]  > zmax)zmax=sp->p[2];
00046      if(sp->pp[2] > zmax)zmax=sp->pp[2];
00047      if(sp->p[2]  < zmin)zmin=sp->p[2];
00048      if(sp->pp[2] < zmin)zmin=sp->pp[2];
00049      sp++;
00050    }
00051  }
00052  size=max(xmax-xmin,ymax-ymin);
00053  size=max(size,zmax-zmin);
00054  c[0]=(double)(xmax+xmin)*0.5;
00055  c[1]=(double)(ymax+ymin)*0.5;
00056  c[2]=(double)(zmax+zmin)*0.5;
00057  return size;
00058 }
00059 
00060 void DrawRobot(HDC hdc[], object *Op, point Offset, double p, double t
00061              , double a, short im, double ima
00062              , double sx, double sy, double sz, short status){
00063  int sh1,sv1,sh2,sv2,i,j,k,ep;
00064  point  v1,v2;
00065  skel *sp;
00066  double mr,RoboT[4][4],x,y,z,xx,yy,zz;
00067  int ifd,ild;
00068  if(View == TRIVIEW){ifd=0;ild=3;}
00069  else               {ifd=ActiveView; ild=ifd+1;}
00070  if(status == DESELECTED)DrawActorCentre(hdc,Offset,p,t,a,im,ima,TVsizeX/24);
00071  if(status == SELECTED)DrawArrow(hdc,Offset,p,t,a,im,ima,TVsizeX/24);
00072  mr=(double)(Op->lastframe - Op->firstframe+1);   /* mr = 1 in key frame */
00073  mr=(double)(CurrentFrame - Op->firstframe+1)/mr;
00074  if(Op->nskeleton > 0){
00075    InterpolateRobot(mr,Op,Op->last);
00076    RobotTransform(Offset,p,t,a,sx,sy,sz,im,ima,RoboT);
00077    sp=Op->skeleton;
00078    for(k=0;k<Op->nskeleton;k++){ /* transform all the points */
00079      xx=(double)sp[k].pp[0];
00080      yy=(double)sp[k].pp[1];
00081      zz=(double)sp[k].pp[2];
00082      m4by1(RoboT,xx,yy,zz,&x,&y,&z);
00083      sp[k].pt[0]=(long)x;   /* keep transformed pt for selection */
00084      sp[k].pt[1]=(long)y;
00085      sp[k].pt[2]=(long)z;
00086    }
00087    for(k=0;k<Op->nskeleton;k++){ /* draw the points */
00088      CopyPoint(sp[k].pt,v1);
00089      if(k > 0 && (j=sp[k].id) < Op->nskeleton)CopyPoint(sp[j].pt,v2);
00090      else                                     CopyPoint(v1,v2);
00091      if(in_stage_triview(v1) || in_stage_triview(v2)){
00092        for(i=ifd;i<ild;i++){
00093          GetWindowCoords(i,v1[0],v1[1],v1[2],&sh1,&sv1);
00094          GetWindowCoords(i,v2[0],v2[1],v2[2],&sh2,&sv2);
00095          MoveToEx(hdc[i],sh1,sv1,NULL); LineTo(hdc[i],sh2,sv2);
00096          if(status == SELECTED){
00097            HPEN holdpen;
00098            if(k == SelectedRobotArm)holdpen=SelectObject(hdc[i],ghEditPen);
00099            Rectangle(hdc[i],(int)sh1-3,(int)sv1-3,(int)sh1+3,(int)sv1+3);
00100            if(k == SelectedRobotArm)SelectObject(hdc[i],holdpen);
00101          }
00102        }
00103      }
00104    }
00105  }
00106 }
00107 
00108 void DrawFullRobot(HDC hdc[], object *Op, point Offset, double p, double t
00109                , double a, short im, double ima
00110                , double sx, double sy, double sz, short status){
00111  short morphflag;
00112  int sh1,sv1,sh2,sv2,i,j,k,ep;
00113  point xyz,*Vp;
00114  skel *sp;
00115  double mr,RoboT[4][4],ViewT[4][4],x,y,z,xx,yy,zz;
00116  int ifd,ild;
00117  long *sid,Nv;
00118  morphflag=0;
00119  if(View == TRIVIEW){ifd=0;ild=3;}
00120  else               {ifd=ActiveView; ild=ifd+1;}
00121  if(status == DESELECTED)DrawActorCentre(hdc,Offset,p,t,a,im,ima,TVsizeX/24);
00122  if(status == SELECTED)DrawArrow(hdc,Offset,p,t,a,im,ima,TVsizeX/24);
00123  mr=(double)(Op->lastframe - Op->firstframe+1);   /* mr = 1 in key frame */
00124  mr=(double)(CurrentFrame - Op->firstframe+1)/mr;
00125  if(Op->nskeleton > 0 && (sp=Op->skeleton) != NULL && (sid=Op->skid) != NULL){
00126    InterpolateRobot(mr,Op,Op->last);
00127    RobotTransform(Offset,p,t,a,sx,sy,sz,im,ima,RoboT);
00128    for(k=0;k<Op->nskeleton;k++){ /* transform all the points */
00129      xx=(double)sp[k].pp[0];
00130      yy=(double)sp[k].pp[1];
00131      zz=(double)sp[k].pp[2];
00132      m4by1(RoboT,xx,yy,zz,&x,&y,&z);
00133      sp[k].pt[0]=(long)x;   /* keep transformed pt for selection */
00134      sp[k].pt[1]=(long)y;
00135      sp[k].pt[2]=(long)z;
00136    }
00137    if(Op->in_ram){
00138      Nv=Op->npoints;
00139      if(Nv > 0){
00140        if((Vp=(point *)X__Malloc(Nv*sizeof(point))) != NULL){
00141          for(i=0;i<Nv;i++){
00142            CopyPoint(Op->points[i],xyz);
00143            m4by4(RoboT,sp[sid[i]].T,ViewT);
00144            x = (double)(xyz[0]-Op->origin[0]);
00145            y = (double)(xyz[1]-Op->origin[1]);
00146            z = (double)(xyz[2]-Op->origin[2]);
00147            m4by1(ViewT,x,y,z,&xx,&yy,&zz);
00148            Vp[i][0]=(long)xx; Vp[i][1]=(long)yy; Vp[i][2]=(long)zz;
00149          }
00150        }
00151        else{
00152          SendPrgmQuery(IDQ_NOMEM3,0);
00153          Nv=0;
00154        }
00155        if(Nv > 0)for(k=0;k<Nv;k++){
00156          if(in_stage_triview(Vp[k])){
00157            for(i=ifd;i<ild;i++){
00158              GetWindowCoords(i,Vp[k][0],Vp[k][1],Vp[k][2],&sh1,&sv1);
00159              MoveToEx(hdc[i],sh1,sv1,NULL); LineTo(hdc[i],sh1+2,sv1);
00160            }
00161          }
00162        }
00163        if(Vp != NULL){ X__Free(Vp); Vp=NULL;}
00164      }
00165    }
00166  }
00167  DrawRobot(hdc,Op,Offset,p,t
00168           ,a,im,ima
00169           ,sx,sy,sz,status);
00170 }
00171 
00172 void SkeletorOn(void){
00173  object *Op;
00174  EDIT_ACTION=YES;
00175  if(SelectedNode == NULL){
00176    SendPrgmQuery(IDQ_NRSELECT,0);
00177    return;
00178  }
00179  if(SelectedNode->type != ROBOT){
00180    SendPrgmQuery(IDQ_NOTAROBOT,0);
00181    return;
00182  }
00183  if(SelectedNode->fobj == NULL){
00184    SendPrgmQuery(IDQ_NOROBOTA,0);
00185    return;
00186  }
00187  Op=SelectedNode->fobj;
00188  while(Op != NULL){
00189   if(CurrentFrame == Op->lastframe){
00190     SelectedRobot=Op;
00191     tool=SKELETOR;
00192 //    if(!IsWindow(ghwndDlgTools)){
00193 //      ghwndDlgTools=CreateDialog(ghinst_main,MAKEINTRESOURCE(DLG_ROBOT),
00194 //                                  ghwnd_main,(DLGPROC)RobotToolDlgProc);
00195 //      if(IsWindow(ghwndDlgTools))ShowWindow(ghwndDlgTools,SW_SHOW);
00196 //    }
00197     if(!IsWindow(ghwndSkEdit))RobotSkeletonTreeView(ghwnd_main);
00198     ReDrawStageDisplay(TRUE);
00199     return;
00200   }
00201   Op=Op->next;
00202  }
00203  SendPrgmQuery(IDQ_NOREDIT,0);
00204  return;
00205 }
00206 
00207 void SkeletorOff(short disengage){
00208  tool=NOTOOL;
00209  if(IsWindow(ghwndSkEdit))RobotSkeletonTreeView(ghwnd_main);
00210  SelectedRobot=NULL;
00211  SelectedRobotArm = -1;
00212  ReDrawStageDisplay(TRUE);
00213 }
00214 
00215 static void SelectRobotArm(void){
00216  BOOL flag=FALSE;
00217  long i;
00218  skel *sp;
00219  double d,dmin,dth;
00220  int sho,svo,H,V;
00221  POINT p;
00222  if(SelectedRobot == NULL)return;
00223  DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00224 // now keep selection   SelectedRobotArm=-1;
00225  sp=SelectedRobot->skeleton;
00226  dmin=(double)TVsizeX*(double)TVsizeX;
00227  dth=dmin/32/32;
00228  GetCursorPos(&p); ScreenToClient(ghwnd_current,&p);
00229  H=(int)p.x; V=(int)p.y;
00230  if(SelectedRobot->nskeleton > 0)for(i=0;i<SelectedRobot->nskeleton;i++){
00231    GetWindowCoords(ActiveView,sp->pt[0],sp->pt[1],sp->pt[2],&sho,&svo);
00232    if( (sho > H-4) && (sho < H+4) && (svo > V-4) && (svo < V+4)){
00233      d=(double)(sp->pt[0]-NpointerX)*(double)(sp->pt[0]-NpointerX)
00234       +(double)(sp->pt[1]-NpointerY)*(double)(sp->pt[1]-NpointerY)
00235       +(double)(sp->pt[2]-NpointerZ)*(double)(sp->pt[2]-NpointerZ);
00236      if(d < dmin){
00237        dmin=d;
00238        SelectedRobotArm=i;
00239        flag=TRUE;
00240      }
00241    }
00242    sp++;
00243  }
00244  DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00245  if(View == ONEVIEW)UpdateWindow(ghwnd_current);
00246  else for(i=0;i<3;i++)UpdateWindow(ghwnd_triview[i]);
00247  if(flag && IsWindow(ghwndRobotView))PostMessage(ghwndRobotView,WM_DRAWROBOT,0,0);
00248 }
00249 
00250 static int A_normalize(vector v){
00251  double n,nn;
00252  n= (double)((v[0]*v[0]) + (v[1]*v[1]) + (v[2]*v[2]));
00253  if(n < 1.e-10)return FAIL;
00254  nn=sqrt(n);
00255  n = 1.0 / nn;
00256  VECSCALE(n,v,v)
00257  return OK;
00258 }
00259 
00260 static void TransformAxis(skel *sid, vector v, vector vv){
00261  vector t;
00262  VECSCALE((double)UNIT2*1000.0,v,t)
00263  VECSUM(t,(double)sid->p,t)
00264  m4by1(sid->T,t[0],t[1],t[2],&vv[0],&vv[1],&vv[2]);
00265  VECSUB(vv,(double)sid->pp,vv)
00266  A_normalize(vv);
00267 }
00268 
00269 static void GetBasisTransform(vector x, vector y, vector z,
00270                               vector u, vector v, vector w,
00271                               double T[4][4]){
00272  int i,j;                     /* return transformation matrix from the   */
00273  double a[3][3],t[4][4];      /* transformed basis to the original basis */
00274  double det;
00275  null_transform(T);
00276  null_transform(t);
00277  a[0][0]=x[0]; a[0][1]=x[1]; a[0][2]=x[2];
00278  a[1][0]=y[0]; a[1][1]=y[1]; a[1][2]=y[2];
00279  a[2][0]=z[0]; a[2][1]=z[1]; a[2][2]=z[2];
00280  det=a[0][0]*(a[1][1]*a[2][2] - a[2][1]*a[1][2])
00281     -a[0][1]*(a[1][0]*a[2][2] - a[2][0]*a[1][2])
00282     +a[0][2]*(a[1][0]*a[2][1] - a[2][0]*a[1][1]);
00283  if(fabs(det) < 1.e-10)return;
00284  det = 1.0/det;
00285  t[0][0] = +(a[1][1]*a[2][2] - a[2][1]*a[1][2])*det;
00286  t[1][0] = -(a[1][0]*a[2][2] - a[2][0]*a[1][2])*det;
00287  t[2][0] = +(a[1][0]*a[2][1] - a[2][0]*a[1][1])*det;
00288  t[0][1] = -(a[0][1]*a[2][2] - a[2][1]*a[0][2])*det;
00289  t[1][1] = +(a[0][0]*a[2][2] - a[2][0]*a[0][2])*det;
00290  t[2][1] = -(a[0][0]*a[2][1] - a[2][0]*a[0][1])*det;
00291  t[0][2] = +(a[0][1]*a[1][2] - a[1][1]*a[0][2])*det;
00292  t[1][2] = -(a[0][0]*a[1][2] - a[1][0]*a[0][2])*det;
00293  t[2][2] = +(a[0][0]*a[1][1] - a[1][0]*a[0][1])*det;
00294  m4by1(t,u[0],v[0],w[0],&T[0][0],&T[0][1],&T[0][2]);
00295  m4by1(t,u[1],v[1],w[1],&T[1][0],&T[1][1],&T[1][2]);
00296  m4by1(t,u[2],v[2],w[2],&T[2][0],&T[2][1],&T[2][2]);
00297 }
00298 
00299 static void InvertRotationMatrix(double T[4][4], double t[4][4]){
00300  int i,j;
00301  double a[3][3];
00302  double det;
00303  null_transform(t);
00304  for(i=0;i<3;i++)for(j=0;j<3;j++)a[i][j]=T[i][j];
00305  det=a[0][0]*(a[1][1]*a[2][2] - a[2][1]*a[1][2])
00306     -a[0][1]*(a[1][0]*a[2][2] - a[2][0]*a[1][2])
00307     +a[0][2]*(a[1][0]*a[2][1] - a[2][0]*a[1][1]);
00308  if(fabs(det) < 1.e-10)return;
00309  det = 1.0/det;
00310  t[0][0] = +(a[1][1]*a[2][2] - a[2][1]*a[1][2])*det;
00311  t[1][0] = -(a[1][0]*a[2][2] - a[2][0]*a[1][2])*det;
00312  t[2][0] = +(a[1][0]*a[2][1] - a[2][0]*a[1][1])*det;
00313  t[0][1] = -(a[0][1]*a[2][2] - a[2][1]*a[0][2])*det;
00314  t[1][1] = +(a[0][0]*a[2][2] - a[2][0]*a[0][2])*det;
00315  t[2][1] = -(a[0][0]*a[2][1] - a[2][0]*a[0][1])*det;
00316  t[0][2] = +(a[0][1]*a[1][2] - a[1][1]*a[0][2])*det;
00317  t[1][2] = -(a[0][0]*a[1][2] - a[1][0]*a[0][2])*det;
00318  t[2][2] = +(a[0][0]*a[1][1] - a[1][0]*a[0][1])*det;
00319 }
00320 
00321 static void rotate_round_vector(double angle, vector v, double t[4][4]){
00322   double dx,dy,dz,phi,theta,dxy;
00323   double t1[4][4],t2[4][4],t3[4][4];
00324   angle *= PI/180.0;
00325   dx=v[0]; dy=v[1]; dz=v[2];
00326   dxy=dx*dx+dy*dy;
00327   if(dxy < 0.00001){ /* vertical so just rotate about z  and return */
00328     if(dz > 0.0)rotz(t, angle);
00329     else        rotz(t,-angle);
00330     return;
00331   }
00332   dxy=sqrt(dxy);
00333   if     (dx == 0.0 && dy > 0.0)phi =  PI2;
00334   else if(dx == 0.0 && dy < 0.0)phi = -PI2;
00335   else phi = atan2(dy,dx);
00336   theta = atan2(dz,dxy);
00337   rotz(t3, -phi);
00338   roty(t2, -theta);
00339   m4by4(t2,t3,t1);
00340   rotx(t2, angle);
00341   m4by4(t2,t1,t3);
00342   roty(t2,theta);
00343   m4by4(t2,t3,t1);
00344   rotz(t2,phi);
00345   m4by4(t2,t1,t);
00346 }
00347 
00348 int Skeletor(void){
00349  POINT pt;
00350  int xi,xo,MickeyX,I;
00351  double ltr[4][4],ctr[4][4];
00352  vector Tv,Rv,Xv={1.0,0.0,0.0},Yv={0.0,1.0,0.0},Zv={0.0,0.0,1.0};
00353  long i,j,k,evTime;
00354  skel *s;
00355  object *op;
00356  if(SelectedNode == NULL)return 1;
00357  if(SelectedNode->type != ROBOT)return 1;
00358  op=GetObjectAtFrame(SelectedNode,CurrentFrame);
00359  UpdateRobot(op);
00360 // if(op != NULL)SelectedRobot=op;  // now in UpdateRobot;
00361  if(SelectedRobot != NULL && SelectedRobot->lastframe != CurrentFrame){
00362    SendPrgmQuery(IDQ_ONLYKEYFRAME,0);
00363    return 0;
00364  }
00365  SelectRobotArm();
00366  if(SelectedRobot != NULL && SelectedRobotArm >= 0){
00367    SelectTreeViewItem();
00368    if(CurrentFrame == SelectedRobot->lastframe){
00369      s=SelectedRobot->skeleton;
00370      i=SelectedRobotArm;
00371      if(gToolFlags.flagK == 6){
00372        if(i > 0){
00373          VECSUB((double)(s+((s+i)->id))->p,(double)(s+i)->p,Tv)
00374          A_normalize(Tv);
00375          m4by1((s+i)->R,Tv[0],Tv[1],Tv[2],&Rv[0],&Rv[1],&Rv[2]);
00376        }
00377        else{
00378          VECCOPY(Zv,Rv)
00379        }
00380      }
00381      else if(gToolFlags.flagK > 2 && i > 0){
00382        if(     gToolFlags.flagK == 3)VECCOPY(Xv,Tv)
00383        else if(gToolFlags.flagK == 4)VECCOPY(Yv,Tv)
00384        else                          VECCOPY(Zv,Tv)
00385        j=s[i].id;
00386        TransformAxis((s+j),s[j].u,s[j].uu);
00387        TransformAxis((s+j),s[j].v,s[j].vv);
00388        TransformAxis((s+j),s[j].w,s[j].ww);
00389        GetBasisTransform(s[j].uu,s[j].vv,s[j].ww,s[j].u,s[j].v,s[j].w,ltr);
00390        m4by1(ltr,Tv[0],Tv[1],Tv[2],&Rv[0],&Rv[1],&Rv[2]);
00391      }
00392      GetCursorPos(&pt); xo=(int)pt.x;
00393      evTime=GetTickCount()+TIME_DELAY;
00394      do {
00395        if(evTime > GetTickCount())continue;
00396        GetCursorPos(&pt); xi=pt.x;
00397        MickeyX = xi-xo; xo=xi;
00398        if(MickeyX != 0){
00399          if(MickeyX > 0)I=max( 1,min( 45,MickeyX));
00400          else           I=min(-1,max(-45,MickeyX));
00401          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00402          if(i > 0){
00403            j=s[i].id;
00404            if(gToolFlags.flagK == 0) /* rotate about v (along axis) */
00405              rotate_round_vector(I,s[j].v,ltr);
00406            else if(gToolFlags.flagK == 1)
00407              rotate_round_vector(I,s[j].u,ltr);
00408            else if(gToolFlags.flagK == 2)
00409              rotate_round_vector(I,s[j].w,ltr);
00410            else if(gToolFlags.flagK > 2 && gToolFlags.flagK <= 6)
00411              rotate_round_vector(I,Rv,ltr);
00412            else null_transform(ltr);
00413            m4by4(ltr,s[i].R,ctr); c4to4(ctr,s[i].R);
00414          }
00415          DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
00416          if(ghwndOpenGLview == NULL)PerspectiveView(0,0);
00417          if(IsWindow(ghwndRobotView)){
00418            SendMessage(ghwndRobotView,WM_DRAWROBOT,0,0);
00419            UpdateWindow(ghwndRobotView);
00420          }
00421          if(View == ONEVIEW)UpdateWindow(ghwnd_current);
00422          else{
00423            for(I=0;I<3;I++)UpdateWindow(ghwnd_triview[I]);
00424          }
00425          UpdateWindow(ghwnd_view);
00426        }
00427        evTime=GetTickCount()+TIME_DELAY;
00428      }
00429      while (GetAsyncKeyState(VK_LBUTTON) & 0x8000);
00430 
00431      if(ghwndOpenGLview != NULL)UpdateGLview(TRUE);
00432      else PerspectiveView(0,1);
00433 
00434      return 0;
00435    }
00436    else{ /* not key frame */
00437      ;
00438    }
00439  }
00440  return 1;
00441 }
00442 
00443 void RobotTransform(point Offset, double p, double t, double a,
00444                     double sx, double sy, double sz,
00445                     short im, double ima, double RoboT[4][4]){
00446  double tr0[4][4],tr1[4][4],tr2[4][4],tr3[4][4],x,y,z;
00447  scal(tr1,sx,sy,sz);
00448  if(im > 0){
00449    if     (im == 1)rotz(tr0,ima*PIo180);
00450    else if(im == 2)rotx(tr0,ima*PIo180);
00451    else if(im == 3)roty(tr0,ima*PIo180);
00452    roty(tr2,t*PI/180.0);
00453    m4by4(tr2,tr0,tr3);
00454  }
00455  else{
00456   roty(tr3,t*PIo180);
00457  }
00458  m4by4(tr3,tr1,tr2);
00459  rotx(tr3,a*PIo180);
00460  m4by4(tr3,tr2,tr1);
00461  rotz(tr2,p*PIo180);
00462  m4by4(tr2,tr1,tr3);
00463  tram(tr1,Offset[0],Offset[1],Offset[2]);
00464  m4by4(tr1,tr3,RoboT);
00465  return;
00466 }
00467 
00468 static void NameRobotDirectory(char *script_file, char *robo_dir){
00469   long l;
00470   l=strlen(script_file);
00471   strcpy(robo_dir,script_file);
00472   strcpy((robo_dir+l-4),".skd");
00473 }
00474 
00475 short OpenRobotDirectory(char * script_file){
00476   SECURITY_ATTRIBUTES sa;
00477   char str[255];
00478   sa.nLength=sizeof(sa);
00479   sa.lpSecurityDescriptor=NULL;
00480   sa.bInheritHandle=FALSE;
00481   NameRobotDirectory(script_file,str);
00482   if(CreateDirectory(str,&sa))return 1;
00483   /* try to remove an old  one before giving up */
00484   RemoveRobotDirectory(script_file);
00485   if(CreateDirectory(str,&sa))return 1;
00486   else               return 0;
00487 }
00488 
00489 void RemoveRobotDirectory(char *script_file){
00490  HANDLE h;
00491  WIN32_FIND_DATA ffd,*lpffd;
00492  char str[255],strr[255],title[64];
00493  NameRobotDirectory(script_file,str);
00494  sprintf(strr,"%s\\$*.*",str);
00495  lpffd=&ffd;
00496  if((h=FindFirstFile(strr,lpffd)) == INVALID_HANDLE_VALUE){
00497    if(!RemoveDirectory(str)){
00498      LoadString(ghinst_main,IDX_MISC_ERROR1,title,64);
00499      MessageBox(NULL,str,title,MB_OK);
00500    }
00501    return;
00502  }
00503  sprintf(strr,"%s\\%s",str,lpffd->cFileName);
00504  if(!DeleteFile(strr))MessageBeep(MB_OK);
00505  while(FindNextFile(h,lpffd)){
00506    sprintf(strr,"%s\\%s",str,lpffd->cFileName);
00507    if(!DeleteFile(strr))MessageBeep(MB_OK);
00508  }
00509  if(GetLastError() != ERROR_NO_MORE_FILES){
00510    SendPrgmQuery(IDQ_BADNEXTFILE,3);
00511  }
00512  if(!FindClose(h))SendPrgmQuery(IDQ_BADFILE,3);
00513  if(!RemoveDirectory(str))MessageBeep(MB_OK);
00514 }
00515 
00516 void GetRobotScriptName(char *script_file, long node_id,
00517                         short lastframe, char *robot_name){
00518   char str[255];
00519   NameRobotDirectory(script_file,str);
00520   sprintf(robot_name,"%s\\$%d.%ld",str,lastframe,node_id);
00521 }
00522 
00523 short RobotFileExists(char *robot_name){
00524   int fd;
00525   if((fd=open(robot_name,O_RDONLY)) < 0)return 0;
00526   close(fd);
00527   return 1;
00528 }
00529 
00530 static void EditRobotTransform(int command){
00531  object *Op;
00532  skel   *sp;
00533  long j,id;
00534  if((Op=SelectedRobot) == NULL)return;
00535  if(command == 0){ /* reset robot */
00536    sp=Op->skeleton;
00537    for(j=0;j<Op->nskeleton;j++){
00538      null_transform(sp->R);
00539      null_transform(sp->Q);
00540      null_transform(sp->T);
00541      sp++;
00542    }
00543  }
00544  else if(command == 2){ /* reset selected */
00545    if(SelectedRobotArm >= 0 && SelectedRobotArm < Op->nskeleton){
00546      sp=(Op->skeleton+SelectedRobotArm);
00547      null_transform(sp->R);
00548      null_transform(sp->Q);
00549      null_transform(sp->T);
00550      sp=Op->skeleton;
00551      if((GetAsyncKeyState(VK_SHIFT) & 0x8000) == 0x8000){
00552        for(j=0;j<Op->nskeleton;j++){
00553          id=sp->id;
00554          while(id != 0){
00555            if(id == SelectedRobotArm){
00556              null_transform(sp->R);
00557              null_transform(sp->Q);
00558              null_transform(sp->T);
00559              break;
00560            }
00561            id=(Op->skeleton+id)->id;
00562          }
00563          sp++;
00564        }
00565      }
00566    }
00567  }
00568  else if(command == 1){/* copy from last */
00569    if(Op->last != NULL && Op->last->nskeleton == Op->nskeleton){
00570      j=(long)(Op->last->nskeleton)*(long)sizeof(skel);
00571      memcpy(Op->skeleton,Op->last->skeleton,j);
00572    }
00573    else MessageBeep(MB_OK);
00574  }
00575  ReDrawStageDisplay(TRUE);
00576  PerspectiveView(0,0);
00577  return;
00578 }
00579 
00580 void WriteRobot(object *Op, char *robot_name){
00581   long i,j,n;
00582   FILE *frobot;
00583   skel *sk;
00584   if((frobot = fopen(robot_name,"w")) != NULL){
00585     if((n=Op->nskeleton) > 0 && (sk=Op->skeleton) != NULL){
00586       fprintf(frobot,"%ld\n",n);
00587       for(i=0;i<n;i++){
00588         for(j=0;j<4;j++)fprintf(frobot,"%lf %lf %lf %lf\n",
00589          sk[i].R[j][0],sk[i].R[j][1],sk[i].R[j][2],sk[i].R[j][3]);
00590       }
00591     }
00592     else{
00593       fprintf(frobot,"0\n");
00594     }
00595     fclose(frobot);
00596   }
00597 }
00598 
00599 static int nSkeleton;
00600 skel   *Skeleton;
00601 
00602 static void ApplyTransformToChildren(int id, double T[4][4]){
00603  static double x,y,z;
00604  static double sst[4][4],t1[4][4],t2[4][4];
00605  int i;
00606  for(i=1;i<nSkeleton;i++){ /* must start at one since root is never a child */
00607    if(Skeleton[i].id == id){
00608      tram(t1,-(Skeleton+id)->p[0],-(Skeleton+id)->p[1],-(Skeleton+id)->p[2]);
00609      m4by4((Skeleton+i)->Q,t1,t2);
00610      tram(t1, (Skeleton+id)->p[0], (Skeleton+id)->p[1], (Skeleton+id)->p[2]);
00611      m4by4(t1,t2,sst);
00612      m4by4(T,sst,Skeleton[i].T);
00613      m4by1(Skeleton[i].T,  /* transform point as well and store for drawing */
00614            (double)Skeleton[i].p[0],
00615            (double)Skeleton[i].p[1],
00616            (double)Skeleton[i].p[2],&x,&y,&z);
00617            Skeleton[i].pp[0]=(long)x;
00618            Skeleton[i].pp[1]=(long)y;
00619            Skeleton[i].pp[2]=(long)z;
00620      ApplyTransformToChildren(i,Skeleton[i].T);
00621    }
00622  }
00623  return;
00624 }
00625 
00626 void  SetRobotToWalkPath(node *Np){ // Np is the robot to put on path
00627  char nodename[255];
00628  node *OnPath;
00629  object *Op,*Opath;
00630  position *Pp,*Ppath;
00631  align *Ap,*Apn;
00632  point cp,lp,pathpos,pathposA;
00633  vector delta,deltaa;
00634  int pathff;
00635  double pl,d,distance=0.0,dd,dxy,x,y,z;
00636  if((OnPath=SelectNode(nodename,NO,ghwnd_main)) != NULL){
00637    if(OnPath->type == PATH){ // path selected so can do it
00638      // remove any rotation keyframes so we can put them back
00639      Ap=Np->fali; while(Ap != NULL){Apn=Ap->next; DeleteAlign(Np,Ap->firstframe); Ap=Apn;}
00640      Ppath=OnPath->fpos;
00641      Opath=OnPath->fobj;
00642 
00643      if(Opath == NULL)return; // no path costume
00644      pathff=Opath->firstframe-1; // this is the first path frame offset from start
00645 
00646      // re-postion the robots keyframes so that they start at the first path frame assumes that robot loaded at frame 1
00647      Op=Np->fobj; while(Op != NULL){
00648        Op->firstframe  += pathff;
00649        Op->lastframe   += pathff;
00650        Op=Op->next;
00651      }
00652      Pp=Np->fpos; while(Pp != NULL){
00653        Pp->firstframe  += pathff;
00654        Pp->lastframe   += pathff;
00655        Pp=Pp->next;
00656      }
00657 
00658      pl=PathLength(Opath->firstpathpoint,Opath->pathtype,Opath->npathpoints);
00659      dd = pl*0.01;  // use 1% to determine the point infront so as to get direction of path on path
00660 //fprintf(debug,"Pl=%lf dd=%lf\n",pl,dd);
00661      Pp=Np->fpos; while(Pp != NULL){
00662        if(Pp == Np->fpos)VECCOPY(Pp->finish,lp)
00663        else VECCOPY(cp,lp) 
00664        VECCOPY(Pp->finish,cp)  // this is the current position of the robot
00665        VECSUB(cp,lp,delta)  // delta is the displacement from previous 
00666        d=sqrt(DOT(delta,delta)); 
00667        distance += d;
00668 //fprintf(debug,"(%d %d) d=%lf\n",Pp->firstframe,Pp->lastframe,distance);
00669        // now get the path position parameterised by distance 
00670        GetPathPositionAtDistance(OnPath,Opath,distance,pathpos); // this is relative to path without position/rotation/scale
00671        GetPathPositionAtDistance(OnPath,Opath,distance+dd,pathposA); // used for Alignment
00672        VECSUB(pathposA,pathpos,deltaa);
00673        // now set the robot position
00674        if(Ppath != NULL)VECSUM(Ppath->finish,pathpos,pathpos)
00675        VECCOPY(pathpos,Pp->finish) // overwrites but not used again
00676        // align it to the path
00677        Ap=CreateAlign(Np,Pp->firstframe,Pp->lastframe); // new align steps to match position
00678        if(Ap!= NULL && A_normalize(deltaa)){
00679          x=deltaa[0]; y=deltaa[1]; z=deltaa[2]; 
00680          dxy=sqrt(x*x+y*y);
00681          Ap->theta=0.0;
00682          Ap->phi=RAD2DEG*atan2(y,x);  
00683          if(GetAsyncKeyState(VK_CONTROL) & 0x8000){
00684            Ap->phi -= 90.0; if(Ap->phi < -180.0)Ap->phi += 360.0; // for front facing character
00685          }
00686          else{
00687            Ap->phi += 90.0; if(Ap->phi >  180.0)Ap->phi -= 360.0; // for back facing character
00688          }
00689          Ap->alpha = -RAD2DEG*atan2(z,dxy);
00690 //fprintf(debug,"Align (%d %d) alpha=%lf phi=%lf  (dx/dy/dz %lf %lf %lf\n",Ap->firstframe,Ap->lastframe,Ap->phi,Ap->alpha,x,y,z);  
00691        } 
00692        Pp=Pp->next;
00693      }
00694    }
00695    else MessageBox(NULL,"Not a path",NULL,MB_OK);
00696  }
00697 }
00698 
00699 void ExportRobotSequence(node *Np){  // export this robot's skeleton orientation 
00700  FILE *pz;
00701  skel *sk;
00702  object *Op;
00703  position *Pp;
00704  point ptstart={0,0.0};
00705  int i,j,n,nr,ko,np,nf=0,ns=0;
00706  if(SelectSfxFileName(1,gszRSQfile,gszRSQdir,IDX_MISC_EXPORT_ROBOT,
00707     "(*.RSQ)|*.rsq|",ghwndTimeline) == TRUE){
00708    AppendFileExtension(gszRSQfile,".rsq");
00709    if((pz=fopen(gszRSQfile,"w")) != NULL){
00710      Op=Np->fobj; nr=0;
00711      if(Op != NULL)ns=Op->firstframe;
00712      while(Op != NULL){
00713        nr++; 
00714       if(Op->next == NULL)nf=Op->lastframe;
00715        Op=Op->next;
00716      }
00717      fprintf(pz,"%ld %ld %ld %ld\n%s\n",nr,ns,nf,nf-ns+1,Np->fobj->name); // number of sequences (duration)
00718      Op=Np->fobj; ko=1; while(Op != NULL){
00719        fprintf(pz,"%ld %ld %ld\n",ko,Op->firstframe,Op->lastframe);   // and then the poses for each robot
00720        if((n=Op->nskeleton) > 0 && (sk=Op->skeleton) != NULL){
00721          fprintf(pz,"%ld\n",n);
00722          for(i=0;i<n;i++){
00723            for(j=0;j<4;j++)fprintf(pz,"%lf %lf %lf %lf\n",
00724             sk[i].R[j][0],sk[i].R[j][1],sk[i].R[j][2],sk[i].R[j][3]);
00725          }
00726        }
00727        else{ fprintf(pz,"0\n");  }
00728        ko++;
00729        Op=Op->next;
00730      }
00731      // Now export the position number of positions 
00732      np=0;
00733      if((Pp=Np->fpos) != NULL){
00734        while(Pp != NULL){
00735          if(np == 0)VECCOPY(Pp->finish,ptstart)// this is the base point
00736          np++;
00737          Pp=Pp->next;
00738        }
00739      }
00740      fprintf(pz,"%ld %ld %ld %ld\n",np,ptstart[0],ptstart[1],ptstart[2]);
00741      if(np > 0){
00742        Pp=Np->fpos; while(Pp != NULL){
00743          fprintf(pz,"%ld %ld %ld %ld %ld\n",Pp->firstframe,Pp->lastframe,
00744                  Pp->finish[0]-ptstart[0],Pp->finish[1]-ptstart[1],Pp->finish[2]-ptstart[2]);
00745          Pp=Pp->next;
00746        }
00747      }
00748      fclose(pz);
00749    } 
00750  }
00751 }
00752 
00753 long ImportRobotSequence(long n, node *Np, char *filename,long firstframe, long lastframe){ 
00754  // n = number of times sequence is to be used
00755  long r,i,j,k,retval=OK,nseq,nfirst,nlast,nfr,ff,ffp,lf,ko,kff,klf,nsk,nsk1,np;
00756  point startpoint;
00757  long dx,dy,dz;
00758  char robot_name[MAX_FILE];
00759  object *tempobj;
00760  position *Pp,*LastPp;
00761  skel *sk;
00762  FILE *pz;  
00763  BOOL bEject=FALSE;
00764  //{char sss[255]; sprintf(sss,"Import from [%s] into %d %d",filename,firstframe,lastframe);
00765  //MessageBox(NULL,sss,"Debug",MB_OK);} 
00766  DeletePositionIn(Np,firstframe,lastframe); // delete any positions present (put in by auto-creation
00767  if((pz=fopen(filename,"r")) != NULL){
00768    DeleteCostume(Np,firstframe);  // get rid of temporary one first 
00769    ff=firstframe;
00770    ffp=firstframe;
00771    for(r=0;r<n;r++){
00772      fscanf(pz,"%ld %ld %ld %ld",&nseq,&nfirst,&nlast,&nfr);
00773      fscanf(pz,"  %[^\n]",robot_name);
00774      //MessageBox(NULL,robot_name,filename,MB_OK);
00775      if(ff > lastframe){ // skip unused
00776        double m1,m2,m3,m4;
00777        for(i=0;i<nseq;i++){ 
00778          fscanf(pz,"%ld %ld %ld\n",&ko,&kff,&klf);
00779          fscanf(pz,"%ld\n",&nsk); 
00780          if(nsk > 0){ 
00781            for(k=0;k<nsk;k++){
00782              for(j=0;j<4;j++)fscanf(pz,"%lf %lf %lf %lf",&m1,&m2,&m3,&m4);
00783            }
00784          }
00785        }
00786      } 
00787      else{
00788        for(i=0;i<nseq;i++){
00789          fscanf(pz,"%ld %ld %ld\n",&ko,&kff,&klf);  //  ko should = i+1; 
00790          lf=ff+(klf-kff); 
00791          lf=min(lf,lastframe);
00792          if(r == 0 || i > 0 || lf-ff > 1){ // to account for loops ignore the first key of subsequent cycles if a single frame
00793            tempobj=CreateCostume(Np,ff,lf);
00794            if(fail_op == YES || tempobj == NULL){fail_op=NO; retval=FAIL; goto ALL_DONE;}
00795            if(r > 0 && i == 1 && tempobj->last != NULL)tempobj->firstframe = tempobj->last->lastframe + 1; // to account for loops
00796            strcpy(tempobj->name,robot_name);
00797            tempobj->morph=0;
00798            if(LoadMeshObject(tempobj->name,tempobj,YES,YES,YES) == FAIL){
00799              DeleteCostume(Np,ff);
00800              retval=FAIL;
00801              goto ALL_DONE;
00802            }
00803          }
00804          fscanf(pz,"%ld\n",&nsk); // number of skeleton pieces read the skeleton and map onto skeleton
00805          nsk1=tempobj->nskeleton;
00806          sk=tempobj->skeleton;
00807          if(sk == NULL || nsk1 != nsk){
00808            MessageBox(NULL,"Incompatible Skeletons",NULL,MB_OK); retval=FAIL; goto ALL_DONE;
00809          }
00810          if(nsk > 0){ 
00811            //float m1,m2,m3,m4;
00812            for(k=0;k<nsk;k++){
00813              for(j=0;j<4;j++)fscanf(pz,"%lf %lf %lf %lf", //&m1,&m2,&m3,&m4);
00814                  &sk[k].R[j][0],&sk[k].R[j][1], &sk[k].R[j][2], &sk[k].R[j][3]);
00815            }
00816          }
00817          ff=lf+1;
00818        } // i
00819      }
00820      // now put in the positions
00821      fscanf(pz,"%ld %ld %ld %ld",&np,&startpoint[0],&startpoint[1],&startpoint[2]);
00822      if(np > 0){
00823        // see if this is an added in robot and get last position to use as start
00824        LastPp=Pp=Np->fpos; while(Pp != NULL){
00825          LastPp=Pp;
00826          Pp=Pp->next;
00827        }
00828        if(LastPp != NULL)VECCOPY(LastPp->finish,startpoint) // use the last point as the starting point
00829        else { // first time offset using the current cursor
00830          startpoint[0] = NpointerX; startpoint[1] = NpointerY; startpoint[2] = NpointerZ;
00831        } 
00832        for(i=0;i<np;i++){
00833          fscanf(pz,"%ld %ld %ld %ld %ld\n",&kff,&klf,&dx,&dy,&dz);
00834          if(ffp <= lastframe){  
00835            lf=ffp+(klf-kff); 
00836            lf=min(lf,lastframe);
00837            if(r == 0 || i > 0 || lf-ffp > 1){ // to account for loops ignore the first key of subsequent cycles if a single frame
00838              Pp=CreatePosition(Np,ffp,lf);
00839              if(Pp != NULL){ 
00840                Pp->type=TWEEN;
00841                if(r > 0 && i == 1 && Pp->last != NULL)Pp->firstframe = Pp->last->lastframe + 1; // to account for loops
00842                //{char sss[255]; sprintf(sss,"%d (%d) Create Position (%d %d) (%d %d)",r,i,kff,klf,ffp,lf);
00843                //MessageBox(NULL,sss,"Debug",MB_OK);} 
00844                Pp->finish[0]=startpoint[0]+dx;
00845                Pp->finish[1]=startpoint[1]+dy;
00846                Pp->finish[2]=startpoint[2]+dz;
00847              }
00848            }
00849            ffp=lf+1;
00850          }
00851        }
00852      }
00853      rewind(pz);   // go get the next sequence 
00854    } // r 
00855    ALL_DONE:
00856    fclose(pz);
00857  }  
00858  return retval;
00859 }
00860 
00861 
00862 #define EPSILON 1.0e-6
00863 
00864 static void MatrixToQuaternion(double m[4][4], quaternion q){
00865  double w4,x2;
00866  q[0]=0.25*(1.0+m[0][0]+m[1][1]+m[2][2]);
00867  if(q[0] > EPSILON){
00868    q[0]=sqrt(q[0]);
00869    w4=1.0/(4.0*q[0]);
00870    q[1]=(m[1][2]-m[2][1])*w4;
00871    q[2]=(m[2][0]-m[0][2])*w4;
00872    q[3]=(m[0][1]-m[1][0])*w4;
00873  }
00874  else{
00875    q[0]=0.0;
00876    q[1]= -0.5*(m[1][1]+m[2][2]);
00877    if(q[1] > EPSILON){
00878      q[1]=sqrt(q[1]);
00879      x2=1.0/(2.0*q[1]);
00880      q[2]=m[0][1]*x2;
00881      q[3]=m[0][2]*x2;
00882    }
00883    else{
00884      q[1]=0.0;
00885      q[2]=0.5*(1.0-m[2][2]);
00886      if(q[2] > EPSILON){
00887        q[2]=sqrt(q[2]);
00888        q[3]=m[1][2]/(2.0*q[2]);
00889      }
00890      else{
00891        q[2]=0.0;
00892        q[3]=1.0;
00893      }
00894    }
00895  }
00896  return;
00897 }
00898 
00899 static void QuaternionToMatrix(quaternion q, double m[4][4]){
00900  double w,x,y,z,x2,y2,z2;
00901  w=q[0]; x=q[1]; y=q[2]; z=q[3]; x2=x*x; y2=y*y; z2=z*z;
00902  m[0][0]=1.0-2*y2-2*z2; m[0][1]=2*x*y+2*w*z;   m[0][2]=2*x*z-2*w*y;
00903  m[1][0]=2*x*y-2*w*z;   m[1][1]=1.0-2*x2-2*z2; m[1][2]=2*y*z+2*w*x;
00904  m[2][0]=2*x*z+2*w*y;   m[2][1]=2*y*z-2*w*x;   m[2][2]=1.0-2*x2-2*y2;
00905  m[3][3]=1.0; m[0][3]=m[1][3]=m[2][3]=m[3][0]=m[3][1]=m[3][2]=0.0;
00906  return;
00907 }
00908 
00909 static void Slerp(double mr, quaternion q1, quaternion q2, quaternion q){
00910  double sum,beta1,beta2,theta;
00911  sum=q1[0]*q2[0]+q1[1]*q2[1]+q1[2]*q2[2]+q1[3]*q2[3];
00912  if(sum > 1.0)sum=1.0;
00913  theta=acos(sum);
00914  if(theta < EPSILON){ beta1=1.0-mr; beta2=mr;}
00915  else{
00916   beta1=sin((1.0-mr)*theta)/sin(theta);
00917   beta2=sin(mr*theta)/sin(theta);
00918  }
00919  q[0]=beta1*q1[0]+beta2*q2[0];
00920  q[1]=beta1*q1[1]+beta2*q2[1];
00921  q[2]=beta1*q1[2]+beta2*q2[2];
00922  q[3]=beta1*q1[3]+beta2*q2[3];
00923 }
00924 
00925 void InterpolateRobot(double mr, object *Op, object *LastOp){
00926  int i;
00927  quaternion q,q1,q2;
00928  nSkeleton=Op->nskeleton;
00929  Skeleton=Op->skeleton;
00930  if(mr < 1.0 && LastOp != NULL && Op->nskeleton == LastOp->nskeleton){
00931    /* interpopate rotation matrices using Quaternion tweening */
00932 #if 0
00933    for(i=0;i<nSkeleton;i++){ /* this interpolation always from original - bad? */
00934      MatrixToQuaternion((LastOp->skeleton+i)->R,q1);
00935      MatrixToQuaternion((Skeleton+i)->R,q2);
00936      Slerp(mr,q1,q2,q);
00937      QuaternionToMatrix(q,(Skeleton+i)->Q);
00938    }
00939 #else
00940    /* this interpolation always from last frame rotation as origin */
00941    quaternion Qi={1.0,0.0,0.0,0.0};
00942    double Q[4][4],Ri[4][4];
00943    for(i=0;i<nSkeleton;i++){
00944      InvertRotationMatrix((LastOp->skeleton+i)->R,Ri);
00945      m4by4((Skeleton+i)->R,Ri,Q);
00946      MatrixToQuaternion(Q,q2);
00947      Slerp(mr,Qi,q2,q);
00948      QuaternionToMatrix(q,Q);
00949 //     m4by4((LastOp->skeleton+i)->R,Q,(Skeleton+i)->Q); fault !!!
00950      m4by4(Q,(LastOp->skeleton+i)->R,(Skeleton+i)->Q);
00951    }
00952 #endif
00953  }
00954  else{
00955    for(i=0;i<nSkeleton;i++)c4to4((Skeleton+i)->R,(Skeleton+i)->Q);
00956  }
00957  ApplyTransformToChildren(0,Skeleton[0].T);
00958  return;
00959 }
00960 
00961 // robot treeview dialog
00962 
00963 #define ptrNMHDR       ((LPNMHDR)lparam)
00964 #define ptrNM_TREEVIEW ((NM_TREEVIEW *)lparam)
00965 #define ptrTV_DISPINFO ((TV_DISPINFO *)lparam)
00966 
00967 #define BOUND(x,min,max) ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x)))
00968 
00969 #define IDM_SKTB_V            100
00970 #define IDM_SKTB_U            101
00971 #define IDM_SKTB_W            102
00972 #define IDM_SKTB_X            103
00973 #define IDM_SKTB_Y            104
00974 #define IDM_SKTB_Z            105
00975 #define IDM_SKTB_R            106
00976 #define IDM_SKTB_RESET        107
00977 #define IDM_SKTB_COPY         108
00978 #define IDM_SKTB_SAVE         109
00979 #define IDM_SKTB_LOAD         110
00980 #define IDM_SKTB_ZOOM         111
00981 #define IDM_SKTB_ZOOM_STATE   112
00982 #define IDM_SKTB_RESET_SELECT 113
00983 #define IDM_SKTB_OVERLAY      114
00984 #define IDM_SKTB_TRANSPARENT  115
00985 #define IDM_SKTB_POINTS       116
00986 
00987 static LRESULT CALLBACK RobotOglViewWndProc(HWND, UINT, WPARAM, LPARAM);
00988 static LRESULT CALLBACK RobotHdcViewWndProc(HWND, UINT, WPARAM, LPARAM);
00989 
00990 static PSTR        lpszSkTreeViewClass="SkTreeViewClass";
00991 static PSTR        lpszRobotViewClass="RobotViewClass";
00992 static HWND        hWndTreeView=NULL;
00993 static HWND        hTBWnd=NULL;
00994 static HIMAGELIST  hCoasterImageList=NULL;
00995 static HDC         hdcRobotView=NULL;
00996 static HBITMAP     hbmRobotView=NULL,hbmOldRobotView=NULL;
00997 static int         RobotViewXpos=-1,RobotViewYpos=-1,
00998                    RobotViewXsize=0,RobotViewYsize=0;
00999                    SkTreeViewXpos=-1,SkTreeViewYpos=-1,
01000                    SkTreeViewXsize=0,SkTreeViewYsize=0;
01001 static BOOL        RobotZoomFlag=FALSE,RobotZoomState=FALSE,
01002                    RobotOverlayFlag=FALSE,RobotGlassFlag=FALSE,
01003                    RobotPointsFlag;
01004 
01005 #define NTOOLBARBITMAPS 17
01006 #define NTOOLBARBUTTONS 22 // 18
01007 
01008 static TBBUTTON tbb[NTOOLBARBUTTONS] = {
01009           {9,IDM_SKTB_LOAD,    TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0 },
01010           {10,IDM_SKTB_SAVE,   TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0 },
01011           {0,0,                TBSTATE_ENABLED,TBSTYLE_SEP,   0,0 },
01012           {7,IDM_SKTB_RESET,   TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0 },
01013           {13,IDM_SKTB_RESET_SELECT, TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0 },
01014           {8,IDM_SKTB_COPY,    TBSTATE_ENABLED,TBSTYLE_BUTTON,0,0 },
01015           {0,0,                TBSTATE_ENABLED,TBSTYLE_SEP,   0,0 },
01016           {11,IDM_SKTB_ZOOM,   TBSTATE_ENABLED,TBSTYLE_BUTTON|
01017                                                 TBSTYLE_CHECK,0,0 },
01018           {12,IDM_SKTB_ZOOM_STATE, TBSTATE_ENABLED,TBSTYLE_BUTTON|
01019                                                 TBSTYLE_CHECK,0,0 },
01020 
01021           {0,0,                TBSTATE_ENABLED,TBSTYLE_SEP,   0,0 },
01022           {14,IDM_SKTB_OVERLAY,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01023                                                 TBSTYLE_CHECK,0,0 },
01024           {15,IDM_SKTB_TRANSPARENT,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01025                                                 TBSTYLE_CHECK,0,0 },
01026           {16,IDM_SKTB_POINTS,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01027                                                 TBSTYLE_CHECK,0,0 },
01028 
01029           {0,0,                TBSTATE_ENABLED|TBSTATE_WRAP,TBSTYLE_SEP,0,0 },
01030           {0,0,                TBSTATE_ENABLED,TBSTYLE_SEP,   0,0 },
01031           {0,IDM_SKTB_V,TBSTATE_ENABLED|TBSTATE_CHECKED,TBSTYLE_BUTTON|
01032                                                TBSTYLE_CHECKGROUP, 0,0 },
01033           {1,IDM_SKTB_U,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01034                                                TBSTYLE_CHECKGROUP, 0,0 },
01035           {2,IDM_SKTB_W,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01036                                                TBSTYLE_CHECKGROUP, 0,0 },
01037           {6,IDM_SKTB_R,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01038                                                TBSTYLE_CHECKGROUP, 0,0 },
01039           {5,IDM_SKTB_Y,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01040                                                TBSTYLE_CHECKGROUP, 0,0 },
01041           {4,IDM_SKTB_X,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01042                                                TBSTYLE_CHECKGROUP, 0,0 },
01043           {3,IDM_SKTB_Z,TBSTATE_ENABLED,TBSTYLE_BUTTON|
01044                                                TBSTYLE_CHECKGROUP, 0,0 }
01045                          };
01046 
01047 static HTREEITEM AddTreeViewItem (HWND        hWndTV,
01048                                   HTREEITEM   hParent,
01049                                   HTREEITEM   hInsertAfter,
01050                                   int         iImage,
01051                                   int         iSelectedImage,
01052                                   LPSTR       szText,
01053                                  LPARAM      lParam){
01054  TV_INSERTSTRUCT       tvIns;
01055  tvIns.item.mask           = TVIF_TEXT  | TVIF_IMAGE |
01056                          TVIF_SELECTEDIMAGE | TVIF_PARAM;
01057  tvIns.item.pszText        = szText;
01058  tvIns.item.cchTextMax     = sizeof(szText);
01059  tvIns.item.iImage         = iImage;
01060  tvIns.item.iSelectedImage = iSelectedImage;
01061  tvIns.item.lParam         = lParam;
01062  tvIns.hParent             = hParent;
01063  tvIns.hInsertAfter        = hInsertAfter;
01064  return TreeView_InsertItem(hWndTV,&tvIns);
01065 }
01066 
01067 static void SelectTreeViewItem(void){
01068  skel *sp;
01069  int n;
01070  if(SelectedRobot == NULL)return;
01071  if((sp=SelectedRobot->skeleton) == NULL)return;
01072  n=SelectedRobot->nskeleton;
01073  if(SelectedRobotArm < 0 || SelectedRobotArm >= n)return;
01074  TreeView_EnsureVisible(hWndTreeView,(HTREEITEM)(sp+SelectedRobotArm)->lParam);
01075  TreeView_Select(hWndTreeView,(HTREEITEM)(sp+SelectedRobotArm)->lParam,TVGN_CARET);
01076 }
01077 
01078 static void AddTwigsTo(long id, HWND hWndTV){
01079  int i;
01080  skel *sp;
01081  HTREEITEM hParent;
01082  sp=(SelectedRobot->skeleton+1);
01083  for(i=1;i<SelectedRobot->nskeleton;i++){
01084    if(sp->id == id){
01085      hParent=(HTREEITEM)((SelectedRobot->skeleton+id)->lParam);
01086      sp->lParam=(LPARAM)AddTreeViewItem(hWndTV,hParent,(HTREEITEM)TVI_FIRST,
01087                                       0,1,
01088                                       (LPSTR)sp->name,
01089                                       (LPARAM)i);
01090      AddTwigsTo(i,hWndTV);
01091    }
01092    sp++;
01093  }
01094 }
01095 
01096 static void UpdateSkTreeView(void){
01097  int i;
01098  skel *sp;
01099  object *Op;
01100  if(!IsWindow(hWndTreeView))return;
01101  TreeView_DeleteItem(hWndTreeView,TVI_ROOT);
01102  SelectedRobot->skeleton->lParam=(LPARAM)AddTreeViewItem(hWndTreeView,
01103                                      TVI_ROOT,
01104                                      (HTREEITEM)TVI_FIRST,
01105                                      0,1,
01106                                      (LPSTR)SelectedRobot->skeleton->name,
01107                                      (LPARAM)0);
01108  AddTwigsTo(0,hWndTreeView);
01109  for(i=1;i<SelectedRobot->nskeleton;i++){
01110   sp=(SelectedRobot->skeleton+i);
01111   if(sp->id == 0){
01112     TreeView_EnsureVisible(hWndTreeView,(HTREEITEM)sp->lParam);
01113     TreeView_Expand(hWndTreeView,(HTREEITEM)sp->lParam,TVE_EXPAND);
01114    }
01115  }
01116  /* now copy all the TV Handles into all the channels skel LPARAMS's in case
01117     we change to different pose channel - this assumes that all poses have
01118     the same skeleton structure and that the TV is NOT changed. */
01119  if(SelectedNode != NULL){
01120    Op=SelectedNode->fobj;
01121    while(Op != NULL){
01122      if(Op != SelectedRobot){
01123        for(i=0;i<SelectedRobot->nskeleton;i++){
01124          if(i < Op->nskeleton)
01125            (Op->skeleton+i)->lParam=(SelectedRobot->skeleton+i)->lParam;
01126        }
01127      }
01128      Op=Op->next;
01129    }
01130  }
01131 }
01132 
01133 static BOOL TreeviewMenuCommand(HWND hWnd, WORD id){
01134  FILE *pz;
01135  long k;
01136  switch (id) {
01137    case IDM_SKTB_V:
01138      gToolFlags.flagK=0;
01139      break;
01140    case IDM_SKTB_U:
01141      gToolFlags.flagK=1;
01142      break;
01143    case IDM_SKTB_W:
01144      gToolFlags.flagK=2;
01145      break;
01146    case IDM_SKTB_X:
01147      gToolFlags.flagK=3;
01148      break;
01149    case IDM_SKTB_Y:
01150      gToolFlags.flagK=4;
01151      break;
01152    case IDM_SKTB_Z:
01153      gToolFlags.flagK=5;
01154      break;
01155    case IDM_SKTB_R:
01156      gToolFlags.flagK=6;
01157      break;
01158    case IDM_SKTB_RESET:
01159      EditRobotTransform(0);
01160      break;
01161    case IDM_SKTB_RESET_SELECT:
01162      EditRobotTransform(2);
01163      break;
01164    case IDM_SKTB_COPY:
01165      EditRobotTransform(1);
01166      break;
01167    case IDM_SKTB_ZOOM:
01168      RobotZoomFlag ^= 1;
01169      break;
01170    case IDM_SKTB_ZOOM_STATE:
01171      RobotZoomState ^= 1;
01172      break;
01173    case IDM_SKTB_SAVE:
01174      if(SelectSfxFileName(1,gszPZEfile,gszPZEdir,
01175         IDX_MISC_SAVEPOSE,"(*.PZE)|*.pze|",ghwnd_main) == TRUE){
01176        AppendFileExtension(gszPZEfile,".pze");
01177        if((pz=fopen(gszPZEfile,"wb")) != NULL){
01178          k=0xFEFE;
01179          fwrite(&k,sizeof(long),1,pz);
01180          k=0;
01181          fwrite(&k,sizeof(long),1,pz); /* use this for future */
01182          fwrite(SelectedRobot->name,255,1,pz);
01183          fwrite(&(SelectedRobot->nskeleton),sizeof(long),1,pz);
01184          if(SelectedRobot->nskeleton > 0)
01185            for(k=0;k<SelectedRobot->nskeleton;k++){
01186            fwrite(SelectedRobot->skeleton[k].R,sizeof(double),16,pz);
01187          }
01188          fclose(pz);
01189        }
01190        else MessageBeep(MB_OK);
01191      }
01192      break;
01193    case IDM_SKTB_LOAD:
01194      if(SelectSfxFileName(0,gszPZEfile,gszPZEdir,
01195         IDX_MISC_LOADPOSE,"(*.PZE)|*.pze|",ghwnd_main) == TRUE){
01196        if((pz=fopen(gszPZEfile,"rb")) != NULL){
01197          fread(&k,sizeof(long),1,pz);
01198          if(k == 0xFEFE){
01199            char robo_name[256];
01200            fread(&k,sizeof(long),1,pz); /* use this for future */
01201            fread(robo_name,255,1,pz);
01202            fread(&k,sizeof(long),1,pz);
01203            if(k == SelectedRobot->nskeleton){
01204              if(SelectedRobot->nskeleton > 0){
01205                for(k=0;k<SelectedRobot->nskeleton;k++){
01206                  fread(SelectedRobot->skeleton[k].R,sizeof(double),16,pz);
01207                }
01208                ReDrawStageDisplay(TRUE);
01209                PerspectiveView(0,0);
01210              }
01211            }
01212            else SendPrgmQuery(IDQ_BADPOSE,0);
01213          }
01214          else SendPrgmQuery(IDQ_NOTPOSE,0);
01215          fclose(pz);
01216        }
01217        else MessageBeep(MB_OK);
01218      }
01219      break;
01220    case IDM_SKTB_OVERLAY:
01221      RobotOverlayFlag ^= 1;
01222      break;
01223    case IDM_SKTB_TRANSPARENT:
01224      RobotGlassFlag ^= 1;
01225      break;
01226    case IDM_SKTB_POINTS:
01227      RobotPointsFlag ^= 1;
01228      break;
01229    default:
01230      break;
01231  }
01232  if(IsWindow(ghwndRobotView))PostMessage(ghwndRobotView,WM_DRAWROBOT,0,0);
01233  return TRUE;
01234 }
01235 
01236 static LRESULT CALLBACK SkTreeViewWndProc(HWND hwnd, UINT msg, WPARAM wparam,
01237                                     LPARAM lparam ){
01238  static int ToolbarHeight;
01239  TV_ITEM  tvi;
01240  RECT rc,rc1;
01241  int dx,dy,y;
01242  DWORD dwStyle;
01243  skel *sp;
01244  switch( msg ){
01245    case WM_CREATE:
01246      dwStyle=WS_CHILD | WS_VISIBLE | WS_BORDER;
01247      if(Preferences.tooltips)dwStyle = dwStyle | TBSTYLE_TOOLTIPS;
01248      hTBWnd = CreateToolbarEx(hwnd,dwStyle,
01249         0,      // control identifier for the toolbar
01250         NTOOLBARBITMAPS,     // bitmaps images
01251         ghinst_main,
01252         IDBM_SKTOOLBAR,
01253         tbb,
01254         NTOOLBARBUTTONS,
01255         16,15,  // size of buttons
01256         16,15,  // size of bitmap
01257         sizeof(TBBUTTON)
01258        );
01259      SendMessage(hTBWnd,TB_AUTOSIZE,0,0);
01260      gToolFlags.flagK=0;
01261      if(0){dx=32; dy=32;} else {dx=16; dy=16;}
01262      hCoasterImageList=ImageList_Create(
01263                          dx,dy,
01264                          TRUE,
01265                          2,
01266                          5
01267                          );
01268      ImageList_AddIcon(hCoasterImageList,
01269                               LoadIcon(ghinst_main,"TREEVIEWICON0"));
01270      ImageList_AddIcon(hCoasterImageList,
01271                               LoadIcon(ghinst_main,"TREEVIEWICON1"));
01272      GetClientRect(hTBWnd,&rc1); ToolbarHeight=rc1.bottom+1;
01273      GetClientRect(hwnd,&rc);
01274      hWndTreeView = CreateWindowEx(0,WC_TREEVIEW,
01275                                  " ",
01276                                  WS_VISIBLE | WS_CHILD | WS_BORDER |
01277                                  TVS_HASLINES | TVS_HASBUTTONS |
01278                                  TVS_EDITLABELS | TVS_LINESATROOT,
01279                                  0,ToolbarHeight,
01280                                  rc.right, rc.bottom,
01281                                  hwnd,
01282                                  (HMENU)0,
01283                                  ghinst_main,
01284                                  NULL
01285                                );
01286      if(hWndTreeView != NULL){
01287        TreeView_SetImageList(hWndTreeView,hCoasterImageList,0);
01288        ImageList_SetBkColor(hCoasterImageList,GetSysColor(COLOR_WINDOW));
01289        UpdateSkTreeView();
01290      }
01291      LastSelectedRobotNode=SelectedNode;
01292      UpdateRobot(SelectedRobot);
01293      break;
01294    case WM_DESTROY:{
01295        char str[32];
01296        GetWindowRect(hwnd,&rc);
01297        sprintf(str,"%ld",rc.left);
01298        WritePrivateProfileString(IniSection,"RSPOSX",str,IniFilename);
01299        sprintf(str,"%ld",rc.top);
01300        WritePrivateProfileString(IniSection,"RSPOSY",str,IniFilename);
01301        sprintf(str,"%ld",rc.right-rc.left);
01302        WritePrivateProfileString(IniSection,"RSSIZX",str,IniFilename);
01303        sprintf(str,"%ld",rc.bottom-rc.top);
01304        WritePrivateProfileString(IniSection,"RSSIZY",str,IniFilename);
01305        SkTreeViewXpos=rc.left;           SkTreeViewYpos=rc.top;
01306        SkTreeViewXsize=rc.right-rc.left; SkTreeViewYsize=rc.bottom-rc.top;
01307        if(hCoasterImageList != NULL)ImageList_Destroy(hCoasterImageList);
01308        hCoasterImageList=NULL;
01309        DestroyWindow(hWndTreeView);
01310        hWndTreeView=NULL;
01311        DestroyWindow(hTBWnd);
01312        hTBWnd=NULL;
01313      }
01314      break;
01315    case WM_SYSCOMMAND:
01316      switch(LOWORD(wparam & 0xfff0)){
01317        case SC_CLOSE:
01318          //         PostMessage(ghwnd_main,WM_COMMAND,IDM_STOP_TOOL,0);
01319          PostQuitMessage(0);   // only for case when THREADED
01320          break;
01321        default:
01322          return(DefWindowProc(hwnd,msg,wparam,lparam));
01323       }
01324       break;
01325    case WM_NOTIFY:
01326      switch (ptrNMHDR->code){
01327        case TTN_NEEDTEXT:{
01328            int idButton;
01329            LPTOOLTIPTEXT lpttt;
01330            lpttt=(LPTOOLTIPTEXT)lparam;
01331            lpttt->hinst=ghinst_main;
01332            idButton=lpttt->hdr.idFrom;
01333            switch(idButton){
01334              case IDM_SKTB_V:
01335                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_1); break;
01336              case IDM_SKTB_U:
01337                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_2); break;
01338              case IDM_SKTB_W:
01339                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_3); break;
01340              case IDM_SKTB_X:
01341                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_4); break;
01342              case IDM_SKTB_Y:
01343                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_5); break;
01344              case IDM_SKTB_Z:
01345                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_6); break;
01346              case IDM_SKTB_R:
01347                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_7); break;
01348              case IDM_SKTB_RESET:
01349                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_8); break;
01350              case IDM_SKTB_COPY:
01351                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_9); break;
01352              case IDM_SKTB_LOAD:
01353                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_0); break;
01354              case IDM_SKTB_SAVE:
01355                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_A); break;
01356              case IDM_SKTB_ZOOM:
01357                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_B); break;
01358              case IDM_SKTB_ZOOM_STATE:
01359                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_C); break;
01360              case IDM_SKTB_RESET_SELECT:
01361                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_D); break;
01362               case IDM_SKTB_OVERLAY:
01363                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_E); break;
01364               case IDM_SKTB_TRANSPARENT:
01365                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_F); break;
01366               case IDM_SKTB_POINTS:
01367                lpttt->lpszText=MAKEINTRESOURCE(IDI_TIP_K_G); break;
01368            }
01369          }
01370          break;
01371        case TVN_SELCHANGED:
01372          if(ptrNM_TREEVIEW->action == TVC_BYKEYBOARD ||
01373             ptrNM_TREEVIEW->action == TVC_BYMOUSE){
01374            tvi.mask  = TVIF_PARAM;
01375            tvi.hItem = ptrNM_TREEVIEW->itemNew.hItem;
01376            TreeView_GetItem(hWndTreeView,&tvi);
01377            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01378            SelectedRobotArm=(long)tvi.lParam;
01379            DrawInvertNode(ghdc_triview_Bitmap,SelectedNode,SELECTED);
01380            if(IsWindow(ghwndRobotView))PostMessage(ghwndRobotView,WM_DRAWROBOT,0,0);
01381          }
01382          break;
01383        case TVN_BEGINLABELEDIT:
01384          return 1;
01385          break;
01386        default: break;
01387      }
01388      return (DefWindowProc(hwnd,msg,wparam,lparam));
01389    case WM_COMMAND:
01390      return TreeviewMenuCommand(hwnd,LOWORD(wparam));
01391      break;
01392    case WM_SIZE:
01393      if(hTBWnd != NULL){
01394        SendMessage(hTBWnd,msg,wparam,lparam);
01395      }
01396      if(hWndTreeView != NULL){
01397        SetWindowPos(hWndTreeView,NULL,
01398                     0,ToolbarHeight,
01399                     LOWORD(lparam),HIWORD(lparam)-ToolbarHeight,
01400                     SWP_NOZORDER);
01401      }
01402      break;
01403    default:
01404      return(DefWindowProc(hwnd,msg,wparam,lparam));
01405  }
01406  return( 0L );
01407 }
01408 
01409 static void ThreadSkeletonTreeView(void *);
01410 static void RobotSkeletonTreeView(HWND hWndParent){
01411  void (*fp)(void *);
01412  if(ghwndSkEdit != NULL){
01413    PostMessage(ghwndSkEdit,WM_SYSCOMMAND,SC_CLOSE,0);
01414    return;
01415  }
01416  fp=ThreadSkeletonTreeView;
01417 #if  __WATCOMC__ && __WATCOMC__ < 1100
01418   _beginthread(fp,0,65536,(void *)hWndParent);
01419 #else
01420   _beginthread(fp,0,(void *)hWndParent);
01421 #endif
01422 }
01423 
01424 static void ThreadSkeletonTreeView(void *arg){
01425  WNDCLASS   wc;
01426  RECT       rc;
01427  int xp,yp,xl,yl;
01428  HWND hWndParent;
01429  hWndParent=(HWND)arg;
01430  RobotZoomFlag=FALSE;
01431  RobotZoomState=FALSE;
01432  RobotOverlayFlag=FALSE;
01433  RobotGlassFlag=FALSE;
01434  RobotPointsFlag=FALSE;
01435  wc.lpszClassName = lpszSkTreeViewClass;
01436  wc.style = CS_HREDRAW | CS_VREDRAW;
01437  wc.lpfnWndProc = (WNDPROC)SkTreeViewWndProc;
01438  wc.cbClsExtra = 0;
01439  wc.cbWndExtra = 0;
01440  wc.hInstance = ghinst_main;
01441  wc.hIcon = LoadIcon(ghinst_main,"ANIMATORICON");
01442  wc.hCursor = LoadCursor(NULL,IDC_ARROW);
01443  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
01444  wc.lpszMenuName = NULL;
01445  if(!RegisterClass(&wc))return;
01446  GetWindowRect(ghwndTools,&rc);
01447  if(SkTreeViewXpos < 0){
01448    xp=GetPrivateProfileInt(IniSection,"RSPOSX",-1,IniFilename);
01449    yp=GetPrivateProfileInt(IniSection,"RSPOSY",-1,IniFilename);
01450    xl=GetPrivateProfileInt(IniSection,"RSSIZX",-1,IniFilename);
01451    yl=GetPrivateProfileInt(IniSection,"RSSIZY",-1,IniFilename);
01452    if(xp < 0 || yp < 0 || xl < 0 || yl < 0){
01453      SkTreeViewXsize=185;
01454      SkTreeViewYsize=255;
01455      if(bToolpannelLeft)SkTreeViewXpos=rc.right+5;
01456      else               SkTreeViewXpos=rc.left-SkTreeViewXsize-5;
01457      SkTreeViewYpos=rc.top;
01458    }
01459    else{
01460      SkTreeViewXsize=xl;
01461      SkTreeViewYsize=yl;
01462      SkTreeViewXpos=xp;
01463      SkTreeViewYpos=yp;
01464    }
01465  }
01466  LoadString(ghinst_main,IDX_MISC_ROBOTHIERARCHY,res_str,256);
01467  ghwndSkEdit = CreateWindow(
01468      wc.lpszClassName,res_str,
01469      WS_POPUP | WS_CAPTION | !WS_SYSMENU | WS_THICKFRAME,
01470      SkTreeViewXpos,SkTreeViewYpos,
01471      SkTreeViewXsize,SkTreeViewYsize,
01472      hWndParent,NULL,ghinst_main,NULL);
01473  ShowWindow(ghwndSkEdit,SW_SHOW);
01474  UpdateWindow(ghwndSkEdit);
01475  if(ghwndSkEdit == NULL){
01476    UnregisterClass(lpszSkTreeViewClass,ghinst_main);
01477    return;
01478  }
01479  wc.lpszClassName = lpszRobotViewClass;
01480  wc.style = CS_HREDRAW | CS_VREDRAW;
01481  if(Preferences.use_gl_robot)wc.lpfnWndProc = (WNDPROC)RobotOglViewWndProc;
01482  else                        wc.lpfnWndProc = (WNDPROC)RobotHdcViewWndProc;
01483  wc.cbClsExtra = 0;
01484  wc.cbWndExtra = 0;
01485  wc.hInstance = ghinst_main;
01486  wc.hIcon = LoadIcon(ghinst_main,"ANIMATORICON");
01487  wc.hCursor = ghcurPan; //LoadCursor(NULL,IDC_ARROW);
01488  wc.hbrBackground = NULL;
01489  wc.lpszMenuName = NULL;
01490  if(!RegisterClass(&wc))return;
01491  LoadString(ghinst_main,IDX_MISC_ROBOTVIEW,res_str,256);
01492  if(RobotViewXpos < 0){
01493    xp=GetPrivateProfileInt(IniSection,"RVPOSX",-1,IniFilename);
01494    yp=GetPrivateProfileInt(IniSection,"RVPOSY",-1,IniFilename);
01495    xl=GetPrivateProfileInt(IniSection,"RVSIZX",-1,IniFilename);
01496    yl=GetPrivateProfileInt(IniSection,"RVSIZY",-1,IniFilename);
01497    if(xp < 0 || yp < 0 || xl < 0 || yl < 0){
01498      RobotViewXpos=150;  RobotViewYpos=100;
01499      RobotViewXsize=300; RobotViewYsize=300;
01500    }
01501    else{
01502      RobotViewXpos=xp;  RobotViewYpos=yp;
01503      RobotViewXsize=xl; RobotViewYsize=yl;
01504    }
01505  }
01506  ghwndRobotView = CreateWindow(
01507      wc.lpszClassName,res_str,
01508      WS_POPUP | WS_CAPTION | !WS_SYSMENU | WS_THICKFRAME |
01509      WS_VSCROLL | WS_HSCROLL |
01510      WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
01511      RobotViewXpos,RobotViewYpos,
01512      RobotViewXsize,RobotViewYsize,
01513      hWndParent,NULL,ghinst_main,NULL);
01514  ShowWindow(ghwndRobotView,SW_SHOW);
01515  UpdateWindow(ghwndRobotView);
01516  if(ghwndRobotView == NULL){
01517    UnregisterClass(lpszRobotViewClass,ghinst_main);
01518    return;
01519  }
01520 //
01521  {
01522    MSG msg;
01523    while(GetMessage(&msg,NULL,0,0)){
01524      TranslateMessage(&msg);
01525      DispatchMessage(&msg);
01526    }
01527    DestroyWindow(ghwndSkEdit);
01528    UnregisterClass(lpszSkTreeViewClass,ghinst_main);
01529    ghwndSkEdit=NULL;
01530    if(ghwndRobotView != NULL){
01531      DestroyWindow(ghwndRobotView);
01532      UnregisterClass(lpszRobotViewClass,ghinst_main);
01533      ghwndRobotView=NULL;
01534    }
01535    //   PostMessage(ghwnd_main,WM_COMMAND,IDM_STOP_SKELETOR,0); // DO NOT CALL THIS BUG
01536    _endthread();
01537  }
01538 //
01539  return;
01540 }
01541 
01542 void UpdateRobot(object *Op){
01543  if(ghwndSkEdit == NULL)return;
01544  if(SelectedNode == NULL || SelectedNode->type != ROBOT){
01545    PostMessage(ghwnd_main,WM_COMMAND,IDM_STOP_TOOL,0);
01546    return;
01547  }
01548  if(SelectedNode != LastSelectedRobotNode){
01549 // Just discard it for now
01550    PostMessage(ghwnd_main,WM_COMMAND,IDM_STOP_TOOL,0);
01551    return;
01552  }
01553  if(Op != SelectedRobot){
01554    vector c;
01555    SelectedRobot=Op;
01556    if(Op == NULL)SelectedRobotArm= -1;
01557    else GetRobotVolume(Op->nskeleton,Op->skeleton,c);
01558  }
01559  return;
01560 }
01561 
01562 static LRESULT CALLBACK RobotHdcViewWndProc(HWND hwnd, UINT msg,
01563                                             WPARAM wparam,LPARAM lparam ){
01564  static BOOL flag=FALSE,mmoved=FALSE,bTrackPan=FALSE;
01565  static long xs,ys;
01566  static double up_angle=0.0,round_angle=0.0;
01567  char str[32];
01568  double old;
01569  HDC  hdc;
01570  RECT rc;
01571  int i,iPos,iMax,iMin,dn;
01572  switch( msg ){
01573    case WM_CREATE:{
01574        vector c;
01575        GetRobotVolume(SelectedRobot->nskeleton,SelectedRobot->skeleton,c);
01576        hdc=GetDC(hwnd);
01577        hdcRobotView=CreateCompatibleDC(hdc);
01578        ReleaseDC(hwnd,hdc);
01579        SetScrollRange(hwnd, SB_VERT, -89,89,TRUE);
01580        SetScrollRange(hwnd, SB_HORZ, -179,179,TRUE);
01581        SetScrollPos(hwnd,SB_HORZ,(int)round_angle,TRUE);
01582        SetScrollPos(hwnd,SB_VERT,(int)up_angle,TRUE);
01583      }
01584      break;
01585    case WM_DESTROY:
01586      if(hbmOldRobotView != NULL)SelectObject(hdcRobotView,hbmOldRobotView);
01587      if(hdcRobotView != NULL)DeleteDC(hdcRobotView);
01588      hdcRobotView=NULL;
01589      if(hbmRobotView != NULL)DeleteObject(hbmRobotView);
01590      hbmRobotView=NULL; hbmOldRobotView=NULL;
01591      GetWindowRect(hwnd,&rc);
01592      RobotViewXpos=rc.left; RobotViewYpos=rc.top;
01593      RobotViewXsize=rc.right-rc.left; RobotViewYsize=rc.bottom-rc.top;
01594      sprintf(str,"%ld",rc.left);
01595      WritePrivateProfileString(IniSection,"RVPOSX",str,IniFilename);
01596      sprintf(str,"%ld",rc.top);
01597      WritePrivateProfileString(IniSection,"RVPOSY",str,IniFilename);
01598      sprintf(str,"%ld",rc.right-rc.left);
01599      WritePrivateProfileString(IniSection,"RVSIZX",str,IniFilename);
01600      sprintf(str,"%ld",rc.bottom-rc.top);
01601      WritePrivateProfileString(IniSection,"RVSIZY",str,IniFilename);
01602      break;
01603    case WM_SYSCOMMAND:
01604      switch(LOWORD(wparam & 0xfff0)){
01605        case SC_CLOSE:
01606          break;
01607        default:
01608          return(DefWindowProc(hwnd,msg,wparam,lparam));
01609       }
01610       break;
01611    case WM_SIZE:
01612      if(hbmOldRobotView != NULL)SelectObject(hdcRobotView,hbmOldRobotView);
01613      if(hbmRobotView != NULL)DeleteObject(hbmRobotView);
01614      hbmRobotView=NULL;
01615 //     SelectPalette(hdcRobotView,ghpaletteScreen,FALSE);
01616 //     RealizePalette(hdcRobotView);
01617      SelectObject(hdcRobotView,ghRobotBrush);
01618      GetClientRect(hwnd,&rc);
01619      hdc=GetDC(hwnd);
01620      hbmRobotView=CreateCompatibleBitmap(hdc,rc.right,rc.bottom);
01621      ReleaseDC(hwnd,hdc);
01622      hbmOldRobotView=SelectObject(hdcRobotView,hbmRobotView);
01623      PatBlt(hdcRobotView,0,0,rc.right,rc.bottom,PATCOPY);
01624      SendMessage(hwnd,WM_DRAWROBOT,0,0);
01625      break;
01626    case WM_LBUTTONDOWN:
01627      mmoved=FALSE;
01628      xs=LOWORD(lparam);
01629      ys=HIWORD(lparam);
01630      SetCapture(hwnd);
01631      bTrackPan=TRUE;
01632      break;
01633    case WM_MOUSEMOVE:
01634      if(bTrackPan){
01635        long dx,dy;
01636        dx=(short)LOWORD(lparam)-xs; xs=(short)LOWORD(lparam);
01637        dy=(short)HIWORD(lparam)-ys; ys=(short)HIWORD(lparam);
01638        if(labs(dx) > 0 || labs(dy) > 0){
01639          mmoved=TRUE;
01640          round_angle=round_angle+(double)dx;
01641          while(round_angle < -180.0)round_angle += 360.0;
01642          while(round_angle >  180.0)round_angle -= 360.0;
01643          SetScrollPos(hwnd,SB_HORZ,(int)round_angle,TRUE);
01644          up_angle=up_angle+(double)dy;
01645          if(up_angle > -90 && up_angle < 90)
01646            SetScrollPos(hwnd,SB_VERT,(int)up_angle,TRUE);
01647          SendMessage(hwnd,WM_DRAWROBOT,0,0);
01648          UpdateWindow(ghwndRobotView);
01649 //         InvalidateRect(hwnd, NULL, FALSE);
01650        }
01651      }
01652      break;
01653    case WM_LBUTTONUP:
01654      if(bTrackPan){
01655        ReleaseCapture();
01656        bTrackPan=FALSE;
01657      }
01658      if(mmoved){
01659        mmoved=FALSE;
01660        break;
01661      }
01662      mmoved=FALSE;
01663    case WM_DRAWROBOT:
01664      if(SelectedRobot != NULL && (i=SelectedRobotArm) > 0){
01665        skel *s;
01666        s=SelectedRobot->skeleton;
01667        if((i=s[i].id) >= 0){
01668          if(gToolFlags.flagK == 0)TransformAxis((s+i),s[i].v,s[i].vv);
01669          if(gToolFlags.flagK == 1)TransformAxis((s+i),s[i].u,s[i].uu);
01670          if(gToolFlags.flagK == 2)TransformAxis((s+i),s[i].w,s[i].ww);
01671        }
01672      }
01673      DrawViewRobot(hdcRobotView,hbmRobotView,hwnd,
01674                   SelectedNode,SelectedRobotArm,(int)gToolFlags.flagK,
01675                   round_angle,up_angle,RobotZoomFlag,RobotZoomState);
01676      break;
01677    case WM_VSCROLL:
01678      GetScrollRange(hwnd,SB_VERT,&iMin,&iMax);
01679      iPos = GetScrollPos(hwnd, SB_VERT);
01680      switch (LOWORD(wparam)) {
01681        case SB_LINEDOWN:      dn =  1;    break;
01682        case SB_LINEUP:        dn = -1;    break;
01683        case SB_PAGEDOWN:      dn =  5;    break;
01684        case SB_PAGEUP:        dn = -5;    break;
01685        case SB_THUMBTRACK:
01686        case SB_THUMBPOSITION: dn = (int)(short)HIWORD(wparam)-iPos;    break;
01687        default:               dn = 0;
01688      }
01689     if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
01690        SetScrollPos(hwnd, SB_VERT, iPos + dn, TRUE);
01691        old=up_angle;
01692        up_angle=(double)(iPos+dn);
01693        if(old != up_angle){
01694          SendMessage(hwnd,WM_DRAWROBOT,0,0);
01695          UpdateWindow(ghwndRobotView);
01696        }
01697      }
01698      break;
01699    case WM_HSCROLL:
01700      GetScrollRange(hwnd, SB_HORZ, &iMin, &iMax);
01701      iPos = GetScrollPos(hwnd, SB_HORZ);
01702      switch (LOWORD(wparam)) {
01703        case SB_LINEDOWN:      dn =  1;     break;
01704        case SB_LINEUP:        dn = -1;     break;
01705        case SB_PAGEDOWN:      dn =  5;     break;
01706        case SB_PAGEUP:        dn = -5;     break;
01707        case SB_THUMBTRACK:
01708        case SB_THUMBPOSITION: dn = (int)(short)HIWORD(wparam) - iPos; break;
01709        default:               dn = 0;
01710      }
01711      if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
01712        SetScrollPos(hwnd, SB_HORZ, iPos + dn, TRUE);
01713        old=round_angle;
01714        round_angle=(double)(iPos+dn);
01715        if(old != round_angle){
01716          SendMessage(hwnd,WM_DRAWROBOT,0,0);
01717          UpdateWindow(ghwndRobotView);
01718        }
01719      }
01720      break;
01721    case WM_PAINT: {
01722        HDC hdc;
01723        PAINTSTRUCT ps;
01724        HPALETTE hpalT;
01725        hdc=BeginPaint(hwnd,&ps);
01726 //       hpalT = SelectPalette(hdc,ghpaletteScreen,FALSE);
01727 //       RealizePalette (hdc);
01728        GetClientRect(hwnd,&rc);
01729        if(hdcRobotView != NULL)
01730        BitBlt(hdc,0,0,rc.right,rc.bottom,hdcRobotView,0,0,SRCCOPY);
01731 //       SelectPalette(hdc,hpalT,FALSE);
01732        EndPaint(hwnd,&ps);
01733      }
01734      break;
01735    default:
01736      return(DefWindowProc(hwnd,msg,wparam,lparam));
01737  }
01738  return( 0L );
01739 }
01740 
01741 // end robot treeview dialog
01742 
01743 // robot opengl viewer
01744 
01745 #include <gl\gl.h>
01746 #include <gl\glu.h>
01747 
01748 static HPALETTE hRobotPalette=NULL,hRobotOldPalette=NULL;
01749 static HGLRC  hRC=NULL;
01750 static HDC    hRobotDC=NULL;
01751 static RECT oldRobotRect;
01752 static GLfloat near_plane,far_plane;
01753 static GLfloat gbRed=0.0,gbGreen=0.1,gbBlue=0.3;
01754 
01755 static unsigned char threeto8[8] = {
01756     0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
01757 };
01758 
01759 static unsigned char twoto8[4] = {
01760     0, 0x55, 0xaa, 0xff
01761 };
01762 
01763 static unsigned char oneto8[2] = {
01764     0, 255
01765 };
01766 
01767 static int defaultOverride[13] = {
01768     0, 3, 24, 27, 64, 67, 88, 173, 181, 236, 247, 164, 91
01769 };
01770 
01771 static PALETTEENTRY defaultPalEntry[20] = {
01772     { 0,   0,   0,    0 },
01773     { 0x80,0,   0,    0 },
01774     { 0,   0x80,0,    0 },
01775     { 0x80,0x80,0,    0 },
01776     { 0,   0,   0x80, 0 },
01777     { 0x80,0,   0x80, 0 },
01778     { 0,   0x80,0x80, 0 },
01779     { 0xC0,0xC0,0xC0, 0 },
01780 
01781     { 192, 220, 192,  0 },
01782     { 166, 202, 240,  0 },
01783     { 255, 251, 240,  0 },
01784     { 160, 160, 164,  0 },
01785 
01786     { 0x80,0x80,0x80, 0 },
01787     { 0xFF,0,   0,    0 },
01788     { 0,   0xFF,0,    0 },
01789     { 0xFF,0xFF,0,    0 },
01790     { 0,   0,   0xFF, 0 },
01791     { 0xFF,0,   0xFF, 0 },
01792     { 0,   0xFF,0xFF, 0 },
01793     { 0xFF,0xFF,0xFF, 0 }
01794 };
01795 
01796 static unsigned char ComponentFromIndex(int i, UINT nbits, UINT shift){
01797  unsigned char val;
01798  val = (unsigned char) (i >> shift);
01799  switch (nbits) {
01800     case 1:
01801         val &= 0x1;
01802         return oneto8[val];
01803     case 2:
01804         val &= 0x3;
01805         return twoto8[val];
01806     case 3:
01807         val &= 0x7;
01808         return threeto8[val];
01809     default:
01810         return 0;
01811  }
01812 }
01813 
01814 static void CreateRGBPalette(HDC hDC){
01815  PIXELFORMATDESCRIPTOR pfd;
01816  LOGPALETTE *pPal;
01817  int n, i;
01818  n = GetPixelFormat(hDC);
01819  DescribePixelFormat(hDC, n, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
01820  if(pfd.dwFlags & PFD_NEED_PALETTE) {
01821    n = 1 << pfd.cColorBits;
01822    pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
01823                                    n * sizeof(PALETTEENTRY));
01824    pPal->palVersion = 0x300;
01825    pPal->palNumEntries = n;
01826    for (i=0; i<n; i++) {
01827      pPal->palPalEntry[i].peRed =
01828             ComponentFromIndex(i, pfd.cRedBits, pfd.cRedShift);
01829      pPal->palPalEntry[i].peGreen =
01830             ComponentFromIndex(i, pfd.cGreenBits, pfd.cGreenShift);
01831      pPal->palPalEntry[i].peBlue =
01832             ComponentFromIndex(i, pfd.cBlueBits, pfd.cBlueShift);
01833      pPal->palPalEntry[i].peFlags = 0;
01834    }
01835    if((pfd.cColorBits == 8)                           &&
01836        (pfd.cRedBits   == 3) && (pfd.cRedShift   == 0) &&
01837        (pfd.cGreenBits == 3) && (pfd.cGreenShift == 3) &&
01838        (pfd.cBlueBits  == 2) && (pfd.cBlueShift  == 6)) {
01839      for(i = 1 ; i <= 12 ; i++)
01840         pPal->palPalEntry[defaultOverride[i]] = defaultPalEntry[i];
01841    }
01842    hRobotPalette = CreatePalette(pPal);
01843    LocalFree(pPal);
01844    hRobotOldPalette = SelectPalette(hDC,hRobotPalette,FALSE);
01845    n = RealizePalette(hDC);
01846  }
01847 }
01848 
01849 static BOOL bSetupPixelFormat(HDC hDC){
01850  static PIXELFORMATDESCRIPTOR pfd = {
01851    sizeof(PIXELFORMATDESCRIPTOR),  // size of this pfd
01852    1,                              // version number
01853    PFD_DRAW_TO_WINDOW |            // support window
01854    PFD_SUPPORT_OPENGL |            // support OpenGL
01855    PFD_DOUBLEBUFFER,               // double buffered
01856    PFD_TYPE_RGBA,                  // RGBA type
01857    24,                             // 24-bit color depth
01858    0, 0, 0, 0, 0, 0,               // color bits ignored
01859    0,                              // no alpha buffer
01860    0,                              // shift bit ignored
01861    0,                              // no accumulation buffer
01862    0, 0, 0, 0,                     // accum bits ignored
01863    32,                             // 32-bit z-buffer
01864    0,                              // no stencil buffer
01865    0,                              // no auxiliary buffer
01866    PFD_MAIN_PLANE,                 // main layer
01867    0,                              // reserved
01868    0, 0, 0                         // layer masks ignored
01869  };
01870  int pixelformat;
01871  if ( (pixelformat = ChoosePixelFormat(hDC, &pfd)) == 0 ){
01872    MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
01873    return FALSE;
01874  }
01875  if (SetPixelFormat(hDC, pixelformat, &pfd) == FALSE) {
01876    MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
01877    return FALSE;
01878  }
01879  CreateRGBPalette(hDC);
01880  return TRUE;
01881 }
01882 
01883 static GLvoid initializeGLrobot(HWND hWnd){
01884  GLfloat   aspect;
01885  GLfloat d[]={1.0,1.0,1.0,1.0};
01886  GLfloat a[]={0.1,0.1,0.1,1.0};
01887  GLfloat s[]={1.0,1.0,1.0,1.0};
01888  GLfloat p[]={0.5,0.5,0.5,0.0};
01889  if(1)p[3]=1.0;
01890  else p[3]=0.0;
01891  GetClientRect(hWnd, &oldRobotRect);
01892  glClearColor(gbRed,gbGreen,gbBlue,1.0);
01893  glMatrixMode(GL_PROJECTION);
01894  aspect = (GLfloat) oldRobotRect.right / oldRobotRect.bottom;;
01895  near_plane = 1.5; far_plane = 9.5;
01896  gluPerspective(45.0, aspect, near_plane, far_plane);
01897  glMatrixMode( GL_MODELVIEW );
01898  glLoadIdentity();
01899  glClearDepth(1.0);
01900  glEnable(GL_DEPTH_TEST);
01901  if(0)glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);
01902  else glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE);
01903  glEnable(GL_LIGHT0);
01904  glLightfv(GL_LIGHT0,GL_DIFFUSE,d);
01905  glLightfv(GL_LIGHT0,GL_AMBIENT,a);
01906  glLightfv(GL_LIGHT0,GL_SPECULAR,s);
01907  glLightfv(GL_LIGHT0,GL_POSITION,p);
01908  glLightf(GL_LIGHT0,GL_LINEAR_ATTENUATION,0.125);
01909  glLightf(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,0.02);
01910  glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
01911  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01912  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01913  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_FASTEST);
01914  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01915  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01916  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
01917 }
01918 
01919 static void DrawViewRobotGL(HWND hWnd,
01920                    node *Np, int arm, int axis,
01921                    double ra, double ua,
01922                    BOOL zoom,BOOL zoom_state){
01923  GLfloat glos_color[]={1.0,1.0,1.0,1.0};
01924  GLfloat shiny[]={100.0};
01925  short   ep1[6]={0,4,0,1,2,0};
01926  short   ep2[6]={1,7,4,5,6,3};
01927  short   ep3[6]={2,6,5,6,7,7};
01928  short   ep4[6]={3,5,1,2,3,4};
01929  double  scale,size,x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,
01930          t1[4][4],t2[4][4],t3[4][4];
01931  vector  cc,p1,p2,p3,p4,p21,p41,nn;
01932  long    i,j,k,n,Nv;
01933  object  *Op;
01934  skel    *sp;
01935  if(Np->type == ROBOT && ((Op=Np->fobj) != NULL))while(Op != NULL){
01936    if(CurrentFrame >= Op->firstframe && CurrentFrame <= Op->lastframe){
01937      if((n=Op->nskeleton) == 0 || (sp=Op->skeleton) == NULL)break;
01938      /* InterpolateRobot - Not Needed other windows call it */
01939      size=(double)GetRobotVolume(n,NULL,cc);
01940      scale=3.25/size;
01941      if(zoom && arm >=0 && arm < n){
01942        if(zoom_state && (j=(sp+arm)->id) >= 0 && j < n){
01943          tram(t1,-((sp+j)->pp[0]),-((sp+j)->pp[1]),-((sp+j)->pp[2]));
01944          scale *= 5.0;
01945        }
01946        else{
01947          tram(t1,-((sp+arm)->pp[0]),-((sp+arm)->pp[1]),-((sp+arm)->pp[2]));
01948          scale *= 4.0;
01949        }
01950      }
01951      else tram(t1,-cc[0],-cc[1],-cc[2]);
01952      rotz(t2, ra*PIo180);
01953      m4by4(t2,t1,t3);
01954      rotx(t1, ua*PIo180);
01955      m4by4(t1,t3,t2);
01956      /* Bounding Box */
01957      if(!RobotPointsFlag){
01958      glEnable(GL_LIGHTING);
01959      glEnable(GL_COLOR_MATERIAL);
01960      if(RobotGlassFlag){
01961        glEnable(GL_BLEND);
01962        glDepthMask(GL_FALSE);
01963        glBlendFunc(GL_SRC_ALPHA,GL_ONE);
01964      }
01965      glBegin(GL_QUADS);
01966      glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shiny);
01967      glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,glos_color);
01968      for(k=0;k<n;k++){
01969        m4by4(t2,(sp+k)->T,t3);
01970        if(k == arm)glColor4f(1.0,0.3,0.3,1.0);
01971        else        glColor4f(1.0,1.0,0.3,1.0);
01972        for(i=0;i<6;i++){
01973          m4by1(t3,(double)(sp+k)->bx[ep1[i]][0]
01974                  ,(double)(sp+k)->bx[ep1[i]][1]
01975                  ,(double)(sp+k)->bx[ep1[i]][2]
01976                  ,&x1,&y1,&z1);
01977          p1[0]=scale*(x1); p1[1]=scale*(y1); p1[2]=scale*(z1);
01978          m4by1(t3,(double)(sp+k)->bx[ep2[i]][0]
01979                  ,(double)(sp+k)->bx[ep2[i]][1]
01980                  ,(double)(sp+k)->bx[ep2[i]][2]
01981                  ,&x2,&y2,&z2);
01982          p2[0]=scale*(x2); p2[1]=scale*(y2); p2[2]=scale*(z2);
01983          m4by1(t3,(double)(sp+k)->bx[ep3[i]][0]
01984                  ,(double)(sp+k)->bx[ep3[i]][1]
01985                  ,(double)(sp+k)->bx[ep3[i]][2]
01986                  ,&x3,&y3,&z3);
01987          p3[0]=scale*(x3); p3[1]=scale*(y3); p3[2]=scale*(z3);
01988          m4by1(t3,(double)(sp+k)->bx[ep4[i]][0]
01989                  ,(double)(sp+k)->bx[ep4[i]][1]
01990                  ,(double)(sp+k)->bx[ep4[i]][2]
01991                  ,&x4,&y4,&z4);
01992          p4[0]=scale*(x4); p4[1]=scale*(y4); p4[2]=scale*(z4);
01993          VECSUB(p2,p1,p21)
01994          VECSUB(p4,p1,p41)
01995          CROSS(p21,p41,nn)
01996          A_normalize(nn);
01997          glNormal3f(nn[0],nn[2],-nn[1]);
01998          glVertex3f(p1[0],p1[2],-p1[1]);
01999          glVertex3f(p2[0],p2[2],-p2[1]);
02000          glVertex3f(p3[0],p3[2],-p3[1]);
02001          glVertex3f(p4[0],p4[2],-p4[1]);
02002        }
02003      }
02004      glEnd();
02005      if(RobotGlassFlag){
02006        glDepthMask(GL_TRUE);
02007        glDisable(GL_BLEND);
02008      }
02009      glDisable(GL_COLOR_MATERIAL);
02010      glDisable(GL_LIGHTING);
02011      } else {
02012      /* Points */
02013      Nv=Op->npoints; 
02014      if(Nv > 0 && Op->in_ram){
02015        glEnable(GL_COLOR_MATERIAL);
02016        if(RobotZoomFlag)glPointSize(3.0); 
02017        else             glPointSize(1.5); 
02018        glBegin(GL_POINTS);
02019        glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shiny);
02020        glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,glos_color);
02021        for(k=0;k<n;k++){
02022          m4by4(t2,(sp+k)->T,t3);
02023          if(k == arm)glColor4f(1.0,0.3,0.3,1.0);
02024          else        glColor4f(1.0,1.0,0.3,1.0);
02025          for(i=0;i<Nv;i++){
02026            if(Op->skid[i] == k){
02027              m4by1(t3,(double)(Op->points[i][0] - Op->origin[0])
02028                      ,(double)(Op->points[i][1] - Op->origin[1])
02029                      ,(double)(Op->points[i][2] - Op->origin[2])
02030                      ,&x1,&y1,&z1);
02031              p1[0]=scale*(x1); p1[1]=scale*(y1); p1[2]=scale*(z1);
02032              glVertex3f(p1[0],p1[2],-p1[1]);
02033            }
02034          }
02035        }
02036        glEnd();
02037        glDisable(GL_COLOR_MATERIAL);
02038      }
02039      } // points or boxes
02040      /* skeleton */
02041      for(k=0;k<n;k++){
02042        x1=(double)sp[k].pp[0]; y1=(double)sp[k].pp[1]; z1=(double)sp[k].pp[2];
02043        m4by1(t2,x1,y1,z1,&x2,&y2,&z2);
02044        sp[k].wk[0]=(long)x2; sp[k].wk[1]=(long)y2; sp[k].wk[2]=(long)z2;
02045      }
02046      glLineWidth(2.0);
02047      if(RobotOverlayFlag)glDepthFunc(GL_ALWAYS);
02048      glBegin(GL_LINES);
02049      for(k=0;k<n;k++){
02050        x1=(double)sp[k].wk[0]; y1=(double)sp[k].wk[1]; z1=(double)sp[k].wk[2];
02051        j=sp[k].id;  /* j is parent ID */
02052        if(j < 0)continue;
02053        x2=(double)sp[j].wk[0]; y2=(double)sp[j].wk[1]; z2=(double)sp[j].wk[2];
02054        x1=scale*(x1); y1=scale*(y1); z1=scale*(z1);
02055        x2=scale*(x2); y2=scale*(y2); z2=scale*(z2);
02056        glColor3f(1.0,1.0,0.0);
02057        glVertex3f(x1,z1,-y1);
02058        glVertex3f(x2,z2,-y2);
02059        if(k == arm && axis < 7){ /* draw node and axis */
02060          vector pp,x={2.0,0.0,0.0},y={0.0,2.0,0.0},z={0.0,0.0,2.0};
02061 //         Ellipse(hdcView,ix1-3,iy1-3,ix1+4,iy1+4);
02062          if     (axis == 0)VECCOPY((double)sp[j].vv,pp)
02063          else if(axis == 1)VECCOPY((double)sp[j].uu,pp)
02064          else if(axis == 2)VECCOPY((double)sp[j].ww,pp)
02065          else if(axis == 3)VECCOPY(x,pp)
02066          else if(axis == 4)VECCOPY(y,pp)
02067          else if(axis == 5)VECCOPY(z,pp)
02068          if(axis == 0 && (i=sp[j].id) >= 0){ /* do axis 0 other way */
02069            x1=sp[i].pp[0]; y1=sp[i].pp[1]; z1=sp[i].pp[2];
02070          }
02071          else if(axis < 6){
02072            x1=(double)sp[j].pp[0]+(double)pp[0]*size*0.1;
02073            y1=(double)sp[j].pp[1]+(double)pp[1]*size*0.1;
02074            z1=(double)sp[j].pp[2]+(double)pp[2]*size*0.1;
02075          }
02076          else {x1=sp[k].pp[0]; y1=sp[k].pp[1]; z1=sp[k].pp[2];}
02077          m4by1(t2,x1,y1,z1,&x3,&y3,&z3);
02078          x3=scale*(x3); y3=scale*(y3); z3=scale*(z3);
02079          glColor3f(1.0,1.0,1.0);
02080          glLineWidth(4.0);
02081          glVertex3f(x2,z2,-y2);
02082          glVertex3f(x3,z3,-y3);
02083          glLineWidth(2.0);
02084        }
02085      }
02086      glEnd();
02087      if(RobotOverlayFlag)glDepthFunc(GL_LESS);
02088      break;
02089    }
02090    Op=Op->next;
02091  }
02092 }
02093 
02094 static GLvoid drawRobotGLscene(HWND hWnd, double up_angle, double round_angle){
02095  HDC hDC;
02096  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
02097  if(1)glShadeModel(GL_FLAT);
02098  else glShadeModel(GL_SMOOTH);
02099  glPushMatrix();
02100  glLoadIdentity();
02101  glTranslatef(0.0, 0.0, -5.0);
02102 // glRotatef(up_angle,1.0,0.0,0.0);
02103 // glRotatef(round_angle,0.0,1.0,0.0);
02104  DrawViewRobotGL(hWnd,
02105                  SelectedNode,SelectedRobotArm,(int)gToolFlags.flagK,
02106                  round_angle,up_angle,RobotZoomFlag,RobotZoomState);
02107  glPopMatrix();
02108  glFinish();
02109  hDC = wglGetCurrentDC();
02110  SwapBuffers(hDC);
02111 }
02112 
02113 static GLvoid resizeRobotGL(HWND hWnd){
02114  RECT    rect;
02115  GLfloat aspect;
02116  GetClientRect(hWnd, &rect);
02117  glViewport(0,0,rect.right,rect.bottom);
02118  oldRobotRect.right = rect.right;
02119  oldRobotRect.bottom = rect.bottom;
02120  glMatrixMode(GL_PROJECTION);
02121  glLoadIdentity();
02122  aspect = (GLfloat)oldRobotRect.right/oldRobotRect.bottom;
02123  gluPerspective( 45.0, aspect, near_plane, far_plane);
02124  glMatrixMode( GL_MODELVIEW );
02125  glLoadIdentity();
02126 }
02127 
02128 static LRESULT CALLBACK RobotOglViewWndProc(HWND hwnd, UINT msg,
02129                           WPARAM wparam, LPARAM lparam ){
02130  static BOOL flag=FALSE,mmoved=FALSE,bTrackPan=FALSE;
02131  static long xs,ys;
02132  static double up_angle=0.0,round_angle=0.0;
02133  char str[32];
02134  double old;
02135  HDC  hDC;
02136  RECT rc;
02137  int i,iPos,iMax,iMin,dn;
02138  switch( msg ){
02139    case WM_CREATE:{
02140        vector c;
02141        GetRobotVolume(SelectedRobot->nskeleton,SelectedRobot->skeleton,c);
02142        SetScrollRange(hwnd, SB_VERT, -89,89,TRUE);
02143        SetScrollRange(hwnd, SB_HORZ, -179,179,TRUE);
02144        SetScrollPos(hwnd,SB_HORZ,(int)round_angle,TRUE);
02145        SetScrollPos(hwnd,SB_VERT,(int)up_angle,TRUE);
02146        hRobotDC = GetDC(hwnd);
02147        bSetupPixelFormat(hRobotDC);
02148        hRC = wglCreateContext(hRobotDC);
02149        wglMakeCurrent(hRobotDC,hRC);
02150        initializeGLrobot(hwnd);
02151      }
02152      break;
02153    case WM_DESTROY:
02154      wglMakeCurrent(NULL,NULL);
02155      if(hRC != NULL)wglDeleteContext(hRC);
02156      if(hRobotDC != NULL)ReleaseDC(hwnd,hRobotDC);
02157      GetWindowRect(hwnd,&rc);
02158      RobotViewXpos=rc.left; RobotViewYpos=rc.top;
02159      RobotViewXsize=rc.right-rc.left; RobotViewYsize=rc.bottom-rc.top;
02160      sprintf(str,"%ld",rc.left);
02161      WritePrivateProfileString(IniSection,"RVPOSX",str,IniFilename);
02162      sprintf(str,"%ld",rc.top);
02163      WritePrivateProfileString(IniSection,"RVPOSY",str,IniFilename);
02164      sprintf(str,"%ld",rc.right-rc.left);
02165      WritePrivateProfileString(IniSection,"RVSIZX",str,IniFilename);
02166      sprintf(str,"%ld",rc.bottom-rc.top);
02167      WritePrivateProfileString(IniSection,"RVSIZY",str,IniFilename);
02168      break;
02169    case WM_SYSCOMMAND:
02170      switch(LOWORD(wparam & 0xfff0)){
02171        case SC_CLOSE:
02172          break;
02173        default:
02174          return(DefWindowProc(hwnd,msg,wparam,lparam));
02175       }
02176       break;
02177    case WM_SIZE:
02178      resizeRobotGL(hwnd);
02179      break;
02180    case WM_LBUTTONDOWN:
02181      mmoved=FALSE;
02182      xs=LOWORD(lparam);
02183      ys=HIWORD(lparam);
02184      SetCapture(hwnd);
02185      bTrackPan=TRUE;
02186      break;
02187    case WM_MOUSEMOVE:
02188      if(bTrackPan){
02189        long dx,dy;
02190        dx=(short)LOWORD(lparam)-xs; xs=(short)LOWORD(lparam);
02191        dy=(short)HIWORD(lparam)-ys; ys=(short)HIWORD(lparam);
02192        if(labs(dx) > 0 || labs(dy) > 0){
02193          mmoved=TRUE;
02194          round_angle=round_angle+(double)dx;
02195          while(round_angle < -180.0)round_angle += 360.0;
02196          while(round_angle >  180.0)round_angle -= 360.0;
02197          SetScrollPos(hwnd,SB_HORZ,(int)round_angle,TRUE);
02198          up_angle=up_angle+(double)dy;
02199          if(up_angle > -90 && up_angle < 90)
02200            SetScrollPos(hwnd,SB_VERT,(int)up_angle,TRUE);
02201          InvalidateRect(hwnd, NULL, FALSE);
02202        }
02203      }
02204      break;
02205    case WM_LBUTTONUP:
02206      if(bTrackPan){
02207        ReleaseCapture();
02208        bTrackPan=FALSE;
02209      }
02210      if(mmoved){
02211        mmoved=FALSE;
02212        break;
02213      }
02214      mmoved=FALSE;
02215    case WM_DRAWROBOT:
02216      if(SelectedRobot != NULL && (i=SelectedRobotArm) > 0){
02217        skel *s;
02218        s=SelectedRobot->skeleton;
02219        if((i=s[i].id) >= 0){
02220          if(gToolFlags.flagK == 0)TransformAxis((s+i),s[i].v,s[i].vv);
02221          if(gToolFlags.flagK == 1)TransformAxis((s+i),s[i].u,s[i].uu);
02222          if(gToolFlags.flagK == 2)TransformAxis((s+i),s[i].w,s[i].ww);
02223        }
02224      }
02225      InvalidateRect(hwnd,NULL,FALSE);
02226      break;
02227    case WM_VSCROLL:
02228      GetScrollRange(hwnd,SB_VERT,&iMin,&iMax);
02229      iPos = GetScrollPos(hwnd, SB_VERT);
02230      switch (LOWORD(wparam)) {
02231        case SB_LINEDOWN:      dn =  1;    break;
02232        case SB_LINEUP:        dn = -1;    break;
02233        case SB_PAGEDOWN:      dn =  5;    break;
02234        case SB_PAGEUP:        dn = -5;    break;
02235        case SB_THUMBTRACK:
02236        case SB_THUMBPOSITION: dn = (int)(short)HIWORD(wparam)-iPos;    break;
02237        default:               dn = 0;
02238      }
02239     if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
02240        SetScrollPos(hwnd, SB_VERT, iPos + dn, TRUE);
02241        old=up_angle;
02242        up_angle=(double)(iPos+dn);
02243        if(old != up_angle){
02244          SendMessage(hwnd,WM_DRAWROBOT,0,0);
02245          UpdateWindow(ghwndRobotView);
02246        }
02247      }
02248      break;
02249    case WM_HSCROLL:
02250      GetScrollRange(hwnd, SB_HORZ, &iMin, &iMax);
02251      iPos = GetScrollPos(hwnd, SB_HORZ);
02252      switch (LOWORD(wparam)) {
02253        case SB_LINEDOWN:      dn =  1;     break;
02254        case SB_LINEUP:        dn = -1;     break;
02255        case SB_PAGEDOWN:      dn =  5;     break;
02256        case SB_PAGEUP:        dn = -5;     break;
02257        case SB_THUMBTRACK:
02258        case SB_THUMBPOSITION: dn = (int)(short)HIWORD(wparam) - iPos; break;
02259        default:               dn = 0;
02260      }
02261      if ((dn = BOUND (iPos + dn, iMin, iMax) - iPos) != 0) {
02262        SetScrollPos(hwnd, SB_HORZ, iPos + dn, TRUE);
02263        old=round_angle;
02264        round_angle=(double)(iPos+dn);
02265        if(old != round_angle){
02266          SendMessage(hwnd,WM_DRAWROBOT,0,0);
02267          UpdateWindow(ghwndRobotView);
02268        }
02269      }
02270      break;
02271    case WM_PAINT: {
02272        PAINTSTRUCT ps;
02273        BeginPaint(hwnd,&ps);
02274        drawRobotGLscene(hwnd,up_angle,round_angle);
02275        EndPaint(hwnd,&ps);
02276      }
02277      break;
02278    case WM_QUERYNEWPALETTE:{
02279        HPALETTE hpalOld;
02280        if(hRobotPalette != NULL){
02281          hDC = GetDC(hwnd);
02282          hpalOld = SelectPalette(hDC, hRobotPalette, FALSE);
02283          RealizePalette(hDC);
02284          InvalidateRect(hwnd,NULL,TRUE);
02285          UpdateWindow(hwnd);
02286          if(hpalOld != NULL)SelectPalette(hDC, hpalOld, FALSE);
02287          ReleaseDC(hwnd,hDC);
02288          return TRUE;
02289        }
02290        return FALSE;
02291      }
02292    case WM_PALETTECHANGED:{
02293        HPALETTE    hpalOld;
02294        if(hRobotPalette != NULL){
02295          if (wparam != (WPARAM)hwnd){
02296            hDC = GetDC(hwnd);
02297            hpalOld = SelectPalette(hDC,hRobotPalette,FALSE);
02298            RealizePalette(hDC);
02299            UpdateColors(hDC);
02300            if(hpalOld != NULL)SelectPalette(hDC,hpalOld,FALSE);
02301            ReleaseDC(hwnd,hDC);
02302          }
02303        }
02304      }
02305      break;
02306    default:
02307      return(DefWindowProc(hwnd,msg,wparam,lparam));
02308  }
02309  return( 0L );
02310 }
02311 
02312 // end robot opengl viewer
02313 

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