Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006112opensim[REGION] Script Functionspublic2012-07-27 09:212013-01-13 08:44
ReporterSignpostMarv 
Assigned To 
PrioritynormalSeverityminorReproducibilityN/A
Statuspatch includedResolutionopen 
PlatformOSOS Version
Product Versionmaster (dev code) 
Target VersionFixed in Version 
Summary0006112: llSetKeyframedMotion
DescriptionIt'd be nice to see this implemented in OpenSim.

http://wiki.secondlife.com/wiki/LlSetKeyframedMotion [^]
TagsNo tags attached.
Git Revision or version number6ee17f5b36
Run ModeStandalone (1 Region) , Standalone (Multiple Regions) , Grid (1 Region per Sim) , Grid (Multiple Regions per Sim)
Physics EngineBasicPhysics
Script Engine
EnvironmentMono / Linux32, Mono / Linux64, Mono / Windows, Mono / OSX, .NET / Windows32, .NET / Windows64
Mono VersionNone
Viewer
Attached Filespatch file icon llSetKeyframedMotion.patch [^] (37,411 bytes) 2012-09-25 07:49 [Show Content]
patch file icon llSetKeyframedMotion-translation-non-velocity.patch [^] (49,143 bytes) 2012-10-15 02:52 [Show Content]
patch file icon borked-velocity-updates.patch [^] (2,066 bytes) 2012-10-15 03:42 [Show Content]

- Relationships
related to 0004072new os_SetPos , os_SetRot commands (dampened movement) 

-  Notes
(0021914)
SignpostMarv (reporter)
2012-07-27 09:22

Just creating the mantis for cross-referencing purposes.
(0022688)
SignpostMarv (reporter)
2012-09-25 07:49

The patch is incomplete, it sort of works but the ping-pong animation goes too far on the reverse translation and rotation frames are completely borked.

default
{
    state_entry()
    {
        llSetKeyframedMotion([], [(integer)KFM_COMMAND, (integer)KFM_CMD_STOP]);
        llSetRegionPos(<128,128,26>);
    }

    touch_start(integer t){
        llSetKeyframedMotion(
            [
                <0.0, 0.0, 5.0>, 5,
                <0.0, 0.0, -5.0>, 5
            ],[
                (integer)KFM_DATA, (integer)KFM_TRANSLATION,
                (integer)KFM_MODE, (integer)KFM_PING_PONG
            ]);
    }
}
(0022736)
justincc (administrator)
2012-09-28 18:14

Hey Marv, I like the look of the patch but unfortunately I have very little opportunity to look right now.

Just to check - you're aware that OnSceneFrame will be fired every 1/11th of a second? In the light of this,

            float delta = (float)Math.Min(currentFrame.Duration,
                    (DateTime.Now - m_frameStarted).TotalSeconds) /
                    currentFrame.Duration;

looks a little suspect to me but this is a bit of a stab in the dark.

As another minor point, a private field can be specified as

public bool Enabled { get; private set; }

if it should not be set externally - there is no need for an m_enabled as well.
(0022758)
SignpostMarv (reporter)
2012-10-01 02:52

I wasn't aware fields could have different visibility for getters and setters :D
(0022855)
Garmin Kawaguichi (reporter)
2012-10-14 15:26

To SignpostMarv:
llSetKeyframedMotion is a function of interest (as important as llTargetOmega was in its time). This is an excellent initiative to integrate it into OpenSim.
So I looked at what was wrong with the Ping-Pong option (only with tests on the Translation)

Given the following sequence (lsl):
        llSetKeyframedMotion(
            [<4.0, 0.0, 0.0>, 5, <0.0, -4.0, 0.0>, 5],
            [(integer)KFM_DATA, (integer)KFM_TRANSLATION,
             (integer)KFM_MODE, (integer)KFM_PING_PONG]);
it can also be programmed:
        llSetKeyframedMotion(
            [<4.0, 0.0, 0.0>, 5, <0.0, -4.0, 0.0>, 5,
            -<0.0, -4.0, 0.0>, 5, -<4.0, 0.0, 0.0>, 5],
            [(integer)KFM_DATA, (integer)KFM_TRANSLATION,
             (integer)KFM_MODE, (integer)KFM_LOOP]);
in which we see that at the Ping part <V1>, D1, <V2>, D2
corresponds the Pong part -<V2>, D2 -<V1>, D1

To obtain this result we modified
OpenSim\Region\OptionalModules\Scripting\KeyframedMotion\KeyframedMotionAnimation.cs
====================
around Ln 239
Select from if ((AnimationData & Data.Rotation) == Data.R...
            to m_object.SendGroupRootTerseUpdate();
and replace with
            if ((AnimationMode == Mode.Ping_Pong) && (m_advanceByFrames == -1))
            {
                if ((AnimationData & Data.Rotation) == Data.Rotation)
                    m_object.UpdateGroupRotationR(m_startRot + m_referenceRotation - (currentFrame.Rotation * delta));

                if ((AnimationData & Data.Translation) == Data.Translation)
                    m_object.AbsolutePosition = m_startPos + m_referenceTranslation - (currentFrame.Translation * delta);
            }
            else
            {
                if ((AnimationData & Data.Rotation) == Data.Rotation)
                    m_object.UpdateGroupRotationR(m_startRot + m_referenceRotation + (currentFrame.Rotation * delta));

                if ((AnimationData & Data.Translation) == Data.Translation)
                    m_object.AbsolutePosition = m_startPos + m_referenceTranslation + (currentFrame.Translation * delta);
            }
            m_object.SendGroupRootTerseUpdate();
====================
around Ln 167
replace
                m_referenceTranslation += currentFrame.Translation;
                m_referenceRotation += currentFrame.Rotation;
by
                if ((AnimationMode == Mode.Ping_Pong) && (m_advanceByFrames == -1))
                {
                    m_referenceTranslation -= currentFrame.Translation;
                    m_referenceRotation -= currentFrame.Rotation;
                }
                else
                {
                    m_referenceTranslation += currentFrame.Translation;
                    m_referenceRotation += currentFrame.Rotation;
                }
====================
====================
For the fact that Ping-Pong and Reverse terminate too fast

At the level of the decrementation of frames, there is a small problem: the last frame is skipped.
In fact, for the Reverse or the Pong part, the frame list is pointed from length-1 to 0; to avoid losing the frame 0 in the inverse iteration of the list:
around Ln 197
replace
                else if (m_currentFrame <= 0)
by
                else if (m_currentFrame < 0)
====================
This is suitable for the Translation. For the rest of the features (Rotation and other Modes), we will test according to the availability of planning.
(0022857)
SignpostMarv (reporter)
2012-10-15 02:53

translations seem to work now, although it isn't using velocity for less frequent network updates.
(0022858)
SignpostMarv (reporter)
2012-10-15 03:43

Experimented with using velocity for updates instead of explicitly setting the position every frame, doesn't quite work.
(0023396)
Garmin Kawaguichi (reporter)
2013-01-10 12:40

After several weeks without having the time to pursue the research, I examined the problem of rotations.
It appears that, as in the LSL, the arithmetic of quaternions is different from that of vectors.

Quaternion + Quaternion = anything
Quaternion - Quaternion = anything
Quaternion * Quaternion = addition
Quaternion / Quaternion = subtraction

Example with module KeyframedMotion
Client side => 1 single frame of 10° in 1 second for an object oriented at 90°
in: KeyframedMotionAnimation.cs
in: public void Animate()
just after: if ((AnimationData & Data.Rotation) == Data.Rotation)
we have the lines:
m_object.UpdateGroupRotationR((m_startRot + m_referenceRotation) + (currentFrame.Rotation * delta));
MainConsole.Instance.Output(String.Format(
    "KFM Oper: 90°={0}" + Environment.NewLine +
    "90° + Quaternion.Identity ={1}" + Environment.NewLine +
    "90° * Quaternion.Identity ={2}",
    m_startRot, m_startRot + Quaternion.Identity, m_startRot * Quaternion.Identity));

MainConsole.Instance.Output(String.Format(
        "KFM: cFram={0}; stRot={1}; refRot={2}" + Environment.NewLine +
        " curRot={3}; delta={4}" + Environment.NewLine +
        " str+stfr={5}; deltRot={6}" + Environment.NewLine +
        " =>Rot={7}",
        m_currentFrame, m_startRot, m_referenceRotation,
        currentFrame.Rotation, delta,
        m_startRot + m_referenceRotation, (currentFrame.Rotation * delta),
        (m_startRot + m_referenceRotation) + (currentFrame.Rotation * delta)
        ));

giving at runtime:
KFM Oper: 90°=<0, 0, 0.7071068, 0.7071068>
90° + Quaternion.Identity =<0, 0, 0.7071068, 1.707107>
90° * Quaternion.Identity =<0, 0, 0.7071068, 0.7071068>
KFM: cFram=0; stRot=<0, 0, 0.7071068, 0.7071068>; refRot=<0, 0, 0, 1>
     curRot=<0, 0, -0.08715516, -0.9961947>; delta=0,041
     str+stfr=<0, 0, 0.7071068, 1.707107>; deltRot=<0, 0, -0.003573362, -0.04084399>
   =>Rot=<0, 0, 0.7035334, 1.666263>

which is understood as:

90° + Quaternion.Identity =<0, 0, 0.7071068, 1.707107> ==>> <0.000000,0.000000,44.999996>
90° * Quaternion.Identity =<0, 0, 0.7071068, 0.7071068> ==>> <0.000000,0.000000,90.000001>

m_startRot is stRot=<0, 0, 0.7071068, 0.7071068> ==>> <0.000000,0.000000,90.000001>
m_referenceRotation is refRot=<0, 0, 0, 1> ==>> <0.000000,0.000000,0.000000>
(currentFrame.Rotation * delta) is deltRot=<0, 0, -0.003573362, -0.04084399> ==>> <0.000000,0.000000,9.999933>
m_object.UpdateGroupRotationR is stRot + refRot + deltRot
    = <0, 0, 0.7035334, 1.666263> ==>> <0.000000,0.000000,45.781112>
    ???? 90 + 0 + 10 = 45.78 ????

and deltRot also seems to be wrong
This is a good base to boost your work.
(0023401)
Garmin Kawaguichi (reporter)
2013-01-13 08:44

"and deltRot also seems to be wrong" ...

We cannot multiply a quaternion with a float/double.
Then just change the quaternion in a vector like that

                if ((AnimationData & Data.Rotation) == Data.Rotation)
                {
                    Vector3 vCfr;
                    currentFrame.Rotation.GetEulerAngles(out vCfr.X, out vCfr.Y, out vCfr.Z);
                    vCfr *= delta;
                    m_object.UpdateGroupRotationR((m_startRot * m_referenceRotation) / Quaternion.CreateFromEulers(vCfr));
                }

- Issue History
Date Modified Username Field Change
2012-07-27 09:21 SignpostMarv New Issue
2012-07-27 09:22 SignpostMarv Note Added: 0021914
2012-07-27 09:23 SignpostMarv Relationship added related to 0004072
2012-09-25 07:49 SignpostMarv File Added: llSetKeyframedMotion.patch
2012-09-25 07:49 SignpostMarv Note Added: 0022688
2012-09-25 07:49 SignpostMarv Status new => patch included
2012-09-28 18:14 justincc Note Added: 0022736
2012-10-01 02:52 SignpostMarv Note Added: 0022758
2012-10-14 15:26 Garmin Kawaguichi Note Added: 0022855
2012-10-15 02:52 SignpostMarv File Added: llSetKeyframedMotion-translation-non-velocity.patch
2012-10-15 02:53 SignpostMarv Note Added: 0022857
2012-10-15 03:42 SignpostMarv File Added: borked-velocity-updates.patch
2012-10-15 03:43 SignpostMarv Note Added: 0022858
2013-01-10 12:40 Garmin Kawaguichi Note Added: 0023396
2013-01-13 08:44 Garmin Kawaguichi Note Added: 0023401


Copyright © 2000 - 2012 MantisBT Group
Powered by Mantis Bugtracker