Archives par mot-clé : design génératif

Liste des cours Processing + P5JS 2016-2017 [Digital Lab]

Retrouvez la liste complètes des cours de digital lab — processing/P5js (3e. année, option) sur l’année 2016-2017

Semestre 1

Le processus génératif, retour sur les classes et le temps

Il est parfois utile de revoir ses bases et quoi de mieux qu’une fin d’année pour cela.
Durant cet exercice nous verrons comment réaliser un grand nombres de variations d’une même idée à l’aide du processus génératif.

Cet exercice nous permettra également de revoir les bases suivantes :

  • Création et utilisation des classes
  • Gestion du temps via un timer
  • Utilisation de coordonnées polaires

Définition du sketch 0

Notre skecth 0 sera la base de nos nombreuses variations. Il se traduit par un idée simple autour de laquelle nous pourrons facilement travailler.

Pour cela nous allons nous inspirer du travail de Joshua Nimoy et GMunk réalisé pour le film Tron Legacy et plus précisément l’arrière plan de la scène des « jeux ». Durant cette scène nous pouvons observer des feux d’artifices en arrière plan, ceux-ci présentent toutes les similitudes d’un feu d’artifice normal (étincelles, explosions, physique…) mais ont aussi la particularité d’être géométrique et ceux afin d’accentuer le fait que l’ensemble se passeau cœur d’un programme informatique.
Pour ce faire Joshua Nimoy a travaillé de nombreuses formes tel que les solides de planton comme l’icosaèdre ou le dodécaèdre.

Sur cette même idée nous allons réaliser un « feu d’artifice » géométrique. Notre skecth présentera un élément au comportement simple. Ce dernier effectuera en un temps déterminé un trajet. Lorsque son temps sera écoulé, ce dernier se stoppera et « explosera », laissant apparaître de nouveaux éléments ayant le même comportement et répartis sur un cercle.

expo

Pour réaliser cela nous aurons besoins d’un objet « Point » ayant un comportement défini et un certains nombre de variables.
Nous souhaitons que notre objet effectue un trajet vertical durant un temps donné avant que ce dernier ne s’arrête et « explose » en créant de nouveaux objets identiques à lui même. Enfin, afin que ces nouveaux points soit placés sur un cercle de centre « point explosé » nous aurons besoins de travailler en coordonnées polaires (cf cours trigonométrie).
Notre objet peut se décomposer de la manière suivante :

  • Variables
    • Positions x, y
    • Angle « theta »
    • Rayon « radius »
    • Vitesse du Rayon « vRadius » (cette variable nous permettra de déplacer notre Objet)
    • Valeur booléenne « vie » (Tant que le temps de vie de l’objet sera supérieur à 0 alors son état vie sera vrai)
    • Valeur booléenne « exploded » (Tant que notre objet n’aura pas explosé et engendré de nouveaux objets, alors son état exploded sera faux)
    • Taille « taille » de notre dessin
    • Valeur de margeX et margeY afin de positionner notre dessin sur la scène
    • Un objet Timer permettant de décompter la vie de l’objet
  • Méthodes
    • Methode « run » contrôlant l’ensemble des méthodes de l’objet
    • Methode « UpdateRadius » faisant parcourir ou non un chemin à l’objet en fonction de son état de vie
    • Méthode « displayPoint » affichant une ellipse à la position de l’objet
    • Méthode « displayLine » affichant une ligne depuis l’objet et son origine
  • Constructeur
    • Définitions du rayon, de l’angle et des marges
    • Initialisation des variables

Une fois l’ensemble de éléments composant notre objet défini, nous pouvons concevoir sa classe.
NB : Ici nous utilisons un timer afin de calculer le temps de vie de notre objet. Il ne faudra donc pas oublier d’inclure ce dernier dans notre sketch. Celui-ci est disponible ici

Nous allons désormais définir nos méthodes en commençant par la méthode permettant à notre objet de se mouvoir.
Notre objet possède un temps de vie durant lequel nous souhaitons qu’il se déplace. Lorsque ce temps de vie est épuisé notre objet devra s’arrêter. Pour cela nous allons créer une méthode « updateRadius » interrogeant le timer de notre objet. Il en résultera deux états :

  • Le timer est fini : Alors notre état de vie passe en faux
  • Le timer n’est pas fini : Alors nous incrémentons notre rayons de sa vitesse et mettons à jour les coordonnées de notre objet

Nous réaliserons ensuite deux méthodes permettant de dessiner notre objet ainsi que son parcours

Enfin nous assemblons l’ensemble des ces méthodes dans une méthode contrôleur

Nous venons alors de créer notre classe Point

Nous pouvons donc attaquer la seconde partie de notre sketch permettant d’appeler et afficher nos objets.
Nous savons que nous aurons besoins de dessiner un nombre encore non-défini d’objets Point.
Nous souhaitons aussi que nos objets explosent en créant un certains nombre de point. Nous définirons tout cela dans notre « setup ».

Afin de pouvoir recréer un nouveau « feu d’artifice » quand bon nous semble, nous allons créer un méthode « mousePressed » permettant de vider notre tableau et de re-initialiser nos variables.

Enfin dans notre méthode « draw » nous allons appeler, créer et afficher nos objets. Pour cela nous allons décomposer notre méthode en plusieurs parties

  • Une boucle for() nous permettant de parcourir notre tableau de points et à l’intérieur de laquelle nous effectuerons plusieurs taches
    • Appeler la méthode run() contrôlant nos objets
    • Interroger l’état de vie et d’explosion de notre objet
      • Si notre objet a fini son état de vie (vie == false) et n’a pas explosé (exploded == false) : alors nous créons de nouveaux objets dont l’origine sera la position de l’objet explosant. Enfin nous passerons l’état « exploded » de l’objet explosant en vrai

Si nous effectuons un « run » de notre skecth nous remarquons que nous obtenons l’effet souhaité, cependant notre sketch se met rapidement à ralentir puis se bloque. Cela s’explique par le fait que ce dernier effectue un calcul infini que la mémoire de l’ordinateur ne pourra supporter.

expo-bug

Si nous reprenons notre concept, nous remarquons que notre tableau d’objets augmente de manière exponentielle.
En effet chaque point, une fois sa vie terminée, explose en un nombre de points défini, par exemple 4.
Ainsi à chaque explosion (ou cycle) nous obtenons le calcul suivant : 1^4^4^4^4… soit : 4^nbDeCycle ou : mesPoints.size() = nbNewPts^nbDeCycle

Afin d’éviter à notre sketch de s’étendre à l’infini nous allons donc définir un nombre maximal de cycles auxquel notre tableau de points aura droit. Pour ce faire nous allons devoir compter les cycles de notre tableau, or nous disposons de 2 valeurs dans l’équation suivante : mesPoints.size() = nbNewPts^nbDeCycle soit mesPoints.size() et nbNewPts.

Pour calculer le nombre de cycles de notre tableau nous allons faire appel à une fonction bien pratique en Maths, la fonction logarithme népérien. En effet, en Maths, nous savons que log(a^x) = N ou a^N = x. Cela se note aussi de la manière suivante :
logNeperien

Nous pourrons alors traduire cela dans processing à l’aide des méthodes round() permettant de calculer un nombre arrondi et de la méthode log() permettant de calculer une valeur logarithmique. Ainsi nous aurons :

Il ne nous reste donc plus qu’à reporter cela dans notre sketch et de définir un nombre maximum de cycle pour notre tableau. Enfin dans notre méthode draw nous autorisons nos objets à se créer que si le nombre de cycle actuel n’est pas supérieur au nombre de cycle maximal. Nous rajoutons donc deux nouvelle variables :
cycle et limiteCycle. Notre « draw » se composera alors de la manière suivante :

Nous venons donc de terminer notre sketch 0, base de notre travail génératif.

ixd_processusgeneratif_00

Processus génératif

Nous venons de réaliser notre sketch 0, base de notre travail. Nous allons maintenant nous interroger sur comment réaliser des variations de cette idée. Pour cela rien de plus simple, ils nous suffit de nous interroger sur les variables, méthodes ou dessins que nous pouvons modifier afin de créer de nouveau sketch. C’est la base du processus génératif, prendre une idée et en réaliser de nombreuses variations en cherchant de nouvelles voies. Nous pouvons procéder de différentes manières :

  • En changeant des variables existantes
  • En changeant/rajoutant des comportements
  • en rajouter des objet dans la composition
  • En travaillant le design (composition, couleur, formes…)

Voici quelques pistes permettant des modifications possible afin de réaliser de nouveaux éléments

  • Afficher uniquement les objets points
  • Afficher uniquement les lignes des objets points
  • Dessiner les liaisons entre les objets point lorsque leur distance est inférieur à une valeur définie
  • Changer la forme des objets point
  • Définir une durée de vie aléatoire pour chaque objet
  • Définir une durée de vie aléatoire pour chaque cycle
  • Définir une durée de vie se décrémentant à chaque cycle
  • Définir une durée de vie se s’incrémentant à chaque cycle
  • Définir la vitesse des objet en aléatoire
  • Effectuer une rotation selon un angle défini ou en bruit perlin durant la course de l’objet
  • Positionner les nouveau objet sur un arc de cercle de 180°, 30°….
  • Dessiner en 3D
  • Ne dessiner les objet ou les ligne un cycle sur deux
  • Dessiner uniquement les objet pair et les ligne impaire
  • Incrémenter l’axe Z à chaque cycle
  • Si la durée de vie de l’objet est fini, il explose puis repart dans une autre direction aléatoire ou défini
  • Varier la taille des objets en fonction de leur distance les séparant du centre
  • … à vous de trouver la suite

Il est donc aisé, à partir d’une idée simple, de générer un grand nombre de variation de cette même idée.

L’ensemble des sources des visuels ci-dessus sont à retrouver dans le dossier DigitalLab – Revision sur gitHub

Design Génératif et Expériences Interactives [Introduction et support]

Lors du premier cours de l’année en option digital lab, les étudiants ont découvert ce qu’était le design génératif et l’expérimentation interactive au travers divers rappels historique.

Ce rappel historique porte à la fois sur les grandes évolutions technologiques, théoriques et de langages de programmation que sur de grandes pièces de l’art numérique ou de son application au travers de la communication visuelle.

Le document ci-joint, support de cours, présente différentes frises chronologiques non-exhaustif, ainsi qu’une présentation du processus créatif génératif. La fin de ce document présente aussi de nombreux liens vers des conférences, interviews, films..

DigitalLab_DesignGeneratifEtExperimentationsInteractives

Retour sur les bases de trigonométrie

Il n’est pas rare de voir les étudiants l’air dépités à l’idée de devoir faire de la trigonométrie, et pourtant celle-ci revient très souvent sur le devant de la scène lorsque l’on commence à vouloir faire des attracteurs ou des mouvements circulaires.

La trigonométrie et ses fonctions sont des éléments indispensables quand on commence à vouloir faire des visuels plus évolués. Même si son nom parait horrible et semble nous renvoyer à nos cours de maths de 3ème nous verrons que processing va vite nous la faire re-aimer.

Ici nous nous attarderons sur le cercle trigonométrique qui nous permettra de voir comment on effectue le calcul d’un angle ou même comment positionner un point sur un cercle. En bref nous verrons nos vieux amis des cours de maths que sont sinus, cosinus et tangente.

Nous appliquerons cela à deux skecth. Le premier nous permettra de réaliser un attracteur/repulseur simple. Le seconde, plus appliquer au design génératif nous permettra de découvrir comment réaliser des visuel simple à l’aide de la trigonométrie.

Petit rappel de trigonométrie

La trigonométrie traite des relations entre distances et angles dans les triangles et notamment dans le triangle rectangle. C’est ce dernier qui va nous intéresser plus particulièrement.

Faisons un rapide bon dans le passé concernant ce triangle. Un triangle rectangle se caractérise par un angle droit (90°) et la somme de ses angles est égale à 180°. L’angle droit est donc son angle le plus grand. Enfin le côté opposé à cet angle s’appel l’hypoténuse et se caractérise par le fait qu’il est le côté le plus grand de ce triangle.

Capture d’écran 2013-03-17 à 18.24.47

Si on s’interesse à l’angle BAC et aux fonctions trigonométriques alors nous remarquons que :

  • sin(BAC) = a/c
  • cos(BAC) = b/c
  • tan(BAC) = a/b

Nous avons ici les fonctions auxquelles nous allons prêter attention dans processing.

Allons maintenant plus loin en traçant un cercle dont l’origine sera A et de rayon AB (notre hypothenuse). Partons du principe que notre hypothenuse AB a un valeur de 1. Nous obtenons alors un cercle trigonométrique.

Capture d’écran 2013-03-17 à 18.31.18

Si on observe ce cercle nous remarquons que les cordonnées du point B peuvent être définies de la sorte

  • x = cos(t)
  • y = sin(t)

Or nous savons ici que notre hypothenuse à un valeur de 1. Si nous voulons être correcte dans nos cordonnées, nous obtenons

  • x = cos(t)*1
  • y = sin(t)*1

Nous venons de voir la formule permettant de calculer les coordonnées d’un point sur un cercle. Nous avons ici l’une des formules que nous utiliserons le plus dans processing par la suite.

  • x = cos(angle)*rayon
  • y = sin(angle)*rayon

Nous venons de voir à quoi les fonctions trigonométriques Sinus et Cosinus pouvaient nous être utile, attardons nous maintenant sur la dernière, la Tangente.

La tangente est le rapport du sinus au cosinus, par définition :

  • tan(angle) = sin(angle)/cos(angle)

On appelle tangente de l’angle aigu , le nombre noté tan(angle) défini par BC/AC. Nous verrons par la suite comment nous pouvons nous servir de la tangente pour calculer un angle.

Capture d’écran 2013-03-17 à 18.24.47

Trigonométrie et processing

Nous venons de voir un résumer des règles de trigonométrie dont nous allons nous servir le plus. Retournons maintenant sur processing pour faire un rapide état des lieux des méthodes disponible. Si nous venons de revoir toute ces bases c’est bien parce que nous allons utiliser les angles afin de positionner des points sur un cercle. Là dessus processing est très bien fait puisqu’il va nous proposer différentes fonctions trigonométriques tel que :

Une des particularités à savoir sur processing et qu’il effectue ses calculs d’angle en radians là où nous avons plutôt tendance utiliser des dégrés. Le radians est l’unité de mesure internationale d’un angle. Ainsi, si en degrés nous divisons un cercle en 360° en radians celui-ci se divise entre 0 et 2PI

cercle_trigonom_trique

Lorsque nous travaillons en degrés on pourrait se dire qu’il va nous falloir entrer dans des calculs fastidieux mais là aussi processing nous offre une fonction permettant de convertir un angle de degrés en radians

Nous avons maintenant tout ce qu’il nous faut pour tester la trigonométrie dans processing.

Attracteur et répulseur simple

Pour voir à quoi peut nous servir la trigonométrie prenons un exemple d’un projet d’un étudiant de 4ème année.
Ce dernier réalisait une installation interactive avec la wiimote. Cette dernière lui servait de pointeur et il souhaitait que régulièrement, les lettres présentent sur le sketch à des positions aléatoires, attaquent le pointeur. Essayons de reproduire cela le plus simplement possible.

Nous allons produire un sketch de 500*500 sur lequel nous placerons des balles à des positions aléatoire. Celles-ci attaqueront notre souris. C’est à dire qu’elles se déplaceront en direction de notre souris et une fois leurs déplacements effectués, retournerons à leurs places avant d’effectuer une autre attaque.

Cela peut sembler compliqué. Comment faire en sorte de rapprocher nos balles vers notre souris sachant que certaines seront plus haute, plus basse, plus à droite ou plus à gauche. Réduisons notre concept à une balle on se rend tout de suite compte qu’il nous suffit d’utiliser la trigonométrie. Nous avons une balle et une cible. Nous connaissons la distance entre ces deux élément et nous savons que la position d’un point sur un cercle est égale à :

  • x = cos(angle)*rayon
  • y = sin(angle)*rayon

Il nous suffit alors de calculer la position de notre balle sur un cercle dont le rayon est égale à sa distance la séparant de sa cible. Nous n’auront plus qu’à incrémenter ou décrémenter notre rayon pour attirer ou repousser notre balle

trigo2

Reproduisons cela à partir d’une balle que nous placerons de maniere aléatoire, nous définirons la position de l’attracteur au centre de notre skecth. La première chose que nous devons faire c’est de replacer cette balle sur un cercle dont le rayons sera égale à la distance entre la balle et sa cible. Pour cela nous allons utiliser la fonction dist() qui nous permettra d’obtenir le rayon de notre cercle. C’est ce rayon que nous incrémenterons puis decrémenterons pour attirer ou repousser notre balle.

Nous savons que les coordonnées x, y d’un point sur un cercle sont respectivement égales à cos(angle)*rayon et sin(angle)*rayon. Nous avons déjà le rayon, il ne nous manque donc plus que l’angle.

Si on regarde de plus pres notre schema, nous avons notre balle sur un cercle de centre cible mais nous avons aussi un triangle rectangle dont nous connaissons déjà l’hypothenuse c’est à dire notre rayon.

gabarit_blogeart_3

Il nous est alors facile d’obtenir les autres valeurs puisque nous avons les cordonnées de notre balle et de sa cible. Ainsi :

  • a = balle_x – cible_x
  • b = balle_y – cible_y

Nous savons aussi que la tangente d’un angle est égale au côté opposé / côté adjacent ou dans notre cas à b/a. Pour obtenir notre angle il nous faudra alors obtenir l’inverse de cette tangente. C’est là l’utilité de la fonction atan() de processing qui nous reverra l’inverse de la tangente et donc notre angle en radians

Nous pouvons donc définir les coordonnées de notre balle sur le cercle comme ceci

  • x = cos(angle)*rayon
  • y = sin(angle)*rayon

Il ne nous reste plus qu’à décrémenter puis incrémenter notre rayons. Nous obtenons alors ceci
(cliquez sur le skecth pour activer l’attracteur ou sur ‘a’ pour repositioner la balle)

ixd_trigo_00

Nous avons une balle attirée par notre cible mais celle-ci est fixe et nous n’avons qu’une balle. Comment appliquer cela à plusieurs balles?

Pour cela rien de plus simple, il nous suffit d’utiliser les listes et de replacer chacune de nos balles sur un cercle dont le rayon sera la distance entre la balle et sa cible. Il nous faut utiliser les notions vu dans le cours précédent à savoir les liste et les boucle for (disponible ici).

Nous obtenons alors ceci (cliquez pour activer l’attracteur, appuyez sur ‘a’ pour repositioner les balles et sur ‘z’ pour retirer les tracés)

ixd_trigo_01

Design génératif et trigonométrie

Nous avons vu comment faire un attracteur/repulseur simple mais allons un peu plus loin dans l’utilisation de ces méthodes et appliquons cela à du design génératif. Il nous est facile à partir de là d’imaginer un visuel génératif type fleur.

Reprenons nos balles. Définissons leur position de départ sur un cercle de rayon 200 et toute équidistantes les une des autres.
Nous gardons notre principe d’attracteur et définissons une vitesse aléatoire pour chacune de nos balles. Au fur et à mesure celle-ci se déplaceront vers le centre de notre skecth. À chaque fois que l’une d’entre elles atteindra le centre nous clôturons le cycle et en déclencherons un nouveau. À chaque début de cycle nous définirons une plage de couleur pour notre fleur générative. Ajoutons un peu de piquant à notre sketch et définissant à chaque debut de cycle un sens de rotation pour notre fleur. Enfin définissons pour chaque cycle un temps de vie de 1000 frame avant de se re-initialiser

trigo3

Globalement nous allons utiliser le même code que notre attracteur à plusieurs balles mais nous ne dessinerons pas la même chose. Commençons par définir une fonction update() dans laquelle nous initialiserons toute nos valeurs.

Maintenant que nous avons notre cercle de départ il ne nous reste plus qu’à le dessiner de la manière suivante

Nous obtenons alors la fleur suivante. À partir de là il nous est facile de rajouter des comportements à notre fleur ou de changer sa forme de départ, son sens de rotation, la manière dont elle se dessine… et tout ça sur une base de trigonométrie.
trigonometrie

Interactive Cover, à la découverte de l’aléatoire [Rendu]

Après plusieurs cours d’initiation à Processing et après le cours sur la gestion du bruit Brownien et bruit Perlin, les étudiants de 3ème années de l’option digital lab ont été amené à réaliser leur première experimentation interactive sur écran à l’aide de Processing.

Le Brief & les contraintes

« Pour annoncer la sortie de leur nouvel album, un groupe de musique vous demande de réaliser une animation interactive de leur cover. »

Les étudiants, par groupe de 2 à 5 personnes, devront choisir un groupe de musique (fictif ou non) et réaliser, à l’aide de processing, une animation interactive.

Celle-ci devra comporter au moins une des deux notion d’aléatoire vu en cours (bruit brownien ou bruit perlin) ainsi que 1 interaction souris ou clavier.

Le sketch ne pourra comporter aucune autre image que le logo du groupe. Le reste du visuel devant être réalisé en utilisant les techniques de design génératif vues en cours.

Temps de production : 2 cours.

Rendus