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; }
// 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()); }