void ETHBucketManager::RequestBucketMove(ETHEntity* target, const Vector2& oldPos, const Vector2& newPos) { ETHBucketMoveRequest request(target, oldPos, newPos, GetBucketSize()); if (request.IsABucketMove()) { m_moveRequests.push_back(request); } }
bool ETHScene::DrawBucketOutlines() { const VideoPtr& video = m_provider->GetVideo(); // Gets the list of visible buckets std::list<Vector2> bucketList; ETHBucketManager::GetIntersectingBuckets(bucketList, m_provider->GetVideo()->GetCameraPos(), video->GetScreenSizeF(), GetBucketSize(), IsDrawingBorderBuckets(), IsDrawingBorderBuckets()); int nVisibleBuckets = 0; // Loop through all visible Buckets for (std::list<Vector2>::iterator bucketPositionIter = bucketList.begin(); bucketPositionIter != bucketList.end(); ++bucketPositionIter) { nVisibleBuckets++; const float width = video->GetLineWidth(); video->SetLineWidth(2.0f); const Vector2 v2BucketPos = *bucketPositionIter * GetBucketSize() - video->GetCameraPos(); video->DrawLine(v2BucketPos, v2BucketPos + Vector2(GetBucketSize().x, 0.0f), gs2d::constant::WHITE, gs2d::constant::WHITE); video->DrawLine(v2BucketPos, v2BucketPos + Vector2(0.0f, GetBucketSize().y), gs2d::constant::WHITE, gs2d::constant::WHITE); video->DrawLine(v2BucketPos + GetBucketSize(), v2BucketPos + Vector2(0.0f, GetBucketSize().y), gs2d::constant::WHITE, gs2d::constant::WHITE); video->DrawLine(v2BucketPos + GetBucketSize(), v2BucketPos + Vector2(GetBucketSize().x, 0.0f), gs2d::constant::WHITE, gs2d::constant::WHITE); video->SetLineWidth(width); // draw bucket key str_type::stringstream ss; if (m_buckets.Find(*bucketPositionIter) != m_buckets.GetLastBucket()) { ss << GS_L("(") << bucketPositionIter->x << GS_L(",") << bucketPositionIter->y << GS_L(")") << GS_L(" - entities: ") << m_buckets.GetNumEntities(*bucketPositionIter); } else { ss << GS_L("(") << bucketPositionIter->x << GS_L(",") << bucketPositionIter->y << GS_L(")"); } const Vector2 v2TextPos(*bucketPositionIter * GetBucketSize() - video->GetCameraPos()); video->DrawBitmapText(v2TextPos, ss.str(), ETH_DEFAULT_BITMAP_FONT, gs2d::constant::WHITE); } str_type::stringstream ss; ss << GS_L("Visible buckets: ") << nVisibleBuckets; video->DrawBitmapText(video->GetScreenSizeF()/2, ss.str(), ETH_DEFAULT_BITMAP_FONT, gs2d::constant::WHITE); return true; }
void ETHBucketManager::Add(ETHRenderEntity* entity, const SIDE side) { const Vector2 bucket = ETHBucketManager::GetBucket(entity->GetPositionXY(), GetBucketSize()); if (side == FRONT) { m_entities[bucket].push_front(entity); } else { m_entities[bucket].push_back(entity); } #if defined(_DEBUG) || defined(DEBUG) ETH_STREAM_DECL(ss) << GS_L("Entity ") << entity->GetEntityName() << GS_L(" (ID#") << entity->GetID() << GS_L(") added to bucket ") << GS_L("(") << bucket.x << GS_L(", ") << bucket.y << GS_L(")"); m_provider->Log(ss.str(), Platform::Logger::INFO); #endif }
bool ETHScene::DeleteEntity(ETHEntity *pEntity) { return m_buckets.DeleteEntity(pEntity->GetID(), ETHBucketManager::GetBucket(pEntity->GetPositionXY(), GetBucketSize())); }
void ETHScene::MapEntitiesToBeRendered( float &minHeight, float &maxHeight, const ETHBackBufferTargetManagerPtr& backBuffer) { // store the max and min height to assign when everything is drawn maxHeight = m_maxSceneHeight; minHeight = m_minSceneHeight; m_nRenderedEntities = 0; const VideoPtr& video = m_provider->GetVideo(); // don't let bucket size equal to 0 assert(GetBucketSize().x != 0 || GetBucketSize().y != 0); // Gets the list of visible buckets std::list<Vector2> bucketList; const Vector2& camPos = video->GetCameraPos(); //for debugging purposes m_buckets.GetIntersectingBuckets(bucketList, camPos, backBuffer->GetBufferSize(), IsDrawingBorderBuckets(), IsDrawingBorderBuckets()); assert(m_activeEntityHandler.IsCallbackListEmpty()); // Loop through all visible Buckets for (std::list<Vector2>::iterator bucketPositionIter = bucketList.begin(); bucketPositionIter != bucketList.end(); ++bucketPositionIter) { ETHBucketMap::iterator bucketIter = m_buckets.Find(*bucketPositionIter); if (bucketIter == m_buckets.GetLastBucket()) continue; ETHEntityList& entityList = bucketIter->second; if (entityList.empty()) continue; ETHEntityList::const_iterator iEnd = entityList.end(); for (ETHEntityList::iterator iter = entityList.begin(); iter != iEnd; ++iter) { ETHRenderEntity *entity = (*iter); // update scene bounding for depth buffer maxHeight = Max(maxHeight, entity->GetMaxHeight()); minHeight = Min(minHeight, entity->GetMinHeight()); if (entity->IsHidden()) continue; // fill the callback list m_activeEntityHandler.AddStaticCallbackWhenEligible(entity); m_renderingManager.AddDecomposedPieces(entity, minHeight, maxHeight, backBuffer, m_sceneProps); m_nRenderedEntities++; } } // Add persistent entities (the ones the user wants to force to render) FillMultimapAndClearPersistenList(bucketList, backBuffer); m_nCurrentLights = m_renderingManager.GetNumLights(); }
bool ETHScene::GenerateLightmaps(const int id) { if (!m_provider->IsRichLightingEnabled()) { return false; } // save current global scale and temporarily set it to 1 const ETHGlobalScaleManagerPtr& scaleManager = m_provider->GetGlobalScaleManager(); const float globalScale = scaleManager->GetScale(); scaleManager->SetScaleFactor(1.0f); const ETHSpriteEntity *pRender = (id >= 0) ? m_buckets.SeekEntity(id) : 0; const Vector2 v2Bucket = (pRender) ? ETHBucketManager::GetBucket(pRender->GetPositionXY(), GetBucketSize()) : Vector2(0,0); for (ETHBucketMap::iterator bucketIter = m_buckets.GetFirstBucket(); bucketIter != m_buckets.GetLastBucket(); ++bucketIter) { // if we're lighting only one entity and it is not in this bucket, skip it. // I know we could have used the find method to go directly to that bucket // but this function os not that critical to make the effort worth it. if (id >= 0) if (v2Bucket != bucketIter->first) continue; // iterate over all entities in this bucket ETHEntityList& entityList = bucketIter->second; ETHEntityList::const_iterator iEnd = entityList.end(); for (ETHEntityList::iterator iter = entityList.begin(); iter != iEnd; ++iter) { ETHRenderEntity* entity = (*iter); // if nID is valid, let's try to generate the lightmap for this one and only entity if (id >= 0) if (id != entity->GetID()) continue; Vector2 v2Size(1,1); Vector2 v2AbsoluteOrigin(0,0); if (entity->GetSprite()) { v2Size = entity->GetCurrentSize(); v2AbsoluteOrigin = entity->ComputeAbsoluteOrigin(v2Size); } // Place the current entity at the top-left corner to align // it to the render target const Vector3 oldPos = entity->GetPosition(); const Vector3 newPos = Vector3(v2AbsoluteOrigin.x, v2AbsoluteOrigin.y, 0); std::list<ETHLight> lights; // fill the light list for (ETHBucketMap::iterator lbucketIter = m_buckets.GetFirstBucket(); lbucketIter != m_buckets.GetLastBucket(); ++lbucketIter) { ETHEntityList& lEntityList = lbucketIter->second; ETHEntityList::const_iterator liEnd = lEntityList.end(); for (ETHEntityList::iterator liter = lEntityList.begin(); liter != liEnd; ++liter) { ETHRenderEntity* lightEntity = (*liter); if (lightEntity->IsStatic() && lightEntity->HasLightSource()) { lights.push_back( ETHEntityRenderingManager::BuildChildLight( *(lightEntity->GetLight()), newPos - oldPos + lightEntity->GetPosition(), lightEntity->GetScale())); } } } if (lights.size() > 0) { ETHLightmapGen((*iter), m_provider->GetShaderManager(), lights.begin(), lights.end(), m_buckets, oldPos, newPos, m_minSceneHeight, m_maxSceneHeight, m_sceneProps); } else { entity->ReleaseLightmap(); } entity->SetOrphanPosition(oldPos); lights.clear(); } } #if defined(_DEBUG) || defined(DEBUG) ETH_STREAM_DECL(ss) << GS_L("Lightmaps created... "); m_provider->Log(ss.str(), Platform::FileLogger::INFO); #endif // go back to the previous global scale scaleManager->SetScaleFactor(globalScale); return true; }
void CRateLimiter::OnTimer(fz::timer_id) { fz::scoped_lock lock(sync_); int64_t const limits[2] = { GetLimit(inbound), GetLimit(outbound) }; for (int i = 0; i < 2; ++i) { m_tokenDebt[i] = 0; if (m_objectList.empty()) continue; if (limits[i] == 0) { for (auto iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) { (*iter)->m_bytesAvailable[i] = -1; if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } continue; } int64_t tokens = (limits[i] * tickDelay) / 1000; int64_t maxTokens = tokens * GetBucketSize(); // Get amount of tokens for each object int64_t tokensPerObject = tokens / m_objectList.size(); if (tokensPerObject == 0) tokensPerObject = 1; tokens = 0; // This list will hold all objects which didn't reach maxTokens std::list<CRateLimiterObject*> unsaturatedObjects; for (auto iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) { if ((*iter)->m_bytesAvailable[i] == -1) { assert(!(*iter)->m_waiting[i]); (*iter)->m_bytesAvailable[i] = tokensPerObject; unsaturatedObjects.push_back(*iter); } else { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } } // If there are any left-over tokens (in case of objects with a rate below the limit) // assign to the unsaturated sources while (tokens != 0 && !unsaturatedObjects.empty()) { tokensPerObject = tokens / unsaturatedObjects.size(); if (tokensPerObject == 0) break; tokens = 0; std::list<CRateLimiterObject*> objects; objects.swap(unsaturatedObjects); for (auto iter = objects.begin(); iter != objects.end(); ++iter) { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); } } } WakeupWaitingObjects(lock); if (m_objectList.empty() || (limits[inbound] == 0 && limits[outbound] == 0)) { if (m_timer) { stop_timer(m_timer); m_timer = 0; } } }
void CRateLimiter::OnTimer(wxTimerEvent& event) { std::list<CRateLimiterObject*> objectsToUnwait; for (int i = 0; i < 2; i++) { m_tokenDebt[i] = 0; if (!m_objectList.size()) continue; int limit = m_pOptions->GetOptionVal(OPTION_SPEEDLIMIT_INBOUND + i) * 1024; if (!limit) { for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); iter++) { (*iter)->m_bytesAvailable[i] = -1; if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } continue; } int tokens = limit * tickDelay / 1000; if (!tokens) tokens = 1; int maxTokens = tokens * GetBucketSize(); // Get amount of tokens for each object int tokensPerObject = tokens / m_objectList.size(); if (!tokensPerObject) tokensPerObject = 1; tokens = 0; // This list will hold all objects which didn't reach maxTokens std::list<CRateLimiterObject*> unsaturatedObjects; for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); iter++) { if ((*iter)->m_bytesAvailable[i] == -1) { wxASSERT(!(*iter)->m_waiting[i]); (*iter)->m_bytesAvailable[i] = tokensPerObject; unsaturatedObjects.push_back(*iter); } else { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } } // If there are any left-over tokens (in case of objects with a rate below the limit) // assign to the unsaturated sources while (tokens && !unsaturatedObjects.empty()) { tokensPerObject = tokens / unsaturatedObjects.size(); if (!tokensPerObject) break; tokens = 0; std::list<CRateLimiterObject*> objects; objects.swap(unsaturatedObjects); for (std::list<CRateLimiterObject*>::iterator iter = objects.begin(); iter != objects.end(); iter++) { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); } } } WakeupWaitingObjects(); if (m_objectList.empty()) m_timer.Stop(); }
void ETHBucketManager::GetIntersectingBuckets(std::list<Vector2>& bucketList, const Vector2& pos, const Vector2& size, const bool upperSeams, const bool lowerSeams) { ETHBucketManager::GetIntersectingBuckets(bucketList, pos, size, GetBucketSize(), upperSeams, lowerSeams); }
// TODO-TO-DO: this method is too large... int ETHBucketManager::SeekEntity(const Vector2& pointAbsPos, ETHEntity** pOutData, const ETHSceneProperties& props, ETHSpriteEntity* pAfterThisOne) { int closestFromBehindID =-1; ETHSpriteEntity *pClosestFromBehind = 0; //int currentID =-1; //ETHSpriteEntity *pCurrent = 0; const Vector2 relativePos(pointAbsPos - m_provider->GetVideo()->GetCameraPos()); int closestFromTheFrontID =-1; ETHSpriteEntity *pClosestFromTheFront = 0; if (pAfterThisOne) { if (!pAfterThisOne->IsPointOnSprite(props, relativePos, pAfterThisOne->GetCurrentSize())) { pAfterThisOne = 0; } } if (IsEmpty()) { return -1; } std::list<Vector2> buckets; ETHBucketManager::GetIntersectingBuckets(buckets, pointAbsPos, Vector2(1,1), GetBucketSize(), true, true); // seeks the closest intersecting entity from behind for (std::list<Vector2>::const_reverse_iterator sceneBucketIter = buckets.rbegin(); sceneBucketIter != buckets.rend(); ++sceneBucketIter) { ETHBucketMap::iterator bucketIter = Find(*sceneBucketIter); if (bucketIter == GetLastBucket()) continue; ETHEntityList& entityList = bucketIter->second; ETHEntityList::const_reverse_iterator iEnd = entityList.rend(); bool escape = false; for (ETHEntityList::reverse_iterator iter = entityList.rbegin(); iter != iEnd; ++iter) { ETHSpriteEntity *pRenderEntity = (*iter); if (pRenderEntity->IsPointOnSprite(props, relativePos, pRenderEntity->GetCurrentSize())) { if (!pAfterThisOne) { if (pOutData) *pOutData = (*iter); return (*iter)->GetID(); } else { if (pRenderEntity->GetID() == pAfterThisOne->GetID()) { escape = true; break; } } pClosestFromBehind = const_cast<ETHRenderEntity*>(*iter); closestFromBehindID = pClosestFromBehind->GetID(); } } if (escape) break; } // seeks the first intersecting entity from the front for (std::list<Vector2>::const_iterator sceneBucketIter = buckets.begin(); sceneBucketIter != buckets.end(); ++sceneBucketIter) { ETHBucketMap::iterator bucketIter = Find(*sceneBucketIter); if (bucketIter == GetLastBucket()) continue; ETHEntityList::iterator iter; ETHEntityList& entityList = bucketIter->second; ETHEntityList::const_iterator iEnd = entityList.end(); bool escape = false; for (iter = entityList.begin(); iter != iEnd; ++iter) { ETHSpriteEntity *pRenderEntity = (*iter); if (pRenderEntity->IsPointOnSprite(props, relativePos, pRenderEntity->GetCurrentSize())) { pClosestFromTheFront = const_cast<ETHRenderEntity*>(*iter); closestFromTheFrontID = pClosestFromTheFront->GetID(); escape = true; break; } } if (escape) break; } if (closestFromBehindID >= 0) { if (pOutData && pClosestFromBehind) *pOutData = pClosestFromBehind; return closestFromBehindID; } if (pOutData && pClosestFromTheFront) *pOutData = pClosestFromTheFront; return closestFromTheFrontID; }
// TODO-TO-DO: this method is too large... bool ETHScene::RenderList(float &minHeight, float &maxHeight, SpritePtr pOutline, SpritePtr pInvisibleEntSymbol, std::list<ETHRenderEntity*> &outParticles, std::list<ETHRenderEntity*> &outHalos, const bool roundUp) { // This multimap will store all entities contained in the visible buckets // It will automatically sort entities to draw them in an "alpha friendly" order std::multimap<float, ETHRenderEntity*> mmEntities; // store the max and min height to assign when everything is drawn maxHeight = m_maxSceneHeight; minHeight = m_minSceneHeight; m_nRenderedEntities = 0; // don't let bucket size be equal to 0 assert(GetBucketSize().x != 0 || GetBucketSize().y != 0); // Gets the list of visible buckets std::list<Vector2> bucketList; const Vector2& v2CamPos = m_provider->GetVideo()->GetCameraPos(); //for debugging pourposes ETHGlobal::GetIntersectingBuckets(bucketList, v2CamPos, m_provider->GetVideo()->GetScreenSizeF(), GetBucketSize(), IsDrawingBorderBuckets(), IsDrawingBorderBuckets()); // Loop through all visible Buckets for (std::list<Vector2>::iterator bucketPositionIter = bucketList.begin(); bucketPositionIter != bucketList.end(); bucketPositionIter++) { ETHBucketMap::iterator bucketIter = m_buckets.Find(*bucketPositionIter); if (bucketIter == m_buckets.GetLastBucket()) continue; if (bucketIter->second.empty()) continue; ETHEntityList::const_iterator iEnd = bucketIter->second.end(); for (ETHEntityList::iterator iter = bucketIter->second.begin(); iter != iEnd; iter++) { ETHSpriteEntity *pRenderEntity = (*iter); // update scene bounding for depth buffer maxHeight = Max(maxHeight, pRenderEntity->GetMaxHeight()); minHeight = Min(minHeight, pRenderEntity->GetMinHeight()); if (pRenderEntity->IsHidden()) continue; // fill the light list for this frame // const ETHEntityFile &entity = pRenderEntity->GetData()->entity; if (pRenderEntity->HasLightSource()) { ETHLight light = *(pRenderEntity->GetLight()); // if it has a particle system in the first slot, adjust the light // brightness according to the number os active particles if (pRenderEntity->GetParticleManager(0) && !pRenderEntity->IsStatic()) { boost::shared_ptr<ETHParticleManager> paticleManager = pRenderEntity->GetParticleManager(0); light.color *= static_cast<float>(paticleManager->GetNumActiveParticles()) / static_cast<float>(paticleManager->GetNumParticles()); } AddLight(light, pRenderEntity->GetPosition()); } // add this entity to the multimap to sort it for an alpha-friendly rendering list const Vector3& v3Pos = pRenderEntity->GetPosition(); const ETH_ENTITY_TYPE type = pRenderEntity->GetType(); const float depth = pRenderEntity->ComputeDepth(maxHeight, minHeight); const float drawHash = ComputeDrawHash(depth, v2CamPos, v3Pos, type); // add the entity to the render map mmEntities.insert(std::pair<float, ETHRenderEntity*>(drawHash, *iter)); m_nRenderedEntities++; } } // Draw visible entities ordered in an alpha-friendly map for (std::multimap<float, ETHRenderEntity*>::iterator iter = mmEntities.begin(); iter != mmEntities.end(); iter++) { ETHRenderEntity *pRenderEntity = (iter->second); m_provider->GetShaderManager()->BeginAmbientPass(pRenderEntity, maxHeight, minHeight); // draws the ambient pass and if we're at the editor, draw the collision box if it's an invisible entity #ifdef _ETHANON_EDITOR if (pOutline && pRenderEntity->IsInvisible() && pRenderEntity->Collidable()) { pRenderEntity->DrawCollisionBox(true, pOutline, GS_WHITE, maxHeight, minHeight, m_sceneProps.zAxisDirection); } #endif m_provider->GetVideo()->RoundUpPosition(roundUp); pRenderEntity->DrawAmbientPass(m_maxSceneHeight, m_minSceneHeight, (m_enableLightmaps && m_showingLightmaps), m_sceneProps); // draw "invisible entity symbol" if we're in the editor #ifdef _ETHANON_EDITOR if (pOutline) { if (pRenderEntity->IsInvisible() && pRenderEntity->Collidable()) { pRenderEntity->DrawCollisionBox(false, pOutline, GS_WHITE, maxHeight, minHeight, m_sceneProps.zAxisDirection); } if (pRenderEntity->IsInvisible() && !pRenderEntity->Collidable()) { const float depth = m_provider->GetVideo()->GetSpriteDepth(); m_provider->GetVideo()->SetSpriteDepth(1.0f); pInvisibleEntSymbol->Draw(pRenderEntity->GetPositionXY()); m_provider->GetVideo()->SetSpriteDepth(depth); } } #endif // fill the halo list // const ETHEntityFile &entity = pRenderEntity->GetData()->entity; if (pRenderEntity->HasLightSource() && pRenderEntity->GetHalo()) { outHalos.push_back(pRenderEntity); } // fill the particle list for this frame if (pRenderEntity->HasParticleSystems()) { outParticles.push_back(pRenderEntity); } // fill the callback list m_tempEntities.AddCallbackWhenEligible(pRenderEntity); m_provider->GetShaderManager()->EndAmbientPass(); //draw light pass for (std::list<ETHLight>::iterator iter = m_lights.begin(); iter != m_lights.end(); iter++) { if (!pRenderEntity->IsHidden()) { if (!(pRenderEntity->IsStatic() && iter->staticLight && m_enableLightmaps)) { m_provider->GetVideo()->RoundUpPosition(roundUp); if (m_provider->GetShaderManager()->BeginLightPass(pRenderEntity, &(*iter), m_maxSceneHeight, m_minSceneHeight, GetLightIntensity())) { pRenderEntity->DrawLightPass(GetZAxisDirection()); m_provider->GetShaderManager()->EndLightPass(); m_provider->GetVideo()->RoundUpPosition(false); if (AreRealTimeShadowsEnabled()) { if (m_provider->GetShaderManager()->BeginShadowPass(pRenderEntity, &(*iter), m_maxSceneHeight, m_minSceneHeight)) { pRenderEntity->DrawShadow(m_maxSceneHeight, m_minSceneHeight, m_sceneProps, *iter, 0); m_provider->GetShaderManager()->EndShadowPass(); } } m_provider->GetVideo()->RoundUpPosition(roundUp); } } } } } mmEntities.clear(); m_nCurrentLights = m_lights.size(); // Show the buckets outline in debug mode #if defined _DEBUG || defined _ETHANON_EDITOR if (m_provider->GetInput()->IsKeyDown(GSK_PAUSE)) { DrawBucketOutlines(); } #endif return true; }
bool ETHScene::GenerateLightmaps(const int id) { const ETHSpriteEntity *pRender = (id >= 0) ? m_buckets.SeekEntity(id) : 0; const Vector2 v2Bucket = (pRender) ? ETHGlobal::GetBucket(pRender->GetPositionXY(), GetBucketSize()) : Vector2(0,0); for (ETHBucketMap::iterator bucketIter = m_buckets.GetFirstBucket(); bucketIter != m_buckets.GetLastBucket(); bucketIter++) { // if we're lighting only one entity and it is not in this bucket, skip it. // I know we could have used the find method to go directly to that bucket // but this function os not that critical to make the effort worth it. if (id >= 0) if (v2Bucket != bucketIter->first) continue; // iterate over all entities in this bucket ETHEntityList::const_iterator iEnd = bucketIter->second.end(); for (ETHEntityList::iterator iter = bucketIter->second.begin(); iter != iEnd; iter++) { // if nID is valid, let's try to generate the lightmap for this one and only entity if (id >= 0) if (id != (*iter)->GetID()) continue; Vector2 v2Size(1,1); Vector2 v2Origin(0,0); if ((*iter)->GetSprite()) { v2Size = (*iter)->GetCurrentSize(); v2Origin = (*iter)->ComputeOrigin(v2Size); } // Place the current entity at the top-left corner to align // it to the render target const Vector3 oldPos = (*iter)->GetPosition(); const Vector3 newPos = Vector3(v2Origin.x, v2Origin.y, 0); // fill the light list for (ETHBucketMap::iterator lbucketIter = m_buckets.GetFirstBucket(); lbucketIter != m_buckets.GetLastBucket(); lbucketIter++) { ETHEntityList::const_iterator liEnd = lbucketIter->second.end(); for (ETHEntityList::iterator liter = lbucketIter->second.begin(); liter != liEnd; liter++) { if ((*liter)->IsStatic() && (*liter)->HasLightSource()) { AddLight(*((*liter)->GetLight()), newPos-oldPos+(*liter)->GetPosition()); } } } ETHLightmapGen((*iter), m_provider->GetShaderManager(), m_lights.begin(), m_lights.end(), m_buckets, oldPos, newPos, m_minSceneHeight, m_maxSceneHeight, m_sceneProps); (*iter)->SetOrphanPosition(oldPos); m_lights.clear(); } } #ifdef _DEBUG ETH_STREAM_DECL(ss) << GS_L("Lightmaps created... "); m_provider->Log(ss.str(), Platform::FileLogger::INFO); #endif return true; }
void CRateLimiter::OnTimer(wxTimerEvent& event) { for (int i = 0; i < 2; ++i) { m_tokenDebt[i] = 0; if (m_objectList.empty()) continue; wxLongLong limit = GetLimit((enum rate_direction)i); if (limit == 0) { for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) { (*iter)->m_bytesAvailable[i] = -1; if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } continue; } wxLongLong tokens = (limit * tickDelay) / 1000; wxLongLong maxTokens = tokens * GetBucketSize(); // Get amount of tokens for each object wxLongLong tokensPerObject = tokens / m_objectList.size(); if (tokensPerObject == 0) tokensPerObject = 1; tokens = 0; // This list will hold all objects which didn't reach maxTokens std::list<CRateLimiterObject*> unsaturatedObjects; for (std::list<CRateLimiterObject*>::iterator iter = m_objectList.begin(); iter != m_objectList.end(); ++iter) { if ((*iter)->m_bytesAvailable[i] == -1) { wxASSERT(!(*iter)->m_waiting[i]); (*iter)->m_bytesAvailable[i] = tokensPerObject; unsaturatedObjects.push_back(*iter); } else { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); if ((*iter)->m_waiting[i]) m_wakeupList[i].push_back(*iter); } } // If there are any left-over tokens (in case of objects with a rate below the limit) // assign to the unsaturated sources while (tokens != 0 && !unsaturatedObjects.empty()) { tokensPerObject = tokens / unsaturatedObjects.size(); if (tokensPerObject == 0) break; tokens = 0; std::list<CRateLimiterObject*> objects; objects.swap(unsaturatedObjects); for (std::list<CRateLimiterObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter) { (*iter)->m_bytesAvailable[i] += tokensPerObject; if ((*iter)->m_bytesAvailable[i] > maxTokens) { tokens += (*iter)->m_bytesAvailable[i] - maxTokens; (*iter)->m_bytesAvailable[i] = maxTokens; } else unsaturatedObjects.push_back(*iter); } } } WakeupWaitingObjects(); if (m_objectList.empty()) m_timer.Stop(); }