Writing a behaviour module

In this section we are going to create a new behaviour module. This behaviour module is a simple follow target module.



Writing the behaviour module

Create a new class and inherit from the base Atoms::BehaviourModule class. Define a a constructor, a destructor and a static creator function (needed by Atoms to create an instance of this module).



class FollowTargetModule: public Atoms::BehaviourModule { public: FollowTargetModule() {} virtual ~FollowTargetModule() {} static Atoms::BehaviourModule* creator(const std::string& parameter); }; Atoms::BehaviourModule* FollowTargetModule::creator(const std::string& parameter) { return new FollowTargetModule(); }



For this module we'll need only a target position attribute. The attributes of the module are stored inside a MapMetadata object, you can add new attributes using the addAttribute function. Attributes should always be added inside the constructor.

The third attribute of the addAttribute method defines if the attribute is overridable per agent or not. In this example we'll make it overridable.



FollowTargetModule(): Atoms::BehaviourModule() { 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", &targetPosition, true); }



Now we need to compute the new agent direction at each frame before the agent pose is computed. This will be done inside the initFrame method.

For this example we won't need to override any other method.





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



In the initFrame function get the targetPosition value, iterate over each agent to read the position and set their new direction.





The target position attribute is overridable per agent, but the code to handle it isn't there yet. When you override an attribute, a new map metadata named "AttributeName_override" is created. The keys of this map metadata are the agent group ids, but they will be present only when the user specifies an override from inside his 3D application.

In order to know if an agent has an override, please check the metadata map. If it's not there, please use the global attribute.







If you want improve the performance of the module you can add tbb to parallelize the main for loop.





Add visual debugging options

Lets implement a the draw function to visually debug the direction vector. Add a std::vector<AtomsCore::Vector3> m_drawLines to the class to store the lines data.

Inside the preDraw function you can collect the data form the agentse because it is called only if the time changes.

Then inside the draw function you can finally call the draw lines function to draw some lines.





Register the behaviour module

Now the behaviour module must be added to the behaviour module factory.





Compile the behaviour module

Use this cmake file as template, change the project name and the source files and set the ATOMS_MAYA_FOLDER or ATOMS_HOUDINI_FOLDER env.









Use the behaviour module

Add to the ATOMS_PLUGINS_PATH environment variable, the folder where the plugin is located. Then the module is automatically loaded when you load atoms.


Final code



Copyright © 2017, Toolchefs LTD.