Ejemplo n.º 1
0
void MatrixAnimFromFlatBuffers(const MatrixAnimFb& params, MatrixAnim* anim) {
  MatrixOpArray& ops = anim->ops();
  ops.Clear(params.ops()->size());

  // Count the number of splines.
  int num_splines = 0;
  for (auto op = params.ops()->begin(); op != params.ops()->end(); ++op) {
    if (op->value_type() == MatrixOpValueFb_CompactSplineFb) num_splines++;
  }

  // Initialize the output structure with the correct number of splines.
  MatrixAnim::Spline* splines = anim->Construct(num_splines);

  // Loop through each op, adding to the MatrixAnim ops.
  int spline_idx = 0;
  for (auto op = params.ops()->begin(); op != params.ops()->end(); ++op) {
    const MatrixOperationType op_type =
        static_cast<MatrixOperationType>(op->type());

    switch (op->value_type()) {
      case MatrixOpValueFb_CompactSplineFb: {
        const CompactSplineFb* spline_fb =
            reinterpret_cast<const CompactSplineFb*>(op->value());
        MatrixAnim::Spline& s = splines[spline_idx++];

        // Copy the spline data into s.spline.
        // TODO: modify CompactSpline so we can just point at spline data
        //       instead of copying it.
        const Range y_range(spline_fb->y_range_start(),
                            spline_fb->y_range_end());
        s.spline.Init(y_range, spline_fb->x_granularity(),
                      spline_fb->nodes()->size());
        for (auto n = spline_fb->nodes()->begin();
             n != spline_fb->nodes()->end(); ++n) {
          s.spline.AddNodeVerbatim(n->x(), n->y(), n->angle());
        }

        // Hold `init` and `playback` data in structures that won't disappear,
        // since these are referenced by pointer.
        const bool modular = ModularOp(op_type);
        const Range& op_range = RangeOfOp(op_type, y_range);
        s.init = SmoothInit(op_range, modular);
        ops.AddOp(op_type, s.init, s.spline);
        break;
      }

      case MatrixOpValueFb_ConstantOpFb: {
        const ConstantOpFb* const_fb =
            reinterpret_cast<const ConstantOpFb*>(op->value());
        ops.AddOp(op_type, const_fb->y_const());
        break;
      }

      default:
        assert(false);  // Invalid FlatBuffer data.
    }
  }
}
Ejemplo n.º 2
0
static void CreateDefiningAnim(const RigAnim** anims, size_t num_anims,
                               RigAnim* defining_anim) {
  // This function only works for animations that follow the canonical order.
  for (size_t i = 0; i < num_anims; ++i) {
    assert(IsCanonicalAnim(*anims[i]));
  }

  // Get the bone hierarchy that covers all the hierarchies in `anims`.
  const RigAnim* complete_rig = FindCompleteRig(anims, num_anims);
  const BoneIndex num_bones = complete_rig->NumBones();
  const BoneIndex* parents = complete_rig->bone_parents();
  defining_anim->Init("defining_anim", num_bones, true);

  // For each bone, consider adding each operation in the canonical operations.
  for (BoneIndex j = 0; j < num_bones; ++j) {
    // Start initializing this bone.
    MatrixAnim& matrix_anim =
        defining_anim->InitMatrixAnim(j, parents[j], complete_rig->BoneName(j));
    MatrixOpArray& ops = matrix_anim.ops();

    // Loop through all possible operations for this bone.
    Range ranges[MOTIVE_ARRAY_SIZE(kCanonicalRigAnimOps)];
    for (size_t k = 0; k < MOTIVE_ARRAY_SIZE(kCanonicalRigAnimOps); ++k) {
      const MatrixOperationType op = kCanonicalRigAnimOps[k];

      // Loop over all anims, checking to see if they have this operation.
      for (size_t i = 0; i < num_anims; ++i) {
        if (j >= anims[i]->NumBones()) continue;

        const MatrixOpArray::OpVector& opv = anims[i]->Anim(j).ops().ops();
        const MatrixOperationInit* op_init = FindOpInit(opv, op);
        if (op_init == nullptr) continue;

        if (op_init->init == nullptr) {
          ranges[k] = ranges[k].Include(op_init->initial_value);
        } else {
          const SplineInit* spline_init =
              static_cast<const SplineInit*>(op_init->init);
          ranges[k] = Range::Union(ranges[k], spline_init->range());
        }
      }
    }

    // Count the number of ranges that need init parameters.
    int num_ops_with_init = 0;
    for (size_t k = 0; k < MOTIVE_ARRAY_SIZE(kCanonicalRigAnimOps); ++k) {
      if (ranges[k].Valid() && ranges[k].Length() > 0.0f) num_ops_with_init++;
    }
    MatrixAnim::Spline* splines = matrix_anim.Construct(num_ops_with_init);

    // Create the array of matrix operations.
    int num_ops_inited = 0;
    for (size_t k = 0; k < MOTIVE_ARRAY_SIZE(kCanonicalRigAnimOps); ++k) {
      if (!ranges[k].Valid()) continue;

      // If this operation exists, add it to the `defining_anim`.
      const MatrixOperationType op = kCanonicalRigAnimOps[k];
      if (ranges[k].Length() == 0.0f) {
        // If there is only one value for an operation, add it as a const.
        const float const_value = ranges[k].start();
        ops.AddOp(op, const_value);
      } else {
        // Otherwise, add it as an animated parameter.
        // The range is modular for rotate operations, but not for scale or
        // translate operations.
        const bool modular = ModularOp(op);
        const Range& op_range = RangeOfOp(op, ranges[k]);
        splines[num_ops_inited].init = SplineInit(op_range, modular);
        ops.AddOp(op, splines[num_ops_inited].init);
        num_ops_inited++;
      }
    }
  }
}