protected override TrTransform CalculateChildXf(List <PbKnot> parentKnots) { TrTransform actionInCanvasSpace; { PbKnot knot = GetAttachKnot(parentKnots); float rotationDegrees = knot.m_distance * App.UNITS_TO_METERS * m_twist; TrTransform offset = m_offset; // It's cleaner to tack a TrTransform.S(size) onto the action, but that // would modify .scale, which is currently interpreted as "pointer size" // (affecting control point density) and which is also assumed by most // brushes to be constant. if (m_pressureAffectsOffset) { offset.translation *= knot.m_pressuredSize; } else { offset.translation *= m_brush.BaseSize_LS; } TrTransform action = TrTransform.R(Quaternion.AngleAxis(rotationDegrees, Vector3.forward)) * offset; actionInCanvasSpace = action.TransformBy(knot.GetFrame(m_frame)); } var cur = parentKnots[parentKnots.Count - 1]; return(actionInCanvasSpace * cur.m_pointer); }
protected override TrTransform CalculateChildXf(List <PbKnot> parentKnots) { PbKnot lastKnot = parentKnots[parentKnots.Count - 1]; float distanceMeters = lastKnot.m_distance * App.UNITS_TO_METERS; float t = O.CyclesPerMeter * distanceMeters + (float)m_strand / O.NumStrands; // Our periodic function makes the plait look pretty square; maybe add // some rotation to break things up a bit? float rotations = (O.CyclesPerMeter * distanceMeters) * O.RotationsPerCycle; float amplitude = lastKnot.m_pressuredSize / 2; // /2 because size is diameter, not radius. TrTransform action = TrTransform.R(rotations * 360, Vector3.forward) * TrTransform.T(SomePeriodicFunction(t) * amplitude); TrTransform actionInCanvasSpace = action.TransformBy(lastKnot.GetFrame(AttachFrame.LineTangent)); return(actionInCanvasSpace * lastKnot.m_pointer); }