source: trunk/src/gfx/mesh_creator.cc @ 457

Last change on this file since 457 was 457, checked in by epyon, 10 years ago
  • mesh_creator - mirror and swap_culling, const on merge and is_same_format
  • mesh_data_pack - get by hash
File size: 20.3 KB
RevLine 
[395]1// Copyright (C) 2012-2015 ChaosForge Ltd
[293]2// http://chaosforge.org/
3//
[395]4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
[293]6
7#include "nv/gfx/mesh_creator.hh"
8
[416]9#include "nv/interface/data_channel_access.hh"
10
[293]11struct nv_key_transform { nv::transform tform; };
12
13void nv::mesh_nodes_creator::pre_transform_keys()
14{
15        if ( m_data->m_flat ) return;
16        merge_keys();
17        uint32 max_frames = 0;
[428]18        for ( auto keys : m_data->m_data )
[293]19        {
[427]20                sint16 parent_id = keys->get_parent_id();
21                data_channel_set* pkeys  = ( parent_id != -1 ? m_data->m_data[parent_id] : nullptr );
[417]22                size_t count     = ( keys ? keys->get_channel_size(0) : 0 );
23                size_t pcount    = ( pkeys ? pkeys->get_channel_size(0) : 0 );
[398]24                max_frames = nv::max<uint32>( count, max_frames );
[416]25                if ( pkeys && pkeys->size() > 0 && keys && keys->size() > 0 )
[293]26                {
[417]27                        data_channel_access< nv_key_transform > channel_creator( keys, 0 );
[413]28                        nv_key_transform* channel = channel_creator.data();
29                        const nv_key_transform* pchannel = pkeys->get_channel(0)->data_cast< nv_key_transform >();
[293]30                        for ( unsigned n = 0; n < count; ++n )
31                        {
[398]32                                channel[n].tform = pchannel[ nv::min( n, pcount-1 ) ].tform * channel[n].tform;
[293]33                        }
34                }
35        }
36
37        // DAE pre_transform hack
38        if ( m_data->m_frame_rate == 1 )
39        {
40                m_data->m_frame_rate = 32;
[406]41                m_data->m_duration   = static_cast<float>( max_frames );
[293]42        }
43
44        m_data->m_flat = true;
45}
46
47
48void nv::mesh_nodes_creator::merge_keys()
49{
[428]50        for ( size_t i = 0; i < m_data->size(); ++i )
[293]51        {
[427]52                data_channel_set* old_keys = m_data->m_data[i];
[416]53                if ( old_keys && old_keys->size() > 0 )
[293]54                {
[416]55                        size_t chan_count = old_keys->size();
[293]56                        if ( chan_count == 1
[415]57                                && old_keys->get_channel(0)->descriptor().size() == 1
[412]58                                && old_keys->get_channel(0)->descriptor()[0].etype == TRANSFORM ) continue;
[293]59
60                        size_t max_keys = 0;
61                        for ( size_t c = 0; c < chan_count; ++c )
62                        {
[415]63                                max_keys = nv::max( max_keys, old_keys->get_channel(c)->size() );
[293]64                        }
65
[424]66                        data_channel_set* new_keys = data_channel_set_creator::create_set( 1 );
[419]67                        data_channel_set_creator nk_access( new_keys );
[424]68                        nk_access.set_name( old_keys->get_name() );
69                        nk_access.set_parent_id( old_keys->get_parent_id() );
70                        nk_access.set_transform( old_keys->get_transform() );
[417]71                        data_channel_access< nv_key_transform > kt_channel( nk_access.add_channel<nv_key_transform>( max_keys ) );
72
[419]73                        raw_channel_interpolator interpolator( old_keys );
74                        data_descriptor final_key = interpolator.get_interpolation_key();
[293]75
76                        for ( unsigned n = 0; n < max_keys; ++n )
77                        {
78                                float key[ 16 ];
79                                float* pkey = key;
80
81                                for ( uint16 c = 0; c < chan_count; ++c )
82                                {
[418]83                                        size_t idx = nv::min( old_keys->get_channel_size(c) - 1, n );
[419]84                                        pkey += raw_channel_interpolator::get_raw( *old_keys->get_channel(c), idx, pkey );
[293]85                                }
[419]86                                kt_channel.data()[n].tform = extract_key_raw< nv::transform >( final_key, key );
[293]87                        }
88
89                        delete old_keys;
[427]90                        m_data->m_data[i] = new_keys;
[293]91                }
92        }
93}
94
95void nv::mesh_nodes_creator::transform( float scale, const mat3& r33 )
96{
[454]97        mat3 ri33 = math::inverse( r33 );
[293]98        mat4 pre_transform ( scale * r33 );
99        mat4 post_transform( 1.f/scale * ri33 );
100
[428]101        for ( auto node : m_data->m_data )
[293]102        {
[427]103                node->m_transform = pre_transform * node->m_transform * post_transform;
104
105                for ( size_t c = 0; c < node->size(); ++c )
[293]106                {
[427]107                        raw_data_channel_access channel( node, c );
108                        size_t key_size = channel.element_size();
109                        for ( size_t n = 0; n < channel.size(); ++n )
[293]110                        {
[427]111                                transform_key_raw( node->get_channel( c )->descriptor(), channel.raw_data() + n * key_size, scale, r33, ri33 );
[293]112                        }
113                }
114        }
115}
116
[456]117nv::mesh_data_creator::mesh_data_creator( data_channel_set* data ) : m_data( data )
118{
119        initialize();
120}
121
[293]122void nv::mesh_data_creator::transform( float scale, const mat3& r33 )
123{
[398]124        vec3 vertex_offset     = vec3();
[293]125        mat3 vertex_transform  = scale * r33;
126        mat3 normal_transform  = r33;
127
[416]128        for ( uint32 c = 0; c < m_data->size(); ++c )
[293]129        {
[417]130                raw_data_channel_access channel( m_data, c );
[413]131                const data_descriptor&  desc    = channel.descriptor();
132                uint8* raw_data = channel.raw_data();
[410]133                uint32 vtx_size = desc.element_size();
[293]134                int p_offset = -1;
135                int n_offset = -1;
136                int t_offset = -1;
[410]137                for ( const auto& cslot : desc  )
138                        switch ( cslot.vslot )
[293]139                        {
[410]140                                case slot::POSITION : if ( cslot.etype == FLOAT_VECTOR_3 ) p_offset = int( cslot.offset ); break;
141                                case slot::NORMAL   : if ( cslot.etype == FLOAT_VECTOR_3 ) n_offset = int( cslot.offset ); break;
142                                case slot::TANGENT  : if ( cslot.etype == FLOAT_VECTOR_4 ) t_offset = int( cslot.offset ); break;
[293]143                                default             : break;
144                        }
145
146                if ( p_offset != -1 )
[413]147                        for ( uint32 i = 0; i < channel.size(); i++)
[293]148                        {
[406]149                                vec3& p = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + p_offset );
[293]150                                p = vertex_transform * p + vertex_offset;
151                        }
152
153                if ( n_offset != -1 )
[413]154                        for ( uint32 i = 0; i < channel.size(); i++)
[293]155                        {
[406]156                                vec3& n = *reinterpret_cast<vec3*>( raw_data + vtx_size*i + n_offset );
[454]157                                n = math::normalize( normal_transform * n );
[293]158                        }
159                if ( t_offset != -1 )
[413]160                        for ( uint32 i = 0; i < channel.size(); i++)
[293]161                        {
[406]162                                vec4& t = *reinterpret_cast<vec4*>(raw_data + vtx_size*i + t_offset );
[454]163                                t = vec4( math::normalize( normal_transform * vec3(t) ), t[3] );
[293]164                        }
165        }
166}
[294]167
168struct vertex_g
169{
170        nv::vec4 tangent;
171};
172
[295]173void nv::mesh_data_creator::flip_normals()
174{
[456]175        if ( m_nrm_channel == nullptr ) return;
176        NV_ASSERT( m_nrm_type == FLOAT_VECTOR_3, "Unknown normal vector type!" );
177        raw_data_channel_access channel( m_nrm_channel );
[413]178        for ( uint32 i = 0; i < channel.size(); ++i )
[295]179        {
[456]180                vec3& normal = *reinterpret_cast<vec3*>( channel.raw_data() + channel.element_size() * i + m_nrm_offset );
[295]181                normal = -normal;
182        }
183}
184
185
[456]186void nv::mesh_data_creator::scale_texture( vec2 min, vec2 max )
[294]187{
[456]188        if ( m_tex_channel == nullptr ) return;
189        NV_ASSERT( m_tex_type == FLOAT_VECTOR_2, "Unknown texcoord vector type!" );
190        raw_data_channel_access channel( m_tex_channel );
191        vec2 scale = max - min;
192        for ( uint32 i = 0; i < channel.size(); ++i )
[294]193        {
[456]194                vec2& tc = *reinterpret_cast<vec2*>( channel.raw_data() + channel.element_size() * i + m_tex_offset );
195                tc = min + tc * scale;
[294]196        }
[456]197}
[294]198
[456]199void nv::mesh_data_creator::generate_tangents()
200{
201        if ( m_tan_channel != nullptr ) return;
202        if ( !m_pos_channel || !m_nrm_channel || !m_tex_channel ) return;
203
204        if ( m_pos_channel->size() != m_nrm_channel->size()
205                || m_pos_channel->size() % m_tex_channel->size() != 0
206                || ( m_idx_type != UINT && m_idx_type != USHORT && m_idx_type != NONE ) )
[294]207        {
208                return;
209        }
210
[456]211        NV_ASSERT( m_pos_type == FLOAT_VECTOR_3, "Unsupported position vector type!" );
212        NV_ASSERT( m_nrm_type == FLOAT_VECTOR_3, "Unsupported normal vector type!" );
213        NV_ASSERT( m_tex_type == FLOAT_VECTOR_2, "Unknown texcoord vector type!" );
214
215        raw_data_channel g_channel  = data_channel_creator::create< vertex_g >( m_pos_channel->size() );
[418]216        vec4* tangents              = &( data_channel_access< vertex_g >( &g_channel ).data()[0].tangent );
[456]217        vec3* tangents2             = new vec3[ m_pos_channel->size() ];
218        uint32 tri_count = m_idx_channel ? m_idx_channel->size() / 3 : m_tex_channel->size() / 3;
219        uint32 vtx_count = m_pos_channel->size();
220        uint32 sets      = m_pos_channel->size() / m_tex_channel->size();
[294]221
222        for ( unsigned int i = 0; i < tri_count; ++i )
223        {
224                uint32 ti0 = 0;
225                uint32 ti1 = 0;
226                uint32 ti2 = 0;
[456]227                if ( m_idx_type == UINT )
[294]228                {
[456]229                        const uint32* idata = reinterpret_cast<const uint32*>( m_idx_channel->raw_data() );
[294]230                        ti0 = idata[ i * 3 ];
231                        ti1 = idata[ i * 3 + 1 ];
232                        ti2 = idata[ i * 3 + 2 ];
233                }
[456]234                else if ( m_idx_type == USHORT )
[294]235                {
[456]236                        const uint16* idata = reinterpret_cast<const uint16*>( m_idx_channel->raw_data() );
[294]237                        ti0 = idata[ i * 3 ];
238                        ti1 = idata[ i * 3 + 1 ];
239                        ti2 = idata[ i * 3 + 2 ];
240                }
[456]241                else // if ( m_idx_type == NONE )
[294]242                {
243                        ti0 = i * 3;
244                        ti1 = i * 3 + 1;
245                        ti2 = i * 3 + 2;
246                }
247
[456]248                const vec2& w1 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti0 + m_tex_offset );
249                const vec2& w2 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti1 + m_tex_offset );
250                const vec2& w3 = *reinterpret_cast<const vec2*>( m_tex_channel->raw_data() + m_tex_channel->element_size()*ti2 + m_tex_offset );
[294]251                vec2 st1 = w3 - w1;
252                vec2 st2 = w2 - w1;
253                float stst = (st1.x * st2.y - st2.x * st1.y);
254                float coef = ( stst != 0.0f ? 1.0f / stst : 0.0f );
255
256                for ( uint32 set = 0; set < sets; ++set )
257                {
[456]258                        uint32 nti0 = m_tex_channel->size() * set + ti0;
259                        uint32 nti1 = m_tex_channel->size() * set + ti1;
260                        uint32 nti2 = m_tex_channel->size() * set + ti2;
261                        const vec3& v1 = *reinterpret_cast<const vec3*>( m_pos_channel->raw_data() + m_pos_channel->element_size()*nti0 + m_pos_offset );
262                        const vec3& v2 = *reinterpret_cast<const vec3*>( m_pos_channel->raw_data() + m_pos_channel->element_size()*nti1 + m_pos_offset );
263                        const vec3& v3 = *reinterpret_cast<const vec3*>( m_pos_channel->raw_data() + m_pos_channel->element_size()*nti2 + m_pos_offset );
[294]264                        vec3 xyz1 = v3 - v1;
265                        vec3 xyz2 = v2 - v1;
266
[454]267                        //vec3 normal = math::cross( xyz1, xyz2 );
[294]268                        //
269                        //vtcs[ ti0 ].normal += normal;
270                        //vtcs[ ti1 ].normal += normal;
271                        //vtcs[ ti2 ].normal += normal;
272                        vec3 tangent  = (( xyz1 * st2.y ) - ( xyz2 * st1.y )) * coef;
273                        vec3 tangent2 = (( xyz2 * st1.x ) - ( xyz1 * st2.x )) * coef;
274
275                        tangents[nti0] = vec4( vec3( tangents[nti0] ) + tangent, 0 );
276                        tangents[nti1] = vec4( vec3( tangents[nti1] ) + tangent, 0 );
277                        tangents[nti2] = vec4( vec3( tangents[nti2] ) + tangent, 0 );
278
279                        tangents2[nti0] += tangent2;
280                        tangents2[nti1] += tangent2;
281                        tangents2[nti2] += tangent2;
282                }
283        }
284
285        for ( unsigned int i = 0; i < vtx_count; ++i )
286        {
[456]287                const vec3 n = *reinterpret_cast<const vec3*>( m_nrm_channel->raw_data() + m_nrm_channel->element_size()*i + m_nrm_offset );
[294]288                const vec3 t = vec3(tangents[i]);
289                if ( ! ( t.x == 0.0f && t.y == 0.0f && t.z == 0.0f ) )
290                {
[454]291                        tangents[i]    = vec4( math::normalize(t - n * math::dot( n, t )), 0.0f );
292                        tangents[i][3] = ( math::dot( math::cross(n, t), tangents2[i]) < 0.0f) ? -1.0f : 1.0f;
[294]293                }
294        }
[419]295        delete[] tangents2;
[294]296
[456]297        uint32 n_channel_index = m_data->get_channel_index( slot::NORMAL );
298        data_channel_set_creator( m_data ).set_channel( n_channel_index, merge_channels( *m_nrm_channel, g_channel ) );
299        initialize();
[294]300}
301
[456]302void nv::mesh_data_creator::rotate_quadrant( uint8 rotation )
303{
304        if ( rotation % 4 == 0 ) return;
305        NV_ASSERT( m_pos_type == FLOAT_VECTOR_3, "Unsupported position vector type!" );
306        NV_ASSERT( m_nrm_type == FLOAT_VECTOR_3, "Unsupported normal vector type!" );
307        NV_ASSERT( m_tan_type == FLOAT_VECTOR_4, "Unsupported tangent vector type!" );
308
309        float r11 = 0.f;
310        float r12 = 0.f;
311        float r21 = 0.f;
312        float r22 = 0.f;
313
314        switch ( rotation % 4 )
315        {
316        case 1: r12 = -1.f; r21 =  1.f; break;
317        case 2: r11 = -1.f; r22 = -1.f; break;
318        case 3: r12 =  1.f; r21 = -1.f; break;
319        default:
320                break;
321        }
322
323        unsigned vtx_count = m_pos_channel->size();
324        uint8* pos_data = raw_data_channel_access( m_pos_channel ).raw_data();
325        uint8* nrm_data = raw_data_channel_access( m_nrm_channel ).raw_data();
326        uint8* tan_data = raw_data_channel_access( m_tan_channel ).raw_data();
327        for ( unsigned int i = 0; i < vtx_count; ++i )
328        {
329                vec3& pos = *reinterpret_cast<vec3*>( pos_data + m_pos_channel->element_size() * i + m_pos_offset );
330                vec3& nrm = *reinterpret_cast<vec3*>( nrm_data + m_nrm_channel->element_size() * i + m_nrm_offset );
331                vec4& tan = *reinterpret_cast<vec4*>( tan_data + m_tan_channel->element_size() * i + m_tan_offset );
332
333                pos = vec3(
334                        pos.x * r11 + pos.z * r12,
335                        pos.y,
336                        pos.x * r21 + pos.z * r22
337                        );
338                nrm = vec3(
339                        nrm.x * r11 + nrm.z * r12,
340                        nrm.y,
341                        nrm.x * r21 + nrm.z * r22
342                        );
343                tan = vec4(
344                        tan.x * r11 + tan.z * r12,
345                        tan.y,
346                        tan.x * r21 + tan.z * r22,
[457]347                        tan.w // make sure this is proper
[456]348                        );
349        }
350
351
352}
353
[457]354void nv::mesh_data_creator::mirror( bool x, bool z )
355{
356        if ( !x && !z ) return;
357        NV_ASSERT( m_pos_type == FLOAT_VECTOR_3, "Unsupported position vector type!" );
358        NV_ASSERT( m_nrm_type == FLOAT_VECTOR_3, "Unsupported normal vector type!" );
359        NV_ASSERT( m_tan_type == FLOAT_VECTOR_4, "Unsupported tangent vector type!" );
360
361        float kx = x ? -1.0f : 1.0f;
362        float kz = z ? -1.0f : 1.0f;
363
364        unsigned vtx_count = m_pos_channel->size();
365        uint8* pos_data = raw_data_channel_access( m_pos_channel ).raw_data();
366        uint8* nrm_data = raw_data_channel_access( m_nrm_channel ).raw_data();
367        uint8* tan_data = raw_data_channel_access( m_tan_channel ).raw_data();
368        for ( unsigned int i = 0; i < vtx_count; ++i )
369        {
370                vec3& pos = *reinterpret_cast<vec3*>( pos_data + m_pos_channel->element_size() * i + m_pos_offset );
371                vec3& nrm = *reinterpret_cast<vec3*>( nrm_data + m_nrm_channel->element_size() * i + m_nrm_offset );
372                vec4& tan = *reinterpret_cast<vec4*>( tan_data + m_tan_channel->element_size() * i + m_tan_offset );
373
374                pos = vec3(
375                        pos.x * kx,
376                        pos.y,
377                        pos.z * kz
378                        );
379                nrm = vec3(
380                        nrm.x * kx,
381                        nrm.y,
382                        nrm.z * kz
383                        );
384                tan = vec4(
385                        tan.x * kx,
386                        tan.y,
387                        tan.z * kz,
388                        tan.w * kx * kz// make sure this is proper
389                        );
390        }
391
392        if ( !( x && z ) )
393                swap_culling();
394}
395
396template < typename T >
397static inline void swap_culling_impl( nv::raw_data_channel* index_channel )
398{
399        nv::raw_data_channel_access ichannel( index_channel );
400        T* indices = reinterpret_cast<T*>( ichannel.raw_data() );
401        nv::uint32 count = index_channel->size() / 3;
402        for ( nv::uint32 i = 0; i < count; ++i )
403        {
404                nv::swap( indices[i * 3], indices[i * 3 + 1] );
405        }
406}
407
408void nv::mesh_data_creator::swap_culling()
409{
410        NV_ASSERT( m_idx_channel, "Swap culling unsupported on non-indexed meshes!" );
411        NV_ASSERT( m_idx_channel->descriptor().size() == 1, "Malformed index channel!" );
412        NV_ASSERT( m_idx_channel->size() % 3 == 0, "Malformed index channel - not per GL_TRIANGLE LAYOUT?" );
413
414        if ( m_idx_channel->size() == 0 ) return;
415        switch ( m_idx_type )
416        {
417        case USHORT: swap_culling_impl< uint16 >( m_idx_channel ); break;
418        case UINT: swap_culling_impl< uint16 >( m_idx_channel ); break;
419        default: NV_ASSERT( false, "Swap culling supports only unsigned and unsigned short indices!" ); break;
420        }
421}
422
[456]423void nv::mesh_data_creator::translate( vec3 offset )
424{
425        if ( m_pos_channel == nullptr ) return;
426        NV_ASSERT( m_pos_type == FLOAT_VECTOR_3, "Unsupported poosition vector type!" );
427        raw_data_channel_access channel( m_pos_channel );
428        for ( uint32 i = 0; i < channel.size(); ++i )
429        {
430                vec3& p = *reinterpret_cast<vec3*>( channel.raw_data() + channel.element_size() * i + m_pos_offset );
431                p = p + offset;
432        }
433
434}
435
436void nv::mesh_data_creator::initialize()
437{
438        NV_ASSERT( m_data, "bad parameter!" );
439        m_pos_channel = nullptr;
440        m_nrm_channel = nullptr;
441        m_tan_channel = nullptr;
442        m_tex_channel = nullptr;
443        m_idx_channel = nullptr;
444
445        m_pos_offset = -1;
446        m_nrm_offset = -1;
447        m_tan_offset = -1;
448        m_tex_offset = -1;
449        m_idx_offset = -1;
450
451        m_pos_type = NONE;
452        m_nrm_type = NONE;
453        m_tan_type = NONE;
454        m_tex_type = NONE;
455        m_idx_type = NONE;
456
457        for ( uint32 c = 0; c < m_data->size(); ++c )
458        {
459                raw_data_channel* channel = data_channel_set_creator( m_data )[c];
460
461                for ( const auto& cslot : channel->descriptor() )
462                        switch ( cslot.vslot )
463                        {
464                        case slot::POSITION:
465                                m_pos_type = cslot.etype;
466                                m_pos_offset = int( cslot.offset );
467                                m_pos_channel = channel;
468                                break;
469                        case slot::NORMAL:
470                                m_nrm_type = cslot.etype;
471                                m_nrm_offset = int( cslot.offset );
472                                m_nrm_channel = channel;
473                                break;
474                        case slot::TANGENT:
475                                m_tan_type = cslot.etype;
476                                m_tan_offset = int( cslot.offset );
477                                m_tan_channel = channel;
478                                break;
479                        case slot::TEXCOORD:
480                                m_tex_type = cslot.etype;
481                                m_tex_offset = int( cslot.offset );
482                                m_tex_channel = channel;
483                                break;
484                        case slot::INDEX:
485                                m_idx_type = cslot.etype;
486                                m_idx_offset = int( cslot.offset );
487                                m_idx_channel = channel;
488                                break;
489                        default: break;
490                        }
491        }
492}
493
[418]494nv::raw_data_channel nv::mesh_data_creator::merge_channels( const raw_data_channel& a, const raw_data_channel& b )
[294]495{
[418]496        NV_ASSERT( a.size() == b.size(), "merge_channel - bad channels!" );
497        data_descriptor desc  = a.descriptor();
498        desc.append( b.descriptor() );
[294]499
[418]500        raw_data_channel result = data_channel_creator::create( desc, a.size() );
501        for ( uint32 i = 0; i < a.size(); ++i )
[294]502        {
[418]503                raw_copy_n( a.raw_data() + i * a.element_size(), a.element_size(), raw_data_channel_access( &result ).raw_data() + i*desc.element_size() );
504                raw_copy_n( b.raw_data() + i * b.element_size(), b.element_size(), raw_data_channel_access( &result ).raw_data() + i*desc.element_size() + a.element_size() );
[294]505        }
[456]506        initialize();
[417]507        return result;
[294]508}
[295]509
[418]510nv::raw_data_channel nv::mesh_data_creator::append_channels( const raw_data_channel& a, const raw_data_channel& b, uint32 frame_count )
[295]511{
[418]512        NV_ASSERT( a.descriptor() == b.descriptor(), "Merge - append not compatible format!" );
513        NV_ASSERT( a.size() % frame_count == 0, "Merge - append first mesh empty!" );
514        NV_ASSERT( b.size() % frame_count == 0, "Merge - append second mesh empty!" );
515        size_t vtx_size = a.element_size();
[295]516
[418]517        raw_data_channel result = data_channel_creator::create( a.descriptor(), a.size() + b.size() );
518        uint8* rdata = raw_data_channel_access( &result ).raw_data();
[295]519
520        if ( frame_count == 1 )
521        {
[418]522                size_t a_size = vtx_size * a.size();
523                raw_copy_n( a.raw_data(), a_size, rdata );
524                raw_copy_n( b.raw_data(), vtx_size * b.size(), rdata + a_size );
[295]525        }
526        else
527        {
[418]528                size_t frame_size_a = ( a.size() / frame_count ) * vtx_size;
529                size_t frame_size_b = ( b.size() / frame_count ) * vtx_size;
[295]530                size_t pos_a = 0;
531                size_t pos_b = 0;
532                size_t pos   = 0;
533                for ( size_t i = 0; i < frame_count; ++i )
534                {
[418]535                        raw_copy_n( a.raw_data() + pos_a, frame_size_a, rdata + pos );
536                        raw_copy_n( b.raw_data() + pos_b, frame_size_b, rdata + pos + frame_size_a );                           pos_a += frame_size_a;
[295]537                        pos_b += frame_size_b;
538                        pos   += frame_size_a + frame_size_b;
539                }
540        }
541
[456]542        initialize();
[417]543        return result;
[295]544}
545
546
547
[457]548bool nv::mesh_data_creator::is_same_format( const data_channel_set* other )
[295]549{
[416]550        if ( m_data->size() != other->size() ) return false;
551        for ( uint32 c = 0; c < m_data->size(); ++c )
[295]552        {
[411]553                if ( m_data->get_channel(c)->descriptor() != other->get_channel(c)->descriptor() )
[295]554                        return false;
555        }
556        return true;
557}
558
[457]559void nv::mesh_data_creator::merge( const data_channel_set* other )
[295]560{
561        if ( !is_same_format( other ) ) return;
562        int ch_pi  = m_data->get_channel_index( slot::POSITION );
563        int ch_ti  = m_data->get_channel_index( slot::TEXCOORD );
564        int och_pi = other->get_channel_index( slot::POSITION );
565        int och_ti = other->get_channel_index( slot::TEXCOORD );
566        if ( ch_pi == -1 || ch_ti == -1 ) return;
[416]567        size_t size   = m_data->get_channel_size( unsigned(ch_ti) );
568        size_t osize  =  other->get_channel_size( unsigned(och_ti) );
569        size_t count  = m_data->get_channel_size( unsigned(ch_pi) );
570        size_t ocount =  other->get_channel_size( unsigned(och_pi) );
[295]571        if ( count % size != 0 || ocount % osize != 0 ) return;
572        if ( count / size != ocount / osize ) return;
573       
[416]574        data_channel_set_creator data( m_data );
575
576        for ( uint32 c = 0; c < m_data->size(); ++c )
[295]577        {
[416]578                const raw_data_channel* old = m_data->get_channel( c );
[418]579                uint32 old_size = old->size();
580                data_descriptor old_desc = old->descriptor();
581                bool old_is_index = old_size > 0 && old_desc[0].vslot == slot::INDEX;
582                size_t frame_count = ( old_is_index ? 1 : old_size / size );
583                data.set_channel( c, append_channels( *old, *other->get_channel(c), frame_count ) );
[412]584                if ( old_is_index )
[295]585                {
[418]586                        switch ( old_desc[0].etype )
[295]587                        {
588                        case USHORT :
589                                {
590                                        NV_ASSERT( size + osize < uint16(-1), "Index out of range!" );
[417]591                                        raw_data_channel_access ic( data[c] );
[413]592                                        uint16* indexes = reinterpret_cast<uint16*>( ic.raw_data() );
[418]593                                        for ( uint16 i = uint16( old_size ); i < ic.size(); ++i )
[406]594                                                indexes[i] += uint16( size );
[295]595
596                                }
597                                break;
598                        case UINT   :
599                                {
[417]600                                        raw_data_channel_access ic( data[c] );
[413]601                                        uint32* indexes = reinterpret_cast<uint32*>( ic.raw_data() );
[418]602                                        for ( uint32 i = old_size; i < ic.size(); ++i )
[295]603                                                indexes[i] += size;
604                                }
605                                break;
606                        default : NV_ASSERT( false, "Unsupported index type!" ); break;
607                        }
608                }
609        }
[456]610        initialize();
[295]611}
[416]612
613void nv::mesh_creator::delete_mesh( uint32 index )
614{
615        if ( index < m_pack->get_count() )
616        {
[427]617
618                m_pack->m_meshes[index] = move( m_pack->m_meshes[m_pack->m_count - 1] );
[416]619                m_pack->m_count--;
620        }
621}
Note: See TracBrowser for help on using the repository browser.