+ private color calculateSpokeColor(final color h1c, final color h2c, final PVector pt) {
+ // Find the closest spoke's t-value and calculate its
+ // axis. Until everything animates in the model reference
+ // frame, this has to be calculated at every step because
+ // the helices rotate.
+ Line axis = h1.getAxis();
+ float t = axis.getTValue(pt) + spokePhase;
+ float spokeAxisTValue = floor(((t + spokePeriod/2) / spokePeriod)) * spokePeriod;
+ PVector h1point = axis.getPointAt(t);
+ h1point.add(h1.getPhaseNormal());
+ h1point = axis.rotatePoint(h1point, (t / helixCoilPeriod) * TWO_PI + h1.getPhase());
+ // TODO(shaheen) investigate why h1.getAxis().getPointAt(spokeAxisTValue) doesn't quite
+ // have the same value as finding the middle between h1point and h2point.
+ PVector spokeCenter = h1.getAxis().getPointAt(spokeAxisTValue);
+ PVector spokeVector = PVector.sub(h1point, spokeCenter);
+ spokeVector.normalize();
+ Line spokeLine = new Line(h1point, spokeVector);
+ PVector pointOnSpoke = spokeLine.projectPoint(pt);
+ float b = ((PVector.dist(pt, pointOnSpoke) < spokeGirth) && (PVector.dist(pointOnSpoke, spokeCenter) < spokeRadius)) ? 100.f : 0.f;
+ return color(100, 80.f, b);
+ }
+