void plPhysicalControllerCore::IApply(float delSecs)
{
    fSimLength = delSecs;

    // Match controller to owner if transform has changed since the last frame
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
    if (!CompareMatrices(fLastGlobalLoc, l2w, 0.0001f))
        SetGlobalLoc(l2w);

    if (fEnabled)
    {
        // Convert velocity from avatar to world space
        if (!fLinearVelocity.IsEmpty())
        {
            fLinearVelocity = l2w * fLinearVelocity;

            const plCoordinateInterface* subworldCI = GetSubworldCI();
            if (subworldCI)
                fLinearVelocity = subworldCI->GetWorldToLocal() * fLinearVelocity;
        }

        fMovementStrategy->Apply(delSecs);
    }
}
示例#2
0
// Called after the simulation has run....sends new positions to the various scene objects
// *** want to do this in response to an update message....
void plPXPhysical::SendNewLocation(bool synchTransform, bool isSynchUpdate)
{
    // we only send if:
    // - the body is active or forceUpdate is on
    // - the mass is non-zero
    // - the physical is not passive
    bool bodyActive = !fActor->isSleeping();
    bool dynamic = fActor->isDynamic();
    
    if ((bodyActive || isSynchUpdate) && dynamic)// && fInitialTransform)
    {
        plProfile_Inc(MaySendLocation);

        if (!GetProperty(plSimulationInterface::kPassive))
        {
            hsMatrix44 curl2w = fCachedLocal2World;
            // we're going to cache the transform before sending so we can recognize if it comes back
            IGetTransformGlobal(fCachedLocal2World);

            if (!CompareMatrices(curl2w, fCachedLocal2World, .0001f))
            {
                plProfile_Inc(LocationsSent);
                plProfile_BeginLap(PhysicsUpdates, GetKeyName().c_str());

                // quick peek at the translation...last time it was corrupted because we applied a non-unit quaternion
//              hsAssert(real_finite(fCachedLocal2World.fMap[0][3]) &&
//                       real_finite(fCachedLocal2World.fMap[1][3]) &&
//                       real_finite(fCachedLocal2World.fMap[2][3]), "Bad transform outgoing");

                if (fCachedLocal2World.GetTranslate().fZ < kMaxNegativeZPos)
                {
                    SimLog("Physical %s fell to %.1f (%.1f is the max).  Suppressing.", GetKeyName().c_str(), fCachedLocal2World.GetTranslate().fZ, kMaxNegativeZPos);
                    // Since this has probably been falling for a while, and thus not getting any syncs,
                    // make sure to save it's current pos so we'll know to reset it later
                    DirtySynchState(kSDLPhysical, plSynchedObject::kBCastToClients);
                    IEnable(false);
                }

                hsMatrix44 w2l;
                fCachedLocal2World.GetInverse(&w2l);
                plCorrectionMsg *pCorrMsg = new plCorrectionMsg(GetObjectKey(), fCachedLocal2World, w2l, synchTransform);
                pCorrMsg->Send();
                if (fProxyGen)
                    fProxyGen->SetTransform(fCachedLocal2World, w2l);
                plProfile_EndLap(PhysicsUpdates, GetKeyName().c_str());
            }
        }
    }
}
void plMovementStrategy::IApplyKinematic()
{
    // first apply sceneobject update to the kinematic
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    if (so)
    {
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
        {
            fCore->SetKinematicLoc(l2w);
            //fCore->SetGlobalLoc(l2w);
        }
    }
}
示例#4
0
// This form is assumed by convention to be global.
void plPXPhysical::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l, bool force)
{
//  hsAssert(real_finite(l2w.fMap[0][3]) && real_finite(l2w.fMap[1][3]) && real_finite(l2w.fMap[2][3]), "Bad transform incoming");


    // make sure the physical is dynamic.
    //  also make sure there is some difference between the matrices...
    // ... but not when a subworld... because the subworld maybe animating and if the object is still then it is actually moving within the subworld
    if (force || (fActor->isDynamic() && (fWorldKey || !CompareMatrices(l2w, fCachedLocal2World, .0001f))) )
    {
        ISetTransformGlobal(l2w);
        plProfile_Inc(SetTransforms);
    }
    else
    {
        if ( !fActor->isDynamic()  && plSimulationMgr::fExtraProfile)
            SimLog("Setting transform on non-dynamic: %s.", GetKeyName().c_str());
    }
}
void plPhysicalControllerCore::IUpdateNonPhysical(float alpha)
{
    // Update global location if owner transform hasn't changed.
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
    if (CompareMatrices(fLastGlobalLoc, l2w, 0.0001f))
    {
        if (fEnabled)
        {
            hsVector3 displacement = (hsVector3)(fLocalPosition - fLastLocalPosition);
            hsPoint3 interpLocalPos = fLastLocalPosition + (displacement * alpha);

            fLocalRotation.MakeMatrix(&fLastGlobalLoc);
            fLastGlobalLoc.SetTranslate(&interpLocalPos);
            const plCoordinateInterface* subworldCI = GetSubworldCI();
            if (subworldCI)
            {
                const hsMatrix44& subL2W = subworldCI->GetLocalToWorld();
                fLastGlobalLoc = subL2W * fLastGlobalLoc;
                fPrevSubworldW2L = subworldCI->GetWorldToLocal();
            }

            ISendCorrectionMessages();
        }
        else
        {
            // Update global location if in a subworld
            const plCoordinateInterface* subworldCI = GetSubworldCI();
            if (subworldCI)
            {
                hsMatrix44 l2s = fPrevSubworldW2L * fLastGlobalLoc;
                const hsMatrix44& subL2W = subworldCI->GetLocalToWorld();
                fLastGlobalLoc = subL2W * l2s;
                fPrevSubworldW2L = subworldCI->GetWorldToLocal();


                ISendCorrectionMessages();
            }
        }
    }
}
void plRidingAnimatedPhysicalStrategy::Apply(float delSecs)
{
    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    if (fCore->IsKinematic())
    {   
        //want to make sure nothing funky happens in the sim
        IApplyKinematic();
        return;
    }
    if (!fCore->IsEnabled())
        return;

    //need to sweep ahead to see what we might hit. 
    // if we hit anything we should probably apply the force that would normally be applied in

    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    hsPoint3 startPos, desiredDestination, endPos;
    fCore->GetPositionSim(startPos);
    uint32_t collideFlags =
    1<<plSimDefs::kGroupStatic |
    1<<plSimDefs::kGroupAvatarBlocker |
    1<<plSimDefs::kGroupDynamic;
    std::multiset<plControllerSweepRecord> GroundHitRecords;
    int possiblePlatformCount =fCore->SweepControllerPath(startPos, startPos + hsPoint3(0.f,0.f, -0.002f), true, true, collideFlags, GroundHitRecords);
    float maxPlatformVel = - FLT_MAX;
    int platformCount=0;
    fGroundHit = false;
    if(possiblePlatformCount)
    {
        
        std::multiset<plControllerSweepRecord>::iterator curRecord; 

        for(curRecord = GroundHitRecords.begin(); curRecord != GroundHitRecords.end(); curRecord++)
        {
            hsBool groundlike=false;
            if((curRecord->locHit.fZ - startPos.fZ)<= .2) groundlike= true;
            if(groundlike)
            {
                if(curRecord->ObjHit !=nil)
                {
                    hsVector3 vel;
                    curRecord->ObjHit->GetLinearVelocitySim(vel);
                    if(vel.fZ > maxPlatformVel)
                    {
                        maxPlatformVel= vel.fZ;
                    }
                }
                platformCount ++;
                fGroundHit = true;
            }
        }
    }
    
    
    
    bool gotGroundHit = fGroundHit;
    if (so)
    {
        
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }
        
        if(!IsOnGround())
        {
            if(!fNeedVelocityOverride)
            {
                LinearVelocity.fZ= AchievedLinearVelocity.fZ;
            }
            else
            {
                LinearVelocity = fOverrideVelocity;
            }
        }
        if(fStartJump)
        {
            LinearVelocity.fZ =12.0f;
        }
        if(platformCount)
        {
            LinearVelocity.fZ = LinearVelocity.fZ + maxPlatformVel;
        }

        //probably neeed to do something with contact normals in here
        //for false ground stuff
        
        fFalseGround = false;
        hsVector3 testLength = LinearVelocity * delSecs + hsVector3(0.0, 0.0, -0.00f);
    //
        hsPoint3 desiredDestination= startPos + testLength;
        if(!IsOnGround())
        {
            if(ICheckMove(startPos, desiredDestination))
            {//we can get there soley by the LinearVelocity
                
                fNeedVelocityOverride =false;
            }
            else
            {
                
                fNeedVelocityOverride =true;
                fOverrideVelocity = LinearVelocity;
                fOverrideVelocity.fZ -=  delSecs * 32.f;
            }
        }
        else
        {
            fNeedVelocityOverride =false;
        }

        fCore->SetLinearVelocity(LinearVelocity);
    
    }
}
void plSwimStrategy::Apply(float delSecs)
{
    hsAssert(fCore,"PlSwimStrategy::Apply No Core shouldn't be Applying");
    uint32_t collideFlags =
        1<<plSimDefs::kGroupStatic |
        1<<plSimDefs::kGroupAvatarBlocker |
        1<<plSimDefs::kGroupDynamic;
    if(!fCore->IsSeeking())
    {
        collideFlags|=(1<<plSimDefs::kGroupExcludeRegion);
    }

    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    if (fCore->IsKinematic())
    {
        plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
        if (so)
        {
            // If we've been moved since the last physics update (somebody warped us),
            // update the physics before we apply velocity.
            const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
            if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            {
                fCore->SetKinematicLoc(l2w);
                fCore->SetGlobalLoc(l2w);
            }
        }
        return;
        
    }
    if (!fCore->IsEnabled())
        return;
    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    fHadContacts=false;
    fOnGround=false;
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    if (so)
    {
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }
        IAdjustBuoyancy();
        float zacc;
        float retardent=0.0f;
        static float FinalBobSpeed=0.5f;
        //trying to dampen the oscillations
        if((AchievedLinearVelocity.fZ>FinalBobSpeed)||(AchievedLinearVelocity.fZ<-FinalBobSpeed))
            retardent=AchievedLinearVelocity.fZ *-.90f;
        zacc=(1-fBuoyancy)*-32.f + retardent;
        
        hsVector3 linCurrent(0.0f,0.0f,0.0f);
        float angCurrent = 0.f;
        if (fCurrentRegion != nil)
        {
        
            fCurrentRegion->GetCurrent(fCore, linCurrent, angCurrent, delSecs);
            //fAngularVelocity+= angCurrent;
        }
        hsVector3 vel(LinearVelocity.fX , LinearVelocity.fY , AchievedLinearVelocity.fZ+ LinearVelocity.fZ );
        vel.fZ= vel.fZ + zacc*delSecs;
        if(fCurrentRegion!=nil){
            if (vel.fZ > fCurrentRegion->fMaxUpwardVel)
            {
                vel.fZ = fCurrentRegion->fMaxUpwardVel;
            }
            vel+= linCurrent;
        }
        static const float kGravity = -32.f;
        if(vel.fZ<kGravity)
        {//applying this terminal velocity just to avoid shooting 100 feet below the surface
            // and losing our surface ray cast
            vel.fZ =kGravity;
        }
        hsVector3 displacement= vel*delSecs;
        unsigned int colFlags = 0;
        fContactNormals.SetCount(0);
        fCore->Move(displacement,collideFlags,colFlags);
        if((colFlags&kBottom)||(colFlags&kSides))fHadContacts=true;
        float angvel=fCore->GetAngularVelocity();
        fCore->SetAngularVelocity(angvel +angCurrent);
    }
}
///////////////////////////
//Walking Strategy
void plWalkingStrategy::Apply(float delSecs)
{
    //Apply Should Only be Called from a PhysicalControllerCore
    hsAssert(fCore,"No Core shouldn't be Applying");
    uint32_t collideFlags =
        1<<plSimDefs::kGroupStatic |
        1<<plSimDefs::kGroupAvatarBlocker |
        1<<plSimDefs::kGroupDynamic;
    if(!fCore->IsSeeking())
    {
        collideFlags|=(1<<plSimDefs::kGroupExcludeRegion);
    }
    bool OnTopOfAnimatedPhys=false;
    hsVector3 LinearVelocity=fCore->GetLinearVelocity();
    hsVector3 AchievedLinearVelocity=fCore->GetAchievedLinearVelocity();
    hsPoint3 positionBegin;
    fCore->GetPositionSim(positionBegin);
    bool recovered=false;
    if (fCore->IsKinematic())
    {
            plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
            if (so)
            {
                // If we've been moved since the last physics update (somebody warped us),
                // update the physics before we apply velocity.
                const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
                if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
                {
                    fCore->SetKinematicLoc(l2w);
                    fCore->SetGlobalLoc(l2w);
                }
            }
        return;
    }

    if (!fCore->IsEnabled())
        return;

    bool gotGroundHit = fGroundHit;
    fGroundHit = false;
    
    fCore->SetPushingPhysical(nil);
    fCore->SetFacingPushingPhysical( false);
    plSceneObject* so = plSceneObject::ConvertNoRef(fOwner->ObjectIsLoaded());
    if (so)
    {
        static const float kGravity = -32.f;
        // If we've been moved since the last physics update (somebody warped us),
        // update the physics before we apply velocity.
        const hsMatrix44& l2w = so->GetCoordinateInterface()->GetLocalToWorld();
        if (!CompareMatrices(l2w, fCore->GetLastGlobalLoc(), .0001f))
            fCore->SetGlobalLoc(l2w);

        // Convert our avatar relative velocity to subworld relative
        if (!LinearVelocity.IsEmpty())
        {
            LinearVelocity = l2w * LinearVelocity;
            const plCoordinateInterface* subworldCI = fCore->GetSubworldCI();
            if (subworldCI)
                LinearVelocity = subworldCI->GetWorldToLocal() * LinearVelocity;
        }

        // Add in gravity if the avatar's z velocity isn't being set explicitly
        // (Add in a little fudge factor, since the animations usually add a
        // tiny bit of z.)
        if (hsABS(LinearVelocity.fZ) < 0.001f)
        {
            // Get our previous z velocity.  If we're on the ground, clamp it to zero at
            // the largest, so we won't launch into the air if we're running uphill.
            float prevZVel = AchievedLinearVelocity.fZ;
            if (IsOnGround())
                prevZVel = hsMinimum(prevZVel, 0.f);
            float grav = kGravity * delSecs;
            // If our gravity contribution isn't high enough this frame, we won't
            // report a collision even when standing on solid ground.
            float maxGrav = -.001f / delSecs;
            if (grav > maxGrav)
                grav = maxGrav;
            LinearVelocity.fZ = prevZVel + grav;
        }

        // If we're airborne and the velocity isn't set, use the velocity from
        // the last frame so we maintain momentum.
        if (!IsOnGround() && LinearVelocity.fX == 0.f && LinearVelocity.fY == 0.f)
        {
            LinearVelocity.fX = AchievedLinearVelocity.fX;
            LinearVelocity.fY = AchievedLinearVelocity.fY;
        }

        //make terminal velocity equal to k. it is wrong but has been this way and
        //don't want to break any puzzles. on top of that it will reduce tunneling behavior
        if(LinearVelocity.fZ<kGravity)LinearVelocity.fZ=kGravity;
        
        

        
        fCore->SetLinearVelocity(LinearVelocity);
        // Scale the velocity to our actual step size (by default it's feet/sec)
        hsVector3 vel(LinearVelocity.fX * delSecs, LinearVelocity.fY * delSecs, LinearVelocity.fZ * delSecs);
        unsigned int colFlags = 0;
        fGroundHit = false;
        fFalseGround = false;
        fContactNormals.Swap(fPrevSlidingNormals);
        fContactNormals.SetCount(0);
        fCore->Move(vel, collideFlags,  colFlags);
        ICheckForFalseGround();
        //if(fReqMove2) fCore->Move2(vel);
        /*If the Physx controller  thinks we have a collision from below, need to make sure we
        have at least have false ground, otherwise Autostepping can send us into the air, and we will some times 
        float/panic link. For some reason the NxControllerHitReport does not always send messages
        regarding Controller contact with ground plane, but will (almost) always return NXCC_COLLISION_DOWN
        with the move method.
        */
        if((colFlags&kBottom ) &&(fGroundHit==false))
        {
            fFalseGround=true;
        }
        
        if(colFlags&kTop)
        {
            fHitHead=true;
            //Did you hit your head on a dynamic?
            //with Physx's wonderful controller hit report vs flags issues we need to actually sweep to see
            std::multiset< plControllerSweepRecord > HitsDynamic;
            uint32_t testFlag=1<<plSimDefs::kGroupDynamic;
            hsPoint3 startPos;
            hsPoint3 endPos;
            fCore->GetPositionSim(startPos);
            endPos= startPos + vel;
            int NumObjsHit=fCore->SweepControllerPath(startPos, endPos, true, false, testFlag, HitsDynamic);
            if(NumObjsHit>0)
            {
                for(std::multiset< plControllerSweepRecord >::iterator curObj= HitsDynamic.begin();
                    curObj!=HitsDynamic.end(); curObj++)
                {

                    hsAssert(curObj->ObjHit,"We allegedly hit something, but there is no plasma physical associated with it");
                    if(curObj->ObjHit)
                    {//really we shouldn't have to check hitObj should be nil only if we miss, or the physX object
                        //doesn't have a user data associated with this either way this just shouldn't happen
                        hsVector3 hitObjVel;
                        curObj->ObjHit->GetLinearVelocitySim(hitObjVel);
                        hsVector3 relativevel=LinearVelocity-hitObjVel;
                        curObj->ObjHit->SetHitForce(relativevel * 10.0f * (*curObj).ObjHit->GetMass(), (*curObj).locHit);
                    }
                }
                HitsDynamic.clear();
            }
        }
    }
}
示例#9
0
文件: house.c 项目: Aretnorp/cs-2010f
/*-----------------------------------------------------------------------------
 *  Draw
 *  The Draw function is the main loop for the Graphics process. Draws each
 *  viewport and the lines within them
 *-----------------------------------------------------------------------------*/
void Draw( void )
{
    char buf[BUF_SIZ];
    GLdouble answer[MATRIX_SIZE];
    GLdouble attempt[MATRIX_SIZE];

    /* Clear the screen ... */
    glClear( GL_COLOR_BUFFER_BIT );

    if(gameComplete)
    {
        DrawText(-25.0, -25.0, DEFAULT_FONT, "GAME OVER! YOU WIN!");
    }
    else if(levelComplete)
    {
        DrawText(-25.0, -25.0, DEFAULT_FONT, "LEVEL COMPLETE!");
    }
    else
    {
        glPushMatrix( );
            /* Draw the Outlines for Transforms */
            glCallList('a');
            glCallList('s');

            /* Draw the Axes */
            glBegin( GL_LINES );
                glColor3f( 0.5, 0.5, 0.5 );
                glVertex3f( 100.0, 0.0, 0.0 );
                glVertex3f(-100.0, 0.0, 0.0 );
                glVertex3f( 0.0, 100.0, 0.0 );
                glVertex3f( 0.0,-100.0, 0.0 );
                glColor3f( 1.0, 1.0, 1.0 );
            glEnd( );
        glPopMatrix( );

        /* Draw the first set of Available Transforms */
        glPushMatrix( );
            /* Move to origin of first list */
            glTranslatef( 115.0, 90.0, 0.0 );

            /* List drawing */
            CreateTransforms( &tlAvailableTransforms, VERTICAL, AVAILABLE );
        glPopMatrix( );

        /* Draw the second set of Used Transforms */
        glPushMatrix( );
            /* Move to origin of first list */
            glTranslatef( -85.0, -120.0, 0.0 );

            /* List drawing */
            CreateTransforms( &tlSelectedTransforms, HORIZONTAL, SELECTED );
        glPopMatrix( );

        glPushMatrix( );
            /* Do all level transforms */
            RunTransformList( &tlLevel );

            /* Create model house */
            glLoadName( 1 );
            glCallList( 'l' );

            /* Get the modelview matrix */
            glGetDoublev( GL_MODELVIEW_MATRIX, answer );
        glPopMatrix( );

        /* Create the new house */
        glPushMatrix(  );
            /* Do all user selected transforms */
            RunTransformList( &tlSelectedTransforms );

            /* Create attempt house */
            glLoadName( HOUSE );
            glCallList( 'h' );

            /* Get the modelview matrix */
            glGetDoublev( GL_MODELVIEW_MATRIX, attempt );
        glPopMatrix( );

        /* Compare the model */
        if(CompareMatrices(answer, attempt))
        {
            levelComplete = TRUE;
            glutPostRedisplay( );
        }
    }

    /* Flush the buffer */
    glutSwapBuffers();

    return;
}