Atoms has several layout modules but you can create new modules with c++. This example shows how create a layout module for generating agents along a input curve.
This example is made of two parts:
- the layout generator responsible for creating the agents
- a behaviour module responsible for creating the layout generator and attaching it to the agent group
Writing the curve layout generator
The layout generator object generates the description of new agents created at every frame. A generator can be static or dynamic. A static generator creates the agent descriptions only at the first frame, while a dynamic one can generate new agents at every frame. In this example our generator is static, since the agents are created only at the first frame along the curve. If you want to create a dynamic generator just use the setAsStaticgenerator(false) function inside the constructor.
The generate function creates a vector of AgentInitData objects. This object defines the position, direction, agent type, groupId of the new agents. The agent group uses this information to create thee new agents.
#include <Atoms/LayoutGenerators/LayoutGenerator.h>
#include <AtomsUtils/Curve.h>
#include <Atoms/AgentTypes.h>
class CurveLayoutGenerator : public LayoutGenerator
{
public:
CurveLayoutGenerator();
virtual ~CurveLayoutGenerator();
virtual std::vector<AgentInitData> generate(double time);
inline void setNumberOfAgents(size_t value) { m_numberOfAgents = value; }
inline void setDirectionType(short value) { m_directionType = value; }
inline void setInvertDirection(short value) { m_invertDirection = value; }
inline void setAgentTypeOverride(const std::map<int, std::string>& value) { m_agentTypeOverride = value; }
inline void setDirectionOverride(const std::map<int, AtomsCore::Vector3>& value) { m_directionOverride = value; }
private:
std::map<int, AtomsCore::Vector3> m_directionOverride;
std::map<int, std::string> m_agentTypeOverride;
size_t m_numberOfAgents;
short m_directionType;
bool m_invertDirection;
};
CurveLayoutGenerator::CurveLayoutGenerator(): LayoutGenerator(),
m_direction(1.0,0.0,0.0),
m_upVector(0.0,1.0,0.0),
m_numberOfAgents(0),
m_directionType(0),
m_invertDirection(false)
{
setAsStaticGenerator(true);
}
CurveLayoutGenerator::~CurveLayoutGenerator()
{
}
std::vector<AgentInitData> CurveLayoutGenerator::generate(double time)
{
if ((m_curve.cvs().size() < 2) || (m_numberOfAgents < 1))
return std::vector<AgentInitData>();
std::vector<AgentInitData> data(m_numberOfAgents);
float curveStep = m_curve.maxU() / static_cast<float>(std::max(static_cast<size_t>(1), m_numberOfAgents - 1));
for (size_t i = 0; i < m_numberOfAgents; i++)
{
float param = static_cast<float>(i) * curveStep;
AgentInitData& agentData = data[i];
agentData.position = m_curve.pointOnCurve(param);
agentData.groupId = i;
auto atIt = m_agentTypeOverride.find(i);
if (atIt != m_agentTypeOverride.end())
{
agentData.agentType = agTypes.
agentType(atIt->second);
}
else
{
agentData.agentType = agentType();
}
auto dIt = m_directionOverride.find(i);
if (dIt != m_directionOverride.end())
{
agentData.direction = dIt->second;
}
else
{
switch (m_directionType)
{
case 0:
{
agentData.direction = m_curve.tangentOnCurve(param);
break;
}
case 1:
{
agentData.direction = m_curve.tangentOnCurve(param);
agentData.direction = agentData.direction.cross(m_upVector);
break;
}
default:
{
agentData.direction = m_direction;
break;
}
}
}
if (m_invertDirection)
{
agentData.direction *= -1.0;
}
}
return std::move(data);
}
Container for all agent types.
Definition: AgentTypes.h:20
static AgentTypes & instance()
Singleton access for global data.
AgentTypePtr agentType(const std::string &typeName)
Gets the agent type with the given name.
Nurbs curve.
Definition: Curve.h:18
AtomsMath::Vector3 Vector3
Vector3 class.
Definition: AtomsMath.h:57
Writing the curve layout module
To use the curve layout generator a new behaviour modules is needed. This behaviour module exposes the generator attributes to the user and sends all the data to the generator itself.
#include <Atoms/BehaviourModule.h>
#include <Atoms/AgentTypes.h>
#include <Atoms/AgentGroup.h>
#include <AtomsCore/Metadata/IntMetadata.h>
#include <AtomsCore/Metadata/Vector3ArrayMetadata.h>
#include <AtomsCore/Metadata/StringMetadata.h>
#include <AtomsCore/Metadata/CurveMetadata.h>
#include <AtomsCore/Metadata/BoolMetadata.h>
{
public:
CurveGeneratorModule();
~CurveGeneratorModule();
};
CurveGeneratorModule::CurveGeneratorModule() :
{
AtomsCore::StringMetadata atype("atomsRobot");
addAttribute("agentType", &atype, true);
AtomsCore::CurveMetadata curve;
AtomsCore::IntMetadata numAgents(10);
metadata.
addEntry(
"numAgents", &numAgents);
AtomsCore::IntMetadata dirType(0);
metadata.
addEntry(
"directionType", &dirType);
AtomsCore::BoolMetadata invDir(false);
metadata.
addEntry(
"invertDirection", &invDir);
addAttribute("direction", &dir, true);
addAttribute("upVector", &up, false);
}
CurveGeneratorModule::~CurveGeneratorModule()
{}
{
AtomsPtr<AtomsCore::CurveMetadata> curvePtr = metadata.
getTypedEntry<AtomsCore::CurveMetadata>(
"curve");
AtomsPtr<AtomsCore::IntMetadata> numAgentsPtr = metadata.
getTypedEntry<AtomsCore::IntMetadata>(
"numAgents");
AtomsPtr<AtomsCore::IntMetadata> directionTypePtr = metadata.
getTypedEntry<AtomsCore::IntMetadata>(
"directionType");
AtomsPtr<AtomsCore::BoolMetadata> invertDirectionPtr = metadata.
getTypedEntry<AtomsCore::BoolMetadata>(
"invertDirection");
AtomsPtr<AtomsCore::Vector3Metadata> directionPtr = metadata.
getTypedEntry<AtomsCore::Vector3Metadata>(
"direction");
AtomsPtr<AtomsCore::Vector3Metadata> upPtr = metadata.
getTypedEntry<AtomsCore::Vector3Metadata>(
"upVector");
AtomsPtr<AtomsCore::StringMetadata> agentTypePtr = metadata.
getTypedEntry<AtomsCore::StringMetadata>(
"agentType");
if (!aType)
{
return;
}
std::map<int, std::string> aTypesOverride;
for (auto it = atypeOverride->begin(); it != atypeOverride->end(); it++)
{
if (!it->second)
continue;
if (it->second->typeId() != AtomsCore::StringMetadata::staticTypeId())
continue;
auto value = std::static_pointer_cast<AtomsCore::StringMetadata>(it->second);
if (!value)
continue;
if (!aType)
{
continue;
}
aTypesOverride[std::stoi(it->first)] = value->get();
}
std::map<int, AtomsCore::Vector3> dirOverride;
for (auto it = directionOverride->begin(); it != directionOverride->end(); it++)
{
if (!it->second)
continue;
if (it->second->typeId() != AtomsCore::Vector3Metadata::staticTypeId())
continue;
auto value = std::static_pointer_cast<AtomsCore::Vector3Metadata>(it->second);
if (value)
dirOverride[std::stoi(it->first)] = value->get();
}
curveLayout->setCurve(curvePtr->get());
curveLayout->setNumberOfAgents(numAgentsPtr->value());
curveLayout->setDirectionType(directionTypePtr->value());
curveLayout->setInvertDirection(invertDirectionPtr->value());
curveLayout->setDirection(directionPtr->value());
curveLayout->setUpVector(upPtr->value());
curveLayout->setAgentTypeOverride(aTypesOverride);
curveLayout->setDirectionOverride(dirOverride);
Atoms::LayoutGeneratorPtr generator(curveLayout);
generator->setAgentType(aType);
}
{
return new CurveGeneratorModule();
}
extern "C"
{
ATOMSPLUGIN_EXPORT bool initializePlugin()
{
moduleManager.
registerBehaviourModule(
"SimpleCurveLayout", &CurveGeneratorModule::creator, Atoms::BehaviourModules::kNative);
return true;
}
ATOMSPLUGIN_EXPORT bool unitializePlugin()
{
return true;
}
}
Agent group.
Definition: AgentGroup.h:36
void setLayoutGenerator(LayoutGeneratorPtr &layoutGen)
Sets the layout generator.
Behaviour module.
Definition: BehaviourModule.h:32
virtual void initSimulation(AgentGroup *agentGroup=nullptr)
Init simulation.
Behaviour module factory.
Definition: BehaviourModules.h:22
bool deregisterBehaviourModule(const std::string &name)
Deregisters a Behaviour module type from the factory.
static BehaviourModules & instance()
Singleton access.
bool registerBehaviourModule(const std::string &moduleName, creatorFn func, unsigned int moduleType=kNative, bool replace=false, const std::string category="")
Registers a behaviour module in the factory.
Definition: CurveLayoutGenerator.h:8
Atoms namespace.
Definition: Agent.h:29
AtomsPtr< AgentType > AgentTypePtr
Agent type pointer.
Definition: AgentType.h:17