Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

A context steering module fills the interest and the danger map.

This is an example of a module that fills the interest map. It takes the main direction and apply a dot product between the direction and the rays.

(Remember to add “AtomsUnreal” and “AtomsRealtime” to the dependency of you plugin/project)

#pragma once

#include "CoreMinimal.h"
#include "AtomsUnreal/Public/ContextSteering/AtomsContextSteeringBehaviour.h"
#include "AtomsContextSteeringMyDirectionBehaviour.generated.h"


/* Take the input agent direction and do a dot with the samples in the angle range, starting form the forward sample 0.*/
UCLASS(DefaultToInstanced, editinlinenew, DisplayName = "My Direction")
class UAtomsContextSteeringMyDirectionBehaviour : public UAtomsContextSteeringBehaviour
{
	GENERATED_BODY()

public:

	/** Angle used to reduce the interest values, decrease the interest value from 1 to 0 insdie hte angle range*/
	UPROPERTY(EditAnywhere, Category = "Behaviour")
	float Angle;

	/** Teh angle coudl be controlled by a metadata if the agent has a double metadat with this name*/
	UPROPERTY(EditAnywhere, Category = "Behaviour")
	FString Metadata;

	UAtomsContextSteeringMyDirectionBehaviour();

	virtual void Initialize(class UContextSteering_BehaviourComponent* ParentComponent) override;

	virtual void Evaluate(Atoms::AgentGroup* AgentGroup, Atoms::Agent* Agent, const float DeltaTime) override;

private:

	std::string m_metadataName;

};
#include "AtomsContextSteeringMyDirectionBehaviour.h"
#include <AtomsCore/Metadata/DoubleMetadata.h>

UAtomsContextSteeringMyDirectionBehaviour::UAtomsContextSteeringMyDirectionBehaviour() :
	Angle(180.0f)
{

}

void UAtomsContextSteeringMyDirectionBehaviour::Initialize(class UContextSteering_BehaviourComponent* ParentComponent)
{
	if (!Metadata.IsEmpty())
		m_metadataName = TCHAR_TO_UTF8(*Metadata);
	else
		m_metadataName.clear();
}

void UAtomsContextSteeringMyDirectionBehaviour::Evaluate(Atoms::AgentGroup* AgentGroup, Atoms::Agent* Agent, const float DeltaTime)
{
	Atoms::ContextSteeringData& data = Agent->contextSteeringData();
	auto& samplesMap = data.samples;
	auto& interestMap = data.interest;
	const AtomsMath::Vector3& Direction = Agent->direction()->get();
	float AngleValue = Angle;
	if (!m_metadataName.empty())
	{
		AtomsCore::DoubleMetadata* angleMeta = Agent->metadata().getTypedEntryRaw<AtomsCore::DoubleMetadata>(m_metadataName);
		AngleValue = angleMeta ? angleMeta->value() : AngleValue;
	}


	AtomsMath::Quaternion quat;
	if (AngleValue < 179.9)
	{
		float AngleRad = FMath::DegreesToRadians(AngleValue);
		for (size_t j = 0; j < interestMap.size(); ++j)
		{
			quat.setAxisAngle(data.up, samplesMap[j]);
			AtomsMath::Vector3 sample_direction = quat.rotateVector(data.direction);
			double CurrentAngle = FMath::Acos(FMath::Min(FMath::Max(-1.0, Direction.dot(sample_direction)), 1.0));
			interestMap[j] = (FMath::Cos(FMath::Min(M_PI, CurrentAngle * M_PI / AngleRad)) * 0.5 + 0.5) * data.distance;
		}
	}
	else
	{
		for (size_t j = 0; j < interestMap.size(); ++j)
		{
			quat.setAxisAngle(data.up, samplesMap[j]);
			AtomsMath::Vector3 sample_direction = quat.rotateVector(data.direction);
			interestMap[j] = (Direction.dot(sample_direction) * 0.5 + 0.5) * data.distance;
		}
	}
}

Instead, this module fills the danger map using the result of the line trace method.

#pragma once

#include "CoreMinimal.h"
#include "Engine/EngineTypes.h"
#include "AtomsUnreal/Public/ContextSteering/AtomsContextSteeringBehaviour.h"
#include "AtomsContextSteeringMyLineTraceAvoidanceBehaviour.generated.h"


/* Filter the inreset/danger map using a gauss filter*/
UCLASS(DefaultToInstanced, editinlinenew, DisplayName = "My Line Trace Avoidance")
class UAtomsContextSteeringMyLineTraceAvoidanceBehaviour : public UAtomsContextSteeringBehaviour
{
	GENERATED_BODY()

public:

	/** Collision channel used by the line trace */
	UPROPERTY(EditAnywhere, Category = "Behaviour")
	TEnumAsByte<enum ECollisionChannel> CollisionChannel;

	/** Height offset */
	UPROPERTY(EditAnywhere, Category = "Behaviour")
	float HeightOffset;

	UAtomsContextSteeringMyLineTraceAvoidanceBehaviour();

	virtual void Initialize(class UContextSteering_BehaviourComponent* ParentComponent) override;

	virtual void Evaluate(Atoms::AgentGroup* AgentGroup, Atoms::Agent* Agent, const float DeltaTime) override;

private:

	class UWorld* World;
};

#include "AtomsContextSteeringMyLineTraceAvoidanceBehaviour.h"
#include "Components/ContextSteeringBehaviourComponent.h"
#include "AtomsConversions.h"

UAtomsContextSteeringMyLineTraceAvoidanceBehaviour::UAtomsContextSteeringMyLineTraceAvoidanceBehaviour() :
	CollisionChannel(ECollisionChannel::ECC_Visibility),
	World(nullptr)
{

}

void UAtomsContextSteeringMyLineTraceAvoidanceBehaviour::Initialize(class UContextSteering_BehaviourComponent* ParentComponent)
{
	if (!ParentComponent)
		return;

	World = ParentComponent->GetWorld();
}

void UAtomsContextSteeringMyLineTraceAvoidanceBehaviour::Evaluate(Atoms::AgentGroup* AgentGroup, Atoms::Agent* Agent, const float DeltaTime)
{
	if (!World) return;
	Atoms::ContextSteeringData& data = Agent->contextSteeringData();
	auto& dangerMap = data.danger;
	auto& sampleDirections = data.samples;

	const AtomsMath::Vector3& AgentPosition = data.position;
	FVector startPoint = AtomsConverter::FromVector3(AgentPosition + Agent->up()->get() * HeightOffset);
	AtomsMath::Quaternion quat;
	FHitResult result;
	for (size_t j = 0; j < dangerMap.size(); ++j)
	{
		quat.setAxisAngle(data.up, data.samples[j]);
		AtomsMath::Vector3 sample_direction = quat.rotateVector(data.direction);
		FVector endPoint = startPoint + AtomsConverter::FromVector3(sample_direction * data.distance);
		if (World->LineTraceSingleByChannel(result, startPoint, endPoint, CollisionChannel))
		{
			dangerMap[j] = data.distance - FMath::Min(FMath::Max(0.0f, result.Distance - 30.0f), data.distance);
		}
	}
}
  • No labels