Beispiel #1
0
///////////////////////////////////////////////////////////////
// METHOD
///////////////////////////////////////////////////////////////
CStatus splinekine_op_Update( CRef& in_ctxt, int mode = 0 )
{
   OperatorContext ctxt( in_ctxt );
   long count = (LONG)ctxt.GetParameterValue(L"count");
   CVector3Array pos(count);
   CVector3Array tangent(count);
   CVector3Array rot(count);
   CDoubleArray roll(count);
   CVector3Array rotParent(count);
   CVector3Array scl(count);
   CTransformation singleXF,singleParentXF;
   CMatrix3 singleMat;
   CTransformation modelXF;

   if(mode == 0) // simple 180 flipping interpolation
   {
      for(long i=0;i<count;i++)
      {
         singleXF = KinematicState(ctxt.GetInputValue(i)).GetTransform();
         singleMat = singleXF.GetRotationMatrix3();
         pos[i] = singleXF.GetTranslation();
         tangent[i].MulByMatrix3(CVector3(singleXF.GetSclX()*2.5,0,0),singleMat);
         rot[i] = singleXF.GetRotationXYZAngles();
         scl[i] = singleXF.GetScaling();
      }
      modelXF = KinematicState(ctxt.GetInputValue(count)).GetTransform();
   }
   else if(mode == 1) // local rotation X based roll
   {
      for(long i=0;i<count;i++)
      {
         singleParentXF = KinematicState(ctxt.GetInputValue(i*2+0)).GetTransform();
         singleXF = KinematicState(ctxt.GetInputValue(i*2+1)).GetTransform();
         roll[i] = singleXF.GetRotX();

         singleXF = MapObjectPoseToWorldSpace(singleParentXF,singleXF);
         singleMat = singleXF.GetRotationMatrix3();

         pos[i] = singleXF.GetTranslation();
         tangent[i].MulByMatrix3(CVector3(singleXF.GetSclX()*2.5,0,0),singleMat);
         rot[i] = singleParentXF.GetRotationXYZAngles();
         scl[i] = singleXF.GetScaling();
      }
      modelXF = KinematicState(ctxt.GetInputValue(count*2)).GetTransform();
   }
   double u = ctxt.GetParameterValue(L"u");
   bool resample = ctxt.GetParameterValue(L"resample");
   long subdiv = (LONG)ctxt.GetParameterValue(L"subdiv");
   bool absolute = ctxt.GetParameterValue(L"absolute");

   double step = 1.0 / max(1,count-1);
   int index1 = (int)min(count-2,u / step);
   int index2 = index1+1;
   int index1temp = index1;
   int index2temp = index2;
   double v = (u - step * double(index1)) / step;
   double vtemp = v;

   // calculate the bezier
   CVector3 bezierPos;
   CVector3 xAxis,yAxis,zAxis;
   if(!resample)
   {
      // straight bezier solve
      CVector3Array results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],v);
      bezierPos = results[0];
      xAxis = results[1];
   }
   else if(!absolute)
   {
      CVector3Array presample(subdiv);
      CVector3Array presampletan(subdiv);
      CDoubleArray samplelen(subdiv);
      double samplestep = 1.0 / double(subdiv-1);
      double sampleu = samplestep;
      presample[0]  = pos[index1];
      presampletan[0]  = tangent[index1];
      CVector3 prevsample(presample[0]);
      CVector3 diff;
      samplelen[0] = 0;
      double overalllen = 0;
      CVector3Array results(2);
      for(long i=1;i<subdiv;i++,sampleu+=samplestep)
      {
         results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],sampleu);
         presample[i] = results[0];
         presampletan[i] = results[1];
         diff.Sub(presample[i],prevsample);
         overalllen += diff.GetLength();
         samplelen[i] = overalllen;
         prevsample = presample[i];
      }
      // now as we have the
      sampleu = 0;
      for(long i=0;i<subdiv-1;i++,sampleu+=samplestep)
      {
         samplelen[i+1] = samplelen[i+1] / overalllen;
         if(v>=samplelen[i] && v <=  samplelen[i+1])
         {
            v = (v - samplelen[i]) / (samplelen[i+1] - samplelen[i]);
            bezierPos.LinearlyInterpolate(presample[i],presample[i+1],v);
            xAxis.LinearlyInterpolate(presampletan[i],presampletan[i+1],v);
            break;
         }
      }
   }
   else
   {
      CVector3Array presample(subdiv);
      CVector3Array presampletan(subdiv);
      CDoubleArray samplelen(subdiv);
      double samplestep = 1.0 / double(subdiv-1);
      double sampleu = samplestep;
      presample[0]  = pos[0];
      presampletan[0]  = tangent[0];
      CVector3 prevsample(presample[0]);
      CVector3 diff;
      samplelen[0] = 0;
      double overalllen = 0;
      CVector3Array results;
      for(long i=1;i<subdiv;i++,sampleu+=samplestep)
      {
         index1 = (int)min(count-2,sampleu / step);
         index2 = index1+1;
         v = (sampleu - step * double(index1)) / step;
         results = bezier4point(pos[index1],tangent[index1],pos[index2],tangent[index2],v);
         presample[i] = results[0];
         presampletan[i] = results[1];
         diff.Sub(presample[i],prevsample);
         overalllen += diff.GetLength();
         samplelen[i] = overalllen;
         prevsample = presample[i];
      }
      // now as we have the
      sampleu = 0;
      for(long i=0;i<subdiv-1;i++,sampleu+=samplestep)
      {
         samplelen[i+1] = samplelen[i+1] / overalllen;
         if(u>=samplelen[i] && u <= samplelen[i+1])
         {
            u = (u - samplelen[i]) / (samplelen[i+1] - samplelen[i]);
            bezierPos.LinearlyInterpolate(presample[i],presample[i+1],u);
            xAxis.LinearlyInterpolate(presampletan[i],presampletan[i+1],u);
            break;
         }
      }
   }

   // compute the scaling (straight interpolation!)
   CVector3 scl1;
   scl1.LinearlyInterpolate(scl[index1temp], scl[index2temp],vtemp);
   scl1.PutX(1);
   // scl1.PutX(modelXF.GetSclX());
   // We need to find another way to manage global scaling

   // compute the rotation!
   CRotation rot1,rot2;
   rot1.SetFromXYZAngles(rot[index1temp]);
   rot2.SetFromXYZAngles(rot[index2temp]);
   CQuaternion quat;
   quat.Slerp(rot1.GetQuaternion(),rot2.GetQuaternion(),vtemp);
   rot1.SetFromQuaternion(quat);
   yAxis.Set(0,1,0);
   yAxis.MulByMatrix3InPlace(rot1.GetMatrix());

   // use directly or project the roll values!
   if (mode == 1)
   {
      double thisRoll = roll[index1temp] * (1.0 - vtemp) + roll[index2temp] * vtemp;
      rot1.SetFromAxisAngle(xAxis,DegreesToRadians(thisRoll));
      yAxis.MulByMatrix3InPlace(rot1.GetMatrix());
   }

   zAxis.Cross(xAxis,yAxis);
   yAxis.Cross(zAxis,xAxis);
   xAxis.NormalizeInPlace();
   yAxis.NormalizeInPlace();
   zAxis.NormalizeInPlace();

   CTransformation result;
   result.SetScaling(scl1);
   result.SetRotationFromXYZAxes(xAxis,yAxis,zAxis);
   result.SetTranslation(bezierPos);
   KinematicState outKine(ctxt.GetOutputTarget());
   outKine.PutTransform(result);

   return CStatus::OK;
}