in src/core/PointOfInterestFeature.js [523:580]
_setMacroSaccade(layerName) {
const layer = this._managedLayers[layerName];
const { macroSaccade } = layer;
let macroSaccadeWaitRange;
// Increase random value range when not focused on a target
if (!this._target) {
macroSaccadeWaitRange = MacroSaccadeWaitRanges.default;
// Normal human horizontal eye rotation limit is about 35 degrees
const hLimit = Utils.getRandomFloat(.143, .286);
const hFactor = Utils.getRandomFloat(-hLimit, hLimit);
macroSaccade.h = hFactor * 35;
// Normal human vertical eye rotation limit is about 25 degrees upward and 30 degrees downward
const vLimit = Utils.getRandomFloat(.093, .186);
const vFactor = Utils.getRandomFloat(-vLimit, vLimit);
macroSaccade.v = vFactor > 0 ? vFactor * 25 : vFactor * 30;
}
// Pick a new face target
else {
// Social triangle - saccade between eyes and mouth, weighted to look at eyes more often
switch (layer.saccadeTarget) {
case 1:
macroSaccadeWaitRange = MacroSaccadeWaitRanges.eyeTarget;
layer.saccadeTarget = Math.random() < 0.75 ? FaceTargetTypes.EyeRight
: FaceTargetTypes.Mouth;
break;
case 2:
macroSaccadeWaitRange = MacroSaccadeWaitRanges.eyeTarget;
layer.saccadeTarget = Math.random() < 0.75 ? FaceTargetTypes.EyeLeft
: FaceTargetTypes.Mouth;
break;
case 3:
macroSaccadeWaitRange = MacroSaccadeWaitRanges.mouthTarget;
layer.saccadeTarget = Math.random() < 0.5 ? FaceTargetTypes.EyeLeft
: FaceTargetTypes.EyeRight;
break;
case 0:
default:
macroSaccadeWaitRange = MacroSaccadeWaitRanges.eyeTarget;
layer.saccadeTarget = Math.random() < 0.5 ? FaceTargetTypes.EyeLeft
: FaceTargetTypes.EyeRight;
break;
}
const { h, v } = this._getFaceTargetAngles(layer.saccadeTarget);
macroSaccade.h = h;
macroSaccade.v = v;
}
this._updateLayerSpeed(layerName, macroSaccade.h, macroSaccade.v);
// Restart the timers
this._initializeMicroTimer(layerName, ...MicroSaccadeWaitRanges.postMacro);
this._initializeMacroTimer(layerName, ...macroSaccadeWaitRange);
}