Exemplo n.º 1
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());
  }
Exemplo n.º 2
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);
  }
Exemplo n.º 3
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;
    }
  }