GALERIE    EN COURS    SCENES    MACROS    GUIDE    A PROPOS


Mondrian

Mondrian Level 3

Le but est de créer de manière aléatoire, des tableaux inspirés du peintre néerlandais reconnu comme un des pionniers de l'abstraction : Piet Mondrian.

Le principe du dessin

Modèle des données

Les rectangles sont stockés dans deux tableaux. Un tableau pour l'ensemble des rectangles 'actuels'. Un autre tableau pour les rectangles découpés. Donc, à chaque itération, le nombre des rectangles découpés est le double des rectangles 'actuels'. La gestion des tableaux dynamiques n'étant pas une chose facile, le nombre total des rectangles est calculé à l'avance en fonction du niveau d'itération choisi.

Le modèle utilse un tableau à deux dimensions. La première est utilisée comme indice (ou référence) du tableau. La seconde est un tableau contenant deux valeurs : les deux points opposés qui définissent le rectangle.
#set Level = Level + 1;
#declare RectNumber = pow(2, Level);
#debug concat("[",str(RectNumber,0,0),"] rectangles to draw\n\n")

#declare SourceRects = array[RectNumber][2];
#declare SplittedRects = array[RectNumber][2];

#declare SourceRects[0][0] = < 0, 0, 0 >;
#declare SourceRects[0][1] = < xDim, 0, zDim >;

Les macros utilisées

Génération d'un nombre aléatoire entre deux valeurs :
#macro RangeRand(Min, Max)
  (rand(alea)*(Max-Min)+Min)
#end
Découpage horizontal d'un rectangle :
#macro SplitHRect(thisRectIndex)
  #local p0 = SourceRects[thisRectIndex][0];
  #local p1 = SourceRects[thisRectIndex][1];
  
  #declare zVal = RangeRand(p0.z,p1.z);
  
  #declare SplittedRects[2*thisRectIndex][0] = p0;
  #declare SplittedRects[2*thisRectIndex][1] = < p1.x, p1.y, zVal >;
  
  #declare SplittedRects[2*thisRectIndex+1][0] = < p0.x, p0.y, zVal >;
  #declare SplittedRects[2*thisRectIndex+1][1] = p1;
#end
Découpage vertical d'un rectangle :
#macro SplitVRect(thisRectIndex)
  #local p0 = SourceRects[thisRectIndex][0];
  #local p1 = SourceRects[thisRectIndex][1];
  
  #declare xVal = RangeRand(p0.x,p1.x);
  
  #declare SplittedRects[2*thisRectIndex][0] = p0;
  #declare SplittedRects[2*thisRectIndex][1] = < xVal, p1.y, p1.z >;

  #declare SplittedRects[2*thisRectIndex+1][0] = < xVal, p0.y, p0.z >;
  #declare SplittedRects[2*thisRectIndex+1][1] = p1;
#end
Construction du rectangle en couleurs :
#macro drawRect(thisIndex, thisColor)
  #local rLine = 0.10;
  #local Pt0 = SplittedRects[thisIndex][0];
  #local Pt2 = SplittedRects[thisIndex][1];
  #local Pt1 = < Pt0.x, Pt0.y, Pt2.z >;
  #local Pt3 = < Pt2.x, Pt2.y, Pt0.z >;
  union {
    sphere { Pt0, rLine }
    sphere { Pt1, rLine }
    sphere { Pt2, rLine }
    sphere { Pt3, rLine }
    cylinder { Pt0, Pt1, rLine }
    cylinder { Pt1, Pt2, rLine }
    cylinder { Pt2, Pt3, rLine }
    cylinder { Pt3, Pt0, rLine }
    
    pigment { color Black }
    finish { ambient 0.40 diffuse 0.60 }
    }
  box {
    Pt0, Pt2
    pigment { color thisColor }
    finish { ambient 0.40 diffuse 0.60 }
    }
#end

Génération du tableau
#declare VSplit = true;
#declare RectToSplit = 0;
#declare index = 0;
#while( index < Level )
  #debug concat("--- Level ",str(index,0,0)," ---\n")
  #declare RectToSplit = pow(2,index);
  #debug concat("    RectToSplit : ",str(RectToSplit,0,0),"\n")
  #declare i=0;
  #if(VSplit)
    // --- split rectangle verticaly ( z axis)
    #while( i < RectToSplit )
      #debug concat("    SplitVRect(",str(i,0,0),")\n")
      SplitVRect(i);
      #set i=i+1;
    #end
  #else
    // --- split rectangle horizontally ( x axis)
    #while( i < RectToSplit )
      #debug concat("    SplitHRect(",str(i,0,0),")\n")
      SplitHRect(i);
      #set i=i+1;
    #end
  #end
  #debug "\n"
  #declare SourceRects = SplittedRects;
  #declare VSplit = !(VSplit);
  #set index=index+1;
#end

Affichage des rectangles

Dans cet exemple, trois couleurs sont fixées dans un tableau. Afin de donner une prédominance au blanc, les couleurs ne sont appliquées que si le nombre aléatoire généré est supérieur à 0.30.
#declare colors = array[3] { Blue, Red, Yellow }
#declare ColorsNumber = dimension_size(colors,1);

#set index = 0;
#declare thisColor = White;
#while( index < RectNumber )
  #set thisColor = White;
  #if(rand(alea)<0.30)
    #set thisColor = colors[RangeRand(0,ColorsNumber)];
  #end
  drawRect(index, thisColor)	
  #set index = index + 1;
#end
L'image en gaut de la page est obtenue avec les paramètres suivants :

#declare xDim = 80;
#declare zDim = 80;

#declare Level = 3;