1 | #include "nv/engine/particle_manager.hh"
|
---|
2 |
|
---|
3 | #include "nv/lua/lua_raw.hh"
|
---|
4 | #include "nv/lua/lua_math.hh"
|
---|
5 |
|
---|
6 | static int nv_psystem_emitter_closure( lua_State * L )
|
---|
7 | {
|
---|
8 | luaL_checktype( L, 1, LUA_TTABLE );
|
---|
9 | lua_settop( L, 1 );
|
---|
10 | lua_pushvalue( L, lua_upvalueindex( 1 ) ); // type
|
---|
11 | lua_setfield( L, 1, "sub_type" );
|
---|
12 | lua_pushliteral( L, "emitter" );
|
---|
13 | lua_setfield( L, 1, "type" );
|
---|
14 | return 1;
|
---|
15 | }
|
---|
16 |
|
---|
17 | static int nv_psystem_affector_closure( lua_State * L )
|
---|
18 | {
|
---|
19 | luaL_checktype( L, 1, LUA_TTABLE );
|
---|
20 | lua_settop( L, 1 );
|
---|
21 | lua_pushvalue( L, lua_upvalueindex( 1 ) ); // type
|
---|
22 | lua_setfield( L, 1, "sub_type" );
|
---|
23 | lua_pushliteral( L, "affector" );
|
---|
24 | lua_setfield( L, 1, "type" );
|
---|
25 | return 1;
|
---|
26 | }
|
---|
27 |
|
---|
28 | static int nv_psystem_emitter( lua_State * L )
|
---|
29 | {
|
---|
30 | luaL_checkstring( L, 1 );
|
---|
31 | lua_settop( L, 1 );
|
---|
32 | lua_pushcclosure( L, nv_psystem_emitter_closure, 1 );
|
---|
33 | return 1;
|
---|
34 | }
|
---|
35 |
|
---|
36 | static int nv_psystem_affector( lua_State * L )
|
---|
37 | {
|
---|
38 | luaL_checkstring( L, 1 );
|
---|
39 | lua_settop( L, 1 );
|
---|
40 | lua_pushcclosure( L, nv_psystem_affector_closure, 1 );
|
---|
41 | return 1;
|
---|
42 | }
|
---|
43 |
|
---|
44 |
|
---|
45 | void nv::particle_manager::initialize( lua::state* state )
|
---|
46 | {
|
---|
47 | lua_resource_manager_base::initialize( state );
|
---|
48 | lua_State* L = state->get_raw();
|
---|
49 | lua_pushcfunction( L, nv_psystem_emitter );
|
---|
50 | lua_setglobal( L, "emitter" );
|
---|
51 | lua_pushcfunction( L, nv_psystem_affector );
|
---|
52 | lua_setglobal( L, "affector" );
|
---|
53 | }
|
---|
54 |
|
---|
55 | bool nv::particle_manager::load_resource( lua::table_guard& table, shash64 id )
|
---|
56 | {
|
---|
57 | particle_system_data* data = new particle_system_data;
|
---|
58 | data->quota = table.get<uint32>("quota", 1024 );
|
---|
59 | // data->local = table.get<bool>("local_space", false );
|
---|
60 | data->accurate_facing = table.get<bool>("accurate_facing", false );
|
---|
61 | data->emitter_count = 0;
|
---|
62 | data->affector_count = 0;
|
---|
63 | data->orientation = particle_orientation( table["orientation"].get_uint32() );
|
---|
64 | data->origin = particle_origin( table["origin"].get_uint32() );
|
---|
65 |
|
---|
66 | data->common_up = math::normalize( table["common_up"].as( vec3(1,0,0) ) );
|
---|
67 | data->common_dir = math::normalize( table["common_dir"].as( vec3(0,1,0) ) );
|
---|
68 |
|
---|
69 | vec2 def_size = table.get<vec2>("size", vec2(0.1,0.1) );
|
---|
70 | uint32 elements = table.size();
|
---|
71 | for ( uint32 i = 0; i < elements; ++i )
|
---|
72 | {
|
---|
73 | lua::table_guard element( table, i+1 );
|
---|
74 | const_string type = element["type"].get_string();
|
---|
75 | const_string sub_type = element["sub_type"].get_string();
|
---|
76 | if ( type == "emitter" )
|
---|
77 | {
|
---|
78 | if ( data->emitter_count < MAX_PARTICLE_EMITTERS )
|
---|
79 | {
|
---|
80 | particle_emitter_data& edata = data->emitters[ data->emitter_count ];
|
---|
81 | edata.emitter_func = particle_engine::get_emitter( sub_type );
|
---|
82 | if ( edata.emitter_func == nullptr )
|
---|
83 | {
|
---|
84 | NV_LOG_WARNING( "Unknown emitter type in particle system! (", sub_type, ")" );
|
---|
85 | break;
|
---|
86 | }
|
---|
87 |
|
---|
88 | edata.position = element["position"].as( vec3() );
|
---|
89 | edata.extents = element["extents"].as( vec3(1,1,1) );
|
---|
90 | edata.extents[0] = element["width"].as( edata.extents[0] );
|
---|
91 | edata.extents[1] = element["depth"].as( edata.extents[1] );
|
---|
92 | edata.extents[2] = element["height"].as( edata.extents[2] );
|
---|
93 | edata.extents[0] = element["radius"].as( edata.extents[0] );
|
---|
94 | edata.iextents = element["inner_extents"].as( vec3() );
|
---|
95 | edata.iextents[0] = element["inner_width"].as( edata.iextents[0] );
|
---|
96 | edata.iextents[1] = element["inner_depth"].as( edata.iextents[1] );
|
---|
97 | edata.iextents[2] = element["inner_height"].as( edata.iextents[2] );
|
---|
98 | edata.iextents[0] = element["inner_radius"].as( edata.iextents[0] );
|
---|
99 | edata.hextents = 0.5f * edata.extents;
|
---|
100 | edata.ihextents = 0.5f * edata.iextents;
|
---|
101 | edata.precise = element["precise"].as( false );
|
---|
102 | edata.square = element["square"].as( true );
|
---|
103 | vec4 color = element["color"].as( vec4(1,1,1,1) );
|
---|
104 | edata.color_min = element["color_min"].as( color );
|
---|
105 | edata.color_max = element["color_max"].as( color );
|
---|
106 | vec2 size = element["size"].as( def_size );
|
---|
107 | edata.size_min = element["size_min"].as( size );
|
---|
108 | edata.size_max = element["size_max"].as( size );
|
---|
109 | edata.angle = element["angle"].as( 0.0f );
|
---|
110 | float velocity = element["velocity"].as( 0.0f );
|
---|
111 | edata.velocity_min = element["velocity_min"].as( velocity );
|
---|
112 | edata.velocity_max = element["velocity_max"].as( velocity );
|
---|
113 | float lifetime = element["lifetime"].as( 1.0f );
|
---|
114 | edata.lifetime_min = element["lifetime_min"].as( lifetime );
|
---|
115 | edata.lifetime_max = element["lifetime_max"].as( lifetime );
|
---|
116 | float duration = element["duration"].as( 0.0f );
|
---|
117 | edata.duration_min = element["duration_min"].as( duration );
|
---|
118 | edata.duration_max = element["duration_max"].as( duration );
|
---|
119 | float repeat = element["repeat_delay"].as( 0.0f );
|
---|
120 | edata.repeat_min = element["repeat_delay_min"].as( repeat );
|
---|
121 | edata.repeat_max = element["repeat_delay_max"].as( repeat );
|
---|
122 |
|
---|
123 | edata.rate = element["rate"].as( 1.0f );
|
---|
124 | edata.dir = math::normalize( element["direction"].as( vec3(0,1,0) ) );
|
---|
125 |
|
---|
126 | edata.odir = vec3( 0, 0, 1 );
|
---|
127 | if ( edata.dir != vec3( 0, 1, 0 ) && edata.dir != vec3( 0, -1, 0 ) )
|
---|
128 | edata.odir = math::normalize( math::cross( edata.dir, vec3( 0, 1, 0 ) ) );
|
---|
129 | edata.cdir = math::cross( edata.dir, edata.odir );
|
---|
130 |
|
---|
131 | data->emitter_count++;
|
---|
132 | }
|
---|
133 | else
|
---|
134 | {
|
---|
135 | NV_LOG_ERROR( "Too many emitters (", MAX_PARTICLE_EMITTERS, " is MAX)!" );
|
---|
136 | }
|
---|
137 | }
|
---|
138 | else if ( type == "affector" )
|
---|
139 | {
|
---|
140 | if ( data->affector_count < MAX_PARTICLE_AFFECTORS )
|
---|
141 | {
|
---|
142 | particle_affector_data& adata = data->affectors[ data->affector_count ];
|
---|
143 | auto afuncs = particle_engine::get_affector( sub_type );
|
---|
144 | if ( !afuncs.init || !afuncs.process )
|
---|
145 | {
|
---|
146 | NV_LOG_WARNING( "Unknown affector type in particle system! (", sub_type, ")" );
|
---|
147 | continue;
|
---|
148 | }
|
---|
149 | adata.process = afuncs.process;
|
---|
150 | if ( !afuncs.init( &element, &adata ) )
|
---|
151 | {
|
---|
152 | NV_LOG_WARNING( "Bad data passed to ", sub_type, " affector in particle system!" );
|
---|
153 | }
|
---|
154 | data->affector_count++;
|
---|
155 | }
|
---|
156 | else
|
---|
157 | {
|
---|
158 | NV_LOG_ERROR( "Too many affectors (", MAX_PARTICLE_AFFECTORS, " is MAX)!" );
|
---|
159 | }
|
---|
160 | }
|
---|
161 | else
|
---|
162 | {
|
---|
163 | NV_LOG_WARNING( "Unknown element in particle system! (", type, ")" );
|
---|
164 | }
|
---|
165 | }
|
---|
166 | add( id, data );
|
---|
167 | return true;
|
---|
168 | }
|
---|
169 |
|
---|