• Bitte schaltet eure Ad Blocker aus. SLinfo kann nur betrieben werden, wenn es durch Werbung Einnahmen erzielt. Vielen Dank!!
  • Wir freuen uns, wenn du dich in unserem Forum anmeldest. Bitte beachte, dass die Freigabe per Hand durchgeführt wird (Schutz vor Spammer). Damit kann die Freigabe bis zu 24 Stunden dauern.
  • Wir verwenden Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und die Zugriffe auf unsere Website zu analysieren. Sie geben Einwilligung zu unseren Cookies, wenn Sie unsere Webseite weiterhin nutzen.

teil eines linksets bewegen

JuelsDreki Resident

Neuer Nutzer
Ich versuche gerade eine Flagge so zu skripten, dass man sie hochziehen und und herablassen kann. Die Positionsberechnungen scheinen korrekt zu sein. Aber der Befehl llSetLinkPrimitiveParamsFast() wird nicht ausgeführt. Muss man beim Zusammenbauen des Linksets etwas beachten? Ob es physisch ist zum Beispiel. Allerdings wird das dann der ganze Mast, wenn ich das mit der Flagge probiere. Oder könnte die Ursache die konvexe Hülle sein? Ich habe aber bei allen Prims das auch auf Prims zurückgestellt gehabt. Ob es am Flexiprim liegt habe ich auch schon ausprobiert. Es hat aber alles nichts geholfen.

Die Linknummer 5 stimmt. Das hab ich mit llMessageLinked() getestet.

Code:
integer high;

Init()
{
    high = FALSE;
}

default
{
    state_entry()
    {
        Init();
    }
    
    on_rez(integer start_param)
    {
        Init();
    }
    
    touch_start(integer total_number)
    {
        list lPos;
        vector vPos;
        
        lPos = llGetLinkPrimitiveParams( 5, [PRIM_POSITION] );
        vPos = llList2Vector(lPos,0);
        
        llOwnerSay("1.0 x: "+(string)vPos.x);
        llOwnerSay("1.0 y: "+(string)vPos.y);
        llOwnerSay("1.0 z: "+(string)vPos.z);
        
        if( high )
        {
            vPos.z += 1.0;
            high = FALSE;
        }
        else
        {
            vPos.z -= 1.0;            
            high = TRUE;
        }
        
        llOwnerSay("1.1 z: "+(string)vPos.z);

        llSetLinkPrimitiveParamsFast( 5, [PRIM_POSITION, vPos/llGetRot()] );

        lPos = llGetLinkPrimitiveParams( 5, [PRIM_POSITION] );
        vPos = llList2Vector(lPos,0);

        llOwnerSay("2.0 x: "+(string)vPos.x);
        llOwnerSay("2.0 y: "+(string)vPos.y);
        llOwnerSay("2.0 z: "+(string)vPos.z);
    }
}
 
hallo juelsdreki und willkommmen im Forum :)

Versuche mal bitte vPos/llGetRot() ausgeben und schauen, ob das Ergebnis nicht mehr als 10m von der Ursprungsposition liegt. Irgendwie kommt mir die Operation verdächtig vor. Bei Positionsänderungen macht man oft den Fehler, dass die Zielposition mehr als 10m weit liegt und dann klappts nicht.

Ich glaube ich weiß warum verdächtig. Man multipliziert einen Vektor mit der Eigenrotation, um diese zu berücksichtigen. Dividieren macht man bei Rotationen für die Differenzbildung, Vektor/Rotation ist mit aber neu :)

Alternativ kannst Du auch PRIM_POS_LOCAL verwenden und brauchst Dich nicht um die Rotation zu kümmern.
 
Zuletzt bearbeitet:
Hallo Jenna,

Erstmal vielen Dank für Deine Antwort. Ich schicke es mal voraus, das Problem ist gelöst. :)

Ich hatte mir als erstes die mit vPos/llGetPos() berechnete Position ausgeben lassen, aber es war, wie ich es erwartet hatte, nur die Z-Achse um 1m verändert. Die Lösung war PRIM_POS_LOCAL. Hier noch mein neuer Code, und weiterhin viel Spass in SL.

Code:
integer high;

Init()
{
    high = FALSE;
}

default
{
    state_entry()
    {
        Init();
    }
    
    on_rez(integer start_param)
    {
        Init();
    }
    
    touch_start(integer total_number)
    {
        list lPos;
        vector vPos;
        
        lPos = llGetLinkPrimitiveParams( 5, [PRIM_POS_LOCAL] );
        vPos = llList2Vector(lPos,0);
        
        llOwnerSay("1.0 x: "+(string)vPos.x);
        llOwnerSay("1.0 y: "+(string)vPos.y);
        llOwnerSay("1.0 z: "+(string)vPos.z);
        
        if( high )
        {
            vPos.z += 1.0;
            high = FALSE;
        }
        else
        {
            vPos.z -= 1.0;            
            high = TRUE;
        }
        
        llOwnerSay("1.1 x: "+(string)vPos.x);
        llOwnerSay("1.1 y: "+(string)vPos.y);
        llOwnerSay("1.1 z: "+(string)vPos.z);

        llSetLinkPrimitiveParamsFast( 5, [PRIM_POS_LOCAL, vPos] );

        lPos = llGetLinkPrimitiveParams( 5, [PRIM_POS_LOCAL] );
        vPos = llList2Vector(lPos,0);

        llOwnerSay("2.0 x: "+(string)vPos.x);
        llOwnerSay("2.0 y: "+(string)vPos.y);
        llOwnerSay("2.0 z: "+(string)vPos.z);
    }
}
 
Ich muss zu meiner Lösung doch noch eine Frage loswerden. Zur Erläuterung, ich möchte das die Fahne beim Hoch- und Herunterziehen sich langsam bewegt, daher setze ich mit llGetLinkPrimitiveParams timergesteuert Stück für Stück die neue Position der Fahne. Was mir dabei nicht gefällt, ist das diese Lösung laganfällig ist, und selber Lag verursacht. Gibt es eine Möglichkeit den Endpunkt der Bewegung vorzugeben, und die Fahne bewegt sich langsam darauf zu? Ich denke dabei an die Funktion llSetKeyframedMotion.
 
Wenn es sich um ein Linkset handelt, scheidet llMoveToTarget aus. Wenn du den beweglichen Teil aber als einzelnes Objekt realisieren kannst, würde ich es mit besagter Funktion versuchen.

Andernfalls: Ich bezweifle, das es nennenswert Lag verursacht. Oder hast du das konkret ermittelt oder bemerkt ?

Ist die Bewegung ihrerseits laganfällig, könntest du grössere Intervalle versuchen. Du könntest aber auch recht grosse Intervalle setzen (wobei die Fahne dann natürlich schneller ist) und dabei die Bewegung mit einem sehr kleinen Intervall beginnen. Das dient dem Zweck, die Interpolierung "zu aktivieren". Ohne diesen Trick würde sich die Fahne ruckartig zur nächsten Position bewegen.


Das bei mehreren grösseren Intervallen sich die Fahne nicht in einem einzigen glatten Vorgang vom start bis zum Ziel bewegt, sähe meiner Meinung nach sogar realistisch aus.
 
Mit llSetKeyframedMotion kriegst du die beste Bewegungsergebnisse mit kaum lag. Wie Argus sagte, die Flagge muss der eigene Prim oder Linkset sein, von der Pole getrennt, aber Du brauchst dann nur den Bewegungsbefehl geben und los gehts. Nur beachten, dass wenn jemand die Flagge dabei berührt, kann sie anhalten. Also must Du den den moving_end() Ereignis behandeln (des wird dann ausgelöst) und wenn die Flagge nahe genug zum Ziel ist, direkt bewegen mit llSetRegionPos() und sonst eine erneute Bewegung mit KFM. Dann klappt es und die Flagge bleibt nicht wtecken.
 
Direkt ermittelt habe ich nicht, wieviel Lag das Skript im Moment verursacht. Aber die Timerintervalle sind sehr kurz, und Timer sollen ja eine Ursache für Lag sein. Allerdings die Fahne zieht man ja nun auch nicht ständig hoch und runter. Aber das die Bewegung selbst laganfällig ist, stört mich sehr viel mehr.

Das die Fahnen mit Euren Tips nur als selbstständiger Prim bewegt werden können, ist etwas ungünstig. Das macht das Rezzen des kompletten Mastes unmöglich. Mal überlegen ob da ein Rezzer eine Lösung wäre.

Jedenfalls vielen Dank für Eure Tips.
 
Aber die Timerintervalle sind sehr kurz
Definiere sehr kurz
100 Millisekunden sind für Computer eine kleine Ewigkeit.

Aber verzichte bei solchen Bewegungen ganz auf einen Timer
Eine simple for oder while Schleife mit jeh nach Hublänge ca. 50 Steps,
welche den llSetlinkPrimitiveParamsFast-Befehl benutzen.

Falls es zu schnell ist, ggf. kleine Sleeps (100-300ms) einfügen (was den restlichen Skripten der SIM etwas Luft zum atmen gibt)
 
Timer an sich sind keine Lag-Quellen... der Code der im Timer ausgeführt wird, kann natürlich eine Lag-Quelle sein. Bei Computern/Computerprogrammen wird praktisch alles mit Timern gemacht, ein Timer ist etwas völlig 'natürliches'. :p
 
Aber das die Bewegung selbst laganfällig ist, stört mich sehr viel mehr.

Was genau meinst du damit ? Wie äussert sich das ? Oder ist das "nur" eine Idee, das es laganfällig sein könnte ?

Ich habe gerade ein einfaches Besipiel gescriptet. Die lokale z-position der Fahne ändere ich mit llSetLinkPrimitiveParamsFast um 0.1 Meter pro Schritt.
Das Timerintervall setze ich auf 0.1 Sekunden. Die Fahne bewege ich dabei um 4 Meter. Also recht viel.

Das läuft tadellos. Eine 100% glatte Bewegung wirst du wohl nie hinbekommen. Minimale Ruckler sind IMMER da. Man überzeuge mich vom Gegenteil ;-)
 
Dividieren macht man bei Rotationen für die Differenzbildung, Vektor/Rotation ist mit aber neu :)

Bei Rotationen gilt erst mal, dass sie nicht kommutativ sind, d.h. (rot1 * rot2) != (rot2 * rot1) - deswegen ist das auch keine Multiplikation und auch keine Division, die da angewandt wird, sondern einfach eine Kombination einer Ausrichtung mit einer Rotation. Dabei ist rot1 * rot2 eine Drehung im Uhrzeigersinn, während rot1/rot2 in LSL einfach eine Drehung gegen den Uhrzeigersinn ist.

Rotationen sind dabei einfach 4-Dimensionale "Ausrichtungsangaben", die mit komplexen Zahlen arbeiten, während in LSL Vektoren 3-Dimensionale "Ausrichtungsangaben" sind, die mit Gradangaben arbeiten (also Eulerwinkel) oder aber Positionsangaben, die dann einen Punkt im Koordinaten-System festlegen. Daher muss man in LSL bisschen aufpassen was man beim Rotieren wie verrechnet.
 
Was genau meinst du damit ? Wie äussert sich das ? Oder ist das "nur" eine Idee, das es laganfällig sein könnte ?

Nur eine Vermutung:
Auf dem Sim ist eh schon bisschen Last.

Scripts werden in SL nicht kontinuierlich abgearbeitet, sondern immer nur Schritt für Schritt. Nach jeder größeren Funktion und nach jedem Event haut der Compiler ein "Stop?" in den Code - und genau da kann ein Script eben angehalten werden (und bei bedarf gespeichert und auf einen andern Sim transferiert usw.). Und Script-Events werden darüber hinaus nur ausgeführt, wenn auf dem Server übrige Zeit ist. Genau deswegen sind Timer in SL eben alles andere als exakt, und wer z.B. einen 100ms Timer in ein Script einbaut, der kann nur darauf vertrauen, dass der Timer mindestens 100ms wartet - es können aber je nach Last auf dem Sim auch mal 102 ms oder 109ms oder gar 110ms sein, bis der Timer Event wieder auslöst.

Timer sind in SL daher schon bisschen laganfällig. Und der von Dianna vorgeschlagene for- oder while Loop ist eben klein bisschen verlässlicher. Und weniger Lag-Anfällig, weil sie nicht so ausgebremst werden wie Timer-Events. Dafür muss man vor allem bei verschachtelten Loops klein bisschen aufpassen, dass sie nicht zu viel Last auf dem Server erzeugen. (mit den enstprechenden loops und den richtigen Funktionen kriegt man mit viel Pech eine Sim zum Reboot...) Weswegen da auch die angesprochenen Sleeps Sinnvoll sind.
 
Ich hatte die Fahne auch mit einer Schleife getestet. Mit einer Schrittweite von 0.001 Metern bewegt sich die Fahne langsam und
recht gleichmässig. Baut man llSleep ein, wird es unregelmässiger. llSleep ist offenbar auch nicht deutlich besser als der Timer. Ausserdem
gibt mir zu denken, das llSleep in opensim verpönt ist. Diese Funktion muss für den Server ziemlichen Stress bedeuten. (Ob das auch so
für SecondLife gilt habe ich jetzt nicht recherchiert).

Schleifen versuche ich aber zu vermeiden. Weil ich Programme und auch Scripte nicht gut finde, wenn sie nicht jederzeit für den User
erreichbar sind: Wenn der User also eine einmal gestartete Aktion abwarten muss und das Programm in der Zwischenzeit auf nichts mehr
reagiert.

Zur Not ("Not" wegen eventueller Servrlast) gäbe es aber auch eine Schleifenmöglichkeit mit einem "gefakten" target-event.
Da bleibt das Script kontrollierbar: Aber bereits die timer-version des Fahnenmastes ist meiner Meinung nach absolut ausreichend und nur
noch minimal optimierbar.
 
Also laut LSL wiki kann man mit llSetTimerEvent() nur ein minimales Intervall von 0,04s = 400ms einstellen, daß das für einen Prozessor eine halbe Ewigkeit ist, ist mir klar. Immerhin werden Assemblerbefehle im Bereich von ns ausgeführt. :)

Das die Lösung mit dem Timer laganfällig ist, äussert sich so, daß die Fahne zum Teil einen Moment regelrecht hängen bleibt, bevor sie die Bewegung vollendet.

Dianna, ich werde mal Deine Lösung mit der Schleife ausprobieren. Funktioniert das lagfest, brauche ich das Linkset nicht auseinandernehmen. Der Lösung von Jenna mit llSetKeyframedMotion() bin ich aber auch nicht abgeneigt. Ich würde die Fahne als Objekt in dem Fall in den Mast packen, und den Mast selbst als Rezzer benutzen. Die Fahne kann man eh abnehmen und wieder anhängen. In dem Fall wird sie dann aber nicht einfach transparent eingestellt, sonder gerezzt oder gelöscht. Mal sehen was es am Ende wird. Vielen Dank!
 
Upps habe eure Antworten auf der zweiten Seite eben erst gesehen. Hmm, ja die Schleife würde einen möglichen Zugriff auf dem Dialog im Skript verzögern. Das wäre nicht so toll. Wird also dann doch wohl die Lösung von Jenna.

Sleep-Befehle sind nicht nur in SL oder Opensim verpönt. Auch in der embedded Programmierung versucht man sie zu vermeiden. Man beschäftigt so den Prozessor mit dem Sleep obwohl er in der Zeit auch anderes erledigen könnte. Ganz besonders krass ist das, wenn man das Sleep nicht mit Timern sondern mit einer Warteschleife realisiert. Ich vermute daher in SL eine Implementation der Sleep-Befehle auf Basis der Timer. Das würde dann erklären, warum sie ähnlich "zuverlässig" wie die Timer sind.
 
Also laut LSL wiki kann man mit llSetTimerEvent() nur ein minimales Intervall von 0,04s = 400ms einstellen, daß das für einen Prozessor eine halbe Ewigkeit ist, ist mir klar. Immerhin werden Assemblerbefehle im Bereich von ns ausgeführt. :)

Das die Lösung mit dem Timer laganfällig ist, äussert sich so, daß die Fahne zum Teil einen Moment regelrecht hängen bleibt, bevor sie die Bewegung vollendet.

Dianna, ich werde mal Deine Lösung mit der Schleife ausprobieren. Funktioniert das lagfest, brauche ich das Linkset nicht auseinandernehmen. Der Lösung von Jenna mit llSetKeyframedMotion() bin ich aber auch nicht abgeneigt. Ich würde die Fahne als Objekt in dem Fall in den Mast packen, und den Mast selbst als Rezzer benutzen. Die Fahne kann man eh abnehmen und wieder anhängen. In dem Fall wird sie dann aber nicht einfach transparent eingestellt, sonder gerezzt oder gelöscht. Mal sehen was es am Ende wird. Vielen Dank!

0,04s = 40 ms nicht 400 ^^
sleep gibt in SL die Kontrolle an den Masterprozess (server-main-loop) ab, also im Gegensatz zu sleeps in Assembler belasten sie nicht die CPU mit wait-Zyklen
Diese Assemblersleeps erreichst du in SL mit einer verschachtelten Unterschleife oder einer Schleifenfunktion so in etwa

Code:
main loop
{
      do something;
      for i=0;i<10000;++i); // do nothing except hochzählen
      do something more;
}


das die Fahne sich während der Bewegung nicht bedienen lässt, finde ich entgegengesetzt sogar nützlich,
ich sperre den Touch-Event sogar explizit währenddessen
Code:
{
      touch_start(integer numdetected)
     { 
          if(!moving) mach_was;
     }
}
 
Ohje, das mit der Umrechung ist peinlich. Du hast natürlich recht, es sind 40ms. So kurz habe ich es gewählt, weil das 25 Bilder/s bedeutet. Das ist die Hälfte der Anzahl der Bilder die ein herkömmlicher Fernseh darstellen kann. Dennoch sieht man mit 25 Bilder/s aufgrund der Trägheit des menschlichen Auges eine flüssige Bewegung, die Grenze dabei liegt bei 16-18 Bilder/s (http://de.wikipedia.org/wiki/Bewegte_Bilder).

Das die Fahne bei Verwendung eines Sleeps mit Schleife, nicht bedienbar ist, würde sicher nicht stören. Aber so richtig sehe ich die Lösung darin nicht, wenn, wie Shirley schreibt, ein Skript auch mal gestoppt werden kann. Dann würde auch so die Fahne hin und wieder hängen bleiben.
 
Ohje, das mit der Umrechung ist peinlich. Du hast natürlich recht, es sind 40ms. So kurz habe ich es gewählt, weil das 25 Bilder/s bedeutet. Das ist die Hälfte der Anzahl der Bilder die ein herkömmlicher Fernseh darstellen kann. Dennoch sieht man mit 25 Bilder/s aufgrund der Trägheit des menschlichen Auges eine flüssige Bewegung, die Grenze dabei liegt bei 16-18 Bilder/s (http://de.wikipedia.org/wiki/Bewegte_Bilder).

Das die Fahne bei Verwendung eines Sleeps mit Schleife, nicht bedienbar ist, würde sicher nicht stören. Aber so richtig sehe ich die Lösung darin nicht, wenn, wie Shirley schreibt, ein Skript auch mal gestoppt werden kann. Dann würde auch so die Fahne hin und wieder hängen bleiben.

25 Bilder/s sollte Videos vorbehalten bleiben.
Für Dinge dieser Art oder auch Cartoons sind eher 5-15fps üblich

Aber das nur am Rande, dieses "Stoppen" liegt selbst im Milliesekundenbereich, kann man aber gelegentlich schon wahrnehmen.
ist aber nicht so tragisch, mein Werbeboard, was so eine Art Überblendrolleffekt macht, läuft zu 95% smooth genug.
Die restlichen paar Prozent hängt mal eine der 10 Stangen beim Drehen etwas nach, was nicht die Bohne störend wirkt, eher wie Shirley schon sagte, sehr natürlich

Lange Rede kurzer Sinn, probiere damit herum.
Unser intelektuelles Geschwafel kann allerhöchstens Anregungen geben, gelöst wird sowas Inworld am Objekt selbst.
 
Wenn dir egal ist, dass das Objekt während der Bewegungsphase nicht ansprechbar ist, dann nutze eine Schleife ohne Timer.
Mit llSetLinkPrimitiveParamsFast und einem Streckenintervall von z.b. 0.01 Metern oder noch kleiner solltest du ein ansehnliches
Ergebnis erzielen.

Was sonst noch bliebe, wäre eine Texturanimation (mittels llSetTexureAnim) oder besser noch eine laufende Änderung des
Texturoffsets (wieder in einer timerlosen Schleife).

Aber selbst da wird man kleinere Ruckler sehen. Was diese Ruckler angeht, gibt es Leute, die weniger empfindlich darauf
reagieren und es innerhalb gewisser Grenzen gar nicht wahrnehmen. Ich selbst habe das Pech, da sehr empfindlich zu sein. Ich
sehe Ruckeln, wo andere nichts dergleichen wahrnehmen. Aber die beschriebenen Lösungen stellen zumindest mich zufrieden.

Kurz zum Texturverfahren: Anstatt die Fahne als eigenständiges, kleines bewegliches Childprim anzulinken, linke ein Childprim
hinzu, dessen vertikale Skalierung der gewünschten Bewegungsstrecke entspricht, und dessen horizontale Skalierung der
gewünschten Fahnenlänge entspricht. Dann erstelle eine Textur, deren Skalierung der gewünschten Fahnenhöhe entspricht. Dann
ändere in der Schleife den vertikalen Texturoffset.
 
Zuletzt bearbeitet:

Users who are viewing this thread

Zurück
Oben Unten