Skip to content

Instantly share code, notes, and snippets.

@typhartez
Last active December 7, 2020 09:44
Show Gist options
  • Select an option

  • Save typhartez/5631a20e36e8437d27043f1ec5d0be43 to your computer and use it in GitHub Desktop.

Select an option

Save typhartez/5631a20e36e8437d27043f1ec5d0be43 to your computer and use it in GitHub Desktop.
Moving a beam with parent prim rotation?

I want to make some lights with a retractable beam: the beam is minimized and centered into the root prim when inactive. The light can rotate while the beam is active or not, and I want only one script in the root prim to control the beam.

FIXED: do not apply any rotation! In fact, when setting PRIM_POS_LOCAL, it seems OpenSim also computes the offset due to root rotation.

Here is a picture of the action:

Diagram of beam movement

The active size of the beam is saved before it's hidden, so it can be used when restoring it. I tried several methods without success. For me, this one was the right one:

integer BEAM_LINK = 2
// returns the new local position of the beam from its stored size
vector restoreBeam(vector beamSize) {
  vector rootSize = llGetScale();
  rotation rootRot = llGetRot();

  // calculate the offset from a "zero-rotation" root prim
  vector beamOffset = <0.0, 0.0, rootSize.z / 2 + beamSize.z / 2>;
  // the wanted beam position relative to the root
  // this is simplified considering the beam has a zero rotation relative to the root
  vector beamPos = beamOffset * rootRot;
}

All is ok as long are there is no rotation, but as soon as there is one, here is the result: Wrong position

I tried several other formulas, like converting first to region coordinates, applying the rotation, then removing the root position from the result.

@liftedpixel
Copy link

Let me know if this is what you're looking for!

integer BEAM_LINK = 2;
vector rootSize;
vector rootPos;
vector smallSize;
vector localPos;
rotation localRot;

restoreBeam( vector beamSize ) {
    // get size of the base
    rootSize = llGetScale();
    
    // get link prim start size
    smallSize = llList2Vector( llGetLinkPrimitiveParams( BEAM_LINK, [ PRIM_SIZE ] ), 0 );
    
    // get link prim rotation vs root prim
    localRot = llList2Rot( llGetLinkPrimitiveParams( BEAM_LINK, [ PRIM_ROT_LOCAL] ), 0 );
    
    // get link prim position vs root prim
    localPos = llList2Vector( llGetLinkPrimitiveParams( BEAM_LINK, [ PRIM_POS_LOCAL ] ), 0 );
    
    // half the height of the base and half the height of the beam for the offset
    vector beamOffset = < 0.0, 0.0, rootSize.z / 2 + beamSize.z / 2 >;
    
    // set link prim size, local rotation, local position with offset
    llSetLinkPrimitiveParams( BEAM_LINK, [ PRIM_SIZE, beamSize, PRIM_ROT_LOCAL, localRot, PRIM_POS_LOCAL, localPos + beamOffset ] );
}

resetBeam() {
    // set link prim to previous size and position
    llSetLinkPrimitiveParams( BEAM_LINK, [ PRIM_SIZE, smallSize, PRIM_POSITION, localPos ] );
}
default
{
    touch_start( integer d )
    {
        restoreBeam( <0.3,0.3,5.0> );
    }
    
    touch_end( integer d )
    {
        resetBeam();
    }
}

@typhartez
Copy link
Author

Solution: do not apply any rotation! In fact, when setting PRIM_POS_LOCAL, it seems OpenSim also computes the offset due to root rotation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment