On Fri, 15 Feb 2013 09:54:16 -0000, MartinRJ Fayray wrote:

I have a similar fix for weeks in the Cool VL Viewer, but it is alas
not as simple as that...

There's a problem with resizing chid primitives (they don't resize
on screen, even when visible).
There's a problem with rotating and moving child primitives when
they are out of FOV, but fixing it by checking for target rot and
position changes like you did also breaks *some* vehicles (when you
or another avatar sits on such vehicles, some chil primitives
pertaining to this vehicle "stay behind" when the vehicle moves).

So, far, I came up with a proper fix for resizing child primitives
and an experimental fix for moving/rotating out of FOV child
primitives (I'm testing for flagUsePhysics() and not applying the
fix when the flag is TRUE, which should exclude vehicles cild prims).
By lack of vehicles to test the latter (I don't use vehicles in SL
and the couple I got in my inventory are not affected by this bug),
I cannot guarantee that it is "final".

Here is the code I use, for people interested in experiencing:

// Returns "distance" between target destination and resulting xfrom
F32 LLDrawable::updateXform(BOOL undamped)
{
        BOOL damped = !undamped;

        // Position
        LLVector3 old_pos(mXform.getPosition());
        LLVector3 target_pos;
        if (mXform.isRoot())
        {
                // get root position in your agent's region
                target_pos = mVObjp->getPositionAgent();
        }
        else
        {
                // parent-relative position
                target_pos = mVObjp->getPosition();
        }

        // Rotation
        LLQuaternion old_rot(mXform.getRotation());
        LLQuaternion target_rot = mVObjp->getRotation();
        bool no_target_omega = mVObjp->getAngularVelocity().isExactlyZero();

        // Scaling
        LLVector3 target_scale = mVObjp->getScale();
        LLVector3 old_scale = mCurrentScale;
        LLVector3 dest_scale = target_scale;

        // Damping
        F32 dist_squared = 0.f;
        F32 camdist2 = mDistanceWRTCamera * mDistanceWRTCamera;

        if (damped && isVisible())
        {
                F32 lerp_amt = 
llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT),
                                                                                
                                          0.f, 1.f);
                LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt);
                dist_squared = dist_vec_squared(new_pos, target_pos);

                LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot);
                dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f;

                LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt);
                dist_squared += dist_vec_squared(new_scale, target_scale);

                if (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2 
&&
                        dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)
                {
                        // interpolate
                        target_pos = new_pos;
                        target_rot = new_rot;
                        target_scale = new_scale;
                }
                else if (no_target_omega)
                {
                        // snap to final position (only if no target omega is 
applied)
                        dist_squared = 0.0f;
                        if (getVOVolume() && !isRoot())
                        {       // child prim snapping to some position, needs 
a rebuild
                                gPipeline.markRebuild(this, 
LLDrawable::REBUILD_POSITION,
                                                                          TRUE);
                        }
                }
        }

        if (old_scale != target_scale)
        {       // scale change requires immediate rebuild
                mCurrentScale = target_scale;
                if (!isRoot() && !isState(LLDrawable::ANIMATED_CHILD))
                {
                        setState(LLDrawable::ANIMATED_CHILD);
                        mVObjp->dirtySpatialGroup();
                }
                gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE);
        }
        else if (!isRoot() && !mVObjp->getRootEdit()->flagUsePhysics() &&
                         (dist_squared > 0.f || old_pos != target_pos ||
                          target_rot != old_rot || !no_target_omega))
        {
                // child prim moving relative to parent, tag as needing to be 
rendered
                // atomically and rebuild
                dist_squared = 1.f; // keep this object on the move list
                if (!isState(LLDrawable::ANIMATED_CHILD))
                {
                        setState(LLDrawable::ANIMATED_CHILD);
                        gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, 
TRUE);
                        mVObjp->dirtySpatialGroup();
                }
        }
        else if (!getVOVolume() && !isAvatar())
        {
                movePartition();
        }

        // Update
        mXform.setPosition(target_pos);
        mXform.setRotation(target_rot);
        mXform.setScale(LLVector3(1, 1, 1)); // no scale in drawable transforms 
(IT'S A RULE!)
        mXform.updateMatrix();

        if (mSpatialBridge)
        {
                gPipeline.markMoved(mSpatialBridge, FALSE);
        }

        return dist_squared;
}

Henri.
_______________________________________________
Policies and (un)subscribe information available here:
http://wiki.secondlife.com/wiki/OpenSource-Dev
Please read the policies before posting to keep unmoderated posting privileges

Reply via email to