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

« Previous Version 4 Next »

In this section we creates a new behaviour module. This module is a simple follow target module.


Writing the behaviour module

First thing to do is create a class and hinerit from the base BehaviourModule class. With a constructor a desctructor and a static creator function used by atoms to create an isntance of this module.

class FollowTargetModule: public Atoms::BehaviourModule
{
	public:

		FollowTargetModule()
		{}

		virtual ~FollowTargetModule()
		{}

		static Atoms::BehaviourModule* creator(const std::string& parameter);
};

Atoms::BehaviourModule* creator(const std::string& parameter)
{
	return new FollowTargetModule();
}

Lets add some attributes to our node. In this case we need only a target position. The attributes of the modules are stored inside a MapMetadata object, and you can add new attribute using the addAttribute function. So lets add this attribute inside the constructor.

FollowTargetModule()
{
	AtomsCore::Vector3Metadata targetPosition(AtomsCore::Vector3(0.0,0.0,0.0));
	// The last argumet specify if this attribute can be override per agent
	addAttribute("targetPosition", &targerPosition, true);
}

Now we need to compute the new agent direction at each frame before the agent pose is computed, so we need to override the initFrame function.

You can override other function linke the endFrame or initSimulation or agentsCreated but in this case we need only the initFrame


void initFrame(const std::vector<Atoms::Agent*>& agents, Atoms::AgentGroup* agentGroup = nullptr)
{
}

In the init frame we need to get our targetPosition value and iterate over each agent to get the position and set the new direction

void initFrame(const std::vector<Atoms::Agent*>& agents, Atoms::AgentGroup* agentGroup = nullptr)
{
	// Get the target position from the moduel attribute
	AtomsCore::MapMetadata& attributeMap = attributes();
	AtomsCore::Vector3& targetPosition = attributeMap.getTypedEntry<AtomsCore::Vector3Metadata>("targetPosition")->get();

	// iterate over each agent
	for(Atoms::Agent* agent: agents)
	{
		if (!agent)
			continue;
		//get the agent position
		AtomsPtr<AtomsCore::Vector3Metadata> positionPtr = agent->metadata().getTypedEntry<AtomsCore::Vector3Metadata>("position");
		AtomsPtr<AtomsCore::Vector3Metadata> directionPtr = agent->metadata().getTypedEntry<AtomsCore::Vector3Metadata>("direction");
		if(!positionPtr || !directionPtr )
			continue;

		// compute the new direction
		directionPtr->set((targetPosition - positionPtr->get()).normalized()); 
	}
}
We created the target position attribute as overraidable per agent but we didn't put the code to handle it. So let's add now. When you override an attribute, Atoms creates an entry using the agent group id inside the mapmetadata saved as AttributeName_override.


void initFrame(const std::vector<Atoms::Agent*>& agents, Atoms::AgentGroup* agentGroup = nullptr)
{
	// Get the target position from the moduel attribute
	AtomsCore::MapMetadata& attributeMap = attributes();
	AtomsCore::Vector3& targetPosition = attributeMap.getTypedEntry<AtomsCore::Vector3Metadata>("targetPosition")->get();

	//get the override map metadata
	AtomsPtr<AtomsCore::MapMetadata> targetPositionOverride = attributeMap.getTypedEntry<AtomsCore::MapMetadata>("targetPosition_override");

	// used to store the groupId as string
	char groupIdChar[12];
	std::string groupIdStr;
	groupIdStr.reserve(12);

	// iterate over each agent
	for(Atoms::Agent* agent: agents)
	{
		if (!agent)
			continue;
		//get the agent position
		AtomsPtr<AtomsCore::Vector3Metadata> positionPtr = agent->metadata().getTypedEntry<AtomsCore::Vector3Metadata>("position");
		AtomsPtr<AtomsCore::Vector3Metadata> directionPtr = agent->metadata().getTypedEntry<AtomsCore::Vector3Metadata>("direction");
		if(!positionPtr || !directionPtr )
			continue;

		// get the agent group id
		AtomsPtr<AtomsCore::IntMetadata> groupIdPtr = agent->metadata().getTypedEntry<AtomsCore::IntMetadata>("groupId");
		if (!groupIdPtr)
			continue;

		//convert the groupId to a string since the map metadata use only strings as key
		sprintf(groupIdChar, "%d", groupIdPtr->value());
		groupIdStr = groupIdChar;

		//check if the agent is inside the override map
		AtomsPtr<AtomsCore::Vector3Metadata> overrideTargetPos = targetPositionOverride ->getTypedEntry<AtomsCore::Vector3Metadata>(groupIdStr);
		if (overrideTargetPos)
		{
			// compute the new direction
			directionPtr->set((overrideTargetPos->get() - positionPtr->get()).normalized()); 
		}
		else
		{
			// compute the new direction
			directionPtr->set((targetPosition - positionPtr->get()).normalized()); 
		}
	}
}

Register the behaviour module

Compile the behaviour module

Use the behaviour module

  • No labels