Ignore:
Timestamp:
08/12/14 20:37:39 (11 years ago)
Author:
epyon
Message:
  • origin parameter for particle system (TOP_LEFT, etc)
  • precise parameter for switching to more precise distribution
  • support for multiple emmiter types: POINT, BOX, CYLINDER, CYLINDROID, SPHERE, ELLIPSOID, HOLLOW_CYLINDER, HOLLOW_CYLINDROID, HOLLOW_SPHERE, HOLLOW_ELLIPSOID
  • minor fixes
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gfx/particle_engine.cc

    r307 r309  
    55#include <nv/lua/lua_glm.hh>
    66#include <nv/logging.hh>
     7#include <cmath>
    78
    89static const char *nv_particle_engine_vertex_shader_world =
     
    6162        data.gravity = table.get<vec3>("gravity", vec3() );
    6263        data.quota   = table.get<uint32>("quota", 1024 );
    63         data.local   = table.get<bool>("local", false );
     64        data.local   = table.get<bool>("local_space", false );
    6465        data.accurate_facing = table.get<bool>("accurate_facing", false );
    6566        data.emmiter_count   = 0;
     
    7374        else
    7475        {
    75                 NV_LOG( LOG_ERROR, "Unknown orientation type! (" << orientation << " is MAX)!" );
     76                NV_LOG( LOG_ERROR, "Unknown orientation type! (" << orientation << ")!" );
    7677                data.orientation = particle_orientation::POINT;
    7778        }
     79
     80        std::string origin = table.get_string( "origin", "center" );
     81        if      ( origin == "center" )        { data.origin = particle_origin::CENTER; }
     82        else if ( origin == "top_left" )      { data.origin = particle_origin::TOP_LEFT; }
     83        else if ( origin == "top_center" )    { data.origin = particle_origin::TOP_CENTER; }
     84        else if ( origin == "top_right" )     { data.origin = particle_origin::TOP_RIGHT; }
     85        else if ( origin == "center_left" )   { data.origin = particle_origin::CENTER_LEFT; }
     86        else if ( origin == "center_right" )  { data.origin = particle_origin::CENTER_RIGHT; }
     87        else if ( origin == "bottom_left" )   { data.origin = particle_origin::BOTTOM_LEFT; }
     88        else if ( origin == "bottom_center" ) { data.origin = particle_origin::BOTTOM_CENTER; }
     89        else if ( origin == "bottom_right" )  { data.origin = particle_origin::BOTTOM_RIGHT; }
     90        else
     91        {
     92                NV_LOG( LOG_ERROR, "Unknown particle origin! (" << origin << ")!" );
     93                data.origin = particle_origin::CENTER;
     94        }
     95
    7896        data.common_up  = glm::normalize( table.get<vec3>("common_up",  vec3(1,0,0) ) );
    7997        data.common_dir = glm::normalize( table.get<vec3>("common_dir", vec3(0,1,0) ) );
    8098
     99        vec2 def_size        = table.get<vec2>("size", vec2(0.1,0.1) );
    81100        uint32 elements = table.get_size();
    82101        for ( uint32 i = 0; i < elements; ++i )
    83102        {
    84103                lua::table_guard element( table, i+1 );
    85                 std::string type  = element.get_string("type");
    86                 std::string etype = element.get_string("etype");
     104                std::string type     = element.get_string("type");
     105                std::string sub_type = element.get_string("sub_type");
    87106                if ( type == "emmiter" )
    88107                {
     
    90109                        {
    91110                                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;
     122                                else
     123                                {
     124                                        edata.type = particle_emmiter_type::POINT;
     125                                        NV_LOG( LOG_WARNING, "Unknown emmiter type in particle system! (" << sub_type << ")" );
     126                                }
     127
     128                                edata.position     = element.get<vec3>("position", vec3() );
     129                                edata.extents      = element.get<vec3>("extents", vec3(1,1,1) );
     130                                edata.extents[0]   = element.get<float>("width",  edata.extents[0] );
     131                                edata.extents[1]   = element.get<float>("depth",  edata.extents[1] );
     132                                edata.extents[2]   = element.get<float>("height", edata.extents[2] );
     133                                edata.extents[0]   = element.get<float>("radius",  edata.extents[0] );
     134                                edata.iextents     = element.get<vec3>("inner_extents", vec3() );
     135                                edata.iextents[0]  = element.get<float>("inner_width",  edata.iextents[0] );
     136                                edata.iextents[1]  = element.get<float>("inner_depth",  edata.iextents[1] );
     137                                edata.iextents[2]  = element.get<float>("inner_height", edata.iextents[2] );
     138                                edata.iextents[0]  = element.get<float>("inner_radius",  edata.iextents[0] );
     139                                edata.hextents     = 0.5f * edata.extents;
     140                                edata.ihextents    = 0.5f * edata.iextents;
     141                                edata.precise      = element.get<bool>("precise", false );
     142                                edata.square       = element.get<bool>("square", true );
    92143                                vec4 color         = element.get<vec4>("color", vec4(1,1,1,1) );
    93144                                edata.color_min    = element.get<vec4>("color_min", color );
    94145                                edata.color_max    = element.get<vec4>("color_max", color );
    95                                 vec2 size          = element.get<vec2>("size", vec2(0.1,0.1) );
     146                                vec2 size          = element.get<vec2>("size", def_size );
    96147                                edata.size_min     = element.get<vec2>("size_min", size );
    97148                                edata.size_max     = element.get<vec2>("size_max", size );
    98                                 edata.square       = element.get<bool>("square", true );
    99149                                edata.angle        = element.get<float>("angle", 0.0f );
    100150                                float velocity     = element.get<float>("velocity", 0.0f );
     
    249299void nv::particle_engine::generate_data( particle_system_info* info )
    250300{
    251         const vec3 x( 0.5f, 0.0f, 0.0f );
    252         const vec3 y( 0.0f, 0.5f, 0.0f );
    253         const vec3 z( 0.0f, 0.0f ,1.0f );
    254 
    255         const vec3 sm[4] = {
    256                 vec3( -x-y ),
    257                 vec3(  x-y ),
    258                 vec3( -x+y ),
    259                 vec3(  x+y )
     301        vec2 lb     = vec2( -0.5f, -0.5f );
     302        vec2 rt     = vec2( 0.5f, 0.5f );
     303
     304        switch ( info->data->origin )
     305        {
     306        case particle_origin::CENTER        : break;
     307        case particle_origin::TOP_LEFT      : lb = vec2(0.f,-1.f); rt = vec2(1.f,0.f);  break;
     308        case particle_origin::TOP_CENTER    : lb.y = -1.f; rt.y = 0.f; break;  break;
     309        case particle_origin::TOP_RIGHT     : lb = vec2(-1.f,-1.f); rt = vec2(); break;
     310        case particle_origin::CENTER_LEFT   : lb.x = 0.f; rt.x = 1.f; break;
     311        case particle_origin::CENTER_RIGHT  : lb.x = -1.f; rt.x = 0.f; break;
     312        case particle_origin::BOTTOM_LEFT   : lb = vec2(); rt = vec2(1.f,1.f); break;
     313        case particle_origin::BOTTOM_CENTER : lb.y = 0.f; rt.y = 1.f; break;
     314        case particle_origin::BOTTOM_RIGHT  : lb = vec2(-1.f,0.f); rt = vec2(.0f,1.f); break;
     315        }
     316
     317        const vec3 sm[4] =
     318        {
     319                vec3( lb.x, lb.y, 0.0f ),
     320                vec3( rt.x, lb.y, 0.0f ),
     321                vec3( lb.x, rt.y, 0.0f ),
     322                vec3( rt.x, rt.y, 0.0f ),
    260323        };
     324        vec3 z( 0.0f, 0.0f ,1.0f );
    261325
    262326        mat3 rot_mat;
     
    353417                orient = mat3( m_model_matrix );
    354418        }
     419        float fms = float(ms);
    355420
    356421        for ( uint32 i = 0; i < ecount; ++i )
     
    360425                if ( einfo.active )
    361426                {
    362                         uint32 period = glm::max<uint32>( uint32(1000.f / edata.rate), 1 );
    363                         while ( ms - einfo.last_create > period )
     427                        float period = 1000.f / edata.rate;
     428                        while ( fms - einfo.last_create > period )
    364429                        {
    365430                                if ( info->count < info->data->quota-1 )
    366431                                {
    367432                                        particle& pinfo = info->particles[info->count];
    368                                         pinfo.position = source;
    369                                         pinfo.color    = edata.color_min == edata.color_max ?
     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                                        }
     538                                        pinfo.position += edata.position;
     539                                        pinfo.color     = edata.color_min == edata.color_max ?
    370540                                                edata.color_min : r.range( edata.color_min, edata.color_max );
    371                                         pinfo.size     = edata.size_min == edata.size_max ?
     541                                        pinfo.size      = edata.size_min == edata.size_max ?
    372542                                                edata.size_min : r.range( edata.size_min, edata.size_max );
    373543                                        if ( edata.square ) pinfo.size.y = pinfo.size.x;
     
    453623                        {
    454624                                einfo.active = true;
    455                                 einfo.last_create = einfo.next_toggle;
     625                                einfo.last_create = float( einfo.next_toggle );
    456626                                einfo.next_toggle += r.urange( edata.duration_min, edata.duration_max );
    457627                        }
Note: See TracChangeset for help on using the changeset viewer.