Changeset 312


Ignore:
Timestamp:
08/16/14 00:40:54 (11 years ago)
Author:
epyon
Message:
  • particle engine now can be extended with affectors and emmiters
  • in the future we'll use a VM, but for now this completes functionality
Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/nv/gfx/particle_engine.hh

    r309 r312  
    1313namespace nv
    1414{
    15         static const int MAX_PARTICLE_EMMITERS = 8;
     15        static const int MAX_PARTICLE_EMMITERS  = 8;
     16        static const int MAX_PARTICLE_AFFECTORS = 8;
     17
     18        struct particle_emmiter_data;
     19        struct particle_affector_data;
     20        struct particle;
     21
     22        typedef void (*particle_emmiter_func)( const particle_emmiter_data*, particle*, uint32 count );
     23        typedef void (*particle_affector_func)( const particle_affector_data*, particle*, float factor, uint32 count );
     24        typedef bool (*particle_affector_init_func)( lua::table_guard* table, particle_affector_data* data );
     25
     26        struct particle_affector_funcs
     27        {
     28                particle_affector_func      process;
     29                particle_affector_init_func init;
     30        };
    1631
    1732        enum class particle_orientation
     
    3550                BOTTOM_RIGHT,
    3651        };
    37         enum class particle_emmiter_type
    38         {
    39                 POINT,
    40                 BOX,
    41                 CYLINDER,
    42                 SPHERE,
    43                 CYLINDROID,
    44                 ELLIPSOID,
    45                 HOLLOW_CYLINDER,
    46                 HOLLOW_SPHERE,
    47                 HOLLOW_CYLINDROID,
    48                 HOLLOW_ELLIPSOID,
    49         };
    5052
    5153        struct particle_vtx
     
    6567                vec3   position;
    6668                vec4   color;
    67                 vec3   dir;
    68                 float  velocity;
     69                vec3   velocity;
    6970                vec2   size;
    7071                //float  rotation;
     
    7273        };
    7374
     75        struct particle_affector_data
     76        {
     77                particle_affector_func process;
     78                uint8 paramters[4*8*16];
     79        };
    7480
    7581        struct particle_emmiter_data
    7682        {
    77                 particle_emmiter_type type;
     83                particle_emmiter_func emmiter_func;
    7884                vec3   position;
    7985                vec3   extents;
     
    111117        struct particle_system_data
    112118        {
    113                 vec3   gravity;
    114119                uint32 quota;
    115120                bool   local;
     
    117122                vec3   common_dir;
    118123                bool   accurate_facing;
    119                 particle_orientation  orientation;
    120                 particle_origin       origin;
    121                 uint32                emmiter_count;
    122                 particle_emmiter_data emmiters[MAX_PARTICLE_EMMITERS];
     124                particle_orientation   orientation;
     125                particle_origin        origin;
     126                uint32                 emmiter_count;
     127                particle_emmiter_data  emmiters[MAX_PARTICLE_EMMITERS];
     128                uint32                 affector_count;
     129                particle_affector_data affectors[MAX_PARTICLE_AFFECTORS];
    123130        };
    124131
     
    154161                void update( particle_system system, const scene_state& s, uint32 ms );
    155162                void set_texcoords( particle_system system, vec2 a, vec2 b );
     163                void register_emmiter_type( const std::string& name, particle_emmiter_func func );
     164                void register_affector_type( const std::string& name, particle_affector_init_func init, particle_affector_func process );
    156165                ~particle_engine();
    157166        private:
     167                void register_standard_emmiters();
     168                void register_standard_affectors();
    158169                void generate_data( particle_system_info* info );
    159170                void destroy_particles( particle_system_info* info, uint32 ms );
     
    162173                void update_emmiters( particle_system_info* info, uint32 ms );
    163174
    164                 device*                        m_device;
    165                 context*                       m_context;
     175                device*  m_device;
     176                context* m_context;
    166177
    167                 program                        m_program_local;
    168                 program                        m_program_world;
     178                program  m_program_local;
     179                program  m_program_world;
    169180
    170                 mat4                           m_view_matrix;
    171                 mat4                           m_model_matrix;
    172                 vec3                           m_inv_view_dir;
    173                 vec3                           m_camera_pos;
     181                mat4     m_view_matrix;
     182                mat4     m_model_matrix;
     183                vec3     m_inv_view_dir;
     184                vec3     m_camera_pos;
    174185
    175                 entity_store< particle_system_info, particle_system > m_systems;
    176                 std::unordered_map< std::string, uint32 >             m_names;
    177                 std::vector< particle_system_data >                   m_data; // constant
     186                entity_store< particle_system_info, particle_system >      m_systems;
     187                std::unordered_map< std::string, uint32 >                  m_names;
     188                std::vector< particle_system_data >                        m_data;
     189                std::unordered_map< std::string, particle_emmiter_func >   m_emmiters;
     190                std::unordered_map< std::string, particle_affector_funcs > m_affectors;
    178191        };
    179192
  • trunk/nv/math.hh

    r282 r312  
    235235        }
    236236
     237        template <typename T>
     238        glm::detail::tvec3<T> normalize_safe(
     239                const glm::detail::tvec3<T>& x,
     240                const glm::detail::tvec3<T>& def = vec3()
     241        )
     242        {
     243                typename glm::detail::tvec3<T>::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z;
     244                return ( sqr > 0 ? x * glm::inversesqrt(sqr) : def );
     245        }
     246
     247
     248
    237249} // namespace nv
    238250
  • trunk/src/gfx/particle_engine.cc

    r309 r312  
    4747        "}\n";
    4848
     49using namespace nv;
     50
     51static void nv_particle_emmiter_point( const particle_emmiter_data*, particle* p, uint32 count )
     52{
     53        for ( uint32 i = 0; i < count; ++i )
     54        {
     55                p[i].position = vec3();
     56        }
     57
     58}
     59
     60static void nv_particle_emmiter_box( const particle_emmiter_data* pe, particle* p, uint32 count )
     61{
     62        random& r = random::get();
     63        for ( uint32 i = 0; i < count; ++i )
     64        {
     65                p[i].position =
     66                        r.frange( -pe->hextents[0], pe->hextents[0] ) * pe->cdir +
     67                        r.frange( 0.0f, pe->extents[1] ) * pe->dir +
     68                        r.frange( -pe->hextents[2], pe->hextents[2] ) * pe->odir;
     69        }
     70}
     71
     72static void nv_particle_emmiter_cylinder( const particle_emmiter_data* pe, particle* p, uint32 count )
     73{
     74        random& r = random::get();
     75        for ( uint32 i = 0; i < count; ++i )
     76        {
     77                vec2 rellipse( r.disk_point( pe->precise ) * pe->extents[0] );
     78                p[i].position =
     79                        rellipse.x * pe->cdir +
     80                        r.frange( 0.0f, pe->extents[1] ) * pe->dir +
     81                        rellipse.y * pe->odir;
     82        }
     83}
     84
     85static void nv_particle_emmiter_sphere( const particle_emmiter_data* pe, particle* p, uint32 count )
     86{
     87        random& r = random::get();
     88        for ( uint32 i = 0; i < count; ++i )
     89        {
     90                vec3 rsphere = r.sphere_point( pe->precise ) * pe->extents[0];
     91                p[i].position =
     92                        rsphere.x * pe->cdir +
     93                        rsphere.y * pe->dir +
     94                        rsphere.z * pe->odir;
     95        }
     96}
     97
     98static void nv_particle_emmiter_cylindroid( const particle_emmiter_data* pe, particle* p, uint32 count )
     99{
     100        random& r = random::get();
     101        for ( uint32 i = 0; i < count; ++i )
     102        {
     103                vec2 rellipse = r.ellipse_point( vec2( pe->hextents[0], pe->hextents[2] ), pe->precise );
     104                p[i].position =
     105                        rellipse.x * pe->cdir +
     106                        r.frange( 0.0f, pe->extents[1] ) * pe->dir +
     107                        rellipse.y * pe->odir;
     108        }
     109}
     110
     111static void nv_particle_emmiter_ellipsoid( const particle_emmiter_data* pe, particle* p, uint32 count )
     112{
     113        random& r = random::get();
     114        for ( uint32 i = 0; i < count; ++i )
     115        {
     116                vec3 rsphere = r.ellipsoid_point( pe->hextents, pe->precise );
     117                p[i].position =
     118                        rsphere.x * pe->cdir +
     119                        rsphere.y * pe->dir +
     120                        rsphere.z * pe->odir;
     121        }
     122}
     123
     124static void nv_particle_emmiter_hollow_cylinder( const particle_emmiter_data* pe, particle* p, uint32 count )
     125{
     126        random& r = random::get();
     127        for ( uint32 i = 0; i < count; ++i )
     128        {
     129                vec2 rellipse = r.hollow_disk_point(
     130                        pe->ihextents[0],
     131                        pe->hextents[0],
     132                        pe->precise );
     133                p[i].position =
     134                        rellipse.x * pe->cdir +
     135                        r.frange( 0.0f, pe->extents[1] ) * pe->dir +
     136                        rellipse.y * pe->odir;
     137        }
     138}
     139
     140static void nv_particle_emmiter_hollow_sphere( const particle_emmiter_data* pe, particle* p, uint32 count )
     141{
     142        random& r = random::get();
     143        for ( uint32 i = 0; i < count; ++i )
     144        {
     145                vec3 rellipse = r.hollow_sphere_point( pe->ihextents[0], pe->hextents[0], pe->precise );
     146                p[i].position =
     147                        rellipse.x * pe->cdir +
     148                        rellipse.y * pe->dir +
     149                        rellipse.z * pe->odir;
     150        }
     151}
     152
     153static void nv_particle_emmiter_hollow_cylindroid( const particle_emmiter_data* pe, particle* p, uint32 count )
     154{
     155        random& r = random::get();
     156        for ( uint32 i = 0; i < count; ++i )
     157        {
     158                vec2 rellipse = r.hollow_ellipse_point(
     159                        vec2( pe->ihextents[0], pe->ihextents[2] ),
     160                        vec2( pe->hextents[0], pe->hextents[2] ),
     161                        pe->precise );
     162                p[i].position =
     163                        rellipse.x * pe->cdir +
     164                        r.frange( 0.0f, pe->extents[1] ) * pe->dir +
     165                        rellipse.y * pe->odir;
     166        }
     167}
     168
     169static void nv_particle_emmiter_hollow_ellipsoid( const particle_emmiter_data* pe, particle* p, uint32 count )
     170{
     171        random& r = random::get();
     172        for ( uint32 i = 0; i < count; ++i )
     173        {
     174                vec3 rellipse = r.hollow_ellipsoid_point( pe->ihextents, pe->hextents, pe->precise );
     175                p[i].position =
     176                        rellipse.x * pe->cdir +
     177                        rellipse.y * pe->dir +
     178                        rellipse.z * pe->odir;
     179        }
     180}
     181
     182struct nvpe_linear_force_data
     183{
     184        nv::vec3 force_vector;
     185        bool     average;
     186};
     187
     188static bool nv_particle_affector_linear_force_init( lua::table_guard* table, particle_affector_data* data )
     189{
     190        nvpe_linear_force_data* datap = ((nvpe_linear_force_data*)data->paramters);
     191        datap->force_vector = table->get<vec3>("force_vector", vec3() );
     192        datap->average      = table->get<bool>("average", false );
     193        return true;
     194}
     195
     196static void nv_particle_affector_linear_force( const particle_affector_data* data, particle* p, float factor, uint32 count )
     197{
     198        nvpe_linear_force_data* datap = ((nvpe_linear_force_data*)data->paramters);
     199        if ( datap->average )
     200        {
     201                float norm_factor = glm::min( factor, 1.0f );
     202                for ( uint32 i = 0; i < count; ++i )
     203                        p[i].velocity = datap->force_vector * norm_factor + p[i].velocity * ( 1.0f - norm_factor );
     204        }
     205        else
     206        {
     207                vec3 scvector = datap->force_vector * factor;
     208                for ( uint32 i = 0; i < count; ++i ) p[i].velocity += scvector;
     209        }
     210}
     211
     212struct nvpe_deflector_plane_data
     213{
     214        nv::vec3 plane_point;
     215        nv::vec3 plane_normal;
     216        float    bounce;
     217        float    distance;
     218};
     219
     220static bool nv_particle_affector_deflector_plane_init( lua::table_guard* table, particle_affector_data* data )
     221{
     222        nvpe_deflector_plane_data* datap = ((nvpe_deflector_plane_data*)data->paramters);
     223        datap->plane_point  = table->get<vec3>("plane_point",  vec3() );
     224        datap->plane_normal = table->get<vec3>("plane_normal", vec3(0.0f,1.0f,0.0f) );
     225        datap->plane_normal = normalize_safe( datap->plane_normal, vec3(0.0f,1.0f,0.0f) );
     226        datap->bounce       = table->get<float>("bounce", 0.0f );
     227        datap->distance     = -glm::dot( datap->plane_normal, datap->plane_point ) / glm::sqrt(glm::dot( datap->plane_normal, datap->plane_normal ) );
     228        return true;
     229}
     230
     231static void nv_particle_affector_deflector_plane( const particle_affector_data* data, particle* p, float factor, uint32 count )
     232{
     233        nvpe_deflector_plane_data* datap = ((nvpe_deflector_plane_data*)data->paramters);
     234        for ( uint32 i = 0; i < count; ++i )
     235        {
     236                particle& pt = p[i];
     237                vec3 direction  = pt.velocity * factor;
     238                if ( glm::dot( datap->plane_normal, pt.position + direction ) + datap->distance <= 0.0f )
     239                {
     240                        float val = glm::dot( datap->plane_normal, pt.position ) + datap->distance;
     241                        if ( val > 0.0f )
     242                        {
     243                                vec3 part_dir = direction * ( -val / glm::dot( datap->plane_normal, direction ) );
     244                                pt.position = pt.position + part_dir + ( part_dir - direction ) * datap->bounce;
     245                                pt.velocity = glm::reflect( pt.velocity, datap->plane_normal ) * datap->bounce;
     246                        }
     247                }
     248        }
     249}
     250
     251struct nvpe_color_fader_data
     252{
     253        nv::vec4 adjustment;
     254};
     255
     256static bool nv_particle_affector_color_fader_init( lua::table_guard* table, particle_affector_data* data )
     257{
     258        nvpe_color_fader_data* datap = ((nvpe_color_fader_data*)data->paramters);
     259        datap->adjustment = table->get<vec4>("adjustment",  vec4() );
     260        return true;
     261}
     262
     263static void nv_particle_affector_color_fader( const particle_affector_data* data, particle* p, float factor, uint32 count )
     264{
     265        nvpe_color_fader_data* datap = ((nvpe_color_fader_data*)data->paramters);
     266        vec4 adjustment = datap->adjustment * factor;
     267        for ( uint32 i = 0; i < count; ++i )
     268        {
     269                p[i].color = glm::clamp( p[i].color + adjustment, 0.0f, 1.0f );
     270        }
     271}
     272
     273struct nvpe_scaler_data
     274{
     275        nv::vec2 adjustment;
     276};
     277
     278static bool nv_particle_affector_scaler_init( lua::table_guard* table, particle_affector_data* data )
     279{
     280        nvpe_scaler_data* datap = ((nvpe_scaler_data*)data->paramters);
     281        float rate        = table->get<float>("rate", 0.0f );
     282        datap->adjustment = table->get<vec2>("adjustment",  vec2(rate,rate) );
     283        return true;
     284}
     285
     286static void nv_particle_affector_scaler( const particle_affector_data* data, particle* p, float factor, uint32 count )
     287{
     288        nvpe_scaler_data* datap = ((nvpe_scaler_data*)data->paramters);
     289        vec2 adjustment = datap->adjustment * factor;
     290        for ( uint32 i = 0; i < count; ++i )
     291        {
     292                p[i].size = glm::max( p[i].size + adjustment, vec2() );
     293        }
     294}
     295
    49296void nv::particle_engine::load( lua::table_guard& table )
    50297{
     
    60307        auto& data = m_data.back();
    61308
    62         data.gravity = table.get<vec3>("gravity", vec3() );
    63309        data.quota   = table.get<uint32>("quota", 1024 );
    64310        data.local   = table.get<bool>("local_space", false );
    65311        data.accurate_facing = table.get<bool>("accurate_facing", false );
    66312        data.emmiter_count   = 0;
     313        data.affector_count  = 0;
    67314
    68315        std::string orientation = table.get_string( "orientation", "point" );
     
    109356                        {
    110357                                particle_emmiter_data& edata = data.emmiters[ data.emmiter_count ];
    111 
    112                                      if ( sub_type == "point" )             edata.type = particle_emmiter_type::POINT;
    113                                 else if ( sub_type == "box" )               edata.type = particle_emmiter_type::BOX;
    114                                 else if ( sub_type == "cylinder" )          edata.type = particle_emmiter_type::CYLINDER;
    115                                 else if ( sub_type == "sphere" )            edata.type = particle_emmiter_type::SPHERE;
    116                                 else if ( sub_type == "cylindroid" )        edata.type = particle_emmiter_type::CYLINDROID;
    117                                 else if ( sub_type == "ellipsoid" )         edata.type = particle_emmiter_type::ELLIPSOID;
    118                                 else if ( sub_type == "hollow_cylinder" )   edata.type = particle_emmiter_type::HOLLOW_CYLINDER;
    119                                 else if ( sub_type == "hollow_sphere" )     edata.type = particle_emmiter_type::HOLLOW_SPHERE;
    120                                 else if ( sub_type == "hollow_cylindroid" ) edata.type = particle_emmiter_type::HOLLOW_CYLINDROID;
    121                                 else if ( sub_type == "hollow_ellipsoid" )  edata.type = particle_emmiter_type::HOLLOW_ELLIPSOID;
     358                                auto emmiter_iter = m_emmiters.find( sub_type );
     359                                if ( emmiter_iter != m_emmiters.end() )
     360                                {
     361                                        edata.emmiter_func = emmiter_iter->second;
     362                                }
    122363                                else
    123364                                {
    124                                         edata.type = particle_emmiter_type::POINT;
     365                                        edata.emmiter_func = nv_particle_emmiter_point;
    125366                                        NV_LOG( LOG_WARNING, "Unknown emmiter type in particle system! (" << sub_type << ")" );
    126367                                }
     
    177418                else if ( type == "affector" )
    178419                {
    179 
     420                        if ( data.affector_count < MAX_PARTICLE_AFFECTORS )
     421                        {
     422                                particle_affector_data& adata = data.affectors[ data.affector_count ];
     423                                data.affector_count++;
     424                                auto affector_iter = m_affectors.find( sub_type );
     425                                if ( affector_iter != m_affectors.end() )
     426                                {
     427                                        adata.process = affector_iter->second.process;
     428                                        if ( !affector_iter->second.init( &element, &adata ) )
     429                                        {
     430                                                data.affector_count--;
     431                                                NV_LOG( LOG_WARNING, "Bad data passed to " << sub_type << " affector in particle system!" );
     432                                        }
     433                                }
     434                                else
     435                                {
     436                                        data.affector_count--;
     437                                        NV_LOG( LOG_WARNING, "Unknown affector type in particle system! (" << sub_type << ")" );
     438                                }
     439                        }
     440                        else
     441                        {
     442                                NV_LOG( LOG_ERROR, "Too many affectors (" << MAX_PARTICLE_AFFECTORS << " is MAX)!" );
     443                        }
    180444                }
    181445                else
     
    193457        m_program_local = m_device->create_program( nv_particle_engine_vertex_shader_local, nv_particle_engine_fragment_shader );
    194458        m_program_world = m_device->create_program( nv_particle_engine_vertex_shader_world, nv_particle_engine_fragment_shader );
     459
     460        register_standard_emmiters();
     461        register_standard_affectors();
    195462}
    196463
     
    324591        vec3 z( 0.0f, 0.0f ,1.0f );
    325592
    326         mat3 rot_mat;
    327         vec3 right;
    328         mat3 irot_mat = glm::transpose( mat3( m_view_matrix ) );
    329593        particle_orientation orientation = info->data->orientation;
    330594        vec3 common_up ( info->data->common_up );
    331595        vec3 common_dir( info->data->common_dir );
    332596        bool accurate_facing = info->data->accurate_facing;
    333 
     597        mat3 rot_mat;
     598        vec3 right;
     599        vec3 pdir( 0.0f, 1.0f, 0.0f );
    334600
    335601        for ( uint32 i = 0; i < info->count; ++i )
     
    346612                        right   = glm::normalize( glm::cross( view_dir, vec3( 0, 1, 0 ) ) );
    347613                        rot_mat = mat3( right, glm::cross( right, -view_dir ), -view_dir );
    348 //                      rot_mat = irot_mat * glm::mat3_cast( glm::angleAxis( pdata.rotation, z ) );
    349614                        break;
    350615                case particle_orientation::ORIENTED :
    351                         right   = glm::normalize( glm::cross( pdata.dir, view_dir ) );
    352                         rot_mat = mat3( right, pdata.dir, glm::cross( pdata.dir, right ) );
     616                        pdir    = normalize_safe( pdata.velocity, pdir );
     617                        right   = glm::normalize( glm::cross( pdir, view_dir ) );
     618                        rot_mat = mat3( right, pdir, glm::cross( pdir, right ) );
    353619                        break;
    354620                case particle_orientation::ORIENTED_COMMON :
     
    357623                        break;
    358624                case particle_orientation::PERPENDICULAR :
    359                         right   = glm::normalize( glm::cross( common_up, pdata.dir ) );
     625                        pdir    = normalize_safe( pdata.velocity, pdir );
     626                        right   = glm::normalize( glm::cross( common_up, pdir ) );
    360627                        rot_mat = mat3( right, common_up, glm::cross( common_up, right ) );
    361628                        break;
     
    412679        vec3 source;
    413680        mat3 orient;
    414         if ( !info->data->local )
     681        bool local = info->data->local;
     682        if ( !local )
    415683        {
    416684                source = vec3( m_model_matrix[3] );
    417685                orient = mat3( m_model_matrix );
    418686        }
     687
    419688        float fms = float(ms);
    420689
     
    431700                                {
    432701                                        particle& pinfo = info->particles[info->count];
    433                                         switch ( edata.type )
    434                                         {
    435                                         case particle_emmiter_type::POINT:
    436                                                 pinfo.position = source;
    437                                                 break;
    438                                         case particle_emmiter_type::BOX:
    439                                                 pinfo.position = source + orient * (
    440                                                         r.frange( -edata.hextents[0], edata.hextents[0] ) * edata.cdir +
    441                                                         r.frange( 0.0f, edata.extents[1] ) * edata.dir +
    442                                                         r.frange( -edata.hextents[2], edata.hextents[2] ) * edata.odir
    443                                                 );
    444                                                 break;
    445                                         case particle_emmiter_type::CYLINDER:
    446                                                 {
    447                                                         vec2 rellipse = r.disk_point( edata.precise );
    448                                                         pinfo.position = source + orient * (
    449                                                                 rellipse.x * edata.extents[0] * edata.cdir +
    450                                                                 r.frange( 0.0f, edata.extents[1] ) * edata.dir +
    451                                                                 rellipse.y * edata.extents[0] * edata.odir
    452                                                                 );
    453                                                 }
    454                                                 break;
    455                                         case particle_emmiter_type::SPHERE:
    456                                                 {
    457                                                         vec3 rellipse = r.sphere_point( edata.precise );
    458                                                         pinfo.position = source + orient * (
    459                                                                 rellipse.x * edata.extents[0] * edata.cdir +
    460                                                                 rellipse.y * edata.extents[0] * edata.dir +
    461                                                                 rellipse.z * edata.extents[0] * edata.odir
    462                                                                 );
    463                                                 }
    464                                                 break;
    465                                         // TODO : this method is NOT uniform if width != height!
    466                                         case particle_emmiter_type::CYLINDROID:
    467                                                 {
    468                                                         vec2 rellipse = r.ellipse_point( vec2( edata.hextents[0], edata.hextents[2] ), edata.precise );
    469                                                         pinfo.position = source + orient * (
    470                                                                 rellipse.x * edata.cdir +
    471                                                                 r.frange( 0.0f, edata.extents[1] ) * edata.dir +
    472                                                                 rellipse.y * edata.odir
    473                                                         );
    474                                                 }
    475                                                 break;
    476                                         // TODO : this method is NOT uniform if all dimension are not equal!
    477                                         case particle_emmiter_type::ELLIPSOID:
    478                                                 {
    479                                                         vec3 rsphere = r.ellipsoid_point( edata.hextents, edata.precise );
    480                                                         pinfo.position = source + orient * (
    481                                                                 rsphere.x * edata.cdir +
    482                                                                 rsphere.y * edata.dir +
    483                                                                 rsphere.z * edata.odir
    484                                                                 );
    485                                                 }
    486                                                 break;
    487                                         case particle_emmiter_type::HOLLOW_CYLINDER:
    488                                                 {
    489                                                         vec2 rellipse = r.hollow_disk_point(
    490                                                                 edata.ihextents[0],
    491                                                                 edata.hextents[0],
    492                                                                 edata.precise );
    493                                                         pinfo.position = source + orient * (
    494                                                                 rellipse.x * edata.cdir +
    495                                                                 r.frange( 0.0f, edata.extents[1] ) * edata.dir +
    496                                                                 rellipse.y * edata.odir
    497                                                                 );
    498                                                 }
    499                                                 break;
    500                                         case particle_emmiter_type::HOLLOW_SPHERE:
    501                                                 {
    502                                                         vec3 rellipse = r.hollow_sphere_point(
    503                                                                 edata.ihextents[0],
    504                                                                 edata.hextents[0],
    505                                                                 edata.precise );
    506                                                         pinfo.position = source + orient * (
    507                                                                 rellipse.x * edata.cdir +
    508                                                                 rellipse.y * edata.dir +
    509                                                                 rellipse.z * edata.odir
    510                                                                 );
    511                                                 }
    512                                                 break;
    513                                         case particle_emmiter_type::HOLLOW_CYLINDROID:
    514                                                 {
    515                                                         vec2 rellipse = r.hollow_ellipse_point(
    516                                                                 vec2( edata.ihextents[0], edata.ihextents[2] ),
    517                                                                 vec2( edata.hextents[0], edata.hextents[2] ),
    518                                                                 edata.precise );
    519                                                         pinfo.position = source + orient * (
    520                                                                 rellipse.x * edata.cdir +
    521                                                                 r.frange( 0.0f, edata.extents[1] ) * edata.dir +
    522                                                                 rellipse.y * edata.odir
    523                                                                 );
    524                                                 }
    525                                                 break;
    526                                         // TODO : this method is NOT uniform if all dimension are not equal!
    527                                         case particle_emmiter_type::HOLLOW_ELLIPSOID:
    528                                                 {
    529                                                         vec3 rellipse = r.hollow_ellipsoid_point( edata.ihextents, edata.hextents, edata.precise );
    530                                                         pinfo.position = source + orient * (
    531                                                                 rellipse.x * edata.cdir +
    532                                                                 rellipse.y * edata.dir +
    533                                                                 rellipse.z * edata.odir
    534                                                                 );
    535                                                 }
    536                                                 break;
    537                                         }
     702                                        edata.emmiter_func( &(info->data->emmiters[i]), &pinfo, 1 );
     703
     704                                        if ( !local ) pinfo.position  = orient * pinfo.position + source;
    538705                                        pinfo.position += edata.position;
    539706                                        pinfo.color     = edata.color_min == edata.color_max ?
     
    542709                                                edata.size_min : r.range( edata.size_min, edata.size_max );
    543710                                        if ( edata.square ) pinfo.size.y = pinfo.size.x;
    544                                         pinfo.velocity  = edata.velocity_min == edata.velocity_max ?
     711                                        float velocity  = edata.velocity_min == edata.velocity_max ?
    545712                                                edata.velocity_min : r.frange( edata.velocity_min, edata.velocity_max );
    546713                                        pinfo.death     = ms + ( edata.lifetime_min == edata.lifetime_max ?
     
    548715                                        //pinfo.rotation = r.frand( 360.0f );
    549716
    550                                         pinfo.dir = edata.dir;
     717                                        pinfo.velocity = edata.dir;
    551718                                        if ( edata.angle > 0.0f )
    552719                                        {
     
    555722                                                float sin_theta = glm::sqrt(1.0f - cos_theta * cos_theta );
    556723                                                float phi       = r.frange( 0.0f, 2*glm::pi<float>() );
    557                                                 pinfo.dir = orient *
     724                                                pinfo.velocity = orient *
    558725                                                        ( edata.odir * ( glm::cos(phi) * sin_theta ) +
    559726                                                        edata.cdir * ( glm::sin(phi)*sin_theta ) +
    560727                                                        edata.dir  * cos_theta );
    561728                                        }
     729
     730                                        pinfo.velocity *= velocity;
    562731
    563732                                        info->count++;
     
    569738}
    570739
    571 void nv::particle_engine::update_particles( particle_system_info* system, uint32 ms )
    572 {
    573         uint32 ticks = ms - system->last_update;
    574         if ( ticks > 0 )
    575                 for ( uint32 i = 0; i < system->count; ++i )
    576                 {
    577                         particle& pdata = system->particles[i];
    578                         vec3 velocity_vec = pdata.dir * pdata.velocity;
    579                         pdata.position += velocity_vec * ( 0.001f * ticks );
    580                         velocity_vec   += system->data->gravity * ( 0.001f * ticks );
    581                         pdata.velocity  = glm::length( velocity_vec );
    582                         if ( pdata.velocity > 0.0f ) pdata.dir       = glm::normalize( velocity_vec );
    583                         if ( pdata.position.y < 0.0f )
    584                         {
    585                                 if ( pdata.velocity > 1.0f )
    586                                 {
    587                                         pdata.position.y = -pdata.position.y;
    588                                         pdata.velocity   = 0.5f*pdata.velocity;
    589                                         pdata.dir.y      = -pdata.dir.y;
    590                                 }
    591                                 else
    592                                 {
    593                                         pdata.position.y = 0.0f;
    594                                         pdata.velocity   = 0.0f;
    595                                 }
    596                         }
    597                 }
    598                 system->last_update = ms;
     740void nv::particle_engine::update_particles( particle_system_info* info, uint32 ms )
     741{
     742        uint32 ticks = ms - info->last_update;
     743        if ( ticks == 0 ) return;
     744        float factor  = 0.001f * ticks;
     745
     746        uint32 acount = info->data->affector_count;
     747        for ( uint32 i = 0; i < acount; ++i )
     748        {
     749                const particle_affector_data* padata = &(info->data->affectors[i]);
     750                padata->process( padata, info->particles, factor, info->count );
     751        }
     752
     753
     754        for ( uint32 i = 0; i < info->count; ++i )
     755        {
     756                particle& pdata = info->particles[i];
     757                pdata.position += pdata.velocity * factor;
     758        }
     759        info->last_update = ms;
    599760}
    600761
     
    630791
    631792}
     793
     794void nv::particle_engine::register_emmiter_type( const std::string& name, particle_emmiter_func func )
     795{
     796        m_emmiters[ name ] = func;
     797}
     798
     799void nv::particle_engine::register_standard_emmiters()
     800{
     801        register_emmiter_type( "point",             nv_particle_emmiter_point );
     802        register_emmiter_type( "box",               nv_particle_emmiter_box );
     803        register_emmiter_type( "cylinder",          nv_particle_emmiter_cylinder );
     804        register_emmiter_type( "sphere",            nv_particle_emmiter_sphere );
     805        register_emmiter_type( "cylindroid",        nv_particle_emmiter_cylindroid );
     806        register_emmiter_type( "ellipsoid",         nv_particle_emmiter_ellipsoid );
     807        register_emmiter_type( "hollow_cylinder",   nv_particle_emmiter_hollow_cylinder );
     808        register_emmiter_type( "hollow_sphere",     nv_particle_emmiter_hollow_sphere );
     809        register_emmiter_type( "hollow_cylindroid", nv_particle_emmiter_hollow_cylindroid );
     810        register_emmiter_type( "hollow_ellipsoid",  nv_particle_emmiter_hollow_ellipsoid );
     811}
     812
     813void nv::particle_engine::register_affector_type( const std::string& name, particle_affector_init_func init, particle_affector_func process )
     814{
     815        m_affectors[ name ].init    = init;
     816        m_affectors[ name ].process = process;
     817}
     818
     819void nv::particle_engine::register_standard_affectors()
     820{
     821        register_affector_type( "linear_force",    nv_particle_affector_linear_force_init, nv_particle_affector_linear_force );
     822        register_affector_type( "deflector_plane", nv_particle_affector_deflector_plane_init, nv_particle_affector_deflector_plane );
     823        register_affector_type( "color_fader",     nv_particle_affector_color_fader_init, nv_particle_affector_color_fader );
     824        register_affector_type( "scaler",          nv_particle_affector_scaler_init, nv_particle_affector_scaler );
     825}
     826
Note: See TracChangeset for help on using the changeset viewer.