예제 #1
0
Path::Path(WorldData* data) {
   worldData = data;
   currentPoint = 1;
   previousPoint = 0;
   
   vector<PathPointData>::iterator newPoint;
   for (newPoint = data->path.begin(); newPoint != data->path.end(); ++newPoint) {
      PathPoint point = PathPoint(*newPoint);
      points.push_back(point);
   }
   
   currentPoint = 1;
   previousPoint = 0;
}
예제 #2
0
bool BezierController::OnNextStep()
{
   if (!mLastPathPoint) { return false; }

   while (mCurrentPoint != mEndPoint && mTotalTime > (*mCurrentPoint).mTime)
   {
      mLastPathPoint = &(*mCurrentPoint);
      ++mCurrentPoint;
   }

   //if we reached the end of the path0
   //it means our time step was greater than
   //our path point resolution so we'll just stop
   //at the last valid path point
   if (mCurrentPoint == mEndPoint)
   {
      StepObject(mLastPathPoint->mPoint);

      mPath.clear();

      if (mShouldLoop)
      {
         // This needs to be false in order to restart
         mIsRunning = false;

         // Restart from the beginning
         Start();        
         return true;
      }

      return false;
   }

   const PathPoint& p = (*mCurrentPoint).mPoint;
   const float currentTime = (*mCurrentPoint).mTime;

   //else if our elapsed time is equal to the next points time
   //ie. the step for the controller = the step for the last BezierNode
   //then we just move to the next point
   if (std::abs(currentTime - mTotalTime) < 0.0001f)
   {
      StepObject(p);
   }

   //else if our elapsed time is equal to the previous points time
   //just move the the previous point
   else if (std::abs(mLastPathPoint->mTime - mTotalTime) < 0.0001f)
   {
      StepObject(mLastPathPoint->mPoint);
   }

   //if our elapsed time is between the last and next pathpoint
   //we will interpolate between the two points
   else if (mLastPathPoint->mTime <= mTotalTime && currentTime >= mTotalTime)
   {
      float perc = (mTotalTime - mLastPathPoint->mTime) / (currentTime  -  mLastPathPoint->mTime );

      osg::Vec3 from = p.GetPosition();
      osg::Vec3 to = mLastPathPoint->mPoint.GetPosition();

      osg::Vec3 vec;
      vec[0] = ((1.0 - perc) * from[0]) + (perc * to[0]);
      vec[1] = ((1.0 - perc) * from[1]) + (perc * to[1]);
      vec[2] = ((1.0 - perc) * from[2]) + (perc * to[2]);

      osg::Quat quat;
      quat.slerp(perc, mLastPathPoint->mPoint.GetOrientation(), p.GetOrientation());

      StepObject(PathPoint(vec, quat));
   }
   else
   {
      //else something went wrong
      assert(0);
   }

   return true;
}
예제 #3
0
PathPoint Path::getStart() const
{
	return PathPoint(_checkPoints, _distanceView);
}
예제 #4
0
TrackGenerator::TrackGenerator() {
  /*
  * Phase 1 -
  * Generate the track tree and place control points that wrap
  * closely around the tree segments.
  */

  // Start by generating the tree
  TrackTreeNode* rootTrackTreeNode = new TrackTreeNode(0.0, 0.0, NULL, 0);

  // Place the control points
  TrackTreeNode* current_start = rootTrackTreeNode;
  TrackTreeNode* previous_start = rootTrackTreeNode->neighbors[0];

  TrackTreeNode* current = current_start;
  TrackTreeNode* previous = previous_start;
  
  vector<vec3> controlPts;

  do {
    TrackTreeNode* next = current->getNextNode(previous);

    if (previous == next) { // happens if current node only has one segment
      vec2 direction = current->xz - previous->xz;
      direction.normalize();
      direction *= current->radius;
      vec2 offset(-direction[1], direction[0]);

      vec2 temp = current->xz + direction + offset;
      vec3 v(temp[0], RAND * 20 + 10, temp[1]);
      controlPts.push_back(v);
      temp = current->xz + direction - offset;
      v = vec3(temp[0], RAND * 20 + 10, temp[1]);
      controlPts.push_back(v);
    }
    else { // Otherwise, do the bisector thing
      vec2 direction1 = current->xz - previous->xz;
      direction1.normalize();
      direction1 = vec2(-direction1[1], direction1[0]);
      vec2 direction2 = next->xz - current->xz;
      direction2.normalize();
      direction2 = vec2(-direction2[1], direction2[0]);

      vec2 newDir = direction1 + direction2;

      double angle = acos(direction1 * direction2);

      newDir.normalize();
      newDir *= current->radius / cos(angle / 2);
      newDir += current->xz;

      // First, randomly assign heights
      vec3 v(newDir[0], RAND * 20 + 10, newDir[1]);
      controlPts.push_back(v);
    }

    // Advance
    previous = current;
    current = next;
  } while (current != current_start || previous != previous_start);
  
  bool majorChange = true;

  while (majorChange) {
    majorChange = false;

    /*
    * Phase 2 -
    * Merge nearby control points and prune control points with angles
    * that are too acute. Repeat until the track stops changing.
    */

    bool changed = true;
    while (changed) {
      changed = false;
      vector<vec3> tempControlPts;

      // Merge close control points first
      double threshold = 20.0;
      int size = controlPts.size();
      for (int i = 0; i < size; i++) {
        vec3 current = controlPts[i];
        vec3 previous = controlPts[(i + size - 1) % size];
        vec3 next = controlPts[(i + 1) % size];

        vec3 distvec1 = current - previous;
        vec3 distvec2 = next - current;
        distvec1[1] = 0.0;
        distvec2[1] = 0.0;
        double dist1 = distvec1.length();
        double dist2 = distvec2.length();
        if (dist1 > threshold && dist2 > threshold) {
          tempControlPts.push_back(current);
        }
        else if (dist2 <= threshold) {
          changed = true;
          vec3 newPoint = (current + next) / 2;
          tempControlPts.push_back(newPoint);
        }
        majorChange |= changed;
      }
      controlPts = tempControlPts;

      // Next, prune sharply angled control points
      tempControlPts.clear();
      size = controlPts.size();
      for (int i = 0; i < size; i++) {
        vec3 current = controlPts[i];
        vec3 previous = controlPts[(i + size - 1) % size];
        vec3 next = controlPts[(i + 1) % size];

        vec3 dir1 = current - previous;
        vec3 dir2 = current - next;
        dir1.normalize();
        dir2.normalize();
        if (acos(dir1 * dir2) < M_PI / 4) {
          changed = true;
        }
        else {
          tempControlPts.push_back(current);
        }
        majorChange |= changed;
      }
      controlPts = tempControlPts;
    }

    /*
    * Phase 3 -
    * Add height information and then adjust to make sure that
    * the track will not overlap too closely.
    */

    // TODO - compare segment distances to make sure that they aren't overalapping too closely
    changed = true;
    while (changed) {
      changed = false;

      for (unsigned int i = 0; i < controlPts.size() - 1; i++) {
        for (unsigned int j = i + 1; j < controlPts.size(); j++) {
          unsigned int jn = (j+1)%controlPts.size();
          pair<vec3, vec3> seg1(controlPts[i], controlPts[i+1]);
          pair<vec3, vec3> seg2(controlPts[j], controlPts[jn]);
          vec3 check = checkSegments(seg1, seg2);
          if (check.length() > 0.01) {
            changed = true;
            controlPts[i] += check / 2;
            controlPts[i+1] += check / 2;
            controlPts[j] -= check / 2;
            controlPts[jn] -= check / 2;
            controlPts[i][1] = max(controlPts[i][1], 4.0);
            controlPts[i+1][1] = max(controlPts[i+1][1], 4.0);
            controlPts[j][1] = max(controlPts[j][1], 4.0);
            controlPts[jn][1] = max(controlPts[jn][1], 4.0);
          }
        }
      }
      
      majorChange |= changed;
    }
  }

  /*
  * Recenter the track
  */
  vector<vec3>::iterator it = controlPts.begin();
  double xMin = (*it)[0];
  double xMax = (*it)[0];
  double zMin = (*it)[2];
  double zMax = (*it)[2];
  it++;
  while (it != controlPts.end()) {
    xMin = min(xMin, (*it)[0]);
    xMax = max(xMax, (*it)[0]);
    zMin = min(zMin, (*it)[2]);
    zMax = max(zMax, (*it)[2]);
    it++;
  }
  double xMid = (xMax + xMin) / 2;
  double zMid = (zMax + zMin) / 2;
  for (unsigned int i = 0; i < controlPts.size(); i++) {
    controlPts[i][0] -= xMid;
    controlPts[i][2] -= zMid;
  }

  xWidth = xMax - xMin;
  zWidth = zMax - zMin;

  /*
  * Add banking to make better turns, and add to pathPts
  */
  for (unsigned int i = 0; i < controlPts.size(); i++) {
    vec2 current = vec2(controlPts[i], VY);
    vec2 prev = vec2(controlPts[(i - 1 + controlPts.size()) % controlPts.size()], VY);
    vec2 next = vec2(controlPts[(i + 1) % controlPts.size()], VY);

    double angle = angleBetween(current, prev, next);
    vec2 dir = current - prev;
    vec2 turn = next - current;
    
    vec3 dir2(dir[0], 0, dir[1]);
    vec3 turn2(turn[0], 0, turn[1]);

    double bankAmount = 45 * pow(0.999, angle * dir.length() * turn.length() / 100);

    if ((dir2 ^ turn2)[1] > 0) {
      bankAmount *= -1;
    }

    pathPts.push_back(PathPoint(controlPts[i], bankAmount));
  }
}