⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 atifly.cpp

📁 游戏编程精粹2第三章源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

   if (CompileOrientations() == FALSE)
      return FALSE;

   return TRUE;
}

//=============================================================================
float32 AtiDistance (AtiVertex4 *v1, AtiVertex4 *v2)
{
   AtiVertex4 tmpv;

   tmpv.x = v1->x - v2->x;
   tmpv.y = v1->y - v2->y;
   tmpv.z = v1->z - v2->z;

   return (float32)(sqrt((tmpv.x*tmpv.x) + (tmpv.y*tmpv.y) + (tmpv.z*tmpv.z)));
}

//=============================================================================
void AtiVertex4Lerp (AtiVertex4 *ret, AtiVertex4 *v1, AtiVertex4 *v2, float32 lerpValue)
{
   ret->x = v1->x + lerpValue*(v2->x - v1->x);
   ret->y = v1->y + lerpValue*(v2->y - v1->y);
   ret->z = v1->z + lerpValue*(v2->z - v1->z);
}

//=============================================================================
void AtiVertex4Copy (AtiVertex4 *v1, AtiVertex4 *v2)
{
   v1->x = v2->x;
   v1->y = v2->y;
   v1->z = v2->z;
}

//=============================================================================
bool8 AtiFlyPath::CompilePositions (void)
{
   int32 i;
   int32 j;
   int32 k;
   float32 tmpf;
   float32 tmpf2;
   int32 numPoints = 0;
   AtiVertex4 *pointArray = NULL;
   AtiVertex4 *tmpD2 = NULL;
   AtiVertex4 *tmpIntD2 = NULL;

   /***********************************/
   /* Make sure we have enough points */
   /***********************************/
   if (mNumFlyPoints < 5)
      return FALSE;

   /********************************************/
   /* Allocate new memory for spline intervals */
   /********************************************/
   AtiFreeArray(mLocationIntervals);
   AtiMallocArray(mLocationIntervals, mNumFlyPoints, AtiSplineInterval);

   /*****************************************/
   /* Allocate memory for temporary storage */
   /*****************************************/
   AtiMallocArray(pointArray, mNumFlyPoints+9, AtiVertex4);
   AtiMallocArray(tmpD2,      mNumFlyPoints+9, AtiVertex4);
   AtiMallocArray(tmpIntD2,   mNumFlyPoints+9, AtiVertex4);

   /***************************************************************************/
   /* Build each array of vertices padding by 1 point on each end and process */
   /***************************************************************************/
   mPathTime = 0.0;
   mNumSplineIntervals = 0;
   for (i=0; i<mNumFlyPoints; i++)
   {
      /*******************/
      /* Skip cut points */
      /*******************/
      if (mLocation[i].w != 0.0)
         continue;

      /****************/
      /* Init counter */
      /****************/
      numPoints = 0;

      /**************************/
      /* Pad spline by 4 points */
      /**************************/
      if ((i == 0) && (mPreviousPath->mNumFlyPoints >= 5) && (mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-1].w == 0.0))
      {
         AtiVertex4Copy (&(pointArray[numPoints+3]), &(mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-1]));
         if (mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-2].w == 0.0)
         {
            AtiVertex4Copy (&(pointArray[numPoints+2]), &(mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-2]));
            if (mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-3].w == 0.0)
            {
               AtiVertex4Copy (&(pointArray[numPoints+1]), &(mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-3]));
               if (mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-4].w == 0.0)
               {
                  AtiVertex4Copy (&(pointArray[numPoints+0]), &(mPreviousPath->mLocation[mPreviousPath->mNumFlyPoints-4]));
               }
               else
               {
                  AtiVertex4Lerp (&(pointArray[numPoints+0]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), -1.0f);
               }
            }
            else
            {
               AtiVertex4Lerp (&(pointArray[numPoints+1]), &(pointArray[numPoints+2]), &(pointArray[numPoints+3]), -1.0f);
               AtiVertex4Lerp (&(pointArray[numPoints+0]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), -1.0f);
            }
         }
         else
         {
            AtiVertex4Lerp (&(pointArray[numPoints+2]), &(pointArray[numPoints+3]), &(mLocation[i]), -1.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+1]), &(pointArray[numPoints+2]), &(pointArray[numPoints+3]), -1.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+0]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), -1.0f);
         }
      }
      else //Not first point on spline, just create phantom points
      {
         if (i < mNumFlyPoints-1) //If not last point on spline
         {
            AtiVertex4Lerp (&(pointArray[numPoints+3]), &(mLocation[i]), &(mLocation[i+1]), -1.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+2]), &(mLocation[i]), &(mLocation[i+1]), -2.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+1]), &(mLocation[i]), &(mLocation[i+1]), -3.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+0]), &(mLocation[i]), &(mLocation[i+1]), -4.0f);
         }
         else
         {
            if (mNextPath->mNumFlyPoints >= 5)
            {
               AtiVertex4Lerp (&(pointArray[numPoints+3]), &(mLocation[i]), &(mNextPath->mLocation[0]), -1.0f);
               AtiVertex4Lerp (&(pointArray[numPoints+2]), &(mLocation[i]), &(mNextPath->mLocation[0]), -2.0f);
               AtiVertex4Lerp (&(pointArray[numPoints+1]), &(mLocation[i]), &(mNextPath->mLocation[0]), -3.0f);
               AtiVertex4Lerp (&(pointArray[numPoints+0]), &(mLocation[i]), &(mNextPath->mLocation[0]), -4.0f);
            }
            else //No next point...something's wrong
            {
               AtiVertex4Copy (&(pointArray[numPoints+3]), &(mLocation[i]));
               AtiVertex4Copy (&(pointArray[numPoints+2]), &(mLocation[i]));
               AtiVertex4Copy (&(pointArray[numPoints+1]), &(mLocation[i]));
               AtiVertex4Copy (&(pointArray[numPoints+0]), &(mLocation[i]));
            }
         }
      }
      numPoints += 4;

      /*****************************************/
      /* Add all points that aren't cut points */
      /*****************************************/
      for (; i<mNumFlyPoints; i++)
      {
         /******************/
         /* Add this point */
         /******************/
         AtiVertex4Copy (&(pointArray[numPoints]), &(mLocation[i]));
         numPoints++;

         /**********************/
         /* Break if cut point */
         /**********************/
         if (mLocation[i].w != 0.0)
            break;
      }

      /*************************************************/
      /* Add last 4 pad points by either getting them  */
      /* from the next path or creating phantom points */
      /*************************************************/
      if (((i < mNumFlyPoints) && (mLocation[i].w != 0.0)) || ((i >= mNumFlyPoints) && (mNextPath->mNumFlyPoints < 5))) //If cut point OR next path isn't valid
      {
         AtiVertex4Lerp (&(pointArray[numPoints+0]), &(pointArray[numPoints-2]), &(pointArray[numPoints-1]), 2.0f);
         AtiVertex4Lerp (&(pointArray[numPoints+1]), &(pointArray[numPoints-2]), &(pointArray[numPoints-1]), 3.0f);
         AtiVertex4Lerp (&(pointArray[numPoints+2]), &(pointArray[numPoints-2]), &(pointArray[numPoints-1]), 4.0f);
         AtiVertex4Lerp (&(pointArray[numPoints+3]), &(pointArray[numPoints-2]), &(pointArray[numPoints-1]), 5.0f);
         numPoints += 4;
      }
      else //Look at next path
      {
         /********************************************************************/
         /* This is the last point and smoothly feeding into the next spline */
         /********************************************************************/
         //Add first point to close the spline
         AtiVertex4Copy (&(pointArray[numPoints]), &(mNextPath->mLocation[0]));
         numPoints++;

         //Pad with next point
         AtiVertex4Copy (&(pointArray[numPoints+0]), &(mNextPath->mLocation[1]));
         if (mNextPath->mLocation[1].w == 0.0f)
         {
            AtiVertex4Copy (&(pointArray[numPoints+1]), &(mNextPath->mLocation[2]));
            if (mNextPath->mLocation[2].w == 0.0f)
            {
               AtiVertex4Copy (&(pointArray[numPoints+2]), &(mNextPath->mLocation[3]));
               if (mNextPath->mLocation[3].w == 0.0f)
               {
                  AtiVertex4Copy (&(pointArray[numPoints+3]), &(mNextPath->mLocation[4]));
               }
               else
               {
                  AtiVertex4Lerp (&(pointArray[numPoints+3]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), 2.0f);
               }
            }
            else
            {
               AtiVertex4Lerp (&(pointArray[numPoints+2]), &(pointArray[numPoints+0]), &(pointArray[numPoints+1]), 2.0f);
               AtiVertex4Lerp (&(pointArray[numPoints+3]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), 2.0f);
            }
         }
         else
         {
            AtiVertex4Lerp (&(pointArray[numPoints+1]), &(pointArray[numPoints-1]), &(pointArray[numPoints+0]), 2.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+2]), &(pointArray[numPoints+0]), &(pointArray[numPoints+1]), 2.0f);
            AtiVertex4Lerp (&(pointArray[numPoints+3]), &(pointArray[numPoints+1]), &(pointArray[numPoints+2]), 2.0f);
         }
         numPoints += 4;
      }

      /********************************************************/
      /* Create spline interval variables based on pointArray */
      /********************************************************/
      tmpD2[0].x = 0.0f;
      tmpD2[0].y = 0.0f;
      tmpD2[0].z = 0.0f;
      tmpD2[0].w = 0.0f;
      tmpIntD2[0].x = 0.0f;
      tmpIntD2[0].y = 0.0f;
      tmpIntD2[0].z = 0.0f;
      tmpIntD2[0].w = 0.0f;

      //Calculate second derivative for all points except first and last
      for (j=1; j<numPoints-1; j++) //For each point
      {
         for (k=0; k<4; k++) //For x, y, and z
         {
            float32 time  = 0.5f;
            float32 time2 = 1.0f;

            tmpf = (time * tmpD2[j-1].v[k]) + 2.0f;
            tmpD2[j].v[k] = (time - 1.0f) / tmpf;

            tmpf2 = ((pointArray[j+1].v[k] - pointArray[j].v[k]) / (time2)) - 
                    ((pointArray[j].v[k] - pointArray[j-1].v[k]) / (time2));

            tmpIntD2[j].v[k] = ((6.0f * tmpf2) / (time2+time2)) - (time * tmpIntD2[j-1].v[k]);
            tmpIntD2[j].v[k] /= tmpf;
         }
      }

      tmpD2[numPoints-1].x = 0.0f;
      tmpD2[numPoints-1].y = 0.0f;
      tmpD2[numPoints-1].z = 0.0f;
      tmpD2[numPoints-1].w = 0.0f;
      tmpIntD2[numPoints-1].x = 0.0f;
      tmpIntD2[numPoints-1].y = 0.0f;
      tmpIntD2[numPoints-1].z = 0.0f;
      tmpIntD2[numPoints-1].w = 0.0f;

      for (j=numPoints-2; j>=1; j--)
      {
         tmpD2[j].x = (tmpD2[j].x * tmpD2[j+1].x) + tmpIntD2[j].x;
         tmpD2[j].y = (tmpD2[j].y * tmpD2[j+1].y) + tmpIntD2[j].y;
         tmpD2[j].z = (tmpD2[j].z * tmpD2[j+1].z) + tmpIntD2[j].z;
         tmpD2[j].w = (tmpD2[j].w * tmpD2[j+1].w) + tmpIntD2[j].w;
      }
      
      for (j=4; j<numPoints-5; j++)
      {
         mLocationIntervals[mNumSplineIntervals].lo.x = pointArray[j].x;
         mLocationIntervals[mNumSplineIntervals].lo.y = pointArray[j].y;
         mLocationIntervals[mNumSplineIntervals].lo.z = pointArray[j].z;
         mLocationIntervals[mNumSplineIntervals].lo.w = pointArray[j].w;

         mLocationIntervals[mNumSplineIntervals].hi.x = pointArray[j+1].x;
         mLocationIntervals[mNumSplineIntervals].hi.y = pointArray[j+1].y;
         mLocationIntervals[mNumSplineIntervals].hi.z = pointArray[j+1].z;
         mLocationIntervals[mNumSplineIntervals].hi.w = pointArray[j+1].w;

         mLocationIntervals[mNumSplineIntervals].lo2.x = tmpD2[j].x;
         mLocationIntervals[mNumSplineIntervals].lo2.y = tmpD2[j].y;
         mLocationIntervals[mNumSplineIntervals].lo2.z = tmpD2[j].z;
         mLocationIntervals[mNumSplineIntervals].lo2.w = tmpD2[j].w;

         mLocationIntervals[mNumSplineIntervals].hi2.x = tmpD2[j+1].x;
         mLocationIntervals[mNumSplineIntervals].hi2.y = tmpD2[j+1].y;
         mLocationIntervals[mNumSplineIntervals].hi2.z = tmpD2[j+1].z;
         mLocationIntervals[mNumSplineIntervals].hi2.w = tmpD2[j+1].w;

         /********************/
         /* Update variables */
         /********************/
         mNumSplineIntervals++;
         mPathTime += mSampleInterval;
      }
   }

   /*********************************/
   /* Free temporary storage memory */
   /*********************************/
   AtiFreeArray(pointArray);
   AtiFreeArray(tmpD2);
   AtiFreeArray(tmpIntD2);

   return TRUE;
}

//=============================================================================
bool8 AtiFlyPath::GetPathPosition (AtiVertex3 *aPosition, float64 aTime)
{
   int32 tmpi;
   int32 interval;
   float32 intervalOffset;
   float64 tmpf64;
   float32 a;
   float32 b;

   if (mInFlight == FALSE)
      return FALSE;

   /******************************/
   /* Take care of loop wrapping */
   /******************************/
   tmpf64 = aTime - mStartTime;
   if (tmpf64 >= mPathTime)
   {
      tmpi = (int32)(tmpf64/mPathTime);
      tmpf64 -= mPathTime * (float64)(tmpi);
   }

   /**********************************************************************************/
   /* Figure out which interval this time falls into and calculate normalized offset */
   /**********************************************************************************/
   interval = (int32)(tmpf64/mSampleInterval);
   intervalOffset = (float32)((tmpf64 - (mSampleInterval*(float64)(interval))) / mSampleInterval);

   a = 1.0f - intervalOffset;
   b = intervalOffset;

   aPosition->x = a*mLocationIntervals[interval].lo.x + b*mLocationIntervals[interval].hi.x + ((a*a*a - a)*mLocationIntervals[interval].lo2.x + (b*b*b - b)*mLocationIntervals[interval].hi2.x) / 6.0f;// * (float32)(mSampleInterval*mSampleInterval) / 6.0f;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -