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); }
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); }
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); }