Layout モジュールの書き込み
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; } }
Copyright © 2017, Toolchefs LTD.