Déplacement de prims liés

Répondre
Partager Rechercher
J'ai fait ce petit tuto pour un ami SL, je pense qu'il peut servir à d'autres.

Le but est de déplacer (translation et rotation) des prims liés par un simple clic sur le prim root. Dans le cas considéré il n'y a que deux états mais il est facile d'étendre le système à plusieurs états.

La première chose est de déterminer la valeur des positions et rotations relatives. Pour cela on met ce script dans les prims enfants concernées :

Code:
default
{
 touch_start(integer total_number)
 {
  llOwnerSay((string)llGetLocalPos());
  llOwnerSay((string)llGetLocalRot());
 }
}
Il suffit de cliquer sur le prim enfant pour récupérer les deux valeurs : translation et rotation. Mettez donc les prims enfants dans les deux états et notez les valeurs. Une fois que c'est fait supprimez ce script.

Mettez ce script dans chaque prim enfant en renseignant les variables pos1, rot1, pos2 et rot2 selon vos relevés précédents :

Code:
integer canal = 1010;
// Première position et rotation
vector pos1 = <0.00000, 1.20337, 0.00000>;
rotation rot1 = <0.00000, 0.00000, 0.00000, 1.00000>;
// Deuxième position et rotation
vector pos2 = <-0.73666, 1.20337, 0.00000>;
rotation rot2 = <0.00000, 0.00000, -0.31730, 0.94832>;
default
{
 link_message(integer sender_number, integer number, string message, key id)
 {
  if(number == canal)
  {
   if(llGetLocalPos() == pos1)
    llSetPrimitiveParams([PRIM_POSITION, pos2, PRIM_ROTATION, rot2]);
   else
    llSetPrimitiveParams([PRIM_POSITION, pos1, PRIM_ROTATION, rot1]);
  }
 }
}

Vous n'avez plus qu'à mettre ce script dans le root :

Code:
integer canal = 1010;
default
{
 touch_start(integer total_number)
 {
  llMessageLinked(LINK_ALL_CHILDREN, canal, "", NULL_KEY);
 }
}
C'est terminé ! Cliquez sur le root pour voir le résultat. L'avantage de cette approche c'est que les coordonnées étant dans le code vous ne craignez pas les reset.
coordonnees rotations
bonjour.....tres vieux post en effet....apres avoir bien apris le build pur, me lance dans les scripts. Alors je ne trouve pas a koi sert la 4e donnees dans " rotation rot1 = <0.00000, 0.00000, 0.00000, 1.00000>;"

X,Y,Z,?

Jai fait un "wagon" avec 3 fauteuils dessus, chaque fauteuils est constitues de 3 prims, puis je les lies et considerer comme un seul enfant ou dois je mettre le scripts dans tous les prims qui constitus un fauteuil?

Je sais que la plus part des reponses se trouvent en cherchant, chose que j effectue chaque fois que j ai du temps libre.....helas j en ai tres peu....si bestmomo ou qqun peut m aider.....

Gd merci par avance
Citation :
Publié par Patryves
bonjour.....tres vieux post en effet....apres avoir bien apris le build pur, me lance dans les scripts. Alors je ne trouve pas a koi sert la 4e donnees dans " rotation rot1 = <0.00000, 0.00000, 0.00000, 1.00000>;"
X,Y,Z,?
Très vieux post en effet . Cette coordonnée est tout simplement une valeur de rotation, ici elle est nulle. Mais ce n'est pas parce qu'elle est nulle qu'elle est sans valeur . Il faut bien indiquer la rotation de la primitive pour cette position.

Citation :
Publié par Patryves
Jai fait un "wagon" avec 3 fauteuils dessus, chaque fauteuils est constitues de 3 prims, puis je les lies et considerer comme un seul enfant ou dois je mettre le scripts dans tous les prims qui constitus un fauteuil?
Je ne sais pas si je comprends bien ce que tu veux faire là. Mon script est fait pour mettre en mouvement des primitives liées au sein d'un ensemble. Je suppose que tu ne veux pas faire bouger tes fauteuil par rapport au wagon . Si toutefois c'est le cas il faut effectivement un script par primitive à animer.
Citation :
Publié par Patryves
bonjour.....tres vieux post en effet....apres avoir bien apris le build pur, me lance dans les scripts. Alors je ne trouve pas a koi sert la 4e donnees dans " rotation rot1 = <0.00000, 0.00000, 0.00000, 1.00000>;"

X,Y,Z,?

Jai fait un "wagon" avec 3 fauteuils dessus, chaque fauteuils est constitues de 3 prims, puis je les lies et considerer comme un seul enfant ou dois je mettre le scripts dans tous les prims qui constitus un fauteuil?

Je sais que la plus part des reponses se trouvent en cherchant, chose que j effectue chaque fois que j ai du temps libre.....helas j en ai tres peu....si bestmomo ou qqun peut m aider.....

Gd merci par avance

Bestmomo t a répondu sur l intéret du script ;

pour ce qui est de la signification de la 4ème donnée d une rotation :
en fait une roration
rotation a quatre composantes x,y,z,s

Les 3 premières composantes sont l axe normalisé ( au sens mathématique ) de rotation multipliées par le sinus du demi angle de la rotation
La quatrième composante est le cosinus du demi angle de la rotation.

Si par exemple on
un axe V et un angle a.
On veut faire la rotation d axe V et d angle a.

Code PHP:

vector V;
float a;
llVecNorm(V);
float sin_a_sur_2 llSin(a/2.0);
float cos_a_sur_2 llCos(a/2.0);
rotation R ;
R.V.sin_a_sur_2 ;
R.V.sin_a_sur_2 ;
R.V.sin_a_sur_2 ;
R.cos_a_sur_2 
Pour pouvoir composer des rotations sans erreurs d arrondis , on doit s assurer que
R.x²+ R.y² + R.z² +R.s² = 1
Si V est normalisé , alors R.x²+ R.y² + R.z² +R.s² = sin_a_sur_2 ² * ( V.x ² + V.y² + V.z ² ) + cos_a_sur_2 ² = sin_a_sur_2 * 1 + cos_a_sur_2 ² = 1

En fait , en pratique , on ne modifie pas directement les composantes de la rotation . On pouvait définir la rotation plus simplement et souvent avec moins d erreurs d arrondis par les fonctions de la librairie . Par exemple on pouvait définir une rotation par
llAxisAngle2Rot.
De plus , certaines fonctions de la librairie nous évite le besoin de devoir normaliser le vecteur V

http://wiki.secondlife.com/wiki/Rotation/fr
et
http://wiki.secondlife.com/wiki/Rotation

Dernière modification par redpurple ; 06/11/2012 à 11h51.
wagon avec 3 fauteuils
Bon , je vais re tester qqchose (j'ai du faire une erreur)
C'est mon premier script (meme si je l'ai copié et modifié de bestmomo)
Grand merci dabord de vos reponses

en fait, bien surs , je n'ai pas besoin de la rotation (c'etait juste pour info la 4e donnee) , je veux simplement déplacer mon wagon (de 4 prims surmonté de 3 fauteuils de 3 prims chacun), d'un point A à un point B (temporisé de 6 secondes des qu'une personne s’assoie)

je ne demande pas qu'on me bacle le travail bien surs , juste que vous comprenez ce que je cherche à faire
rotation..
Redpurple grand merci à toi aussi... ce que tu viens de m'apprendre est tout simplement jubilant...
tres instructif tu portes bien "l'etiquette" de princesse
j'ai du pain sur la planche...
Citation :
Publié par tristof
Bonjour,
je trouve ce script vraiment bien,mais comment faire pour ajouté plusieurs positions.
Merci
Bonjour,

Ce script souffre quand même de son antiquité technologique. Aujourd'hui on mettrait tout dans le root. Pour ce qui est d'ajouter des positions ce n'est pas forcément évident selon le résultat désiré au niveau de la commande : étape par étape ? Tout d'un coup ? En cas de processus à plusieurs états les limites de ce script seront criantes : l'objet va avoir un peu le hoquet et la mise en oeuvre un peu laborieuse. Il vaut mieux alors se tourner par exemple vers la superbe application d'Elenia.
bonsoir,
et merci pour cette réponse rapide.
je connais le script de Elenia,mais en fait oui,je voudrai un emplacement a chaque clic,genre 4 positions .
un clic première position,deuxième clic deuxième position etc avec un max de 4 cela me parait correct pour mon projet.
j'ai rajouté dans le script les positions,mais le soucis est en bas avec les else,ou autre,j'avoue être perdu la dedans.

Merci
Comme je suis à l'origine de ce script voilà une version dépoussiérée, actualisée, ergonomisée (ça se dit ça ? ). Il suffit de préparer le build et de glisser ce script de setup dans le root :

Code PHP:

///////////////////////////////////////////////////////
//                                                   //
//                  Setup V1.0                       //
//                                                   //
///////////////////////////////////////////////////////

// Nom des primitives
string NOM "prim";

integer i_step;
list 
l_num_links;
integer i_nbr_prims;
list 
l_states;
string s_url;

// Initialisations
init(){
    
integer n llGetNumberOfPrims();
    
integer i;
    for(
2<= n; ++i) {
        
// Nom de la prim
        
string nom llList2String(llGetObjectDetails(llGetLinkKey(i), [OBJECT_NAME]), 0);
        
// Traitement
        
if(nom == NOMl_num_links += i;
    }
    
i_nbr_prims llGetListLength(l_num_links);
}

// Ajout valeurs
add_values() {
    
integer i;
    for(; 
i_nbr_prims; ++i)
        
l_states += llGetLinkPrimitiveParams(llList2Integer(l_num_linksi), [PRIM_POS_LOCALPRIM_ROT_LOCAL]);
    
llOwnerSay("Valeurs ajoutées");
}

// Envoi code pour le script à la page web
affiche_setup(key id) {
    
string s "Copiez les lignes suivantes pour créer un script de commande :\n\n";
    
+= "string NOM = \"" NOM "\";\n";
    
+= "list STATES = [\n";
    
integer n llGetListLength(l_states);
    
integer i;
    for(; 
n; ++i+= llList2String(l_statesi) + ",\n";
    
llGetSubString(s0, -3) + "\n";
    
+= "];\n";
    
+= "integer i_step = 1;\n";
    
+= "integer i_nbr_prims = " + (string)i_nbr_prims +";\n";
    
+= "integer i_nbr_states;\n";
    
+= "list l_num_links;\n";
    
+= "init(){\n";
    
+= "    i_nbr_states = llGetListLength(STATES) / i_nbr_prims / 2;\n";
    
+= "    integer n = llGetNumberOfPrims();\n";
    
+= "    integer i;\n";
    
+= "    for(i = 2; i <= n; ++i) {\n";
    
+= "        string nom = llList2String(llGetObjectDetails(llGetLinkKey(i), [OBJECT_NAME]), 0);\n";
    
+= "        if(nom == NOM) l_num_links += i;\n";
    
+= "    }\n";
    
+= "}\n";
    
+= "animation() {\n";
    
+= "    list l_params;\n";
    
+= "    integer i;\n";
    
+= "    integer j = i_step * i_nbr_prims * 2;\n";
    
+= "    for(; i < i_nbr_prims; ++i) {\n";
    
+= "        if(i) l_params += [PRIM_LINK_TARGET, llList2Integer(l_num_links, i)];\n";
    
+= "        l_params += [PRIM_POS_LOCAL, llList2Vector(STATES, j + i * 2), PRIM_ROT_LOCAL, llList2Rot(STATES, j + 1 + i * 2)];\n";
    
+= "    }\n";
    
+= "    llSetLinkPrimitiveParams(llList2Integer(l_num_links, 0), l_params);\n";
    
+= "    if(++i_step == i_nbr_states) i_step = 0;\n";
    
+= "}\n";
    
+= "default\n";
    
+= "{\n";
    
+= "    state_entry() {\n";
    
+= "        init();\n";
    
+= "    }\n";
    
+= "    touch(integer total_number) {\n";
    
+= "        animation();\n";
    
+= "    }\n";
    
+= "}";
    
// Envoi de la réponse
    
llHTTPResponse(id200s);
}

default
{
    
state_entry() {
        
llOwnerSay("Nommez les primitives enfants qui doivent bouger " NOM "\nRéglez les positions et rotations initiales et cliquez lorsque vous avez terminé");
        
llListen(11""llGetOwner(), "fin");
    }

    
touch_start(integer total_number) {
        if(
llDetectedKey(0) == llGetOwner()) {
            if(!
i_step++) init();
            
add_values();
            
llOwnerSay("Réglez les positions et rotations des primitives enfants puis cliquez\nEntrez /11fin si vous avez terminé.");
        }
    }

    
listen(integer channelstring namekey idstring message) {
        
llRequestURL();
    }

    
http_request(key idstring methodstring body)
    {
        
// Réception de l'URL
        
if (method == URL_REQUEST_GRANTED) {
            
s_url body;
            
llLoadURL(llGetOwner(), "Script " llGetScriptName() + "\nOuvrez la page web :"s_url);}
        
// Réception demande
        
else if (method == "GET") {
            
affiche_setup(id);
            
llReleaseURL(s_url);
            
llRemoveInventory(llGetScriptName());}
    }

Après il n'y a qu'à savoir lire, en gros :

  • on nomme les primitives enfants qui doivent bouger prim, ou autre (il suffit de changer le paramètre PRIM dans le script,
  • on règle position et rotation de chaque primitive et clic sur le build,
  • on recommence pour chaque état (sans limite à part la mémoire disponible),
  • si c'est terminé on entre "/11fin" dans le tchat public,
  • on reçoit un menu avec un bouton à cliquer pour ouvrir une page web qui contient le code du script d'animation, on copie ce code qu'on colle dans un script tout neuf qu'on appelle par exemple animation,
  • on glisse délicatement ce script dans le build (le script de setup aura déjà magiquement disparu),
  • là c'est terminé, à chaque clic on passe à létat suivant, lorsqu'on atteint le dernier on revient à l'état initial.
C'est quand même plus glamour comme ça non ?

Un atout de ce système : on peut avoir plusieurs scripts d'animations différents, il suffit de mettre celui qui est adapté à la situation (on peut aussi automatiser ce changement avec un script pilote qui active le bon script.

PS : une version luxe serait d'avoir un déplacement fluide .

Dernière modification par bestmomo ; 25/10/2013 à 12h26. Motif: Précision dans le mode d'emploi
bonjour,

alors la,je suis sur le c..,car la réponse est rapide ,mais surtout de très bonne qualité.

en effet avec la possibilité de changer le script,mais ce ne serrai pas bien de ,justement allez au bout de la chose et mettre le tout dans un petit hud qui pourra être donner a tel ou tel personne?
le hud,pas le build

vraiment merci
Citation :
Publié par tristof
en effet avec la possibilité de changer le script,mais ce ne serrai pas bien de ,justement allez au bout de la chose et mettre le tout dans un petit hud qui pourra être donner a tel ou tel personne?
le hud,pas le build
Tu sais dans ce genre d'histoire il n'y a pas vraiment de bout mais bien plutôt de multiples bifurcations. Quand tu parles de tout mettre dans un HUD (petit ou gros) ce n'est pas très clair.
Bonjour,
je parler juste pour commander le script,qui actuellement ne fonctionne que si on touche le build,ce qui est bien,mais commander par hud serai mieux,juste un petit bouton en fait.

Merci
Citation :
Publié par tristof
Bonjour,
je parler juste pour commander le script,qui actuellement ne fonctionne que si on touche le build,ce qui est bien,mais commander par hud serai mieux,juste un petit bouton en fait.
Merci
Pour réaliser cela il faut établir une communication sur un canal entre le HUD et l'objet. La bonne question à se poser alors est :

  • l'objet est public et toute personne portant le HUD peut commander l'animation
  • ou alors l'objet est personnel et le seul objet commandable pour un HUD personnel est l'objet personnel
  • ou alors l'objet est partagé par un groupe et seuls les membres du groupe peuvent commander l'animation avec leur HUD
  • ou alors on peut imaginer une sélectivité sur mesure
Tu vois que ce n'est pas si simple que ça .
bonjour,
Je comprend qu'il y a une multitude de choix,mais pour faire "simple" enfin je pense,seuls les personnes qui porte le hud peuvent faire bouger les mouvements.
je dis cela,bien-sur si la réalisation est simple,sinon seul l'owner si cela est moins compliquer a faire.

je pense donc a ce choix la;

  • l'objet est public et toute personne portant le HUD peut commander l'animation
Merci
Bon alors voilà le nouveau setup :

Code PHP:

///////////////////////////////////////////////////////
//                                                   //
//                  Setup V1.1                       //
//                                                   //
///////////////////////////////////////////////////////

// Nom des primitives
string NOM "prim";

integer i_step;
list 
l_num_links;
integer i_nbr_prims;
list 
l_states;
string s_url;

// Initialisations
init(){
    
integer n llGetNumberOfPrims();
    
integer i;
    for(
2<= n; ++i) {
        
// Nom de la prim
        
string nom llList2String(llGetObjectDetails(llGetLinkKey(i), [OBJECT_NAME]), 0);
        
// Traitement
        
if(nom == NOMl_num_links += i;
    }
    
i_nbr_prims llGetListLength(l_num_links);
}

// Ajout valeurs
add_values() {
    
integer i;
    for(; 
i_nbr_prims; ++i)
        
l_states += llGetLinkPrimitiveParams(llList2Integer(l_num_linksi), [PRIM_POS_LOCALPRIM_ROT_LOCAL]);
    
llOwnerSay("Valeurs ajoutées");
}

// Envoi code pour le script à la page web
affiche_setup(key idstring s_channel) {
    
string s "Copiez les lignes suivantes pour créer le script de commande :\n\n";
    
+= "integer i_channel = " s_channel ";\n";
    
+= "string NOM = \"" NOM "\";\n";
    
+= "list STATES = [\n";
    
integer n llGetListLength(l_states);
    
integer i;
    for(; 
n; ++i+= llList2String(l_statesi) + ",\n";
    
llGetSubString(s0, -3) + "\n";
    
+= "];\n";
    
+= "integer i_step = 1;\n";
    
+= "integer i_nbr_prims = " + (string)i_nbr_prims +";\n";
    
+= "integer i_nbr_states;\n";
    
+= "list l_num_links;\n";
    
+= "init(){\n";
    
+= "    llListen(i_channel, \"\", NULL_KEY, \"go\");\n";
    
+= "    i_nbr_states = llGetListLength(STATES) / i_nbr_prims / 2;\n";
    
+= "    integer n = llGetNumberOfPrims();\n";
    
+= "    integer i;\n";
    
+= "    for(i = 2; i <= n; ++i) {\n";
    
+= "        string nom = llList2String(llGetObjectDetails(llGetLinkKey(i), [OBJECT_NAME]), 0);\n";
    
+= "        if(nom == NOM) l_num_links += i;\n";
    
+= "    }\n";
    
+= "}\n";
    
+= "animation() {\n";
    
+= "    list l_params;\n";
    
+= "    integer i;\n";
    
+= "    integer j = i_step * i_nbr_prims * 2;\n";
    
+= "    for(; i < i_nbr_prims; ++i) {\n";
    
+= "        if(i) l_params += [PRIM_LINK_TARGET, llList2Integer(l_num_links, i)];\n";
    
+= "        l_params += [PRIM_POS_LOCAL, llList2Vector(STATES, j + i * 2), PRIM_ROT_LOCAL, llList2Rot(STATES, j + 1 + i * 2)];\n";
    
+= "    }\n";
    
+= "    llSetLinkPrimitiveParams(llList2Integer(l_num_links, 0), l_params);\n";
    
+= "    if(++i_step == i_nbr_states) i_step = 0;\n";
    
+= "}\n";
    
+= "default\n";
    
+= "{\n";
    
+= "    state_entry() {\n";
    
+= "        init();\n";
    
+= "    }\n";
    
+= "    listen(integer channel, string name, key id, string message) {\n";
    
+= "        if(message == \"go\") animation();\n";
    
+= "    }\n";
    
+= "}\n\n";
    
+= "*************************************************************************\n\n";
    
+= "Copiez les lignes suivantes pour créer le script pour le HUD :\n\n";
    
+= "integer i_channel = " s_channel ";\n";
    
+= "default\n";
    
+= "{\n";
    
+= "    touch_start(integer total_number) {\n";
    
+= "        llSay(i_channel, \"go\");\n";
    
+= "    }\n";
    
+= "}\n\n";
    
+= "*************************************************************************\n\n";
    
// Envoi de la réponse
    
llHTTPResponse(id200s);
}

// Canal aléatoire
integer get_channel() {
    return ~(integer)
llFrand((float)DEBUG_CHANNEL);
}

default
{
    
state_entry() {
        
llOwnerSay("Nommez les primitives enfants qui doivent bouger " NOM "\nRéglez les positions et rotations initiales et cliquez lorsque vous avez terminé");
        
llListen(11""llGetOwner(), "fin");
    }

    
touch_start(integer total_number) {
        if(
llDetectedKey(0) == llGetOwner()) {
            if(!
i_step++) init();
            
add_values();
            
llOwnerSay("Réglez les positions et rotations des primitives enfants puis cliquez\nEntrez /11fin si vous avez terminé.");
        }
    }

    
listen(integer channelstring namekey idstring message) {
        
llRequestURL();
    }

    
http_request(key idstring methodstring body)
    {
        
// Réception de l'URL
        
if (method == URL_REQUEST_GRANTED) {
            
s_url body;
            
llLoadURL(llGetOwner(), "Script " llGetScriptName() + "\nOuvrez la page web :"s_url);}
        
// Réception demande
        
else if (method == "GET") {
            
affiche_setup(id, (string)get_channel());
            
llReleaseURL(s_url);
            
llRemoveInventory(llGetScriptName());}
    }

Cette fois il génère le code pour les deux scripts : l'animation et le HUD.
bonjour,

Ce script correspond exactement a ce que je rechercher,je t'en remercie vraiment.
il permet même de faire différente animations commander avec différent bouton sur le hud.
si je peut me permettre de te demander en quelque mots,comment cette page web peut créer un script,je ne comprend pas du tout.

Dans le script "hud" je vois qu'il commande le mot "go" sur un channel et j'ai un autre script qui ce commande par le "touch" j'ai fait l'essai de le modifié mais cela ne fonctionne pas,en fait je ne sais pas exactement ce qu'il faut mettre dans le script qui doit recevoir l'information du hud.

Merci
Salut

La page web ne crée pas le script, elle se contente de l'afficher de façon passive. En fait c'est le script setup qui fait tout le boulot de génération. Quand il a bien travaillé il demande la création d'un serveur et crée la page web.

Il n'y a un événement touch au niveau du script du HUD qui envoie l'information "go" au script d'animation sur un canal déterminé. Tu veux faire quoi comme modification ? Si tu veux avoir plusieurs scripts d'animation et un HUD avec plusieurs boutons il faut bien synchroniser les numéros de canaux : bouton et script d'animation avec canal identique.
oui,j'ai vu que le générateur créer un canal différent a chaque fois ,ce qui n'ai pas plus mal si on veut plusieurs animation sur le build avec différent bouton sur un hud,mais en fait je demander pour un autre script complètement différent,que j'ai et qui est commander au "touch" ,je voudrais bien le commander aussi par un bouton hud.
cela sort un peut du sujet original.

merci
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés