14 mai 2009

China

Une petite visite pour le week end : aujourd'hui je vous emmène sur une sim qu'il est bien difficile de qualifier...
La description la plus juste serait de dire que c'est du Terry Gilliam !!
On se croirait dans les animations qui ont fait la grande époque du Flying Circus de Monthy Python !!

Notre destination : China - SLURL

L'arrivée se fait sur une plage, remplie d'objets plus bizarres les uns que les autres... Rien n'est "droit", même la maison sur la plage est de travers !!


Dans le fond, sur une sorte de petite île, un salon télé ....


Une structure démente occupe le reste de l'espace.. Et quand je dis démente, je pèse mes mots. Une construction en perpétuelle évolution, qui monte, qui grandit, qui perd des morceaux... On ne peut faire deux fois la même visite. On entre et on se retrouve dans une salle avec des couloirs qui en partent.


Chaque "couloir" est tortueux, monte, ou descend... par fois même débouche sur du vide et l'on tombe !
Quand tout va bien, on se retrouve dans une nouvelle pièce. Parfois, elle est vide... puis, une brume noire apparait et se dissipe un instant plus tard, révélant un nouveau passage inexistant la seconde d'avant. Et ainsi de suite...
L'édifice se bâtit, change tout le temps, il pousse comme une plante... perd des "feuilles", et ce sont des pièces entières qui retombent au sol, les passages compris, pour repousser à nouveau d'une manière différente...

Hallucinant !! mais tellement beau et surprenant !
Je m'incline avec respect devant le concepteur et réalisateur de cette merveille !!


Une salle avec une terrasse et la brume qui libère un passage


D'autres salles au détour du chemin


Des vues de l'extérieur...



Conseillez cette sim est un faible mot... courrez-y !!

11 mai 2009

Une borne de détection

Continuons nos petits tutos de build, en y ajoutant un peu de script.
Aujourd'hui, le build sera simple, mais il permettra de revoir ce que nous avons déjà vu de manière moins théorique.

Le projet du jour : une borne de détection.

Cette borne détectera tous les avatars présents autour d'elle, et en afficher le nom et la distance au dessus d'elle. Pour la mettre en route, il suffira de cliquer dessus, et pareillement pour l'arrêter.

Voila notre cahier des charges...

En route donc. Commencons par builder la borne. Nous ferons simple : un cylindre surmonté d'une demi-sphère.


La borne


Commencons par créer un cylindre au sol : clic droit : créer. Puis choisir la forme du cylindre. On clique et hop voila le résultat :


Modifions la taille du cylindre : une base de 0.5 sur 0.5 me convient, mais je la grandis un peu à 1m.



Ensuite, créons à côté une sphère. Par défaut, elle mesure 0.5 x 0.5 x 0.5. Donc aucune raison d'en modifier la taille, elle collera parfaitement sur la base cylindrique.
Toutefois nous ne voulons pas une sphère, mais une demi-sphère. Pour cela, on règle sur l'onglet objet, la valeur de Début et fin de découpe :
D : 0.500 et F : 1.000
On commence à la moitié, donc on obtient une demi sphère.



La demi-sphère n'est pas correctement orientée, elle est "couchée". Remettons la debout, en lui appliquant une rotation



Notre borne est presque finie, nous avons ces deux composantes. Il ne reste plus qu'à les assembler. On bouge la demi-sphère pour l'amener au-dessus du cylindre. Là, nous avons deux techniques pour les aligner :



  • Le pifomètre : on déplace la primitive, on tourne autour avec la cam, pour être sur que l'alignement avec le cylindre est correct.
  • La rigueur : notre demi-sphère a la meme taille à la base que le cylindre, donc, ses coordonnées X et Y sont les mêmes que celles du cylindre. On note donc les X et Y du cylindre, et on les copie en X et Y pour la demi-sphère.




Il ne reste plus ensuite qu'a descendre la demi-sphere pour la poser sur le cylindre



Et voila.... notre borne est finie, je vous laisse le soin de mettre des textures pour la rendre encore plus jolie.

Toutefois, nous n'avons pas encore un objet borne, mais deux primitives. Il faut les lier. Pour cela, on en selectionne une, puis on clique sur la seconde en ayant pris soin de maintenir la touche MAJ du clavier enfoncer (rappel : ajouter à la sélection : MAJ + clic).
La dernière prim choisie sera la prim root. Dans le cas présent, cela n'a pas trop d'importance pour la suite.
Les deux morceaux sont surlignés de jaune.




Puis, on procède à la liaison : Outils > Lier  ou CTRL + L
Notre objet existe ! La prim root se repère des autres par sa couleur jaune, les autres prims "filles" sont en bleu.



Sélectionnons l'objet et donnons lui un nom sur l'onglet Général : Borne de détection.
On remarque l'information du nombre de prims qui le composent.


Passons à la phase 2 : le script !


Le script


On se place sur le dernier onglet, contenu, et on clique sur nouveau script. Il apparait et l'objet nous dit déjà "Hello avatar !!" car le script par defaut est toujours celui-là. Faisons un clic droit sur le script et renommer : donnons lui le nom de detection, car c'est à cela qu'il servira.



Bien commencons par voir ce dont nous allons avoir besoin niveau du script.

On fera deux états :
  • default : état borne eteinte
  • running : la borne est en marche, elle détecte

Nous aurons besoin de quelques fonctions du lsl :

llSetText qui permet d'afficher un texte au-dessus de notre objet. On affichera le texte en blanc (code couleur <1.0, 1.0, 1.0>), et afficher sans transparence (alpha = 1.0)
llSensorRepeat : la fonction qui rendra possible la détection. On fera un scan toutes les 2 secondes par exemple, et nous fixerons la portée a 30m.
La fonction llSensorRepeat lance un évènement qui est capturé et traité par l'event sensor.

Note sur le code couleur : la couleur s'ecrit par son code RVB, les trois composantes Rouge, Vert, et Bleu, séparées par des virgules, au sein d'un vector.
Chaque composante est un nombre décimal de 0.0 à 1.0. Le blanc étant toutes les couleurs à fond, le vector est donc : <1.0,1.0,1.0>

Pour permettre de modifier facilement le script dans ses paramètres, on définit des variables au début du script. Ainsi, pour changer la portée par exemple, il suffira de modifier la variable, et de recompiler le script.

float portee = 30.0;        // portée du scan : 30 m
float frequence = 2.0;        // frequence du scan : 2.0 sec
vector couleur = <1.0,1.0,1.0>;    // couleur du texte de la borne


Voci donc le script, je le commente pour en détailler le fonctionnement.
Pour plus d'infos sur les fonctions utilisées, allez faire un tit tour sur le wiki du LSL est une excellllllente idée !!

Pour mesurer la distance entre la personne détectée et la borne, on utilise la fonction llVectDist. Elle donne la distance entre deux positions connues par leurs coordonnées. llDetectedPos renvoit les coordonnées de la personne détectée, et llGetPos celles de la borne.
Lors de la fabrication de la string msg, \n permet le retour à la ligne.



Page du wiki à consulter :



float portee = 30.0; // portée du scan : 30 m
float frequence = 2.0; // frequence du scan : 2.0 sec
vector couleur = <1.0,1.0,1.0>; // couleur du texte de la borne


// cette fonction écrit un message au dessus du détecteur
// juste pour le plaisir de faire une fonction
ecrireMessage(string msg){
llSetText(msg,couleur,1.0);
}

// état du détecteur au repos....
default
{
state_entry(){
ecrireMessage("Détecteur : Arrêt");
}

// quand on clique, on passe a l'état running
touch_start(integer total_number){
llWhisper(PUBLIC_CHANNEL, "Mise en marche");
state running;
}
}


// le détecteur est actif
state running{

//evènement appelé lors de l'entrée dans l'état... on active le sensor
// on ne cherche que les AGENT, les avatars......
state_entry(){
llSensorRepeat("",NULL_KEY, AGENT, portee, TWO_PI, frequence );
}

// si le sensor detecte des AGENT
sensor (integer numberDetected){
integer i;
integer distance;
string msg = "";
for(i = 0; i < numberDetected; i++){
distance = (integer)llVecDist(llGetPos(), llDetectedPos(i));
msg += llDetectedName(i) + " ("+ (string)distance + " m)\n";
}
ecrireMessage(msg);
}

// quand on clique, on passe a l'état default
touch_start(integer total_number){
llWhisper(PUBLIC_CHANNEL, "Arrêt...");
state default;
}

//evènement appelé lors de la sortie de l'état... on supprime le sensor
// juste apres avoir été exécutée on passe dans l'état default et son event state_entry est appelé
state_exit(){
llSensorRemove();
}
}


Et voila, c'est tout pour aujourd'hui....
Amusez vous bien avec tout ca.