ProtoTracer  1.0
Real-time 3D rendering and animation engine
Loading...
Searching...
No Matches
AphoriAnimation.h
Go to the documentation of this file.
1#pragma once
2
3#include "../Animation.h"
4#include "../KeyFrameTrack.h"
5#include "../EasyEaseAnimator.h"
6#include "../../Objects/Background.h"
7#include "../../Objects/LEDStripBackground.h"
8#include "../../Morph/Commissions/AphoriFace.h"
9#include "../../Render/Scene.h"
10#include "../../Signals/FunctionGenerator.h"
11#include "../../Menu/NeoTrellisMenu.h"
12#include "../../Sensors/APDS9960.h"
13
14#include "../../Materials/Animated/RainbowNoise.h"
15#include "../../Materials/Animated/RainbowSpiral.h"
16#include "../../Materials/Animated/SpectrumAnalyzer.h"
17#include "../../Materials/Animated/AudioReactiveGradient.h"
18#include "../../Materials/Animated/Oscilloscope.h"
19#include "../../Materials/MaterialMask.h"
20#include "../../Shapes/Circle.h"
21#include "../../Shapes/Rectangle.h"
22
23#include "../../Materials/MaterialAnimator.h"
24
25#include "../AnimationTracks/BlinkTrack.h"
26
27#include "../../Signals/FFTVoiceDetection.h"
28
29#include "../../Sensors/MicrophoneFourier_MAX9814.h"
30
31#include "../../Render/ObjectAlign.h"
32
33class AphoriAnimation : public Animation<3> {
34private:
35 static const uint8_t faceCount = 12;
36 AphoriFace pM;
37 Background background;
38 LEDStripBackground ledStripBackground;
39 EasyEaseAnimator<25> eEA = EasyEaseAnimator<25>(EasyEaseInterpolation::Overshoot, 1.0f, 0.35f);
40
41 Circle angryEyeCirc = Circle(Vector2D(102.0f, 62.0f), 12.0f);
42 Rectangle toastEyeRect = Rectangle(Vector2D(60.0f, 34.0f), Vector2D(80.0f, 50.0f), 0.0f);
43 Rectangle blushRect = Rectangle(Vector2D(75.0f, 20.0f), Vector2D(40.0f, 15.0f), 0.0f);
44 Rectangle sadRect = Rectangle(Vector2D(75.0f, 18.0f), Vector2D(40.0f, 15.0f), 0.0f);
45
46 //Materials
61
62 RGBColor gradientSpectrum[2] = {RGBColor(175, 175, 175), RGBColor(175, 175, 175)};
64
67
68 SpectrumAnalyzer sA = SpectrumAnalyzer(Vector2D(200, 100), Vector2D(100, 50), true, true);
71
72 //Animation controllers
74
81
85
87
89
90 ObjectAlign objA = ObjectAlign(Vector2D(0.0f, 0.0f), Vector2D(189.0f, 93.0f), Quaternion());
91
92 float offsetFace = 0.0f;
93 float offsetFaceSA = 0.0f;
94 float offsetFaceARG = 0.0f;
95 float offsetFaceOSC = 0.0f;
96 uint8_t offsetFaceInd = 50;
97 uint8_t offsetFaceIndSA = 51;
98 uint8_t offsetFaceIndARG = 52;
99 uint8_t offsetFaceIndOSC = 53;
100
102 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Happy), AphoriFace::Happy, 15, 0.0f, 1.0f);
103 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Concern), AphoriFace::Concern, 25, 0.0f, 1.0f);
104 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Blush), AphoriFace::Blush, 25, 0.0f, 1.0f);
105 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Upset), AphoriFace::Upset, 45, 0.0f, 1.0f);
106 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Angry), AphoriFace::Angry, 15, 0.0f, 1.0f);
107 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Sad), AphoriFace::Sad, 50, 0.0f, 1.0f);
108 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Nervous), AphoriFace::Nervous, 45, 0.0f, 1.0f);
109 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Thrilled), AphoriFace::Thrilled, 10, 0.0f, 1.0f);
110 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Toast), AphoriFace::Toast, 30, 0.0f, 1.0f);
111 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::Boop), AphoriFace::Boop, 30, 0.0f, 1.0f);
112 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::HideU), AphoriFace::HideU, 30, 1.0f, 0.0f);
113
114 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_ee), AphoriFace::vrc_v_ee, 2, 0.0f, 1.0f);
115 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_ih), AphoriFace::vrc_v_ih, 2, 0.0f, 1.0f);
116 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_dd), AphoriFace::vrc_v_dd, 2, 0.0f, 1.0f);
117 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_rr), AphoriFace::vrc_v_rr, 2, 0.0f, 1.0f);
118 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_ch), AphoriFace::vrc_v_ch, 2, 0.0f, 1.0f);
119 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_aa), AphoriFace::vrc_v_aa, 2, 0.0f, 1.0f);
120 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_oh), AphoriFace::vrc_v_oh, 2, 0.0f, 1.0f);
121 eEA.AddParameter(pM.GetMorphWeightReference(AphoriFace::vrc_v_ss), AphoriFace::vrc_v_ss, 2, 0.0f, 1.0f);
122
123 eEA.AddParameter(&offsetFace, offsetFaceInd, 40, 0.0f, 1.0f);
124 eEA.AddParameter(&offsetFaceSA, offsetFaceIndSA, 40, 0.0f, 1.0f);
127 }
128
130 blink.AddParameter(pM.GetMorphWeightReference(AphoriFace::Blink));
131 }
132
134 eEA.SetInterpolationMethod(AphoriFace::Sad, EasyEaseInterpolation::Cosine);
135 eEA.SetInterpolationMethod(AphoriFace::Angry, EasyEaseInterpolation::Cosine);
136
137 eEA.SetInterpolationMethod(AphoriFace::vrc_v_ee, EasyEaseInterpolation::Linear);
138 eEA.SetInterpolationMethod(AphoriFace::vrc_v_ih, EasyEaseInterpolation::Linear);
139 eEA.SetInterpolationMethod(AphoriFace::vrc_v_dd, EasyEaseInterpolation::Linear);
140 eEA.SetInterpolationMethod(AphoriFace::vrc_v_rr, EasyEaseInterpolation::Linear);
141 eEA.SetInterpolationMethod(AphoriFace::vrc_v_ch, EasyEaseInterpolation::Linear);
142 eEA.SetInterpolationMethod(AphoriFace::vrc_v_aa, EasyEaseInterpolation::Linear);
143 eEA.SetInterpolationMethod(AphoriFace::vrc_v_oh, EasyEaseInterpolation::Linear);
144 eEA.SetInterpolationMethod(AphoriFace::vrc_v_ss, EasyEaseInterpolation::Linear);
145 }
146
154 materialAnimator.AddMaterial(Material::Replace, &redMaterial, 40, 0.0f, 1.0f);//layer 6
157 materialAnimator.AddMaterial(Material::Replace, &rainbowNoise, 40, 0.15f, 1.0f);//layer 9
162
167 }
168
170 blink.Update();
171 }
172
173 void Default(){
174 eEA.AddParameterFrame(AphoriFace::Happy, 1.0f);
175 }
176
177 void Concern(){
178 eEA.AddParameterFrame(AphoriFace::Concern, 1.0f);
179 }
180
181 void Blush(){
182 eEA.AddParameterFrame(AphoriFace::Blush, 1.0f);
183 eEA.AddParameterFrame(AphoriFace::HideU, 0.0f);
185 }
186
187 void Upset(){
188 eEA.AddParameterFrame(AphoriFace::Upset, 1.0f);
189 }
190
191 void Angry(){
192 eEA.AddParameterFrame(AphoriFace::Angry, 1.0f);
194 }
195
196 void Sad(){
197 eEA.AddParameterFrame(AphoriFace::Sad, 0.75f);
199 }
200
201 void Nervous(){
202 eEA.AddParameterFrame(AphoriFace::Nervous, 1.0f);
203 eEA.AddParameterFrame(AphoriFace::HideU, 0.0f);
204 }
205
206 void Thrilled(){
207 eEA.AddParameterFrame(AphoriFace::Thrilled, 1.0f);
209 }
210
211 void Toast(){
212 eEA.AddParameterFrame(AphoriFace::Toast, 1.0f);
213 eEA.AddParameterFrame(AphoriFace::HideU, 0.0f);
215 }
216
217 void Boop(){
218 eEA.AddParameterFrame(AphoriFace::Boop, 1.0f);
220 }
221
228
235
242
245 eEA.AddParameterFrame(AphoriFace::vrc_v_ss, MicrophoneFourierIT::GetCurrentMagnitude() / 2.0f);
246
247 if(MicrophoneFourierIT::GetCurrentMagnitude() > 0.05f){
248 voiceDetection.Update(MicrophoneFourierIT::GetFourierFiltered(), MicrophoneFourierIT::GetSampleRate());
249
257 }
258 }
259 }
260
262 switch(Menu::GetFaceColor()){
263 case 1: materialAnimator.AddMaterialFrame(redMaterial, 0.8f); break;
265 case 3: materialAnimator.AddMaterialFrame(whiteMaterial, 0.8f); break;
266 case 4: materialAnimator.AddMaterialFrame(greenMaterial, 0.8f); break;
267 case 5: materialAnimator.AddMaterialFrame(blueMaterial, 0.8f); break;
270 case 8: materialAnimator.AddMaterialFrame(rainbowSpiral, 0.8f); break;
271 case 9: materialAnimator.AddMaterialFrame(rainbowNoise, 0.8f); break;
272 default: break;
273 }
274 }
275
276public:
278 scene.AddObject(pM.GetObject());
279 scene.AddObject(background.GetObject());
280 scene.AddObject(ledStripBackground.GetObject());
281
282 LinkEasyEase();
284
286
288
289 pM.GetObject()->SetMaterial(&materialAnimator);
290 background.GetObject()->SetMaterial(&backgroundMaterial);
291 ledStripBackground.GetObject()->SetMaterial(&materialAnimator);
292
293 boop.Initialize(5);
294
295 MicrophoneFourierIT::Initialize(15, 8000, 50.0f, 120.0f);//8KHz sample rate, 50dB min, 120dB max
296 Menu::Initialize(faceCount);//7 is number of faces
297
299 objA.SetMirrorX(true);
300 }
301
304 };
305
306 uint8_t GetBrightness(){
307 return Menu::GetBrightness();
308 };
309
310 void FadeIn(float stepRatio) override {}
311 void FadeOut(float stepRatio) override {}
312
314 return pM.GetObject();
315 }
316
317 void Update(float ratio) override {
318 pM.Reset();
319
320 float xOffset = fGenMatXMove.Update();
321 float yOffset = fGenMatYMove.Update();
322
323 Menu::Update(ratio);
324
326
327 bool isBooped = Menu::UseBoopSensor() ? boop.isBooped() : 0;
328 uint8_t mode = Menu::GetFaceState();//change by button press
329
330 MicrophoneFourierIT::Update();
331 sA.SetHueAngle(ratio * 360.0f * 4.0f);
334
335 aRG.SetRadius((xOffset + 2.0f) * 2.0f + 25.0f);
336 aRG.SetSize(Vector2D((xOffset + 2.0f) * 10.0f + 50.0f, (xOffset + 2.0f) * 10.0f + 50.0f));
337 aRG.SetHueAngle(ratio * 360.0f * 8.0f);
338 aRG.SetRotation(ratio * 360.0f * 2.0f);
339 aRG.SetPosition(Vector2D(80.0f + xOffset * 4.0f, 48.0f + yOffset * 4.0f));
340
341 oSC.SetSize(Vector2D(200.0f, 100.0f));
342 oSC.SetHueAngle(ratio * 360.0f * 8.0f);
343 oSC.SetPosition(Vector2D(100.0f, 50.0f));
344
345 voiceDetection.SetThreshold(map(Menu::GetMicLevel(), 0, 10, 1000, 50));
346
348
349 if (isBooped && mode != 8){
350 Boop();
351 }
352 else{
353 if (mode == 0) Default();
354 else if (mode == 1) Concern();
355 else if (mode == 2) Blush();
356 else if (mode == 3) Upset();
357 else if (mode == 4) Angry();
358 else if (mode == 5) Sad();
359 else if (mode == 6) Nervous();
360 else if (mode == 7) Thrilled();
361 else if (mode == 8) Toast();
362 else if (mode == 9) {
363 aRG.Update(MicrophoneFourierIT::GetFourierFiltered());
365 }
366 else if (mode == 10){
367 oSC.Update(MicrophoneFourierIT::GetSamples());
369 }
370 else {
371 sA.Update(MicrophoneFourierIT::GetFourierFiltered());
373 }
374 }
375
377
378 eEA.Update();
379 pM.Update();
380
381 rainbowNoise.Update(ratio);
382 rainbowSpiral.Update(ratio);
385
386 uint8_t faceSize = Menu::GetFaceSize();
387 float scale = Menu::ShowMenu() * 0.6f + 0.4f;
388 float faceSizeOffset = faceSize * 8.0f;
389
391 objA.SetEdgeMargin(2.0f);
392 objA.SetCameraMax(Vector2D(110.0f + faceSizeOffset, 93.0f - 93.0f * offsetFace).Multiply(scale));
393
394 objA.AlignObjects(scene.GetObjects(), 1);
395
396 pM.GetObject()->GetTransform()->SetPosition(Vector3D(xOffset, yOffset, 0.0f));
397 pM.GetObject()->UpdateTransform();
398 }
399};
A class for managing the Adafruit APDS9960 sensor.
Definition APDS9960.h:27
static bool Initialize(uint8_t threshold)
Initializes the APDS9960 sensor.
Definition APDS9960.cpp:14
static bool isBooped()
Checks if the sensor is "booped" (close proximity detected).
Definition APDS9960.cpp:43
void AddParameter(float *parameter)
Adds a parameter to the animation track.
float Update()
Updates the animation track and returns the current parameter value.
FunctionGenerator fGenMatHue
SimpleMaterial greenMaterial
FunctionGenerator fGenMatYMove
SpectrumAnalyzer sA
Oscilloscope oSC
SimpleMaterial pinkMaterial
SimpleMaterial redMaterial
RainbowSpiral rainbowSpiral
SimpleMaterial blueMaterial
FunctionGenerator fGenMatRMenu
void AudioReactiveGradientFace()
MaterialMask sadMaterial
Rectangle toastEyeRect
SimpleMaterial yellowMaterial
EasyEaseAnimator< 25 > eEA
BlinkTrack< 1 > blink
MaterialMask toastEyeMaterial
LEDStripBackground ledStripBackground
void ChangeInterpolationMethods()
MaterialMask blushMaterial
GradientMaterial< 2 > gradientMat
FunctionGenerator fGenMatPos
FunctionGenerator fGenScale
Background background
MaterialMask angryEyeMaterial
FunctionGenerator fGenRotation
SimpleMaterial orangeMaterial
FunctionGenerator fGenMatXMenu
void FadeIn(float stepRatio) override
void FadeOut(float stepRatio) override
RainbowNoise rainbowNoise
FunctionGenerator fGenMatYMenu
FunctionGenerator fGenMatXMove
SimpleMaterial purpleMaterial
void Update(float ratio) override
static const uint8_t faceCount
FFTVoiceDetection< 128 > voiceDetection
RGBColor gradientSpectrum[2]
MaterialAnimator< 4 > backgroundMaterial
MaterialAnimator< 15 > materialAnimator
uint8_t GetBrightness()
uint8_t GetAccentBrightness()
Object3D * GetObject()
SimpleMaterial whiteMaterial
AudioReactiveGradient aRG
A material class for creating an audio-reactive gradient effect.
void SetRadius(float radius)
Sets the radius for circular gradient patterns.
void SetPosition(Vector2D offset)
Sets the position of the gradient.
void Update(float *readData)
Updates the gradient based on new audio data.
void SetSize(Vector2D size)
Sets the size of the gradient.
void SetRotation(float angle)
Sets the rotation angle of the gradient.
void SetHueAngle(float hueAngle)
Sets the hue angle for color adjustments.
A template class for animating eye blinking using keyframes.
Definition BlinkTrack.h:27
Represents a circle in 2D space.
Definition Circle.h:21
A template class for implementing advanced animation easing.
void AddParameterFrame(uint16_t dictionaryValue, float value) override
Adds a single frame value for a parameter.
void Update() override
Updates the animator, advancing all animations.
void SetInterpolationMethod(uint16_t dictionaryValue, InterpolationMethod interpMethod) override
Sets the interpolation method for a specific parameter.
void AddParameter(float *parameter, uint16_t dictionaryValue, uint16_t frames, float basis, float goal) override
Adds a parameter to the animator.
Detects visemes based on FFT voice analysis.
float GetViseme(MouthShape viseme)
Retrieves the probability of a specific viseme.
void SetThreshold(float threshold)
Sets the threshold for formant calculations.
void Update(float *peaks, float maxFrequency)
Updates the viseme probabilities based on new FFT data.
A class to generate various waveform functions with customizable parameters.
@ Sine
Sine waveform.
@ Triangle
Triangle waveform.
float Update()
Updates and calculates the next value of the waveform.
Creates a customizable gradient material for rendering.
Animates transitions and blends between multiple materials.
void AddMaterial(Material::Method method, Material *material, uint16_t frames, float minOpacity, float maxOpacity)
Adds a material to the animation with specified properties.
void SetBaseMaterial(Material::Method method, Material *material)
Sets the base material for the animation.
void AddMaterialFrame(Material &material, float opacity)
Adds a specific frame for a material in the animation.
void Update()
Updates the animator, advancing the transitions.
Combines two materials using a shape as a mask.
@ Add
Adds colors together.
Definition Material.h:35
@ Replace
Replaces the base color.
Definition Material.h:44
static uint8_t GetFaceState()
Retrieves the current face state. In hardware mode, it is read from the MenuHandler.
Definition Menu.cpp:381
static uint8_t GetFaceColor()
Gets the current face color index.
Definition Menu.cpp:453
static uint8_t GetMicLevel()
Gets the current microphone level.
Definition Menu.cpp:417
static float ShowMenu()
Returns how much of the menu is shown, typically normalized (0.0 to 1.0).
Definition Menu.cpp:494
static Material * GetMaterial()
Provides a pointer to the material used for rendering the menu text.
Definition Menu.cpp:155
static uint8_t MirrorSpectrumAnalyzer()
Checks if the spectrum analyzer mirroring is toggled on or off.
Definition Menu.cpp:435
static uint8_t GetFaceSize()
Gets the current face size.
Definition Menu.cpp:444
static void Initialize(uint8_t faceCount, uint8_t pin, uint16_t holdingTime, Vector2D size=Vector2D(240, 50))
Initializes the Menu using a face count, input pin, holding time, and size.
Definition Menu.cpp:102
static uint8_t UseMicrophone()
Checks if the microphone usage is toggled on or off.
Definition Menu.cpp:408
static uint8_t UseBoopSensor()
Checks if the boop sensor usage is toggled on or off.
Definition Menu.cpp:426
static void Update(float ratio)
Updates the menu each frame, handling transitions, wiggle effects, and text generation.
Definition Menu.cpp:208
static uint8_t GetBrightness()
Gets the current brightness level. In hardware mode, it is read from the MenuHandler.
Definition Menu.cpp:390
static uint8_t GetAccentBrightness()
Gets the current accent brightness level.
Definition Menu.cpp:399
Represents a 3D object with geometry, material, and transformation data.
Definition Object3D.h:28
Handles aligning and transforming 3D objects to fit within specified 2D camera bounds.
Definition ObjectAlign.h:24
void SetEdgeMargin(float edgeMargin)
Sets the margin to keep from the edges when aligning objects.
@ Stretch
Attempt to scale the object(s) to fill the entire area.
Definition ObjectAlign.h:43
void SetJustification(Justification jst)
Sets the justification mode for alignment.
void SetPlaneOffsetAngle(float offsetPlaneAngle)
Sets the additional rotation offset (plane offset angle), in degrees or radians, that will be applied...
void SetCameraMax(Vector2D camMax)
Updates the maximum bounds for the 2D camera region.
void AlignObjects(Object3D **objs, uint8_t numObjects)
Aligns multiple objects within the camera bounds, including scale factors.
void SetMirrorX(bool mirrorX)
Enables or disables mirroring along the X-axis for the aligned objects.
A dynamic oscilloscope material for visualizing audio signals.
void SetPosition(Vector2D offset)
Sets the position of the oscilloscope visualization.
void SetSize(Vector2D size)
Sets the size of the oscilloscope visualization.
void Update(float *data)
Updates the oscilloscope visualization based on new audio data.
void SetHueAngle(float hueAngle)
Sets the hue angle for color adjustments.
A mathematical construct representing a rotation in 3D space.
Definition Quaternion.h:30
Represents an RGB color and provides methods for manipulation.
Definition RGBColor.h:23
A dynamic material that creates a rainbow effect using simplex noise.
void Update(float ratio)
Updates the material animation based on the time ratio.
A dynamic material creating a colorful rainbow spiral animation.
void Update(float ratio)
Updates the material animation based on the time ratio.
Represents a rectangle in 2D space.
Definition Rectangle.h:21
A material that applies a single, solid RGB color to surfaces.
A material that visualizes audio data as a spectrum.
void SetMirrorYState(bool state)
Sets the mirroring state for the visualization.
void Update(float *readData)
Updates the spectrum visualization with new audio data.
void SetFlipYState(bool state)
Sets the flipping state for the visualization.
void SetHueAngle(float hueAngle)
Sets the hue adjustment angle for the spectrum colors.
Represents a 2D vector (X, Y) and provides methods for vector arithmetic.
Definition Vector2D.h:27
Represents a 3D vector (X, Y, Z) and provides methods for vector arithmetic.
Definition Vector3D.h:26
@ ER
Mouth shape corresponding to the "ER" sound.
@ OO
Mouth shape corresponding to the "OO" sound.
@ AH
Mouth shape corresponding to the "AH" sound.
@ UH
Mouth shape corresponding to the "UH" sound.
@ AR
Mouth shape corresponding to the "AR" sound.
@ EE
Mouth shape corresponding to the "EE" sound.