void plCoordinateInterface::ITransformChanged(hsBool force, uint16_t reasons, hsBool checkForDelay)
{
    plProfile_IncCount(CITrans, 1);
    plProfile_BeginTiming(CITransT);

    // inherit reasons for transform change from our parents
    fReason |= reasons;
    
    uint16_t propagateReasons = fReason;

    hsBool process = !(checkForDelay && GetProperty(kDelayedTransformEval)) || !fDelayedTransformsEnabled;

    if (process)
    {
        if( fState & kTransformDirty )
            force = true;
    }

    if( force )
    {
        IRecalcTransforms();

        plProfile_IncCount(CISet, 1);
        plProfile_BeginTiming(CISetT);
        if( IGetOwner() )
        {
            IGetOwner()->ISetTransform(fLocalToWorld, fWorldToLocal);
        }
        plProfile_EndTiming(CISetT);
        fState &= ~kTransformDirty;     
    }

    plProfile_EndTiming(CITransT);
    if (process)
    {
        int i;
        for( i = 0; i < fChildren.GetCount(); i++ )
        {
            if( fChildren[i] && fChildren[i]->GetVolatileCoordinateInterface() )
                fChildren[i]->GetVolatileCoordinateInterface()->ITransformChanged(force, propagateReasons, checkForDelay);
        }
    }
    else if (force)
    {
        plProfile_IncCount(CIDirty, 1);
        plProfile_BeginTiming(CITransT);
        // Our parent is dirty and we're bailing out on evaluating right now.
        // Need to ensure we'll be evaluated in the delay pass
        plProfile_BeginTiming(CIDirtyT);
        IDirtyTransform();
        plProfile_EndTiming(CIDirtyT);
        plProfile_EndTiming(CITransT);
    }       
}
void plCoordinateInterface::IRecalcTransforms()
{
    plProfile_IncCount(CIRecalc, 1);
    plProfile_BeginTiming(CIRecalcT);
    if( fParent )
    {
        fLocalToWorld = IMatrixMul34(fParent->GetLocalToWorld(), fLocalToParent);
        fWorldToLocal = IMatrixMul34(fParentToLocal, fParent->GetWorldToLocal());
    }
    else
    {
        fLocalToWorld = fLocalToParent;
        fWorldToLocal = fParentToLocal;
    }
    plProfile_EndTiming(CIRecalcT);
}
void plSimulationMgr::Advance(float delSecs)
{
    if (fSuspended)
        return;

    plProfile_IncCount(StepLen, (int)(delSecs*1000));

#ifndef PLASMA_EXTERNAL_RELASE
    uint32_t stepTime = hsTimer::GetPrecTickCount();
#endif
    plProfile_BeginTiming(Step);
    plPXPhysicalControllerCore::UpdatePrestep(delSecs);
    plPXPhysicalControllerCore::UpdatePoststep( delSecs);
    
    for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
    {
        NxScene* scene = it->second;
        bool do_advance = true;
        if (fSubworldOptimization)
        {
            plKey world = (plKey)it->first;
            if (world == GetKey())
                world = nil;
            do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
        }
        if (do_advance)
        {
            scene->simulate(delSecs);
            scene->flushStream();
            scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
        }
    }
    plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);

    plProfile_EndTiming(Step);
#ifndef PLASMA_EXTERNAL_RELEASE
    if(plSimulationMgr::fDisplayAwakeActors)IDrawActiveActorList();
#endif 
    if (fExtraProfile)
    {
        int contacts = 0, dynActors = 0, dynShapes = 0, awake = 0, stShapes=0, actors=0, scenes=0, controllers=0 ;
        for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
        {
            bool do_advance = true;
            if (fSubworldOptimization)
            {
                plKey world = (plKey)it->first;
                if (world == GetKey())
                    world = nil;
                do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
            }
            if (do_advance)
            {
                NxScene* scene = it->second;
                NxSceneStats stats;
                scene->getStats(stats);

                contacts += stats.numContacts;
                dynActors += stats.numDynamicActors;
                dynShapes += stats.numDynamicShapes;
                awake += stats.numDynamicActorsInAwakeGroups;
                stShapes += stats.numStaticShapes;
                actors += stats.numActors;
                scenes += 1;
                controllers += plPXPhysicalControllerCore::NumControllers();
            }
        }

        plProfile_IncCount(Awake, awake);
        plProfile_IncCount(Contacts, contacts);
        plProfile_IncCount(DynActors, dynActors);
        plProfile_IncCount(DynShapes, dynShapes);
        plProfile_IncCount(StaticShapes, stShapes);
        plProfile_IncCount(Actors, actors);
        plProfile_IncCount(Scenes, scenes);
        plProfile_IncCount(Controllers, controllers);
    }

    plProfile_IncCount(AnimatedPhysicals, plPXPhysical::fNumberAnimatedPhysicals);
    plProfile_IncCount(AnimatedActivators, plPXPhysical::fNumberAnimatedActivators);

    fSoundMgr->Update();

    plProfile_BeginTiming(ProcessSyncs);
    IProcessSynchs();
    plProfile_EndTiming(ProcessSyncs);

    plProfile_BeginTiming(UpdateContexts);
    ISendUpdates();
    plProfile_EndTiming(UpdateContexts);
}
Beispiel #4
0
void pl3DPipeline::BeginVisMgr(plVisMgr* visMgr)
{
    // Make Light Lists /////////////////////////////////////////////////////
    // Look through all the current lights, and fill out two lists.
    // Only active lights (not disabled, not exactly black, and not
    // ignored because of visibility regions by plVisMgr) will
    // be considered.
    // The first list is lights that will affect the avatar and similar
    // indeterminately mobile (physical) objects - fCharLights.
    // The second list is lights that aren't restricted by light include
    // lists.
    // These two abbreviated lists will be further refined for each object
    // and avatar to find the strongest 8 lights which affect that object.
    // A light with an include list, or LightGroup Component) has
    // been explicitly told which objects it affects, so they don't
    // need to be in the search lists.
    // These lists are only constructed once per render, but searched
    // multiple times

    plProfile_BeginTiming(FindSceneLights);
    fCharLights.SetCount(0);
    fVisLights.SetCount(0);
    if (visMgr)
    {
        const hsBitVector& visSet = visMgr->GetVisSet();
        const hsBitVector& visNot = visMgr->GetVisNot();
        plLightInfo* light;

        for (light = fActiveLights; light != nullptr; light = light->GetNext())
        {
            plProfile_IncCount(LightActive, 1);
            if (!light->IsIdle() && !light->InVisNot(visNot) && light->InVisSet(visSet))
            {
                plProfile_IncCount(LightOn, 1);
                if (light->GetProperty(plLightInfo::kLPHasIncludes))
                {
                    if (light->GetProperty(plLightInfo::kLPIncludesChars))
                        fCharLights.Append(light);
                }
                else
                {
                    fVisLights.Append(light);
                    fCharLights.Append(light);
                }
            }
        }
    }
    else
    {
        plLightInfo* light;
        for (light = fActiveLights; light != nullptr; light = light->GetNext())
        {
            plProfile_IncCount(LightActive, 1);
            if (!light->IsIdle())
            {
                plProfile_IncCount(LightOn, 1);
                if (light->GetProperty(plLightInfo::kLPHasIncludes))
                {
                    if (light->GetProperty(plLightInfo::kLPIncludesChars))
                        fCharLights.Append(light);
                }
                else
                {
                    fVisLights.Append(light);
                    fCharLights.Append(light);
                }
            }
        }
    }
    plProfile_IncCount(LightVis, fVisLights.GetCount());
    plProfile_IncCount(LightChar, fCharLights.GetCount());

    plProfile_EndTiming(FindSceneLights);
}
// Cycle through the Cull Nodes, paring down the list of who to test (through ITestNode above).
// We reclaim the scratch indices in clear and split when we're done (SetCount(0)), but we can't
// reclaim the culled, because our caller may be looking at who all we culled. See below in split.
// If a node is disabled, we can just ignore we ever got called.
void plCullNode::ITestNode(const plSpaceTree* space, int16_t who, hsBitVector& totList, hsBitVector& outList) const
{
    if( space->IsDisabled(who) )
        return;

    uint32_t myClearStart = ScratchClear().GetCount();
    uint32_t mySplitStart = ScratchSplit().GetCount();
    uint32_t myCullStart = ScratchCulled().GetCount();

    if( kPureSplit == ITestNode(space, who, ScratchClear(), ScratchSplit(), ScratchCulled()) )
        ScratchSplit().Append(who);

    uint32_t myClearEnd = ScratchClear().GetCount();
    uint32_t mySplitEnd = ScratchSplit().GetCount();
    uint32_t myCullEnd = ScratchCulled().GetCount();

    int i;
    // If there's no OuterChild, everything in clear and split is visible. Everything in culled
    // goes to innerchild (if any).
    if( fOuterChild < 0 )
    {
        plProfile_IncCount(HarvestNodes, myClearEnd - myClearStart + mySplitEnd - mySplitStart);
        // Replace these with a memcopy or something!!!!
        for( i = myClearStart; i < myClearEnd; i++ )
        {
            space->HarvestLeaves(ScratchClear()[i], totList, outList);
        }
        for( i = mySplitStart; i < mySplitEnd; i++ )
        {
            space->HarvestLeaves(ScratchSplit()[i], totList, outList);
        }

        if( fInnerChild >= 0 )
        {
            for( i = myCullStart; i < myCullEnd; i++ )
            {
                IGetNode(fInnerChild)->ITestNode(space, ScratchCulled()[i], totList, outList);
            }
        }
        ScratchClear().SetCount(myClearStart);
        ScratchSplit().SetCount(mySplitStart);
        ScratchCulled().SetCount(myCullStart);

        return;
    }

    // There is an OuterChild, so whether there's an InnerChild or not,
    // everything in ClearList is visible soley on the discretion of OuterChild.
    for( i = myClearStart; i < myClearEnd; i++ )
    {
        IGetNode(fOuterChild)->ITestNode(space, ScratchClear()[i], totList, outList);
    }

    // If there's no InnerChild, then the SplitList is also visible soley
    // on the discretion of OuterChild.
    if( fInnerChild < 0 )
    {
        for( i = mySplitStart; i < mySplitEnd; i++ )
        {
            IGetNode(fOuterChild)->ITestNode(space, ScratchSplit()[i], totList, outList);
        }

        ScratchClear().SetCount(myClearStart);
        ScratchSplit().SetCount(mySplitStart);
        ScratchCulled().SetCount(myCullStart);

        return;
    }

    // There is an inner child. Everything in culled list is visible
    // soley on its discretion.
    for( i = myCullStart; i < myCullEnd; i++ )
    {
        IGetNode(fInnerChild)->ITestNode(space, ScratchCulled()[i], totList, outList);
    }

    // Okay, here's the rub.
    // Everyone in the split list needs to be tested against InnerChild and OuterChild.
    // If either child says it's okay (puts it in OutList), then it's okay.
    // The problem is that if both children say it's okay, it will wind up in outList twice.
    // This is complicated by the fact that outList is still subTrees at this point,
    // so InnerChild adding a subTree and OuterChild adding a child of that subTree isn't
    // even appending the same value to the list.
    // Sooooo.
    // What we do is keep track of every node (interior and leaf) that gets harvested.
    // When we go to harvest a subtree, we check in totList for its bit being set. Bits
    // set in totList are ENTIRE SUBTREE IS HARVESTED. SpaceTree understands this too in
    // its HarvestLeaves. Seems obvious now, but I didn't hear you suggest it.

    for( i = mySplitStart; i < mySplitEnd; i++ )
    {
        IGetNode(fOuterChild)->ITestNode(space, ScratchSplit()[i], totList, outList);
    }

    for( i = mySplitStart; i < mySplitEnd; i++ )
    {
        if( !totList.IsBitSet(ScratchSplit()[i]) )
            IGetNode(fInnerChild)->ITestNode(space, ScratchSplit()[i], totList, outList);
    }

    ScratchClear().SetCount(myClearStart);
    ScratchSplit().SetCount(mySplitStart);
    ScratchCulled().SetCount(myCullStart);
}
Beispiel #6
0
void plSimulationMgr::Advance(float delSecs)
{
    if (fSuspended)
        return;

    fAccumulator += delSecs;
    if (fAccumulator < kDefaultStepSize)
    {
        // Not enough time has passed to perform a substep.
        plPXPhysicalControllerCore::UpdateNonPhysical(fAccumulator / kDefaultStepSize);
        return;
    }
    else if (fAccumulator > kDefaultMaxDelta)
    {
        if (fExtraProfile)
            Log("Step clamped from %f to limit of %f", fAccumulator, kDefaultMaxDelta);
        fAccumulator = kDefaultMaxDelta;
    }

    ++fStepCount;

    // Perform as many whole substeps as possible saving the remainder in our accumulator.
    int numSubSteps = (int)(fAccumulator / kDefaultStepSize + 0.000001f);
    float delta = numSubSteps * kDefaultStepSize;
    fAccumulator -= delta;

    plProfile_IncCount(StepLen, (int)(delta*1000));
    plProfile_BeginTiming(Step);

    plPXPhysicalControllerCore::Apply(delta);
    
    for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
    {
        NxScene* scene = it->second;
        bool do_advance = true;
        if (fSubworldOptimization)
        {
            plKey world = (plKey)it->first;
            if (world == GetKey())
                world = nil;
            do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
        }
        if (do_advance)
        {
            scene->simulate(delta);
            scene->flushStream();
            scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
        }
    }

    plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / kDefaultStepSize);

    plProfile_EndTiming(Step);
#ifndef PLASMA_EXTERNAL_RELEASE
    if(plSimulationMgr::fDisplayAwakeActors)IDrawActiveActorList();
#endif 
    if (fExtraProfile)
    {
        int contacts = 0, dynActors = 0, dynShapes = 0, awake = 0, stShapes=0, actors=0, scenes=0, controllers=0 ;
        for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
        {
            bool do_advance = true;
            if (fSubworldOptimization)
            {
                plKey world = (plKey)it->first;
                if (world == GetKey())
                    world = nil;
                do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
            }
            if (do_advance)
            {
                NxScene* scene = it->second;
                NxSceneStats stats;
                scene->getStats(stats);

                contacts += stats.numContacts;
                dynActors += stats.numDynamicActors;
                dynShapes += stats.numDynamicShapes;
                awake += stats.numDynamicActorsInAwakeGroups;
                stShapes += stats.numStaticShapes;
                actors += stats.numActors;
                scenes += 1;
                controllers += plPXPhysicalControllerCore::NumControllers();
            }
        }

        plProfile_IncCount(Awake, awake);
        plProfile_IncCount(Contacts, contacts);
        plProfile_IncCount(DynActors, dynActors);
        plProfile_IncCount(DynShapes, dynShapes);
        plProfile_IncCount(StaticShapes, stShapes);
        plProfile_IncCount(Actors, actors);
        plProfile_IncCount(Scenes, scenes);
        plProfile_IncCount(Controllers, controllers);
    }

    plProfile_IncCount(AnimatedPhysicals, plPXPhysical::fNumberAnimatedPhysicals);
    plProfile_IncCount(AnimatedActivators, plPXPhysical::fNumberAnimatedActivators);

    fSoundMgr->Update();

    plProfile_BeginTiming(ProcessSyncs);
    IProcessSynchs();
    plProfile_EndTiming(ProcessSyncs);

    plProfile_BeginTiming(UpdateContexts);
    ISendUpdates();
    plProfile_EndTiming(UpdateContexts);
}