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

Last change on this file since 536 was 520, checked in by epyon, 9 years ago
  • ecs updates
  • animation updates
  • ragdoll manager
  • lua has own random engine
  • several minor fixes
  • particle engine/particle group
  • shitload of other stuff
  • bullet world
File size: 6.7 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        particle_group_info* info = m_groups.get( group );
36        if ( info )
37        {
38                delete[] info->quads;
39                m_context->release( info->vtx_array );
40                m_groups.destroy( group );
41        }
42}
43
44void particle_group_manager::prepare( particle_group group )
45{
46        particle_group_info* info = m_groups.get( group );
47        if ( info )
48        {
49                info->count = 0;
50        }
51}
52
53void particle_group_manager::reset()
54{
55        clear();
56}
57
58void particle_group_manager::generate_data(
59        array_view< particle > particles,
60        const particle_group_settings* data,
61        particle_group pgroup,
62        const scene_state& s
63)
64{
65        //      void* rawptr = m_context->map_buffer( info->vtx_buffer, nv::WRITE_UNSYNCHRONIZED, offset, info->count*sizeof( particle_quad ) );
66        //      particle_quad* quads = reinterpret_cast<particle_quad*>( rawptr );
67
68        particle_group_info* group = m_groups.get( pgroup );
69
70        if ( particles.size() == 0 || !data || !group )
71        {
72                return;
73        }
74
75        vec2 lb = vec2( -0.5f, -0.5f );
76        vec2 rt = vec2( 0.5f, 0.5f );
77
78        switch ( data->origin )
79        {
80        case particle_origin::CENTER: break;
81        case particle_origin::TOP_LEFT: lb = vec2( 0.f, -1.f ); rt = vec2( 1.f, 0.f );  break;
82        case particle_origin::TOP_CENTER: lb.y = -1.f; rt.y = 0.f; break;
83        case particle_origin::TOP_RIGHT: lb = vec2( -1.f, -1.f ); rt = vec2(); break;
84        case particle_origin::CENTER_LEFT: lb.x = 0.f; rt.x = 1.f; break;
85        case particle_origin::CENTER_RIGHT: lb.x = -1.f; rt.x = 0.f; break;
86        case particle_origin::BOTTOM_LEFT: lb = vec2(); rt = vec2( 1.f, 1.f ); break;
87        case particle_origin::BOTTOM_CENTER: lb.y = 0.f; rt.y = 1.f; break;
88        case particle_origin::BOTTOM_RIGHT: lb = vec2( -1.f, 0.f ); rt = vec2( .0f, 1.f ); break;
89        }
90
91        const vec3 sm[4] =
92        {
93                vec3( lb.x, lb.y, 0.0f ),
94                vec3( rt.x, lb.y, 0.0f ),
95                vec3( lb.x, rt.y, 0.0f ),
96                vec3( rt.x, rt.y, 0.0f ),
97        };
98        vec3 z( 0.0f, 0.0f, 1.0f );
99
100        particle_orientation orientation = data->orientation;
101        vec3 common_up( data->common_up );
102        vec3 common_dir( data->common_dir );
103        bool accurate_facing = data->accurate_facing;
104        mat3 rot_mat;
105        vec3 right;
106        vec3 pdir( 0.0f, 1.0f, 0.0f );
107
108        vec3 camera_pos = s.get_camera().get_position();
109        vec3 inv_view_dir = math::normalize( -s.get_camera().get_direction() );
110
111        for ( uint32 i = 0; i < particles.size(); ++i )
112        {
113                const particle& pdata = particles[i];
114                //              particle_quad& rdata  = quads[i];
115                particle_quad& rdata = group->quads[i + group->count];
116
117                vec3 view_dir( inv_view_dir );
118                if ( accurate_facing ) view_dir = math::normalize( camera_pos - pdata.position );
119
120                switch ( orientation )
121                {
122                case particle_orientation::POINT:
123                        right = math::normalize( math::cross( view_dir, vec3( 0, 1, 0 ) ) );
124                        right = math::rotate( right, pdata.rotation, view_dir );
125                        rot_mat = mat3( right, math::cross( right, -view_dir ), -view_dir );
126                        break;
127                case particle_orientation::ORIENTED:
128                        pdir = normalize_safe( pdata.velocity, pdir );
129                        right = math::normalize( math::cross( pdir, view_dir ) );
130                        rot_mat = mat3( right, pdir, math::cross( pdir, right ) );
131                        break;
132                case particle_orientation::ORIENTED_COMMON:
133                        right = math::normalize( math::cross( common_dir, view_dir ) );
134                        rot_mat = mat3( right, common_dir, math::cross( common_dir, right ) );
135                        break;
136                case particle_orientation::PERPENDICULAR:
137                        pdir = normalize_safe( pdata.velocity, pdir );
138                        right = math::normalize( math::cross( common_up, pdir ) );
139                        rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
140                        break;
141                case particle_orientation::PERPENDICULAR_COMMON:
142                        right = math::normalize( math::cross( common_up, common_dir ) );
143                        rot_mat = mat3( right, common_up, math::cross( common_up, right ) );
144                        break;
145                }
146
147                vec2 texcoords[4] =
148                {
149                        pdata.tcoord_a,
150                        vec2( pdata.tcoord_b.x, pdata.tcoord_a.y ),
151                        vec2( pdata.tcoord_a.x, pdata.tcoord_b.y ),
152                        pdata.tcoord_b
153                };
154
155                vec3 size( pdata.size.x, pdata.size.y, 0.0f );
156                vec3 s0 = rot_mat * ( ( size * sm[0] ) );
157                vec3 s1 = rot_mat * ( ( size * sm[1] ) );
158                vec3 s2 = rot_mat * ( ( size * sm[2] ) );
159                vec3 s3 = rot_mat * ( ( size * sm[3] ) );
160
161                rdata.data[0].position = pdata.position + s0;
162                rdata.data[0].color = pdata.color;
163                rdata.data[0].texcoord = texcoords[0];
164
165                rdata.data[1].position = pdata.position + s1;
166                rdata.data[1].color = pdata.color;
167                rdata.data[1].texcoord = texcoords[1];
168
169                rdata.data[2].position = pdata.position + s2;
170                rdata.data[2].color = pdata.color;
171                rdata.data[2].texcoord = texcoords[2];
172
173                rdata.data[3].position = pdata.position + s3;
174                rdata.data[3].color = pdata.color;
175                rdata.data[3].texcoord = texcoords[3];
176
177                rdata.data[4] = rdata.data[2];
178                rdata.data[5] = rdata.data[1];
179        }
180        //      m_context->unmap_buffer( info->vtx_buffer );
181
182        m_context->update( group->vtx_buffer, group->quads, group->count * sizeof( particle_quad ), particles.size() * sizeof( particle_quad ) );
183        group->count += particles.size();
184}
185
186particle_render_data nv::particle_group_manager::get_render_data( particle_group group )
187{
188        const particle_group_info* info = m_groups.get( group );
189        if ( info )
190        {
191                return{ info->count, info->vtx_array };
192        }
193        return{ 0, nv::vertex_array() };
194}
195
196particle_group_manager::~particle_group_manager()
197{
198        clear();
199}
200
201void particle_group_manager::clear()
202{
203        while ( m_groups.size() > 0 )
204                release( m_groups.get_handle( 0 ) );
205}
206
207bool particle_group_manager::ref( particle_group group )
208{
209        particle_group_info* info = m_groups.get( group );
210        if ( !info ) return false;
211        info->ref_counter++;
212        return true;
213}
214
215bool particle_group_manager::unref( 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
223
Note: See TracBrowser for help on using the repository browser.