Atomsには、いくつかのLayoutモジュールがありますが、C ++を使用して、新しいモジュールを作成できます。こちらの例では、入力カーブに沿ってエージェントを生成するためのLayoutモジュールを作成する方法を説明しています。
こちらの例は、2つの部分から構成されています。
- エージェントの作成を担当するLayoutジェネレータ、レイアウトの作成を担当するBehaviourモジュール
- ジェネレータとそれをエージェントグループにアタッチを実施
Curve Layoutジェネレータを書く
Layoutジェネレータオブジェクトは、すべてのフレームで作成された新しいエージェントの描写を生成します。ジェネレータは、StaticでもDynamicのどちらでも構いません。Staticジェネレータは、最初のフレームでのみ、エージェントの描写を作成しますが、Dynamicジェネレータは、すべてのフレームで新しいエージェントを生成できます。この例では、エージェントはカーブに沿った最初のフレームでのみ作成されるので、ジェネレータはStaticです。Dynamicジェネレータを作成したい場合は、コンストラクタ内でsetAsStaticgenerator(false)関数を使用するだけです。
generate関数は、AgentInitDataオブジェクトのベクトルを作成します。このオブジェクトは、新しいエージェントの位置、方向、エージェントタイプ、グループIDを定義します。エージェントグループは、この情報を使用して新しいエージェントを作成します。
コード ブロック | ||
---|---|---|
| ||
#include <Atoms/LayoutGenerators/LayoutGenerator.h>
#include <AtomsUtils/Curve.h>
#include <Atoms/AgentTypes.h>
class CurveLayoutGenerator : public LayoutGenerator
{
public:
CurveLayoutGenerator();
virtual ~CurveLayoutGenerator();
// the generator function
virtual std::vector<AgentInitData> generate(double time);
inline void setCurve(AtomsUtils::Curve& curve) { m_curve = curve; }
inline void setDirection(AtomsCore::Vector3& dir) { m_direction = dir; }
inline void setUpVector(AtomsCore::Vector3& dir) { m_upVector = dir; }
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:
// Input curve
AtomsUtils::Curve m_curve;
// Agent direction
AtomsCore::Vector3 m_direction;
// Up vector
AtomsCore::Vector3 m_upVector;
// Agent direction override
std::map<int, AtomsCore::Vector3> m_directionOverride;
// Agent type override
std::map<int, std::string> m_agentTypeOverride;
// Number of agents along the curve
size_t m_numberOfAgents;
// Direction type: 0 - tangent, 1 - normal, 2 - custom
short m_directionType;
// Invert the direction
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()
{
}
// the generator function since is a static generator this function is called once
std::vector<AgentInitData> CurveLayoutGenerator::generate(double time)
{
// Check if the curve is a valid
if ((m_curve.cvs().size() < 2) || (m_numberOfAgents < 1))
return std::vector<AgentInitData>();
Atoms::AgentTypes &agTypes = Atoms::AgentTypes::instance();
// initialize the vector
std::vector<AgentInitData> data(m_numberOfAgents);
// curve parameter step
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];
// set the agent position
agentData.position = m_curve.pointOnCurve(param);
// set the agent group id, this must be unique
agentData.groupId = i;
// set the agent type checking if there is any override
auto atIt = m_agentTypeOverride.find(i);
if (atIt != m_agentTypeOverride.end())
{
agentData.agentType = agTypes.agentType(atIt->second);
}
else
{
agentData.agentType = agentType();
}
// set the agent direction checking if there is any override
auto dIt = m_directionOverride.find(i);
if (dIt != m_directionOverride.end())
{
agentData.direction = dIt->second;
}
else
{
switch (m_directionType)
{
case 0: // use the tangent
{
agentData.direction = m_curve.tangentOnCurve(param);
break;
}
case 1: // use the normal
{
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);
}
|
Curve Layout モジュールを書く
Curve Layoutジェネレータを使用する場合は、新規のBehaviourモジュールが必要です。このBehaviourモジュールは、ジェネレータのアトリビュートをユーザーに公開し、すべてのデータをジェネレータ自体に送信します。
コード ブロック | ||
---|---|---|
| ||
#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>
class CurveGeneratorModule : public Atoms::BehaviourModule
{
public:
CurveGeneratorModule();
~CurveGeneratorModule();
virtual void initSimulation(Atoms::AgentGroup* agentGroup = nullptr);
static Atoms::BehaviourModule* creator(const std::string& parameter);
};
CurveGeneratorModule::CurveGeneratorModule() :
Atoms::BehaviourModule()
{
AtomsCore::MapMetadata& metadata = attributes();
AtomsCore::StringMetadata atype("atomsRobot");
addAttribute("agentType", &atype, true);
AtomsCore::CurveMetadata curve;
metadata.addEntry("curve", &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);
AtomsCore::Vector3Metadata dir(AtomsCore::Vector3(1.0, 0.0, 0.0));
addAttribute("direction", &dir, true);
AtomsCore::Vector3Metadata up(AtomsCore::Vector3(0.0, 1.0, 0.0));
addAttribute("upVector", &up, false);
}
CurveGeneratorModule::~CurveGeneratorModule()
{}
void CurveGeneratorModule::initSimulation(Atoms::AgentGroup* agentGroup)
{
// Get the module attributes
AtomsCore::MapMetadata& metadata = attributes();
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");
// Check if the agent type is valid
Atoms::AgentTypePtr aType = Atoms::AgentTypes::instance().agentType(agentTypePtr->value());
if (!aType)
{
return;
}
// Get all agent type overrides
AtomsPtr<AtomsCore::MapMetadata> atypeOverride = metadata.getTypedEntry<AtomsCore::MapMetadata>("agentType_override");
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;
Atoms::AgentTypePtr aType = Atoms::AgentTypes::instance().agentType(value->get());
if (!aType)
{
continue;
}
aTypesOverride[std::stoi(it->first)] = value->get();
}
// Get all agent direction overrides
AtomsPtr<AtomsCore::MapMetadata> directionOverride = metadata.getTypedEntry<AtomsCore::MapMetadata>("direction_override");
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();
}
// Create the layout generator and set all the attributes
Atoms::CurveLayoutGenerator* curveLayout = new Atoms::CurveLayoutGenerator();
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);
agentGroup->setLayoutGenerator(generator);
}
Atoms::BehaviourModule* CurveGeneratorModule::creator(const std::string& parameter)
{
return new CurveGeneratorModule();
}
extern "C"
{
ATOMSPLUGIN_EXPORT bool initializePlugin()
{
return true;
}
ATOMSPLUGIN_EXPORT bool unitializePlugin()
{
return true;
}
ATOMSPLUGIN_EXPORT bool initializeScene()
{
Atoms::BehaviourModules& moduleManager = Atoms::BehaviourModules::instance();
moduleManager.registerBehaviourModule("SimpleCurveLayout", &CurveGeneratorModule::creator, Atoms::BehaviourModules::kNative);
return true;
}
ATOMSPLUGIN_EXPORT bool unitializeScene()
{
return true;
}
} |