/// <summary> /// Override to compute rotations unconstrained as a rotation about the gravity vector, Y-axis. /// </summary> /// <returns>True on success.</returns> /// <remarks> /// It takes at least 3 non-collinear points to imply a rotation. /// If there are fewer than that, this reverts back to the behavior of /// computing a rotation which pitches to align points but doesn't introduce roll. /// </remarks> protected override bool ComputeRotations() { bool haveNonZero = false; for (int i = 0; i < actives.Count; ++i) { for (int j = i + 1; j < actives.Count; ++j) { for (int k = j + 1; k < actives.Count; ++k) { WeightedRotation wrotNew = ComputeRotation(actives[i].orientable, actives[j].orientable, actives[k].orientable); if (wrotNew.weight > 0) { haveNonZero = true; WeightedRotation wrot = actives[i]; wrot = AverageRotation(wrot, wrotNew); actives[i] = wrot; wrot = actives[j]; wrot = AverageRotation(wrot, wrotNew); actives[j] = wrot; wrot = actives[k]; wrot = AverageRotation(wrot, wrotNew); actives[k] = wrot; } } } } if (!haveNonZero) { // This can happen if there aren't enough points, or they are all collinear. return(base.ComputeRotations()); } return(true); }
/// <summary> /// Compute a new weighted rotation representing the two input weighted rotations. /// </summary> /// <param name="accum">The accumulator rotation.</param> /// <param name="add">The rotation to add in.</param> /// <returns>A new aggregate weighted rotation.</returns> private WeightedRotation AverageRotation(WeightedRotation accum, WeightedRotation add) { float interp = add.weight / (accum.weight + add.weight); Quaternion combinedRot = Quaternion.Slerp(accum.rotation, add.rotation, interp); combinedRot.Normalize(); float combinedWeight = accum.weight + add.weight; return(new WeightedRotation() { orientable = accum.orientable, rotation = combinedRot, weight = combinedWeight }); }
/// <summary> /// Compute rotations by pairs, weighting by distance and averaging for each orientable. /// </summary> /// <returns></returns> private bool ComputeRotations() { for (int i = 0; i < actives.Count; ++i) { for (int j = i + 1; j < actives.Count; ++j) { WeightedRotation wrotNew = ComputeRotation(actives[i].orientable, actives[j].orientable); WeightedRotation wrot = actives[i]; wrot = AverageRotation(wrot, wrotNew); actives[i] = wrot; wrot = actives[j]; wrot = AverageRotation(wrot, wrotNew); actives[j] = wrot; } } return(true); }