home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / VPR_DATA / DOGA / SOURCES / MEDIT.LZH / MOTION.CPP < prev    next >
C/C++ Source or Header  |  1996-06-13  |  15KB  |  584 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include "matrix.h"
  4. #include "parts.h"
  5. #include "motion.h"
  6. #include "bezier.h"
  7. #include "mecha.h"
  8. //#include "anim.h"
  9.  
  10. #include "log.h"
  11.  
  12. const double TargetDistance = 4;
  13.  
  14. MotionData::MotionData(Bezier *b)
  15. {
  16.     if (b != NULL) {
  17.         bezier = b;
  18.         if (bezier->points == 0) {
  19.             bezier->AddPoint(bezier->point[0], bezier->point[0]);
  20.         } else if (bezier->points >=2) {
  21.             bezier->points = 1;
  22.         }
  23.     } else {
  24.         Vector v(0,0,0);
  25.         bezier = new Bezier();
  26.         bezier->AddPoint(v,v);
  27.         bezier->AddPoint(v,v);
  28.     }
  29.     speed[0] = speed[1] = 1.0;
  30.     scale[0] = scale[1] = Vector(1,1,1);
  31.     rotation[0] = (bezier->GetVector(0.0) ^ Vector(0,0,1)).GetRotation();
  32.     SetForward();
  33.  
  34. }
  35.  
  36. MotionData::MotionData(MotionData& md)
  37. {
  38.     memcpy(this, &md, sizeof(MotionData));
  39.     bezier = new Bezier();
  40.     bezier->AddPoint(md.bezier->point[0], md.bezier->point[1]);
  41.     bezier->AddPoint(md.bezier->point[3], md.bezier->point[4]);
  42. }
  43.  
  44. MotionData::~MotionData()
  45. {
  46.     delete bezier;
  47. }
  48.  
  49. static inline Matrix RotationAnyAxis(Vector& vx1, Vector& vx2)
  50. {
  51.     double lx1 = vx1.length();
  52.     double lx2 = vx2.length();
  53.     if ((-minimumdouble < lx1 && lx1 < minimumdouble)
  54.      || (-minimumdouble < lx2 && lx2 < minimumdouble)) {
  55.         return Matrix(1);
  56.     }
  57.     Vector vz = (1.0/lx1/lx2) * vx1 * vx2;
  58.     double l = vz.length();
  59.     if (-minimumdouble < l && l < minimumdouble) {
  60.         return Matrix(1);
  61.     }
  62.     vz *= (1.0/l);
  63.     Vector vy1 = (1.0/lx1) * vz * vx1;
  64.     Vector vy2 = (1.0/lx2) * vz * vx2;
  65.     return Matrix((1.0/lx2)*vx2, vy2, vz) * Matrix((1.0/lx1)*vx1,vy1,vz).inv();
  66. }
  67.  
  68. static Vector RotationInterpolation(Vector& vx1, Vector& vx2, double t)
  69. {
  70.     Vector vz = vx1 * vx2;
  71.     double l = vz.length();
  72.     double l1 = vx1 & vx2;
  73.     if (-minimumdouble < l  && l  < minimumdouble
  74.      && -minimumdouble < l1 && l1 < minimumdouble) {
  75.         return vx1;
  76.     }
  77.     double theta = atan2(l,l1);
  78.     if (l < minimumdouble) {
  79.         vz = vx1 * Vector(0,1,0);
  80.         if ((l = vz.length()) < minimumdouble) {
  81.             vz = vx1 * Vector(1,0,0);
  82.             if ((l = vz.length()) < minimumdouble) {
  83.                 return vx1;
  84.             }
  85.         }
  86.     }
  87.     vz *= (1.0/l);
  88.     Vector vy1 = vz * vx1;
  89.     return cos(theta * t) * vx1 + sin(theta * t) * vy1;
  90. }
  91.  
  92. void MotionData::GetPosition(double t, Vector& pos, Vector& rot, Vector& scal)
  93. {
  94.     if (t <= 0.0) {
  95.         pos = bezier->point[0];
  96.         rot = rotation[0];
  97.         scal = scale[0];
  98.         return;
  99.     } else if (t >= 1.0) {
  100.         pos = bezier->point[3];
  101.         scal = scale[1];
  102.         if (dirtype != DirForward) {
  103.             rot = rotation[1];
  104.         } else {
  105.             Vector v1 = bezier->GetVector(0.0);
  106.             Vector v2 = bezier->GetVector(1.0);
  107.             rot = (RotationAnyAxis(v1, v2) * Matrix::m_rot(rotation[0])).GetRotation();
  108.         }
  109.         return;
  110.     }
  111.  
  112.  
  113.     double b = speed[0] / 3.0;
  114.     double c = 1.0 - speed[1] / 3.0;
  115.  
  116.     double lrate = 3 * b *      t  * (1.0-t) * (1.0-t)
  117.                  + 3 * c *      t  *      t  * (1.0-t)
  118.                  +              t  *      t  *      t;
  119.     double length = bezier->TotalLength();
  120.     double rate = bezier->GetRate(lrate * length);
  121.     pos = bezier->GetPoint(rate);
  122.  
  123.     if (dirtype == DirForward) {
  124.         Vector v1 = bezier->GetVector(0.0);
  125.         Vector v2 = bezier->GetVector(rate);
  126.         rot = (RotationAnyAxis(v1, v2) * Matrix::m_rot(rotation[0])).GetRotation();
  127.     } else {
  128.         Matrix& m1 = Matrix::m_rot(rotation[0]);
  129.         Matrix& m2 = Matrix::m_rot(rotation[1]);
  130.         Vector vx = RotationInterpolation(m1.v[0], m2.v[0], t);
  131.         Matrix m = RotationAnyAxis(m1.v[0], vx);
  132.         Vector vz = RotationInterpolation(m * m1.v[2], m2.v[2], t);
  133.         rot = Matrix(vx,vz).GetRotation();
  134.     }
  135.  
  136.     scal = (1.0-t) * scale[0] + t * scale[1];
  137. }
  138.  
  139. void MotionData::SetForward(void)
  140. {
  141.     dirtype = DirForward;
  142.     Vector v1 = bezier->GetVector(0.0);
  143.     Vector v2 = bezier->GetVector(1.0);
  144.     Matrix mrot = Matrix::m_rot(rotation[0]);
  145.     rotation[0] = (v1 ^ mrot.v[2]).GetRotation();
  146.     rotation[1] = (RotationAnyAxis(v1, v2) * Matrix::m_rot(rotation[0])).GetRotation();
  147. }
  148.  
  149. void MotionData::SetAnyAxis(Vector& v1, Vector& v2)
  150. {
  151.     rotation[0] = (RotationAnyAxis(v1, v2) * Matrix::m_rot(rotation[0])).GetRotation();
  152. }
  153.  
  154.  
  155. Motion::Motion(Mechanic *mec, int bf, int ef, Bezier* bez)
  156. {
  157.  
  158.     if (bez == NULL) {
  159.         motiondata = NULL;
  160.     } else {
  161.         motiondata = new MotionData(bez);
  162.     }
  163.     beginframe = bf;
  164.     endframe = ef;
  165.     next = NULL;
  166.     nowframe = -1;
  167.  
  168.     position = Vector(0,0,0);
  169.     rotation = Vector(0,0,0);
  170.     scale = Vector(1,1,1);
  171.  
  172.     point_x = point_y = point_z = NULL;
  173.     view_x = view_y = view_z = NULL;
  174.     line_1 = line_2 = NULL;
  175.     boxflag = FALSE;
  176.  
  177.     SetMech(mec);
  178. }
  179.  
  180. Motion::Motion(Motion& m)
  181. {
  182.     memcpy(this, &m, sizeof(Motion));
  183.     if (m.motiondata != NULL) {
  184.         motiondata = new MotionData(*m.motiondata);
  185.     }
  186.  
  187.     if (mecha != NULL) {
  188.         point_x = new int[mecha->points];
  189.         point_y = new int[mecha->points];
  190.         point_z = new int[mecha->points];
  191.         view_x = new int[mecha->points];
  192.         view_y = new int[mecha->points];
  193.         view_z = new int[mecha->points];
  194.         line_1 = mecha->line_1;
  195.         line_2 = mecha->line_2;
  196.         lines = mecha->lines;
  197.     }
  198. }
  199.  
  200. Motion::~Motion()
  201. {
  202.     delete motiondata;
  203.     delete[] point_x;
  204.     delete[] point_y;
  205.     delete[] point_z;
  206.     delete[] view_x;
  207.     delete[] view_y;
  208.     delete[] view_z;
  209.  
  210. }
  211.  
  212. void Motion::GetPosition(int frame)
  213. {
  214.     if (motiondata != NULL) {
  215.         double t = (double)(frame - beginframe) / (double)(endframe - beginframe);
  216.         motiondata->GetPosition(t, position, rotation, scale);
  217.     }
  218.     nowframe = frame;
  219. }
  220.  
  221. void Motion::GetMatrix(Matrix& move, Matrix& rot, Matrix& scal, int frame)
  222. {
  223.     if (frame >= -1 && nowframe != frame) {
  224.         GetPosition(frame);
  225.     }
  226.     move = Matrix::m_move(position);
  227.     rot = Matrix::m_rot(rotation);
  228.     scal = Matrix::m_scale(scale);
  229. }
  230.  
  231. Matrix Motion::GetMatrix(int frame)
  232. {
  233.     if (frame >= -1 && nowframe != frame) {
  234.         GetPosition(frame);
  235.     }
  236.     return Matrix::m_move(position).rot(rotation).scale(scale);
  237. }
  238.  
  239.  
  240. void Motion::SetRotation(Vector& rot, int pos)
  241. {
  242.     if (motiondata == NULL) {
  243.         rotation = rot;
  244.     } else {
  245.         if (pos == 0) {
  246.             motiondata->rotation[0] = rot;
  247.         } else {
  248.             motiondata->rotation[1] = rot;
  249.             motiondata->dirtype = DirLinear;
  250.         }
  251.         GetPosition(nowframe);
  252.     }
  253. }
  254.  
  255. void Motion::SetScale(Vector& scal, int pos)
  256. {
  257.     if (motiondata == NULL) {
  258.         scale = scal;
  259.     } else {
  260.         if (pos == 0) {
  261.             motiondata->scale[0] = scal;
  262.         } else {
  263.             motiondata->scale[1] = scal;
  264.         }
  265.         GetPosition(nowframe);
  266.     }
  267. }
  268.  
  269. void Motion::SetPosition(Vector& vec, int pos)
  270. {
  271.     if (motiondata == NULL) {
  272.         position = vec;
  273.     } else {
  274.         if (pos < 0) pos = 0;
  275.         if (pos > 3) pos = 3;
  276.         motiondata->bezier->MovePoint(pos, vec);
  277.         motiondata->bezier->UpdateLength();
  278.         GetPosition(nowframe);
  279.     }
  280. }
  281.  
  282.  
  283. void Motion::CalcPoints(Matrix& m)
  284. {
  285.     boxflag = FALSE;
  286.     if (mecha != NULL) {
  287.         for (int i = 0; i < mecha->points; ++i) {
  288.             Vector v1 = m * Vector(mecha->point_x[i], mecha->point_y[i], mecha->point_z[i]);
  289.             point_x[i] = int(v1.x);
  290.             point_y[i] = int(v1.y);
  291.             point_z[i] = int(v1.z);
  292.         }
  293.     }
  294. }
  295.  
  296. void Motion::CalcView(Matrix& m)
  297. {
  298. #define CLIPZ 100.0
  299.     boxflag = FALSE;
  300.     if (mecha != NULL) {
  301.         for (int i = 0; i < mecha->points; ++i) {
  302.             Vector v1 = m * Vector(mecha->point_x[i], mecha->point_y[i], mecha->point_z[i]);
  303.             if (v1.z <= CLIPZ) {
  304.                 view_z[i] = -1;
  305.                 view_x[i] = 0;
  306.                 view_y[i] = 0;
  307.             } else {
  308.                 double vx = v1.x / v1.z;
  309.                 double vy = v1.y / v1.z;
  310.                 if (vx < -4096|| vx > 4096 || vy < -4096 || vy > 4096) {
  311.                     view_x[i] = 0;
  312.                     view_y[i] = 0;
  313.                     view_z[i] = -1;
  314.                 } else {
  315.                     view_x[i] = (int)vx;
  316.                     view_y[i] = (int)vy;
  317.                     view_z[i] = (int)(32768.0 * CLIPZ / v1.z);
  318.                 }
  319.             }
  320.         }
  321.     }
  322. }
  323.  
  324. static inline void assign(int point_x[], int point_y[], int point_z[], int i, Vector& v)
  325. {
  326.     point_x[i] = (int)v.x;
  327.     point_y[i] = (int)v.y;
  328.     point_z[i] = (int)v.z;
  329. }
  330.  
  331.  
  332. void Motion::CalcPointsBox(Matrix& m)
  333. {
  334.     if (mecha == NULL || mecha->points < 8) {
  335.         CalcPoints(m);
  336.     } else {
  337.         boxflag = TRUE;
  338.         if (motiondata == NULL) {
  339.             assign(point_x, point_y, point_z, 0, m * Vector(mecha->maxx, mecha->maxy,mecha->maxz));
  340.             assign(point_x, point_y, point_z, 1, m * Vector(mecha->minx, mecha->maxy,mecha->maxz));
  341.             assign(point_x, point_y, point_z, 2, m * Vector(mecha->minx, mecha->miny,mecha->maxz));
  342.             assign(point_x, point_y, point_z, 3, m * Vector(mecha->maxx, mecha->miny,mecha->maxz));
  343.             assign(point_x, point_y, point_z, 4, m * Vector(mecha->maxx, mecha->maxy,mecha->minz));
  344.             assign(point_x, point_y, point_z, 5, m * Vector(mecha->minx, mecha->maxy,mecha->minz));
  345.             assign(point_x, point_y, point_z, 6, m * Vector(mecha->minx, mecha->miny,mecha->minz));
  346.             assign(point_x, point_y, point_z, 7, m * Vector(mecha->maxx, mecha->miny,mecha->minz));
  347.         } else {
  348.             assign(point_x, point_y, point_z, 0, m * Vector(mecha->maxx, 0,0));
  349.             assign(point_x, point_y, point_z, 1, m * Vector(mecha->minx, mecha->maxy,0));
  350.             assign(point_x, point_y, point_z, 2, m * Vector(mecha->minx, mecha->miny,0));
  351.             assign(point_x, point_y, point_z, 3, m * Vector(mecha->minx, 0,mecha->maxz));
  352.             assign(point_x, point_y, point_z, 4, m * Vector(mecha->minx, 0,mecha->minz));
  353.         }
  354.     }
  355. }
  356.  
  357. static inline void assignv(int view_x[], int view_y[], int view_z[], int i, Vector& v1)
  358. {
  359.     if (v1.z <= 1.0) {
  360.         view_z[0] = -1;
  361.         view_x[i] = 0;
  362.         view_y[i] = 0;
  363.     } else {
  364.         double vx = v1.x / v1.z;
  365.         double vy = v1.y / v1.z;
  366.         if (vx < -4096|| vx > 4096 || vy < -4096 || vy > 4096) {
  367.             view_x[i] = 0;
  368.             view_y[i] = 0;
  369.             view_z[0] = -1;
  370.         } else {
  371.             view_x[i] = (int)vx;
  372.             view_y[i] = (int)vy;
  373.         }
  374.     }
  375. }
  376.  
  377. void Motion::CalcViewBox(Matrix& m)
  378. {
  379.     if (mecha == NULL || mecha->points < 8) {
  380.         CalcView(m);
  381.     } else {
  382.         boxflag = TRUE;
  383.         view_z[0] = 1;
  384.         if (motiondata == NULL) {
  385.             assignv(view_x, view_y, view_z, 0, m * Vector(mecha->maxx, mecha->maxy,mecha->maxz));
  386.             assignv(view_x, view_y, view_z, 1, m * Vector(mecha->minx, mecha->maxy,mecha->maxz));
  387.             assignv(view_x, view_y, view_z, 2, m * Vector(mecha->minx, mecha->miny,mecha->maxz));
  388.             assignv(view_x, view_y, view_z, 3, m * Vector(mecha->maxx, mecha->miny,mecha->maxz));
  389.             assignv(view_x, view_y, view_z, 4, m * Vector(mecha->maxx, mecha->maxy,mecha->minz));
  390.             assignv(view_x, view_y, view_z, 5, m * Vector(mecha->minx, mecha->maxy,mecha->minz));
  391.             assignv(view_x, view_y, view_z, 6, m * Vector(mecha->minx, mecha->miny,mecha->minz));
  392.             assignv(view_x, view_y, view_z, 7, m * Vector(mecha->maxx, mecha->miny,mecha->minz));
  393.         } else {
  394.             assignv(view_x, view_y, view_z, 0, m * Vector(mecha->maxx, 0,0));
  395.             assignv(view_x, view_y, view_z, 1, m * Vector(mecha->minx, mecha->maxy,0));
  396.             assignv(view_x, view_y, view_z, 2, m * Vector(mecha->minx, mecha->miny,0));
  397.             assignv(view_x, view_y, view_z, 3, m * Vector(mecha->minx, 0,mecha->maxz));
  398.             assignv(view_x, view_y, view_z, 4, m * Vector(mecha->minx, 0,mecha->minz));
  399.         }
  400.     }
  401. }
  402.  
  403.  
  404.  
  405. void Motion::SetMech(Mechanic *mec)
  406. {
  407.     delete[] point_x;
  408.     delete[] point_y;
  409.     delete[] point_z;
  410.     delete[] view_x;
  411.     delete[] view_y;
  412.     delete[] view_z;
  413.  
  414.     if (mec ==  NULL) {
  415.         mecha = NULL;
  416.         point_x = point_y = point_z = NULL;
  417.         view_x = view_y = view_z = NULL;
  418.         line_1 = line_2 = NULL;
  419.         lines = 0;
  420.     } else {
  421.         mecha = mec;
  422.         point_x = new int[mec->points];
  423.         point_y = new int[mec->points];
  424.         point_z = new int[mec->points];
  425.         view_x = new int[mec->points];
  426.         view_y = new int[mec->points];
  427.         view_z = new int[mec->points];
  428.         line_1 = mec->line_1;
  429.         line_2 = mec->line_2;
  430.         lines = mec->lines;
  431.     }
  432. }
  433.  
  434. void Motion::Zoom(int begin, int end)
  435. {
  436.     beginframe = begin;
  437.     endframe = end;
  438.     if (motiondata != NULL) {
  439.         GetPosition(nowframe);
  440.     }
  441. }
  442.  
  443. void Motion::SetForward()
  444. {
  445.     if (motiondata == NULL) {
  446.         return;
  447.     }
  448.     motiondata->SetForward();
  449.     GetPosition(nowframe);
  450. }
  451.  
  452. void Motion::ChangeMove(Vector& dir)
  453. {
  454.     if (motiondata != NULL) {
  455.         return;
  456.     }
  457.     Bezier *b = new Bezier();
  458.     b->AddPoint(position    , position + (1.0/2.0) * dir);
  459.     b->AddPoint(position+dir, position + (4.0/2.0) * dir);
  460.     motiondata = new MotionData(b);
  461.     motiondata->rotation[0] = motiondata->rotation[1] = rotation;
  462.     motiondata->scale[0]    = motiondata->scale[1]    = scale;
  463. }
  464.  
  465. void Motion::ChangeFix(void)
  466. {
  467.     if (motiondata == NULL) {
  468.         return;
  469.     }
  470.     position = motiondata->bezier->point[0];
  471.     rotation = motiondata->rotation[0];
  472.     scale = motiondata->scale[0];
  473.     delete motiondata;
  474.     motiondata = NULL;
  475. }
  476.  
  477. CameraMotion::CameraMotion(Motion *t, int frames):    Motion(NULL, BEGIN, frames)
  478. {
  479.     SetAngle(deg(60));
  480.     target = t;
  481.  
  482.     line_1 = l1;
  483.     line_2 = l2;
  484.  
  485.     for (int i = 0; i < CameraLines; ++i) {
  486.         line_1[i] = 0;
  487.         line_2[i] = i+1;
  488.     }
  489.  
  490.     lines = CameraLines;;
  491.  
  492.     point_x = new int[CameraPoints];
  493.     point_y = new int[CameraPoints];
  494.     point_z = new int[CameraPoints];
  495.     view_x = new int[CameraPoints];
  496.     view_y = new int[CameraPoints];
  497.     view_z = new int[CameraPoints];
  498. }
  499.  
  500. CameraMotion::CameraMotion(Motion* m, Motion* t) : Motion(*m)
  501. {
  502.     SetAngle(deg(60));
  503.     target = t;
  504.  
  505.     line_1 = l1;
  506.     line_2 = l2;
  507.  
  508.     for (int i = 0; i < CameraLines; ++i) {
  509.         line_1[i] = 0;
  510.         line_2[i] = i+1;
  511.     }
  512.  
  513.     lines = CameraLines;;
  514.  
  515.     point_x = new int[CameraPoints];
  516.     point_y = new int[CameraPoints];
  517.     point_z = new int[CameraPoints];
  518.     view_x = new int[CameraPoints];
  519.     view_y = new int[CameraPoints];
  520.     view_z = new int[CameraPoints];
  521.  
  522. }
  523.  
  524.  
  525.  
  526. void CameraMotion::SetAngle(double a)
  527. {
  528.     angle = a;
  529.     pv[0] = Vector(0,0,0);
  530.     pv[1] = Vector(1.0, 0.0, 0.0);
  531.     for (int i = 2; i < CameraPoints; ++i) {
  532.         pv[i].x = TargetDistance;
  533.     }
  534.     pv[2].y = pv[3].y = TargetDistance * tan(angle/2.0);
  535.     pv[4].y = pv[5].y = -pv[2].y;
  536.     pv[2].z = pv[4].z = pv[2].y * 3 / 4;
  537.     pv[3].z = pv[5].z = -pv[2].z;
  538. }
  539.  
  540. void CameraMotion::GetPosition(int frame)
  541. {
  542.     if (motiondata != NULL) {
  543.         double t = (double)(frame - beginframe) / (double)(endframe - beginframe);
  544.         motiondata->GetPosition(t, position, rotation, scale);
  545.         target->GetPosition(frame);
  546.     }
  547.     Vector v = target->position - position;
  548.     rotation = (v ^ Vector(0,0,1)).GetRotation();
  549.     double d = v.length();
  550.     scale = Vector(d,d,d);
  551.     nowframe = frame;
  552. }
  553.  
  554. void CameraMotion::CalcPoints(Matrix& m)
  555. {
  556.     boxflag = FALSE;
  557.     for (int i = 0; i < CameraPoints; ++i) {
  558.         Vector v1 = m * pv[i];
  559.         point_x[i] = int(v1.x);
  560.         point_y[i] = int(v1.y);
  561.         point_z[i] = int(v1.z);
  562.     }
  563. }
  564.  
  565. void CameraMotion::CalcView(Matrix& /*m*/)
  566. {
  567.     for (int i = 0; i < CameraPoints; ++i) {
  568.         view_x[i] = view_y[i] = 0;
  569.         view_z[i] = -1;
  570.     }
  571. }
  572.  
  573. void CameraMotion::CalcPointsBox(Matrix& m)
  574. {
  575.     CalcPoints(m);
  576. }
  577.  
  578. void CameraMotion::CalcViewBox(Matrix& m)
  579. {
  580.     CalcView(m);
  581. }
  582.  
  583.  
  584.