source: trunk/src/engine/particle_group.cc @ 543

Last change on this file since 543 was 543, checked in by epyon, 8 years ago
  • fixes in handle store
  • removal of get_handle
  • indices instead of handles
  • efficient handle store clears
File size: 6.8 KB
Line 
1// Copyright (C) 2016-2016 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/engine/particle_group.hh"
8
9using namespace nv;
10
11particle_group_manager::particle_group_manager( context* a_context )
12        : m_context( a_context )
13{
14
15}
16
17particle_group particle_group_manager::create_group( uint32 max_particles )
18{
19        particle_group result = m_groups.create();
20        particle_group_info* info = m_groups.get( result );
21        info->local = false;
22        info->count = 0;
23        info->quota = max_particles;
24        info->vtx_buffer = m_context->create_buffer( VERTEX_BUFFER, STREAM_DRAW, info->quota * sizeof( particle_quad )/*, info->quads_[0].data*/ );
25        vertex_array_desc desc;
26        desc.add_vertex_buffers< particle_vtx >( info->vtx_buffer, true );
27        info->vtx_array = m_context->create_vertex_array( desc );
28        info->quads = new particle_quad[info->quota];
29        info->ref_counter = 0;
30        return result;
31}
32
33void particle_group_manager::release( particle_group group )
34{
35        if ( particle_group_info* info = m_groups.get( group ) )
36        {
37                release( info );
38                m_groups.destroy( group );
39        }
40}
41
42void particle_group_manager::prepare( particle_group group )
43{
44        particle_group_info* info = m_groups.get( group );
45        if ( info )
46        {
47                info->count = 0;
48        }
49}
50
51void particle_group_manager::reset()
52{
53        clear();
54}
55
56void particle_group_manager::generate_data(
57        array_view< particle > particles,
58        const particle_group_settings* data,
59        particle_group pgroup,
60        const scene_state& s
61)
62{
63        //      void* rawptr = m_context->map_buffer( info->vtx_buffer, nv::WRITE_UNSYNCHRONIZED, offset, info->count*sizeof( particle_quad ) );
64        //      particle_quad* quads = reinterpret_cast<particle_quad*>( rawptr );
65
66        particle_group_info* group = m_groups.get( pgroup );
67
68        if ( particles.size() == 0 || !data || !group )
69        {
70                return;
71        }
72
73        vec2 lb = vec2( -0.5f, -0.5f );
74        vec2 rt = vec2( 0.5f, 0.5f );
75
76        switch ( data->origin )
77        {
78        case particle_origin::CENTER: break;
79        case particle_origin::TOP_LEFT: lb = vec2( 0.f, -1.f ); rt = vec2( 1.f, 0.f );  break;
80        case particle_origin::TOP_CENTER: lb.y = -1.f; rt.y = 0.f; break;
81        case particle_origin::TOP_RIGHT: lb = vec2( -1.f, -1.f ); rt = vec2(); break;
82        case particle_origin::CENTER_LEFT: lb.x = 0.f; rt.x = 1.f; break;
83        case particle_origin::CENTER_RIGHT: lb.x = -1.f; rt.x = 0.f; break;
84        case particle_origin::BOTTOM_LEFT: lb = vec2(); rt = vec2( 1.f, 1.f ); break;
85        case particle_origin::BOTTOM_CENTER: lb.y = 0.f; rt.y = 1.f; break;
86        case particle_origin::BOTTOM_RIGHT: lb = vec2( -1.f, 0.f ); rt = vec2( .0f, 1.f ); break;
87        }
88
89        const vec3 sm[4] =
90        {
91                vec3( lb.x, lb.y, 0.0f ),
92                vec3( rt.x, lb.y, 0.0f ),
93                vec3( lb.x, rt.y, 0.0f ),
94                vec3( rt.x, rt.y, 0.0f ),
95        };
96        vec3 z( 0.0f, 0.0f, 1.0f );
97
98        particle_orientation orientation = data->orientation;
99        vec3 common_up( data->common_up );
100        vec3 common_dir( data->common_dir );
101        bool accurate_facing = data->accurate_facing;
102        mat3 rot_mat;
103        vec3 right;
104        vec3 pdir( 0.0f, 1.0f, 0.0f );
105
106        vec3 camera_pos = s.get_camera().get_position();
107        vec3 inv_view_dir = math::normalize( -s.get_camera().get_direction() );
108
109        for ( uint32 i = 0; i < particles.size(); ++i )
110        {
111                const particle& pdata = particles[i];
112                //              particle_quad& rdata  = quads[i];
113                particle_quad& rdata = group->quads[i + group->count];
114
115                vec3 view_dir( inv_view_dir );
116                if ( accurate_facing ) view_dir = math::normalize( camera_pos - pdata.position );
117
118                switch ( orientation )
119                {
120                case particle_orientation::POINT:
121                        right = math::normalize( math::cross( view_dir, vec3( 0, 1, 0 ) ) );
122                        right = math::rotate( right, pdata.rotation, view_dir );
123                        rot_mat = mat3( right, math::cross( right, -view_dir ), -view_dir );
124                        break;
125                case particle_orientation::ORIENTED:
126                        pdir = normalize_safe( pdata.velocity, pdir );
127                        right = math::normalize( math::cross( pdir, view_dir ) );
128                        rot_mat = mat3( right, pdir, math::cross( pdir, right ) );
129                        break;
130                case particle_orientation::ORIENTED_COMMON:
131                        right = math::normalize( math::cross( common_dir, view_dir ) );
132                        rot_mat = mat3( right, common_dir, math::cross( common_dir, right ) );
133                        break;
134                case particle_orientation::PERPENDICULAR:
135                        pdir = normalize_safe( pdata.velocity, pdir );
136                        right = math::normalize( math::cross( common_up, pdir ) );
137                        rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
138                        break;
139                case particle_orientation::PERPENDICULAR_COMMON:
140                        right = math::normalize( math::cross( common_up, common_dir ) );
141                        rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
142                        break;
143                }
144
145                vec2 texcoords[4] =
146                {
147                        pdata.tcoord_a,
148                        vec2( pdata.tcoord_b.x, pdata.tcoord_a.y ),
149                        vec2( pdata.tcoord_a.x, pdata.tcoord_b.y ),
150                        pdata.tcoord_b
151                };
152
153                vec3 size( pdata.size.x, pdata.size.y, 0.0f );
154                vec3 s0 = rot_mat * ( ( size * sm[0] ) );
155                vec3 s1 = rot_mat * ( ( size * sm[1] ) );
156                vec3 s2 = rot_mat * ( ( size * sm[2] ) );
157                vec3 s3 = rot_mat * ( ( size * sm[3] ) );
158
159                rdata.data[0].position = pdata.position + s0;
160                rdata.data[0].color = pdata.color;
161                rdata.data[0].texcoord = texcoords[0];
162
163                rdata.data[1].position = pdata.position + s1;
164                rdata.data[1].color = pdata.color;
165                rdata.data[1].texcoord = texcoords[1];
166
167                rdata.data[2].position = pdata.position + s2;
168                rdata.data[2].color = pdata.color;
169                rdata.data[2].texcoord = texcoords[2];
170
171                rdata.data[3].position = pdata.position + s3;
172                rdata.data[3].color = pdata.color;
173                rdata.data[3].texcoord = texcoords[3];
174
175                rdata.data[4] = rdata.data[2];
176                rdata.data[5] = rdata.data[1];
177        }
178        //      m_context->unmap_buffer( info->vtx_buffer );
179
180        m_context->update( group->vtx_buffer, group->quads, group->count * sizeof( particle_quad ), particles.size() * sizeof( particle_quad ) );
181        group->count += particles.size();
182}
183
184particle_render_data nv::particle_group_manager::get_render_data( particle_group group )
185{
186        const particle_group_info* info = m_groups.get( group );
187        if ( info )
188        {
189                return{ info->count, info->vtx_array };
190        }
191        return{ 0, nv::vertex_array() };
192}
193
194void nv::particle_group_manager::release( particle_group_info* info )
195{
196        if ( info )
197        {
198                delete[] info->quads;
199                m_context->release( info->vtx_array );
200        }
201}
202
203particle_group_manager::~particle_group_manager()
204{
205        clear();
206}
207
208void particle_group_manager::clear()
209{
210        for ( auto& g : m_groups )
211                release( &g );
212        m_groups.clear();
213}
214
215bool particle_group_manager::ref( particle_group group )
216{
217        particle_group_info* info = m_groups.get( group );
218        if ( !info ) return false;
219        info->ref_counter++;
220        return true;
221}
222
223bool particle_group_manager::unref( particle_group group )
224{
225        particle_group_info* info = m_groups.get( group );
226        if ( !info ) return false;
227        info->ref_counter--;
228        return true;
229}
230
231
Note: See TracBrowser for help on using the repository browser.