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

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