2. Neutrino API Guide

2.1. Introduction

Neutrino supports dynamic loading of various kinds of plugins which are recognized as they are placed in the appropriate folder under Neutrino Data.

2.2. Plugin Types

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

2.2.1. 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

class NESampleSimpleSolver

Implementation of a simple particle solver.

A Simple Solver which moves particles

Inherits from NESphLiquidSolver

Public Functions

uint NESampleSimpleSolverinit(uint initMode = NE::kInitOnCreate)

Node initialization function, should be called from all inheriting classes.

virtual void NESampleSimpleSolverdeleteParticles()

Deletes all marked particles out of the vector.

virtual void NESampleSimpleSolverdeleteParticle(NEParticle *particle)

Deletes the particle.

virtual bool NESampleSimpleSolverexplicitBoundaryHandling() const

Returns true if explicit boundary handling is required used when integrating particles.

virtual uint NESampleSimpleSolvermemoryConsumption()

Returns the memory consumption of the particles.

Public Slots

virtual void NESampleSimpleSolveraddParticles(NEParticleSource *source, std::vector<NEParticle> &newParticles, const vec3f vel)

For adding particles to the fluid, for example by a source that is connected to the fluid.

void NESampleSimpleSolverupdate()

The main update routine for single-phase fluids, called by Liquid Manager.

NESphUpdatePart NESampleSimpleSolverupdateMultiPhase(NESphUpdatePart currentStep)

The main update routine for multiphase fluids.

virtual qreal NESampleSimpleSolverupdateTimeStep()

Computes the required time step and sets it.

virtual uint NESampleSimpleSolversaveFrameData(QString path, const int frameNumber)

Overloaded function, to additionally save the timestep.

virtual uint NESampleSimpleSolverloadFrameData(QString path, const int frameNumber)

Overloaded function, to additionally load the timestep.

void NESampleSimpleSolversetRadius(qreal r)

Overloaded function for modifying fluid radius.

void NESampleSimpleSolversetRestDensity(qreal density)

Overloaded function for modifying rest density of the fluid.

2.3. Neutrino Classes

The full class documentation can be found under classes

2.4. Particle Cache Format

Download NEParticleLoader.cpp - sample code which loads an NEParticle cache file and displays information.

The particle cache file is divided into the following sections

  1. Header
     struct NEBinaryDataSection
             short Id;
             int contentFlag;
             int nParticles;
             long long Offset;
  1. 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
        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; }


        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;