protected override void OnStart() { EmotionSpectrum currentEmotion = ProceduralEngine.Instance.GetCurrentEmotion(); float expectation = currentEmotion.Dot(new EmotionSpectrum(EmotionVector.GetCoreEmotion(CoreEmotion.Anticipation))); camera.RotationDampingTime = .1f + Mathf.Lerp(.4f, 0f, Mathf.Clamp01(expectation - 2f)); camera.PositionDampingTime = .1f + Mathf.Lerp(.4f, 0f, Mathf.Clamp01(expectation - 2f)); camera.SetNoiseParameters(Mathf.Clamp(expectation * .4f, 0f, .25f), .75f); Vector3 boundsAxis = mainInterestPoint.AssociatedItemBounds.size.normalized; List <KeyValuePair <Vector3, float> > possibleDirections = new List <KeyValuePair <Vector3, float> >(); // Chance of following the frustum average possibleDirections.Add(new KeyValuePair <Vector3, float>(mainInterestAxis, .5f)); // Chance of picking a dolly direction based on the item boundaries possibleDirections.Add(new KeyValuePair <Vector3, float>(mainInterestPoint.transform.right * boundsAxis.x, boundsAxis.x)); possibleDirections.Add(new KeyValuePair <Vector3, float>(mainInterestPoint.transform.up * boundsAxis.y, boundsAxis.y)); possibleDirections.Add(new KeyValuePair <Vector3, float>(mainInterestPoint.transform.forward * boundsAxis.z, boundsAxis.z)); // Chance of doing a dolly in/out float inOutDirection = ProceduralEngine.Instance.EmotionEngine.GetStructureAtTime(ProceduralEngine.Instance.CurrentTimeNormalized) == StructureType.Decreasing ? -1f : 1f; possibleDirections.Add(new KeyValuePair <Vector3, float>(GetForward() * inOutDirection, .5f)); movementDirection = ProceduralEngine.SelectRandomWeighted(possibleDirections, x => x.Value).Key.normalized; keepAttention = ProceduralEngine.RandomRange(0f, 1f) > .5f; // TODO: associate this with the rotation smoothness/lag, and with emotions (e.g. sadness lags, expectation keeps) }
public float GetTrackAffinityInTime(float nT) { TrackData track = ProceduralEngine.Instance.EmotionEngine.GetTrackById(TrackId); if (track != null) { return(internalSpectrum.Dot(ProceduralEngine.Instance.EmotionEngine.EvaluateTrack(track, nT))); } return(0f); }
/// <summary> /// This heuristic is useful for two cases: /// - Trying to find the main interest point /// - Trying to evaluate different views for the same interest point (shot heuristic) /// </summary> public float EvaluateHeuristic(EmotionSpectrum currentEmotion, float normalizedTime, bool primaryInterest = false) { // If this GO is inactive just ignore this IP // This is useful for state machines if (!gameObject.activeInHierarchy) { return(0f); } float heuristic = importance; heuristic += emotionalImpact * currentEmotion.Dot(internalSpectrum); // If this is the primary interest point, we want to make sure it is // close to other interesting places, so biasing the importance with a heatmap is useful. if (primaryInterest) { // Interesting: while being on an important place is good, we must not make unimportant elements important. // Thus we need to be careful with this multiplier heuristic += .35f * ProceduralCameraDirector.Instance.GetGrid().GetAverageImportanceForPosition(transform.position); // This is somewhat of a hack. The correct idea is to // predict if this state is going to be triggered, but that is not trivial if (stateMachine != null) { float stateEmotionResponse = stateMachine.GetGlobalAffinityInTime(normalizedTime) + stateMachine.GetTrackAffinityInTime(normalizedTime); heuristic += emotionalImpact * stateEmotionResponse; if (stateMachine.CurrentState == EmotionStateMachineState.State.Enabled || stateMachine.CurrentState == EmotionStateMachineState.State.IntroTransition) { heuristic *= 2f; } } } // Let's try to favor small or big objects based on general flow Vector3 worldScale = transform.lossyScale * size; float worldSizeNormalized = Mathf.Min(worldScale.magnitude, 200f) / 200f; float smoothEnergy = ProceduralEngine.Instance.EmotionEngine.GetSmoothEnergy(normalizedTime) / ProceduralEngine.Instance.EmotionEngine.MaxEnergy; // We assume smoothEnergy to be the normalized size we favor float sizeTargetOffset = Mathf.Abs(smoothEnergy - worldSizeNormalized) * 2f; heuristic = Mathf.Lerp(heuristic * 2f, heuristic, sizeTargetOffset); // TODO: ideas: // - Is it being lit right now? Or in shadow? // - If it is reflective/specular, where would be a good place to look at it from? // - Is it moving? return(heuristic); }
public float GetGlobalAffinityInTime(float nT) { EmotionSpectrum globalEmotion = smooth ? ProceduralEngine.Instance.EmotionEngine.GetSmoothSpectrum(nT) : ProceduralEngine.Instance.EmotionEngine.GetSpectrum(nT); return(globalEmotion.Dot(internalSpectrum)); }