Hello,
I am working on a text deformed and scaled using Geomerative library. I am on hurry…
I would like to reverse these transformations when the sound loop. How should I proceed ?
Register the RPoints [i][j] positions at the begining and after the transformations RPoint startingPoints
and RPoint [][]endingPoints and then lerp between them?!
Thanks a lot for your help.
L
import processing.pdf.*;
import geomerative.*;
import ddf.minim.analysis.*;
import ddf.minim.*;
Minim minim;
AudioPlayer[] soundsFR;
FFT fftFR;
float bandHeightFR;
float PosX, PosY;
int x, y;
String []message={
"On me dit de te haïr et je m'y efforce",
"Je t'imagine cruel, violent, implacable",
};
color textColor=0;
RFont f;
float fontSize=60;
int splitGlyph = 120;
RPoint[][] pointsP;
float r = random(5, 20);
WordAttractor attractorW;
// We create 3 new lists parallel to pointsP
// List of attractors, one per glyph
WordAttractor [][] listWordAttractors;
// List of all the distances between all the attractors and the pointsP
float [][] listDistMap;
// List of vectors to replace the pointsP coordinates
PVector [][] listPV;
int tChildCount;
characterSpec []characters = new characterSpec[message.length];
RShape [] gShape = new RShape[message.length+5];
int sentenceCurrentlyModified;
int indexPhrase;
int indexPhraseSet;
int startTime;
int loop=0;
boolean isTransitioning = false;
boolean messageOn = false;
String []soundNamesFR = {"FR_01", "FR_02"};
boolean modifyThis;
float transitionTime = 0;
int startTransitionTime;
int transitionDuration = 1500;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
size(1920, 1920);
RG.init(this);
f = new RFont("SFNSText.ttf", int( fontSize), LEFT);
minim=new Minim(this);
soundsFR=new AudioPlayer[soundNamesFR.length];
for (int i=0; i<soundNamesFR.length; i++) {
soundsFR[i]=minim.loadFile(soundNamesFR[i]+".wav", 512);
fftFR= new FFT(soundsFR[i].bufferSize(), soundsFR[i].sampleRate());
}
for (int i=0; i<message.length; i++) {
characters[i]= new characterSpec( gShape[i], message[i]);
}
indexPhrase=0;
indexPhraseSet=-1;
startTime = millis();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw() {
background(0);
smooth();
// we start to read the 1rst sound
if (isTransitioning) {
if (millis() >= startTransitionTime+transitionDuration) {
// transition end
if (indexPhraseSet < soundsFR.length) {
isTransitioning=false;
transitionTime=0;
//nextPhraseSetFR();
playSound();
// si on a lu tous les groupes on recommence à zero
} else if (indexPhraseSet == soundsFR.length && millis() >= startTransitionTime+transitionDuration) {
// reset from the beginning
isTransitioning=false;
transitionTime=0;
indexPhraseSet=0;
indexPhrase=0;
sentenceCurrentlyModified=0;
startTime = millis();
playSound();
}
} else if (millis() <= startTransitionTime+transitionDuration) {
// we are transiting
transitionTime = map(millis(), startTransitionTime, startTransitionTime+transitionDuration, 0., 1.);
}
} else {
if ( indexPhraseSet==-1) {
// Initialise all
sentenceCurrentlyModified=0;
indexPhraseSet=0;
indexPhrase=0;
playSound();
} else if ( !soundsFR[indexPhrase].isPlaying()) {
// sound file is finished read next one
indexPhrase++;
sentenceCurrentlyModified++;
if ( isTransitioning==false && indexPhrase >= soundsFR.length) {
// If phrases'index is greater than the stanza's index then go on to the next stanza
indexPhrase=0;// 1rst sentence
sentenceCurrentlyModified=0;
indexPhraseSet++;// increase stanza's index
isTransitioning = true;
startTransitionTime = millis();
} else {
//go to the next phrase
//nextPhrase();
}
if (millis() >= startTransitionTime+transitionDuration) {
playSound();
}
} else {
// we're reading the sound file
// analyse of the sound
soundFFTAnalyse();
wordAttractorToSound();
}
}
println(indexPhrase);
translate(500, 200);
for (int i=0; i<2; i++) {
translate(0, 50);
if (sentenceCurrentlyModified>=i) {
characters[i].update();
}
if (sentenceCurrentlyModified>=i) {
characters[i].display();
}
}
}
void playSound() {
AudioPlayer fr = soundsFR[indexPhrase];
fr.rewind();
fr.play();
fftFR = new FFT(fr.bufferSize(), fr.sampleRate());
PosX = 0;
PosY =0;
bandHeightFR = 0;
}
void soundFFTAnalyse() {
AudioPlayer fr = soundsFR[indexPhrase];
fftFR.forward(fr.mix);
for (int i =0; i< fftFR.specSize(); i++) {
float bandDBFR = 10*log(fftFR.getBand(i)/fftFR.timeSize());
bandDBFR = constrain(bandDBFR, -1000, 1000);
bandHeightFR = map(bandDBFR*4, 0, -220, 0, height);
}
}
void wordAttractorToSound() {
AudioPlayer fr = soundsFR[indexPhrase];
PosX = map(fr.position(), 0, fr.length(), 100, width-1000);
PosY= bandHeightFR/8-350;
}
class characterSpec {
String m;
int tChildCount;
RShape bShape;
RShape letterShapes;
characterSpec(RShape _letterShapes, String _m) {
letterShapes=_letterShapes;
m=_m;
pointsP= new RPoint [m.length()][splitGlyph];
listWordAttractors= new WordAttractor [m.length()][splitGlyph];
listDistMap = new float [m.length()][splitGlyph];
for (int n=0; n<m.length(); n++) {
for (int j=0; j<splitGlyph; j++) {
listDistMap[n][j]=100000;
}
}
listPV = new PVector[m.length()][splitGlyph];
if (m.length()>0) {
bShape= new RShape();
bShape= f.toShape(m);
RShape[]letterShapes = bShape.children;
letterShapes = bShape.children;
tChildCount = bShape.children.length;
}
//}
}
void update() {
for (int k=0; k<tChildCount; k++) {
float d= dist(PosX, 0, bShape.children[k].getCenter().x, 0);
float s=map(d, 0, 75, 1.0, 1.04);
if (d<75) {
bShape.children[k].scale(s, bShape.children[k].getCenter());
}
for (int j=0; j<splitGlyph; j++) {
float frac =(1.0/splitGlyph);
pointsP[k][j]=bShape.children[k].getPoint(j*frac);
float dist1 = dist(PosX-200, PosY +50, pointsP[k][j].x, pointsP[k][j].y);
if (dist1 < listDistMap[k][j]) {
// On remplace toutes les distances possibles entre la souris et les points par la distance minimale
listDistMap[k][j]=dist1;
listPV[k][j]=new PVector(PosX -200, PosY +50);
listWordAttractors[k][j]=new WordAttractor(listPV[k][j].x, listPV[k][j].y, pointsP[k][j]);
}
listWordAttractors[k][j].points=pointsP[k][j];
listWordAttractors[k][j].attract();
pushMatrix();
if (m==",") {
pointsP[k][j].x+=10*k;
}
popMatrix();
}
}
}
void display() {
for (int k=0; k< tChildCount; k++) {
for (int j=0; j<splitGlyph; j++) {
pushMatrix();
translate(pointsP[k][j].x, pointsP[k][j].y);
stroke(255);
beginShape();
noFill();
strokeWeight(0.5);
float angle = TWO_PI/18;
rotate(angle*j/4+noise(pointsP[k][j].x)/20);
bezier(-3*(noise(5)), 3, -6*(noise(2)), 3, -4*noise(10), -3, 3, -3);
endShape();
popMatrix();
}
}
}
void pauseSound() {
AudioPlayer fr = soundsFR[indexPhrase];
fr.rewind();
fr.pause();
fftFR = new FFT(fr.bufferSize(), fr.sampleRate());
}
void reset() {
if (indexPhrase>soundsFR.length) {
for (int k=0; k< tChildCount; k++) {
for (int j=0; j<splitGlyph; j++) {
pointsP= new RPoint [m.length()][splitGlyph];
if (m.length()>0) {
bShape= new RShape();
bShape= f.toShape(m);
RShape[]letterShapes = bShape.children;
letterShapes = bShape.children;
tChildCount = bShape.children.length;
}
float fraction =(1.0/splitGlyph);
pointsP[k][j]=bShape.children[k].getPoint(j*fraction);
}
}
}
}
}
class WordAttractor {
float force_radious = 200;
float maxForce = 20;
RPoint position;
RPoint points;
float pX;
float pY;
WordAttractor(float x, float y, RPoint p) {
points =p;
position = new RPoint(x, y);
}
void attract() {
float d= points.dist(position);
if (d < force_radious) {
RPoint desired = new RPoint(points);
desired.sub(position);
desired.normalize();
desired.scale(map(d, 0, force_radious, maxForce, 0));
points.add(desired);
}
}
}