예제 #1
0
int main() {
  //! [Own Processor Register]
  LinearInit::Register();
  //! [Own Processor Register]

  MotiveEngine engine;

  //! [Own Processor Create Instance]
  // Move from 10 --> -5 in 100 internal time units.
  const MotiveTarget1f target = motive::CurrentToTarget1f(10, 0, -5, 0, 100);

  // Create the one dimensional motivator of type Linear by passing in
  // LinearInit.
  Motivator1f linear_motivator(LinearInit(), &engine, target);
  //! [Own Processor Create Instance]

  //! [Own Processor Advance Simulation]
  // Advance the simulation one tick at a time by calling engine.AdvanceFrame().
  std::vector<vec2> points;
  points.reserve(target.EndTime() + 1);
  for (MotiveTime t = 0; t <= target.EndTime(); ++t) {
    points.push_back(vec2(static_cast<float>(t), linear_motivator.Value()));
    engine.AdvanceFrame(1);
  }
  printf("\n%s",
         motive::Graph2DPoints(&points[0], static_cast<int>(points.size()))
             .c_str());
  //! [Own Processor Advance Simulation]

  return 0;
}
예제 #2
0
  // TODO: Change to CreateSplineToTarget()
  void SetTarget(MotiveIndex index, const MotiveTarget1f& t) {
    SplineData& d = Data(index);

    // If the first node specifies time=0 or there is no valid data in the
    // interpolator, we want to override the current values with the values
    // specified in the first node.
    const MotiveNode1f& node0 = t.Node(0);
    const bool override_current =
        node0.time == 0 || !interpolator_.Valid(index);
    // TODO(b/65298927):  It seems that the animation pipeline can produce data
    // that is out of range.  Instead of just using node0.value directly, if
    // the interpolator is doing modular arithmetic, normalize the y value to
    // the modulator's range.
    const float start_y =
        override_current
            ? (interpolator_.ModularArithmetic(index)
                   ? interpolator_.ModularRange(index).Normalize(node0.value)
                   : node0.value)
            : interpolator_.NormalizedY(index);
    const float start_derivative =
        override_current ? node0.velocity : Velocity(index);
    const int start_node_index = override_current ? 1 : 0;

    // Ensure we have a local spline available, allocated from our pool of
    // splines.
    if (d.local_spline == nullptr) {
      d.local_spline = AllocateSpline();
    }

    // Initialize the compact spline to hold the sequence of nodes in 't'.
    // Add the first node, which has the start condition.
    const float end_x = static_cast<float>(t.EndTime());
    const Range y_range = CalculateYRange(index, t, start_y);
    const float x_granularity = CompactSpline::RecommendXGranularity(end_x);
    d.local_spline->Init(y_range, x_granularity);
    d.local_spline->AddNode(0.0f, start_y, start_derivative);

    // Add subsequent nodes, in turn, taking care to respect the 'direction'
    // request when using modular arithmetic.
    float prev_y = start_y;
    for (int i = start_node_index; i < t.num_nodes(); ++i) {
      const MotiveNode1f& n = t.Node(i);
      const float y = interpolator_.NextY(index, prev_y, n.value, n.direction);
      d.local_spline->AddNode(static_cast<float>(n.time), y, n.velocity,
                              motive::kAddWithoutModification);
      prev_y = y;
    }

    // Point the interpolator at the spline we just created. Always start our
    // spline at time 0.
    interpolator_.SetSplines(index, 1, d.local_spline, SplinePlayback());
  }
예제 #3
0
  Range CalculateYRange(MotiveIndex index, const MotiveTarget1f& t,
                        float start_y) const {
    if (interpolator_.ModularArithmetic(index)) {
      // For modular splines, we need to expand the spline's y-range to match
      // the number of nodes in the spline. It's possible for the spline to jump
      // up the entire range every node, so the range has to be broad enough
      // to hold it all.
      //
      // Note that we only normalize the first value of the spline, and
      // subsequent values are allowed to curve out of the normalized range.
      const float num_spline_nodes = static_cast<float>(t.num_nodes());
      return interpolator_.ModularRange(index).Lengthen(num_spline_nodes);
    }

    // Calculate the union of the y ranges in the target, then expand it a
    // little to allow for intermediate nodes that jump slightly beyond the
    // union's range.
    return t.ValueRange(start_y).Lengthen(kYRangeBufferPercent);
  }
예제 #4
0
  virtual void SetTarget(MotiveIndex index, const MotiveTarget1f& t) {
    OvershootData& d = Data(index);

    // A 'time' of 0 means that we're setting the current values.
    const MotiveNode1f& current = t.Node(0);
    if (current.time == 0) {
      d.value = current.value;
      d.velocity = current.velocity;
    }

    // A 'time' > 0 means that we're setting the target values.
    // We can also use the second node to set target values, if it exists.
    const MotiveNode1f* target =
        current.time == 0 ? (t.num_nodes() > 1 ? &t.Node(1) : nullptr)
                          : &t.Node(0);
    if (target != nullptr) {
      d.target_value = target->value;
    }
  }