예제 #1
0
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);
    }
}
예제 #2
0
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;
}
예제 #3
0
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
}
예제 #4
0
bool ETHScene::DeleteEntity(ETHEntity *pEntity)
{
	return m_buckets.DeleteEntity(pEntity->GetID(), ETHBucketManager::GetBucket(pEntity->GetPositionXY(), GetBucketSize()));
}
예제 #5
0
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();
}
예제 #6
0
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;
}
예제 #7
0
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;
		}
	}
}
예제 #8
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();
}
예제 #9
0
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);
}
예제 #10
0
// 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;
}
예제 #11
0
// 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;
}
예제 #12
0
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;
}
예제 #13
0
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();
}