Example #1
1
	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
	{
		QUICK_SCOPE_CYCLE_COUNTER( STAT_LineBatcherSceneProxy_GetDynamicMeshElements );

		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
		{
			if (VisibilityMap & (1 << ViewIndex))
			{
				const FSceneView* View = Views[ViewIndex];
				FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);

				for (int32 i = 0; i < Lines.Num(); i++)
				{
					PDI->DrawLine(Lines[i].Start, Lines[i].End, Lines[i].Color, Lines[i].DepthPriority, Lines[i].Thickness);
				}

				for (int32 i = 0; i < Points.Num(); i++)
				{
					PDI->DrawPoint(Points[i].Position, Points[i].Color, Points[i].PointSize, Points[i].DepthPriority);
				}

				for (int32 i = 0; i < Meshes.Num(); i++)
				{
					static FVector const PosX(1.f,0,0);
					static FVector const PosY(0,1.f,0);
					static FVector const PosZ(0,0,1.f);

					FBatchedMesh const& M = Meshes[i];

					// this seems far from optimal in terms of perf, but it's for debugging
					FDynamicMeshBuilder MeshBuilder;

					// set up geometry
					for (int32 VertIdx=0; VertIdx < M.MeshVerts.Num(); ++VertIdx)
					{
						MeshBuilder.AddVertex( M.MeshVerts[VertIdx], FVector2D::ZeroVector, PosX, PosY, PosZ, FColor::White );
					}
					//MeshBuilder.AddTriangles(M.MeshIndices);
					for (int32 Idx=0; Idx < M.MeshIndices.Num(); Idx+=3)
					{
						MeshBuilder.AddTriangle( M.MeshIndices[Idx], M.MeshIndices[Idx+1], M.MeshIndices[Idx+2] );
					}

					FMaterialRenderProxy* const MaterialRenderProxy = new(FMemStack::Get()) FColoredMaterialRenderProxy(GEngine->DebugMeshMaterial->GetRenderProxy(false), M.Color);
					MeshBuilder.GetMesh(FMatrix::Identity, MaterialRenderProxy, M.DepthPriority, false, false, ViewIndex, Collector);
				}
			}
		}
	}
void UGameplayTagReponseTable::TagResponseEvent(const FGameplayTag Tag, int32 NewCount, UAbilitySystemComponent* ASC, int32 idx)
{
	if (!ensure(Entries.IsValidIndex(idx)))
	{
		return;
	}

	const FGameplayTagResponseTableEntry& Entry = Entries[idx];
	int32 TotalCount = 0;

	{
		QUICK_SCOPE_CYCLE_COUNTER(ABILITY_TRT_CALC_COUNT);

		TotalCount += ASC->GetAggregatedStackCount(MakeQuery(Entry.Positive.Tag));
		TotalCount -= ASC->GetAggregatedStackCount(MakeQuery(Entry.Negative.Tag));
	}

	FGameplayTagResponseAppliedInfo& Info = RegisteredASCs.FindChecked(ASC);

	if (TotalCount < 0)
	{
		Remove(ASC, Info.PositiveHandle);
		AddOrUpdate(ASC, Entry.Negative.ResponseGameplayEffect, TotalCount, Info.NegativeHandle);
	}
	else if (TotalCount > 0)
	{
		Remove(ASC, Info.NegativeHandle);
		AddOrUpdate(ASC, Entry.Positive.ResponseGameplayEffect, TotalCount, Info.PositiveHandle);
	}
	else if (TotalCount == 0)
	{
		Remove(ASC, Info.PositiveHandle);
		Remove(ASC, Info.NegativeHandle);
	}
}
Example #3
0
void FPhysScene::WaitPhysScenes()
{
	FGraphEventArray ThingsToComplete;
	if (PhysicsSceneCompletion.GetReference())
	{
		ThingsToComplete.Add(PhysicsSceneCompletion);
	}
	// Loop through scene types to get all scenes
	// we just wait on everything, though some of these are redundant
	for (uint32 SceneType = 0; SceneType < NumPhysScenes; ++SceneType)
	{
		if (PhysicsSubsceneCompletion[SceneType].GetReference())
		{
			ThingsToComplete.Add(PhysicsSubsceneCompletion[SceneType]);
		}
		if (FrameLaggedPhysicsSubsceneCompletion[SceneType].GetReference())
		{
			ThingsToComplete.Add(FrameLaggedPhysicsSubsceneCompletion[SceneType]);
		}
	}
	if (ThingsToComplete.Num())
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_FPhysScene_WaitPhysScenes);
		FTaskGraphInterface::Get().WaitUntilTasksComplete(ThingsToComplete, ENamedThreads::GameThread);
	}
}
void UPaperGroupedSpriteComponent::CreateAllInstanceBodies()
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_UPaperGroupedSpriteComponent_CreateAllInstanceBodies);

	FPhysScene* PhysScene = GetWorld()->GetPhysicsScene();

	const int32 NumBodies = PerInstanceSpriteData.Num();
	check(InstanceBodies.Num() == 0);
	InstanceBodies.SetNumUninitialized(NumBodies);

	TArray<FTransform> Transforms;
	Transforms.Reserve(NumBodies);

	TArray<TWeakObjectPtr<UBodySetup>> BodySetups;
	BodySetups.Reserve(NumBodies);

	for (int32 InstanceIndex = 0; InstanceIndex < NumBodies; ++InstanceIndex)
	{
		const FSpriteInstanceData& InstanceData = PerInstanceSpriteData[InstanceIndex];
		FBodyInstance* InstanceBody = InitInstanceBody(InstanceIndex, InstanceData, PhysScene);
		InstanceBodies[InstanceIndex] = InstanceBody;
		BodySetups.Add((InstanceBody != nullptr) ? InstanceBody->BodySetup : TWeakObjectPtr<UBodySetup>());
	}

	if (SceneProxy != nullptr)
	{
		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
			FSendPaperGroupBodySetups,
			FGroupedSpriteSceneProxy*, InSceneProxy, (FGroupedSpriteSceneProxy*)SceneProxy,
			TArray<TWeakObjectPtr<UBodySetup>>, InBodySetups, BodySetups,
			{
			InSceneProxy->SetAllBodySetups_RenderThread(InBodySetups);
		});
PxCollection* MakePhysXCollection(const TArray<UPhysicalMaterial*>& PhysicalMaterials, const TArray<UBodySetup*>& BodySetups, uint64 BaseId)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_CreateSharedData);
	PxCollection* PCollection = PxCreateCollection();
	for (UPhysicalMaterial* PhysicalMaterial : PhysicalMaterials)
	{
		if (PhysicalMaterial)
		{
			PCollection->add(*PhysicalMaterial->GetPhysXMaterial());
		}
	}

	for (UBodySetup* BodySetup : BodySetups)
	{
		for(PxTriangleMesh* TriMesh : BodySetup->TriMeshes)
		{
			AddToCollection(PCollection, TriMesh);
		}

		for (const FKConvexElem& ConvexElem : BodySetup->AggGeom.ConvexElems)
		{
			AddToCollection(PCollection, ConvexElem.ConvexMesh);
			AddToCollection(PCollection, ConvexElem.ConvexMeshNegX);
		}
	}

	PxSerialization::createSerialObjectIds(*PCollection, PxSerialObjectId(BaseId));

	return PCollection;
}
void FStartAsyncSimulationFunction::ExecuteTick(float DeltaTime, enum ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)
{
	QUICK_SCOPE_CYCLE_COUNTER(FStartAsyncSimulationFunction_ExecuteTick);

	check(Target);
	Target->StartAsyncSim();
}
void UPhysicsSerializer::Serialize( FArchive& Ar )
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_Serialize);
	Super::Serialize(Ar);
	if (Ar.UE4Ver() >= VER_UE4_BODYINSTANCE_BINARY_SERIALIZATION)
	{
		bool bCooked = Ar.IsCooking();
		Ar << bCooked;

		if (bCooked)
		{
			if (Ar.IsCooking())
			{
				TArray<FName> ActualFormatsToSave;
				ActualFormatsToSave.Add(FPlatformProperties::GetPhysicsFormat());
				BinaryFormatData.Serialize(Ar, this, &ActualFormatsToSave);
			}
			else
			{
#if WITH_PHYSX
				const uint32 Alignment = PHYSX_SERIALIZATION_ALIGNMENT;
#else
				const uint32 Alignment = DEFAULT_ALIGNMENT;
#endif
				BinaryFormatData.Serialize(Ar, this, nullptr, false, Alignment);
			}
		}
	}
}
/**
 *	Retrieves the dynamic data for the emitter
 *	
 *	@param	bSelected					Whether the emitter is selected in the editor
 *
 *	@return	FDynamicEmitterDataBase*	The dynamic data, or NULL if it shouldn't be rendered
 */
FDynamicEmitterDataBase* FParticleBeam2EmitterInstance::GetDynamicData(bool bSelected)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_ParticleBeam2EmitterInstance_GetDynamicData);

	UParticleLODLevel* LODLevel = SpriteTemplate->GetCurrentLODLevel(this);
	if (IsDynamicDataRequired(LODLevel) == false)
	{
		return NULL;
	}

	//@todo.SAS. Have this call the UpdateDynamicData function to reduce duplicate code!!!
	//@SAS. This removes the need for the assertion in the actual render call...
	if ((ActiveParticles > FDynamicBeam2EmitterData::MaxBeams) ||	// TTP #33330 - Max of 2048 beams from a single emitter
		(ParticleStride >
			((FDynamicBeam2EmitterData::MaxInterpolationPoints + 2) * (sizeof(FVector) + sizeof(float))) + 
			(FDynamicBeam2EmitterData::MaxNoiseFrequency * (sizeof(FVector) + sizeof(FVector) + sizeof(float) + sizeof(float)))
		)	// TTP #33330 - Max of 10k per beam (includes interpolation points, noise, etc.)
		)
	{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
		if (Component && Component->GetWorld())
		{
			FString ErrorMessage = 
				FString::Printf(TEXT("BeamEmitter with too much data: %s"),
					Component ? 
						Component->Template ? 
							*(Component->Template->GetName()) :
							TEXT("No template") :
						TEXT("No component"));
			FColor ErrorColor(255,0,0);
			GEngine->AddOnScreenDebugMessage((uint64)((PTRINT)this), 5.0f, ErrorColor,ErrorMessage);
			UE_LOG(LogParticles, Log, TEXT("%s"), *ErrorMessage);
		}
#endif	//#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
		return NULL;
	}

	// Allocate the dynamic data
	FDynamicBeam2EmitterData* NewEmitterData = ::new FDynamicBeam2EmitterData(LODLevel->RequiredModule);
	{
		SCOPE_CYCLE_COUNTER(STAT_ParticleMemTime);
		INC_DWORD_STAT(STAT_DynamicEmitterCount);
		INC_DWORD_STAT(STAT_DynamicBeamCount);
		INC_DWORD_STAT_BY(STAT_DynamicEmitterMem, sizeof(FDynamicBeam2EmitterData));
	}

	// Now fill in the source data
	if( !FillReplayData( NewEmitterData->Source ) )
	{
		delete NewEmitterData;
		return NULL;
	}

	// Setup dynamic render data.  Only call this AFTER filling in source data for the emitter.
	NewEmitterData->Init( bSelected );

	return NewEmitterData;
}
FMeshBatchAndRelevance::FMeshBatchAndRelevance(const FMeshBatch& InMesh, const FPrimitiveSceneProxy* InPrimitiveSceneProxy, ERHIFeatureLevel::Type FeatureLevel) :
	Mesh(&InMesh),
	PrimitiveSceneProxy(InPrimitiveSceneProxy)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_FMeshBatchAndRelevance);
	EBlendMode BlendMode = InMesh.MaterialRenderProxy->GetMaterial(FeatureLevel)->GetBlendMode();
	bHasOpaqueOrMaskedMaterial = !IsTranslucentBlendMode(BlendMode);
	bRenderInMainPass = PrimitiveSceneProxy->ShouldRenderInMainPass();
}
void FNavigationOctree::DemandLazyDataGathering(FNavigationRelevantData& ElementData)
{
	UObject* ElementOb = ElementData.GetOwner();
	if (ElementOb == nullptr)
	{
		return;
	}

	bool bShrink = false;
	const int32 OrgElementMemory = ElementData.GetGeometryAllocatedSize();

	if (ElementData.IsPendingLazyGeometryGathering() == true && ElementData.SupportsGatheringGeometrySlices() == false)
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_RecastNavMeshGenerator_LazyGeometryExport);
		UActorComponent& ActorComp = *CastChecked<UActorComponent>(ElementOb);
		ComponentExportDelegate.ExecuteIfBound(&ActorComp, ElementData);

		bShrink = true;

		// mark this element as no longer needing geometry gathering
		ElementData.bPendingLazyGeometryGathering = false;
	}

	if (ElementData.IsPendingLazyModifiersGathering())
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_RecastNavMeshGenerator_LazyModifiersExport);
		INavRelevantInterface* NavElement = Cast<INavRelevantInterface>(ElementOb);
		check(NavElement);
		NavElement->GetNavigationData(ElementData);
		ElementData.bPendingLazyModifiersGathering = false;
		bShrink = true;
	}

	if (bShrink)
	{
		// shrink arrays before counting memory
		// it will be reallocated when adding to octree and RemoveNode will have different value returned by GetAllocatedSize()
		ElementData.Shrink();
	}

	const int32 ElementMemoryChange = ElementData.GetGeometryAllocatedSize() - OrgElementMemory;
	const_cast<FNavigationOctree*>(this)->NodesMemory += ElementMemoryChange;
	INC_MEMORY_STAT_BY(STAT_Navigation_CollisionTreeMemory, ElementMemoryChange);
}
Example #11
0
void FSingleThreadManager::Tick()
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_FSingleThreadManager_Tick);

	// Tick all registered threads.
	for (int32 RunnableIndex = 0; RunnableIndex < ThreadList.Num(); ++RunnableIndex)
	{
		ThreadList[RunnableIndex]->Tick();
	}
}
/**
 *	Updates the dynamic data for the instance
 *
 *	@param	DynamicData		The dynamic data to fill in
 *	@param	bSelected		true if the particle system component is selected
 */
bool FParticleBeam2EmitterInstance::UpdateDynamicData(FDynamicEmitterDataBase* DynamicData, bool bSelected)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_ParticleBeam2EmitterInstance_UpdateDynamicData);

	if (ActiveParticles <= 0)
	{
		return false;
	}

	UParticleLODLevel* LODLevel = SpriteTemplate->GetCurrentLODLevel(this);
	if ((LODLevel == NULL) || (LODLevel->bEnabled == false))
	{
		return false;
	}

	//@SAS. This removes the need for the assertion in the actual render call...
	if ((ActiveParticles > FDynamicBeam2EmitterData::MaxBeams) ||	// TTP #33330 - Max of 2048 beams from a single emitter
		(ParticleStride >
			((FDynamicBeam2EmitterData::MaxInterpolationPoints + 2) * (sizeof(FVector) + sizeof(float))) + 
			(FDynamicBeam2EmitterData::MaxNoiseFrequency * (sizeof(FVector) + sizeof(FVector) + sizeof(float) + sizeof(float)))
		)	// TTP #33330 - Max of 10k per beam (includes interpolation points, noise, etc.)
		)
	{
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
		if (Component && Component->GetWorld())
		{
			FString ErrorMessage = 
				FString::Printf(TEXT("BeamEmitter with too much data: %s"),
					Component ? 
						Component->Template ? 
							*(Component->Template->GetName()) :
							TEXT("No template") :
						TEXT("No component"));
			FColor ErrorColor(255,0,0);
			GEngine->AddOnScreenDebugMessage((uint64)((PTRINT)this), 5.0f, ErrorColor,ErrorMessage);
			UE_LOG(LogParticles, Log, TEXT("%s"), *ErrorMessage);
		}
#endif	//#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
		return false;
	}

	checkf((DynamicData->GetSource().eEmitterType == DET_Beam2), TEXT("Beam2::UpdateDynamicData> Invalid DynamicData type!"));

	// Now fill in the source data
	FDynamicBeam2EmitterData* BeamDynamicData = (FDynamicBeam2EmitterData*)DynamicData;
	if( !FillReplayData( BeamDynamicData->Source ) )
	{
		return false;
	}

	// Setup dynamic render data.  Only call this AFTER filling in source data for the emitter.
	BeamDynamicData->Init( bSelected );

	return true;
}
void UWorld::WaitForAllAsyncTraceTasks()
{
#if RUN_ASYNC_TRACE
	// if running thread, wait until all threads finishes, if we don't do this, there might be more thread running
	AsyncTraceData& DataBufferExecuted = AsyncTraceState.GetBufferForPreviousFrame();
	if (DataBufferExecuted.AsyncTraceCompletionEvent.Num() > 0)
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_WaitForAllAsyncTraceTasks);
		FTaskGraphInterface::Get().WaitUntilTasksComplete(DataBufferExecuted.AsyncTraceCompletionEvent,ENamedThreads::GameThread);
		DataBufferExecuted.AsyncTraceCompletionEvent.Reset();
	}
#endif // RUN_ASYNC_TRACE
}
void FPrimitiveSceneInfo::UpdateStaticMeshes(FRHICommandListImmediate& RHICmdList)
{
	checkSlow(bNeedsStaticMeshUpdate);
	bNeedsStaticMeshUpdate = false;

	QUICK_SCOPE_CYCLE_COUNTER(STAT_FPrimitiveSceneInfo_UpdateStaticMeshes);

	// Remove the primitive's static meshes from the draw lists they're currently in, and re-add them to the appropriate draw lists.
	for (int32 MeshIndex = 0; MeshIndex < StaticMeshes.Num(); MeshIndex++)
	{
		StaticMeshes[MeshIndex].RemoveFromDrawLists();
		StaticMeshes[MeshIndex].AddToDrawLists(RHICmdList, Scene);
	}
}
Example #15
0
void FPhysScene::WaitClothScene()
{
	FGraphEventArray ThingsToComplete;
	if (PhysicsSubsceneCompletion[PST_Cloth].GetReference())
	{
		ThingsToComplete.Add(PhysicsSubsceneCompletion[PST_Cloth]);
	}

	if (ThingsToComplete.Num())
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_FPhysScene_WaitClothScene);
		FTaskGraphInterface::Get().WaitUntilTasksComplete(ThingsToComplete, ENamedThreads::GameThread);
	}
}
void FThreadManager::Tick()
{	
	if (!FPlatformProcess::SupportsMultithreading())
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_FSingleThreadManager_Tick);

		FScopeLock ThreadsLock(&ThreadsCritical);

		// Tick all registered threads.
		for (TPair<uint32, FRunnableThread*>& ThreadPair : Threads)
		{
			ThreadPair.Value->Tick();
		}
	}
}
	/** 
	* Draw the scene proxy as a dynamic element
	*
	* @param	PDI - draw interface to render to
	* @param	View - current view
	*/
	virtual void DrawDynamicElements(FPrimitiveDrawInterface* PDI,const FSceneView* View)
	{
		QUICK_SCOPE_CYCLE_COUNTER( STAT_ArrowSceneProxy_DrawDynamicElements );

		FMatrix EffectiveLocalToWorld;
#if WITH_EDITOR
		if (bLightAttachment)
		{
			EffectiveLocalToWorld = GetLocalToWorld().GetMatrixWithoutScale();
		}
		else
#endif	//WITH_EDITOR
		{
			EffectiveLocalToWorld = GetLocalToWorld();
		}
		DrawDirectionalArrow(PDI,EffectiveLocalToWorld,ArrowColor,ArrowSize * 3.0f * ARROW_SCALE,ARROW_SCALE,GetDepthPriorityGroup(View));
	}
bool FAnalyticsProviderET::Tick(float DeltaSeconds)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_FAnalyticsProviderET_Tick);

	if (CachedEvents.Num() > 0)
	{
		// Countdown to flush
		FlushEventsCountdown -= DeltaSeconds;
		// If reached countdown or already at max cached events then flush
		if (FlushEventsCountdown <= 0 ||
			CachedEvents.Num() >= MaxCachedNumEvents)
		{
			FlushEvents();
		}
	}
	return true;
}
FVector2D SGameLayerManager::GetAspectRatioInset(ULocalPlayer* LocalPlayer) const
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_SGameLayerManager_GetAspectRatioInset);
	FVector2D Offset(0.f, 0.f);
	if (LocalPlayer)
	{
		FSceneViewInitOptions ViewInitOptions;
		if (LocalPlayer->CalcSceneViewInitOptions(ViewInitOptions, LocalPlayer->ViewportClient->Viewport))
		{
			FIntRect UnscaledViewRect = ViewInitOptions.GetConstrainedViewRect();
			Offset.X = -UnscaledViewRect.Min.X;
			Offset.Y = -UnscaledViewRect.Min.Y;
		}
	}

	return Offset;
}
FByteBulkData* UPhysicsSerializer::GetBinaryData(FName Format, const TArray<FBodyInstance*>& Bodies, const TArray<class UBodySetup*>& BodySetups, const TArray<class UPhysicalMaterial*>& PhysicalMaterials)
{
	if (!FParse::Param(FCommandLine::Get(), TEXT("PhysxSerialization")))
	{
		return nullptr;
	}

#if PLATFORM_MAC
	return nullptr;	//This is not supported right now
#endif

	QUICK_SCOPE_CYCLE_COUNTER(STAT_GetBinaryData);
	const bool bContainedData = BinaryFormatData.Contains(Format);
	FByteBulkData* Result = &BinaryFormatData.GetFormat(Format);
	if (!FParse::Param(FCommandLine::Get(), TEXT("NoPhysxAlignment")))
	{
		Result->SetBulkDataAlignment(PHYSX_SERIALIZATION_ALIGNMENT);
	}
	
	if (!bContainedData)
	{
#if WITH_EDITOR
#if WITH_PHYSX
		TArray<uint8> OutData;
		FDerivedDataPhysXBinarySerializer* DerivedPhysXSerializer = new FDerivedDataPhysXBinarySerializer(Format, Bodies, BodySetups, PhysicalMaterials, FGuid::NewGuid()); //TODO: Maybe it's worth adding this to the DDC. For now there's a lot of complexity with the guid invalidation so I've left it out.
		if (DerivedPhysXSerializer->CanBuild())
		{

			DerivedPhysXSerializer->Build(OutData);
#endif
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
		else
#endif
		{
			UE_LOG(LogPhysics, Warning, TEXT("Attempt to use binary physics data but we are unable to."));
		}
	}

	return Result->GetBulkDataSize() > 0 ? Result : nullptr;
}
Example #21
0
		virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
		{
			QUICK_SCOPE_CYCLE_COUNTER( STAT_BoxSceneProxy_GetDynamicMeshElements );

			const FMatrix& LocalToWorld = GetLocalToWorld();
			
			for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
			{
				if (VisibilityMap & (1 << ViewIndex))
				{
					const FSceneView* View = Views[ViewIndex];

					const FLinearColor DrawColor = GetViewSelectionColor(BoxColor, *View, IsSelected(), IsHovered(), false, IsIndividuallySelected() );

					FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
					DrawOrientedWireBox(PDI, LocalToWorld.GetOrigin(), LocalToWorld.GetScaledAxis( EAxis::X ), LocalToWorld.GetScaledAxis( EAxis::Y ), LocalToWorld.GetScaledAxis( EAxis::Z ), BoxExtents, DrawColor, SDPG_World);
				}
			}
		}
void FMeshElementCollector::ProcessTasks()
{
	check(IsInRenderingThread());
	check(!ParallelTasks.Num() || bUseAsyncTasks);

	if (ParallelTasks.Num())
	{
		QUICK_SCOPE_CYCLE_COUNTER(STAT_FMeshElementCollector_ProcessTasks);
		TArray<TFunction<void()>*, SceneRenderingAllocator>& LocalParallelTasks(ParallelTasks);
		ParallelFor(ParallelTasks.Num(), 
			[&LocalParallelTasks](int32 Index)
			{
				TFunction<void()>* Func = LocalParallelTasks[Index];
				(*Func)();
				Func->~TFunction<void()>();
			}
			);
		ParallelTasks.Empty();
	}
}
		virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
		{
			QUICK_SCOPE_CYCLE_COUNTER( STAT_GetDynamicMeshElements_DrawDynamicElements );

		
			const FMatrix& LocalToWorld = GetLocalToWorld();
			const int32 CapsuleSides =  FMath::Clamp<int32>(CapsuleRadius/4.f, 16, 64);

			for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
			{

				if (VisibilityMap & (1 << ViewIndex))
				{
					const FSceneView* View = Views[ViewIndex];
					const FLinearColor DrawCapsuleColor = GetViewSelectionColor(ShapeColor, *View, IsSelected(), IsHovered(), false, IsIndividuallySelected() );

					FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
					DrawWireCapsule( PDI, LocalToWorld.GetOrigin(), LocalToWorld.GetScaledAxis( EAxis::X ), LocalToWorld.GetScaledAxis( EAxis::Y ), LocalToWorld.GetScaledAxis( EAxis::Z ), DrawCapsuleColor, CapsuleRadius, CapsuleHalfHeight, CapsuleSides, SDPG_World );
				}
			}
		}
void FEndPhysicsTickFunction::ExecuteTick(float DeltaTime, enum ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)
{
	QUICK_SCOPE_CYCLE_COUNTER(FEndPhysicsTickFunction_ExecuteTick);

	check(Target);
	FPhysScene* PhysScene = Target->GetPhysicsScene();
	if (PhysScene == NULL)
	{
		return;
	}
	FGraphEventRef PhysicsComplete = PhysScene->GetCompletionEvent();
	if (PhysicsComplete.GetReference() && !PhysicsComplete->IsComplete())
	{
		// don't release the next tick group until the physics has completed and we have run FinishPhysicsSim
		DECLARE_CYCLE_STAT(TEXT("FSimpleDelegateGraphTask.FinishPhysicsSim"),
			STAT_FSimpleDelegateGraphTask_FinishPhysicsSim,
			STATGROUP_TaskGraphTasks);

		MyCompletionGraphEvent->DontCompleteUntil(
			FSimpleDelegateGraphTask::CreateAndDispatchWhenReady(
				FSimpleDelegateGraphTask::FDelegate::CreateUObject(Target, &UWorld::FinishPhysicsSim),
				GET_STATID(STAT_FSimpleDelegateGraphTask_FinishPhysicsSim), PhysicsComplete, ENamedThreads::GameThread
			)
		);
	}
	else
	{
		// it was already done, so let just do it.
		Target->FinishPhysicsSim();
	}

#if PHYSX_MEMORY_VALIDATION
	static int32 Frequency = 0;
	if (Frequency++ > 10)
	{
		Frequency = 0;
		GPhysXAllocator->ValidateHeaders();
	}
#endif
}
void FTextRenderSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const 
{
	QUICK_SCOPE_CYCLE_COUNTER( STAT_TextRenderSceneProxy_GetDynamicMeshElements );

	// Vertex factory will not been initialized when the text string is empty or font is invalid.
	if(VertexFactory.IsInitialized())
	{
		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
		{
			if (VisibilityMap & (1 << ViewIndex))
			{
				const FSceneView* View = Views[ViewIndex];
				// Draw the mesh.
				FMeshBatch& Mesh = Collector.AllocateMesh();
				FMeshBatchElement& BatchElement = Mesh.Elements[0];
				BatchElement.IndexBuffer = &IndexBuffer;
				Mesh.VertexFactory = &VertexFactory;
				BatchElement.PrimitiveUniformBufferResource = &GetUniformBuffer();
				BatchElement.FirstIndex = 0;
				BatchElement.NumPrimitives = IndexBuffer.Indices.Num() / 3;
				BatchElement.MinVertexIndex = 0;
				BatchElement.MaxVertexIndex = VertexBuffer.Vertices.Num() - 1;
				Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
				Mesh.bDisableBackfaceCulling = false;
				Mesh.Type = PT_TriangleList;
				Mesh.DepthPriorityGroup = SDPG_World;
				const bool bUseSelectedMaterial = GIsEditor && (View->Family->EngineShowFlags.Selection) ? IsSelected() : false;
				Mesh.MaterialRenderProxy = TextMaterial->GetRenderProxy(bUseSelectedMaterial);
				Mesh.bCanApplyViewModeOverrides = !bAlwaysRenderAsText;

				Collector.AddMesh(ViewIndex, Mesh);

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
				RenderBounds(Collector.GetPDI(ViewIndex), View->Family->EngineShowFlags, GetBounds(), IsSelected());
#endif
			}
		}
	}
}
void FPoseLinkBase::Update(const FAnimationUpdateContext& Context)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_FPoseLinkBase_Update);
#if DO_CHECK
	checkf( !bProcessed, TEXT( "Update already in progress, circular link for AnimInstance [%s] Blueprint [%s]" ), \
		*Context.AnimInstanceProxy->GetAnimInstanceName(), *GetFullNameSafe(IAnimClassInterface::GetActualAnimClass(Context.AnimInstanceProxy->GetAnimClassInterface())));
	TGuardValue<bool> CircularGuard(bProcessed, true);
#endif

#if WITH_EDITOR
	if (GIsEditor)
	{
		if (LinkedNode == NULL)
		{
			//@TODO: Should only do this when playing back
			AttemptRelink(Context);
		}

		// Record the node line activation
		if (LinkedNode != NULL)
		{
			if (Context.AnimInstanceProxy->IsBeingDebugged())
			{
				Context.AnimInstanceProxy->RecordNodeVisit(LinkID, SourceLinkID, Context.GetFinalBlendWeight());
			}
		}
	}
#endif

#if ENABLE_ANIMGRAPH_TRAVERSAL_DEBUG
	checkf(InitializationCounter.IsSynchronizedWith(Context.AnimInstanceProxy->GetInitializationCounter()), TEXT("Calling Update without initialization!"));
	UpdateCounter.SynchronizeWith(Context.AnimInstanceProxy->GetUpdateCounter());
#endif

	if (LinkedNode != NULL)
	{
		LinkedNode->Update(Context);
	}
}
void FIndirectLightingCache::UpdateCachePrimitivesInternal(FScene* Scene, FSceneRenderer& Renderer, bool bAllowUnbuiltPreview, TMap<FIntVector, FBlockUpdateInfo>& OutBlocksToUpdate, TArray<FIndirectLightingCacheAllocation*>& OutTransitionsOverTimeToUpdate)
{
	SCOPE_CYCLE_COUNTER(STAT_UpdateIndirectLightingCachePrims);
	const TMap<FPrimitiveComponentId, FAttachmentGroupSceneInfo>& AttachmentGroups = Scene->AttachmentGroups;
	if (IndirectLightingAllowed(Scene, Renderer))
	{		
		if (bUpdateAllCacheEntries)
		{
			const uint32 PrimitiveCount = Scene->Primitives.Num();

			for (uint32 PrimitiveIndex = 0; PrimitiveIndex < PrimitiveCount; ++PrimitiveIndex)
			{
				FPrimitiveSceneInfo* PrimitiveSceneInfo = Scene->Primitives[PrimitiveIndex];
				const bool bPrecomputedLightingBufferWasDirty = PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate();

				UpdateCachePrimitive(AttachmentGroups, PrimitiveSceneInfo, false, true, OutBlocksToUpdate, OutTransitionsOverTimeToUpdate);

				// If it was already dirty, then the primitive is already in one of the view dirty primitive list at this point.
				// This also ensures that a primitive does not get added twice to the list, which could create an array reallocation.
				if (!bPrecomputedLightingBufferWasDirty)
				{
					PrimitiveSceneInfo->MarkPrecomputedLightingBufferDirty();

					// Check if it is visible otherwise, it will be updated next time it is visible.
					for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
					{
						FViewInfo& View = Renderer.Views[ViewIndex];

						if (View.PrimitiveVisibilityMap[PrimitiveIndex])
						{
							// Since the update can be executed on a threaded job (see GILCUpdatePrimTaskEnabled), no reallocation must happen here.
							checkSlow(View.DirtyPrecomputedLightingBufferPrimitives.Num() < View.DirtyPrecomputedLightingBufferPrimitives.Max());
							View.DirtyPrecomputedLightingBufferPrimitives.Push(PrimitiveSceneInfo);
							break; // We only need to add it in one of the view list.
						}
					}
				}
			}
		}
		else
		{
			TArray<uint32> SetBitIndices[4];
			{
				QUICK_SCOPE_CYCLE_COUNTER(STAT_UpdateCachePreWalk);
			
				for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
				{
					FViewInfo& View = Renderer.Views[ViewIndex];
					SetBitIndices[ViewIndex].Reserve(View.PrimitiveVisibilityMap.Num());

					for (FSceneSetBitIterator BitIt(View.PrimitiveVisibilityMap); BitIt; ++BitIt)
					{
						uint32 PrimitiveIndex = BitIt.GetIndex();
						SetBitIndices[ViewIndex].Add(PrimitiveIndex);					
					}

					// Any visible primitives with an indirect shadow need their ILC updated, since that determines the indirect shadow direction
					for (int32 IndirectPrimitiveIndex = 0; IndirectPrimitiveIndex < View.IndirectShadowPrimitives.Num(); IndirectPrimitiveIndex++)
					{
						int32 PrimitiveIndex = View.IndirectShadowPrimitives[IndirectPrimitiveIndex]->GetIndex();
						SetBitIndices[ViewIndex].AddUnique(PrimitiveIndex);
					}
				}			
			}

			// Go over the views and operate on any relevant visible primitives
			for (int32 ViewIndex = 0; ViewIndex < Renderer.Views.Num(); ViewIndex++)
			{
				FViewInfo& View = Renderer.Views[ViewIndex];

				const TArray<uint32>& SetBits = SetBitIndices[ViewIndex];
				for (int32 i = 0; i < SetBits.Num(); ++i)
				{
					uint32 PrimitiveIndex = SetBits[i];

					FPrimitiveSceneInfo* PrimitiveSceneInfo = Scene->Primitives[PrimitiveIndex];
					const bool bPrecomputedLightingBufferWasDirty = PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate();

					const FPrimitiveViewRelevance& PrimitiveRelevance = View.PrimitiveViewRelevanceMap[PrimitiveIndex];
					UpdateCachePrimitive(AttachmentGroups, PrimitiveSceneInfo, bAllowUnbuiltPreview, PrimitiveRelevance.bOpaqueRelevance, OutBlocksToUpdate, OutTransitionsOverTimeToUpdate);

					// If it was already dirty, then the primitive is already in one of the view dirty primitive list at this point.
					// This also ensures that a primitive does not get added twice to the list, which could create an array reallocation.
					if (!bPrecomputedLightingBufferWasDirty && PrimitiveSceneInfo->NeedsPrecomputedLightingBufferUpdate())
					{
						// Since the update can be executed on a threaded job (see GILCUpdatePrimTaskEnabled), no reallocation must happen here.
						checkSlow(View.DirtyPrecomputedLightingBufferPrimitives.Num() < View.DirtyPrecomputedLightingBufferPrimitives.Max());
						View.DirtyPrecomputedLightingBufferPrimitives.Push(PrimitiveSceneInfo);
					}
				}
			}
		}
		bUpdateAllCacheEntries = false;
	}
}
/**
 * Captures dynamic replay data for this particle system.
 *
 * @param	OutData		[Out] Data will be copied here
 *
 * @return Returns true if successful
 */
bool FParticleBeam2EmitterInstance::FillReplayData( FDynamicEmitterReplayDataBase& OutData )
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_ParticleBeam2EmitterInstance_FillReplayData);

	if (ActiveParticles <= 0)
	{
		return false;
	}
	// Call parent implementation first to fill in common particle source data
	if( !FParticleEmitterInstance::FillReplayData( OutData ) )
	{
		return false;
	}

	// If the template is disabled, don't return data.
	UParticleLODLevel* LODLevel = SpriteTemplate->GetCurrentLODLevel(this);
	if ((LODLevel == NULL) || (LODLevel->bEnabled == false))
	{
		return false;
	}

	OutData.eEmitterType = DET_Beam2;

	FDynamicBeam2EmitterReplayData* NewReplayData =
		static_cast< FDynamicBeam2EmitterReplayData* >( &OutData );

	NewReplayData->MaterialInterface = GetCurrentMaterial();

	// We never want local space for beams
	NewReplayData->bUseLocalSpace = false;

	// Never use axis lock for beams
	NewReplayData->bLockAxis = false;

	DetermineVertexAndTriangleCount();

	NewReplayData->UpVectorStepSize = BeamTypeData->UpVectorStepSize;
	NewReplayData->TrianglesPerSheet.Empty(BeamTrianglesPerSheet.Num());
	NewReplayData->TrianglesPerSheet.AddZeroed(BeamTrianglesPerSheet.Num());
	for (int32 BeamIndex = 0; BeamIndex < BeamTrianglesPerSheet.Num(); BeamIndex++)
	{
		NewReplayData->TrianglesPerSheet[BeamIndex] = BeamTrianglesPerSheet[BeamIndex];
	}


	int32 IgnoredTaperCount = 0;
	BeamTypeData->GetDataPointerOffsets(this, NULL, TypeDataOffset, 
		NewReplayData->BeamDataOffset, NewReplayData->InterpolatedPointsOffset,
		NewReplayData->NoiseRateOffset, NewReplayData->NoiseDeltaTimeOffset,
		NewReplayData->TargetNoisePointsOffset, NewReplayData->NextNoisePointsOffset, 
		IgnoredTaperCount, NewReplayData->TaperValuesOffset,
		NewReplayData->NoiseDistanceScaleOffset);

	NewReplayData->VertexCount = VertexCount;


	if (BeamModule_Source)
	{
		NewReplayData->bUseSource = true;
	}
	else
	{
		NewReplayData->bUseSource = false;
	}

	if (BeamModule_Target)
	{
		NewReplayData->bUseTarget = true;
	}
	else
	{
		NewReplayData->bUseTarget = false;
	}

	if (BeamModule_Noise)
	{
		NewReplayData->bLowFreqNoise_Enabled = BeamModule_Noise->bLowFreq_Enabled;
		NewReplayData->bHighFreqNoise_Enabled = false;
		NewReplayData->bSmoothNoise_Enabled = BeamModule_Noise->bSmooth;

	}
	else
	{
		NewReplayData->bLowFreqNoise_Enabled = false;
		NewReplayData->bHighFreqNoise_Enabled = false;
		NewReplayData->bSmoothNoise_Enabled = false;
	}
	NewReplayData->Sheets = (BeamTypeData->Sheets > 0) ? BeamTypeData->Sheets : 1;
	NewReplayData->Sheets = FMath::Max(NewReplayData->Sheets, 1);

	NewReplayData->TextureTile = BeamTypeData->TextureTile;
	NewReplayData->TextureTileDistance = BeamTypeData->TextureTileDistance;
	NewReplayData->TaperMethod = BeamTypeData->TaperMethod;
	NewReplayData->InterpolationPoints = BeamTypeData->InterpolationPoints;

	NewReplayData->NoiseTessellation	= 0;
	NewReplayData->Frequency			= 1;
	NewReplayData->NoiseRangeScale		= 1.0f;
	NewReplayData->NoiseTangentStrength= 1.0f;

	int32 TessFactor = 1;
	if ((BeamModule_Noise == NULL) || (BeamModule_Noise->bLowFreq_Enabled == false))
	{
		TessFactor	= BeamTypeData->InterpolationPoints ? BeamTypeData->InterpolationPoints : 1;
	}
	else
	{
		NewReplayData->Frequency			= (BeamModule_Noise->Frequency > 0) ? BeamModule_Noise->Frequency : 1;
		NewReplayData->Frequency = FMath::Max(NewReplayData->Frequency, 1);
		NewReplayData->NoiseTessellation	= (BeamModule_Noise->NoiseTessellation > 0) ? BeamModule_Noise->NoiseTessellation : 1;
		NewReplayData->NoiseTangentStrength= BeamModule_Noise->NoiseTangentStrength.GetValue(EmitterTime);
		if (BeamModule_Noise->bNRScaleEmitterTime)
		{
			NewReplayData->NoiseRangeScale = BeamModule_Noise->NoiseRangeScale.GetValue(EmitterTime, Component);
		}
		else
		{	//-V523 Remove when todo will be implemented
			//@todo.SAS. Need to address this!!!!
			//					check(0 && TEXT("NoiseRangeScale - No way to get per-particle setting at this time."));
			//					NewReplayData->NoiseRangeScale	= BeamModule_Noise->NoiseRangeScale.GetValue(Particle->RelativeTime, Component);
			NewReplayData->NoiseRangeScale = BeamModule_Noise->NoiseRangeScale.GetValue(EmitterTime, Component);
		}
		NewReplayData->NoiseSpeed = BeamModule_Noise->NoiseSpeed.GetValue(EmitterTime);
		NewReplayData->NoiseLockTime = BeamModule_Noise->NoiseLockTime;
		NewReplayData->NoiseLockRadius = BeamModule_Noise->NoiseLockRadius;
		NewReplayData->bTargetNoise = BeamModule_Noise->bTargetNoise;
		NewReplayData->NoiseTension = BeamModule_Noise->NoiseTension;
	}

	int32 MaxSegments	= ((TessFactor * NewReplayData->Frequency) + 1 + 1);		// Tessellation * Frequency + FinalSegment + FirstEdge;

	// Determine the index count
	NewReplayData->IndexCount	= 0;
	for (int32 Beam = 0; Beam < ActiveParticles; Beam++)
	{
		DECLARE_PARTICLE_PTR(Particle, ParticleData + ParticleStride * ParticleIndices[Beam]);

		int32						CurrentOffset		= TypeDataOffset;
		FBeam2TypeDataPayload*	BeamData			= NULL;
		FVector*				InterpolatedPoints	= NULL;
		float*					NoiseRate			= NULL;
		float*					NoiseDelta			= NULL;
		FVector*				TargetNoisePoints	= NULL;
		FVector*				NextNoisePoints		= NULL;
		float*					TaperValues			= NULL;
		float*					NoiseDistanceScale	= NULL;
		FBeamParticleModifierPayloadData* SourceModifier = NULL;
		FBeamParticleModifierPayloadData* TargetModifier = NULL;

		BeamTypeData->GetDataPointers(this, (const uint8*)Particle, CurrentOffset, BeamData, 
			InterpolatedPoints, NoiseRate, NoiseDelta, TargetNoisePoints, NextNoisePoints, 
			TaperValues, NoiseDistanceScale, SourceModifier, TargetModifier);

		if (BeamData->TriangleCount > 0)
		{
			if (NewReplayData->IndexCount == 0)
			{
				NewReplayData->IndexCount = 2;
			}
			NewReplayData->IndexCount	+= BeamData->TriangleCount * NewReplayData->Sheets;	// 1 index per triangle in the strip PER SHEET
			NewReplayData->IndexCount	+= ((NewReplayData->Sheets - 1) * 4);					// 4 extra indices per stitch (degenerates)
			if (Beam > 0)
			{
				NewReplayData->IndexCount	+= 4;	// 4 extra indices per beam (degenerates)
			}
		}
	}

	if (NewReplayData->IndexCount > 15000)
	{
		NewReplayData->IndexStride	= sizeof(uint32);
	}
	else
	{
		NewReplayData->IndexStride	= sizeof(uint16);
	}


	//@todo. SORTING IS A DIFFERENT ISSUE NOW! 
	//		 GParticleView isn't going to be valid anymore?
	uint8* PData = NewReplayData->ParticleData.GetData();
	for (int32 i = 0; i < NewReplayData->ActiveParticleCount; i++)
	{
		DECLARE_PARTICLE(Particle, ParticleData + ParticleStride * ParticleIndices[i]);
		FMemory::Memcpy(PData, &Particle, ParticleStride);
		PData += ParticleStride;
	}

	// Set the debug rendering flags...
	NewReplayData->bRenderGeometry = BeamTypeData->RenderGeometry;
	NewReplayData->bRenderDirectLine = BeamTypeData->RenderDirectLine;
	NewReplayData->bRenderLines = BeamTypeData->RenderLines;
	NewReplayData->bRenderTessellation = BeamTypeData->RenderTessellation;


	return true;
}
void FDecalRendering::BuildVisibleDecalList(const FScene& Scene, const FViewInfo& View, EDecalRenderStage DecalRenderStage, FTransientDecalRenderDataList& OutVisibleDecals)
{
	QUICK_SCOPE_CYCLE_COUNTER(BuildVisibleDecalList);

	OutVisibleDecals.Empty(Scene.Decals.Num());

	const float FadeMultiplier = CVarDecalFadeScreenSizeMultiplier.GetValueOnRenderThread();
	const EShaderPlatform ShaderPlatform = View.GetShaderPlatform();

	const bool bIsPerspectiveProjection = View.IsPerspectiveProjection();

	// Build a list of decals that need to be rendered for this view in SortedDecals
	for (const FDeferredDecalProxy* DecalProxy : Scene.Decals)
	{
		bool bIsShown = true;

		if (!DecalProxy->IsShown(&View))
		{
			bIsShown = false;
		}

		const FMatrix ComponentToWorldMatrix = DecalProxy->ComponentTrans.ToMatrixWithScale();

		// can be optimized as we test against a sphere around the box instead of the box itself
		const float ConservativeRadius = FMath::Sqrt(
				ComponentToWorldMatrix.GetScaledAxis(EAxis::X).SizeSquared() +
				ComponentToWorldMatrix.GetScaledAxis(EAxis::Y).SizeSquared() +
				ComponentToWorldMatrix.GetScaledAxis(EAxis::Z).SizeSquared());

		// can be optimized as the test is too conservative (sphere instead of OBB)
		if(ConservativeRadius < SMALL_NUMBER || !View.ViewFrustum.IntersectSphere(ComponentToWorldMatrix.GetOrigin(), ConservativeRadius))
		{
			bIsShown = false;
		}

		if (bIsShown)
		{
			FTransientDecalRenderData Data(Scene, DecalProxy, ConservativeRadius);
			
			// filter out decals with blend modes that are not supported on current platform
			if (IsBlendModeSupported(ShaderPlatform, Data.DecalBlendMode))
			{
				if (bIsPerspectiveProjection && Data.DecalProxy->Component->FadeScreenSize != 0.0f)
				{
					float Distance = (View.ViewMatrices.ViewOrigin - ComponentToWorldMatrix.GetOrigin()).Size();
					float Radius = ComponentToWorldMatrix.GetMaximumAxisScale();
					float CurrentScreenSize = ((Radius / Distance) * FadeMultiplier);

					// fading coefficient needs to increase with increasing field of view and decrease with increasing resolution
					// FadeCoeffScale is an empirically determined constant to bring us back roughly to fraction of screen size for FadeScreenSize
					const float FadeCoeffScale = 600.0f;
					float FOVFactor = ((2.0f/View.ViewMatrices.ProjMatrix.M[0][0]) / View.ViewRect.Width()) * FadeCoeffScale;
					float FadeCoeff = Data.DecalProxy->Component->FadeScreenSize * FOVFactor;
					float FadeRange = FadeCoeff * 0.5f;

					float Alpha = (CurrentScreenSize - FadeCoeff) / FadeRange;
					Data.FadeAlpha = FMath::Min(Alpha, 1.0f);
				}

				EDecalRenderStage LocalDecalRenderStage = FDecalRenderingCommon::ComputeRenderStage(ShaderPlatform, Data.DecalBlendMode);

				// we could do this test earlier to avoid the decal intersection but getting DecalBlendMode also costs
				if (View.Family->EngineShowFlags.ShaderComplexity || (DecalRenderStage == LocalDecalRenderStage && Data.FadeAlpha>0.0f) )
				{
					OutVisibleDecals.Add(Data);
				}
			}
		}
	}

	if (OutVisibleDecals.Num() > 0)
	{
		// Sort by sort order to allow control over composited result
		// Then sort decals by state to reduce render target switches
		// Also sort by component since Sort() is not stable
		struct FCompareFTransientDecalRenderData
		{
			FORCEINLINE bool operator()(const FTransientDecalRenderData& A, const FTransientDecalRenderData& B) const
			{
				if (B.DecalProxy->SortOrder != A.DecalProxy->SortOrder)
				{ 
					return A.DecalProxy->SortOrder < B.DecalProxy->SortOrder;
				}
				// bHasNormal here is more important then blend mode because we want to render every decals that output normals before those that read normal.
				if (B.bHasNormal != A.bHasNormal)
				{
					return B.bHasNormal < A.bHasNormal; // < so that those outputting normal are first.
				}
				if (B.DecalBlendMode != A.DecalBlendMode)
				{
					return (int32)B.DecalBlendMode < (int32)A.DecalBlendMode;
				}
				// Batch decals with the same material together
				if (B.MaterialProxy != A.MaterialProxy)
				{
					return B.MaterialProxy < A.MaterialProxy;
				}
				return (PTRINT)B.DecalProxy->Component < (PTRINT)A.DecalProxy->Component;
			}
		};

		// Sort decals by blend mode to reduce render target switches
		OutVisibleDecals.Sort(FCompareFTransientDecalRenderData());
	}
}
Example #30
-1
void UNavCollision::GetNavigationModifier(FCompositeNavModifier& Modifier, const FTransform& LocalToWorld)
{
	QUICK_SCOPE_CYCLE_COUNTER(STAT_NavCollision_GetNavigationModifier);

	const TSubclassOf<UNavArea> UseAreaClass = AreaClass ? AreaClass : UNavigationSystem::GetDefaultObstacleArea();

	Modifier.ReserveForAdditionalAreas(CylinderCollision.Num() + BoxCollision.Num()
		+ (ConvexCollision.VertexBuffer.Num() > 0 ? ConvexShapeIndices.Num() : 0));

	for (int32 i = 0; i < CylinderCollision.Num(); i++)
	{
		FTransform CylinderToWorld = LocalToWorld;
		const FVector Origin = CylinderToWorld.TransformPosition(CylinderCollision[i].Offset);
		CylinderToWorld.SetTranslation(Origin);

		FAreaNavModifier AreaMod(CylinderCollision[i].Radius, CylinderCollision[i].Height, CylinderToWorld, UseAreaClass);
		AreaMod.SetIncludeAgentHeight(true);
		Modifier.Add(AreaMod);
	}

	for (int32 i = 0; i < BoxCollision.Num(); i++)
	{
		FTransform BoxToWorld = LocalToWorld;
		const FVector Origin = BoxToWorld.TransformPosition(BoxCollision[i].Offset);
		BoxToWorld.SetTranslation(Origin);

		FAreaNavModifier AreaMod(BoxCollision[i].Extent, BoxToWorld, UseAreaClass);
		AreaMod.SetIncludeAgentHeight(true);
		Modifier.Add(AreaMod);
	}

	if (ShouldUseConvexCollision())
	{
		// rebuild collision data if needed
		if (!bHasConvexGeometry)
		{
			GatherCollision();
		}

		if (ConvexCollision.VertexBuffer.Num() > 0)
		{
			int32 LastVertIndex = 0;
			TArray<FVector> Verts(ConvexCollision.VertexBuffer);

			for (int32 i = 0; i < ConvexShapeIndices.Num(); i++)
			{
				int32 FirstVertIndex = LastVertIndex;
				LastVertIndex = ConvexShapeIndices.IsValidIndex(i + 1) ? ConvexShapeIndices[i + 1] : ConvexCollision.VertexBuffer.Num();

				FAreaNavModifier AreaMod(Verts, FirstVertIndex, LastVertIndex, ENavigationCoordSystem::Unreal, LocalToWorld, UseAreaClass);
				AreaMod.SetIncludeAgentHeight(true);
				Modifier.Add(AreaMod);
			}
		}
	}
}