Skip to content

Neutrino API Guide

Neutrino Developers Guide

This guide is provided for C++ developers willing to extend the features of Neutrino.

Introduction

Neutrino’s system overview is depicted in the following figure.

Neutrino supports dynamic loading of various kinds of plugins which are recognized as they are placed in the appropriate folder under Neutrino Data. Each plugin can be a single Neutrino node or several nodes. Whether its a single node or a multi node, they have to be associated with a factory. (NEFactory).

If a plugin consists of several nodes the associated factory is derived from NEMultiNodeFactory. If its a single node then its derived from NENodeFactory

Factories

  1. NENodeFactory
  2. NEMultiNodeFactory

The following are the node types. Each of the node types have an associated manager managing them. The list of managers can be found in the earlier figure

The following are the node types and their associated managers.

Node Types

  1. Solvers
    1. Particle Solvers
  2. Daemons
    1. Emitters
      1. Particle Emitters
    2. Force Fields
  3. Rigids
  4. Surface Generation
  5. Materials

Particle Solvers

Its best to explain plugins in Neutrino with the help of an example plugin.

In this case lets take an example of an implementation of a sample solver plugin Look at the example in Data/Plugins/SampleSPHSolver

This implements a solver based on predictive corrective SPH.

Building the plugin

A sample qmake pro file is included in the plugin. Please update the NE_BINARY_PATH to where the binary Neutrino is installed. Typically this is the directory containing the file neutrino.lib or neutrino.so depending on the Operating System.

Execute qmake and build/make.

The dlls or so of the plugin is installed in Neutrino_Install_Directory/Data/Plugins

Next time neutrino is started it loads the plugins from this directory structure. The various kinds of plugins supported by neutrino are indicated by the subfolders under Plugins.

For example a solver plugin would be under

Neutrino Data Folder (Neutrino Install Dir/Data) | Plugins -> release -> Spatial -> Physical -> SphFluid (For Release build)

Neutrino finds the plugin type from the directory structure and the type of plugin written and loads it in the Plugin Manager

Simulation Init

* NESceneManager::startUpdateTimer()
* NESceneManager::prepareSceneForSimulation()
* NESimulationManager::preparePhysicalsForSimulation
* NERigidManager::prepareRigidsForSimulation()
* Ex: NESphBox::generateBoundaryParticles
* NECollisionManager::update()
* NECollider::update()
* NEUniformGridCollider::update()
* Ex: NESortedHashingCollider::constructGrid()
* Ex: NESortedHashingCollider::insertRigidsIntoGrid()
* Ex: NESortedHashingCollider::insertStaticRigidIntoGrid()
* NEGeometryManager::update()
* NEPostProcessManager::update()

Simulation Update

* NESceneManager::update()
* NESimulationManger::update()
* NELiquidManager::updateForces()
* NESphLiquidSolver::update()
* NESphLiquidManager::integrate()
* NESphLiquidSolver::integrate()
* NECollisionManager::update()
* NECollider::update()

Classes

The full class documentation can be found in the API Documentation.

Particle Cache Format

The particle cache file is divided into the following sections

1. Header

struct NEBinaryDataSection
{
short Id;
int contentFlag;
int nParticles;
long long Offset;
};

2. Section Data

Particle as stored sequentially with their corresponding data described as follows.

enum NEParticleDataType
{
IdPosition = 1,
Color = 2,
Velocity = 4,
Density = 8,
Pressure = 16,
Vorticity = 32,
Normal = 64,
Neighbors = 128,
Type = 256
};
struct Color32
{
inline Color32(){}
inline Color32(uchar r, uchar g, uchar b, uchar a)
{
red = r; green = g; blue = b; alpha = a;
}
uchar red;
uchar green;
uchar blue;
uchar alpha;
inline void Set(uchar r, uchar g, uchar b, uchar a)
{
red = r; green = g; blue = b; alpha = a;
}
// Some preset colors
static Color32 kRed;
static Color32 kGreen;
static Color32 kBlue;
static Color32 kMagenta;
static Color32 kYellow;
static Color32 kCyan;
static Color32 kOrange;
static Color32 kWhite;
static Color32 kBlack;
};

Data structure describing per particle data.

class NEParticle
{
public:
NEParticle() : m_Id(0), m_Color(200,200,255,255), m_Position(0,0,0), m_Velocity(0,0,0),
m_Density(0), m_Pressure(0), m_Normal(0,0,0){}
virtual ~NEParticle() {}
inline const vec3f& position() const { return m_Position; }
vec3f& position() { return m_Position; }
inline void setPosition(const vec3f& position) { m_Position = position; }
inline const vec3f& velocity() const { return m_Velocity; }
inline vec3f& velocity() { return m_Velocity; }
inline void setVelocity(const vec3f& velocity) { m_Velocity = velocity; }
inline uint id() const {return m_Id; }
inline void setId(const uint id){m_Id = id; }
inline const Color32& color() const { return m_Color; }
inline void setColor(Color32 color) { m_Color = color; }
inline float density() const { return m_Density; }
inline float& density() { return m_Density; }
inline void setDensity(const float density){m_Density = density; }
inline float pressure() const {return m_Pressure; }
inline float& pressure() { return m_Pressure; }
inline void setPressure(float pressure){m_Pressure = pressure; }
vec3f normal() const { return m_Normal; }
void setNormal(vec3f val) { m_Normal = val; }
uint type() const { return m_Type; }
void setType(const uint &Type) { m_Type = Type; }
protected:
uint m_Id;
// Modifying the relative order of color and position will break the renderer
// NEW: keep these variables at the end of the member variables list
Color32 m_Color;
vec3f m_Position;
vec3f m_Velocity;
float m_Density;
float m_Pressure;
vec3f m_Normal;
uint m_Type;
};