source: trunk/src/gfx/keyframed_mesh.cc @ 292

Last change on this file since 292 was 288, checked in by epyon, 11 years ago
  • unified animation_entry class
  • virtuals removed from animation_entry
  • lua_table - added missing get_float
  • lua_table - fixed has_field
File size: 6.1 KB
RevLine 
[158]1// Copyright (C) 2011 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#include "nv/gfx/keyframed_mesh.hh"
6
7#include <glm/gtc/matrix_access.hpp>
8#include <glm/gtx/matrix_interpolation.hpp>
9#include "nv/interface/context.hh"
10#include "nv/interface/device.hh"
11
12
13#include "nv/logging.hh"
14
15using namespace nv;
16
[287]17nv::keyframed_mesh::keyframed_mesh( device* a_device, const mesh_data* a_data, const mesh_nodes_data* a_tag_map )
[231]18        : animated_mesh()
[239]19        , m_mesh_data( a_data )
20        , m_tag_map( a_tag_map )
[158]21        , m_last_frame( 0 )
22        , m_next_frame( 0 )
23        , m_interpolation( 0.0f )
24        , m_active( false )
25{
[275]26        m_va = a_device->create_vertex_array();
[239]27
28        m_index_count  = m_mesh_data->get_index_channel()->count;
[280]29        m_vertex_count = m_mesh_data->get_channel<vertex_t>()->count;
30        m_frame_count  = m_mesh_data->get_channel<vertex_pn>()->count / m_vertex_count;
[158]31}
32
[204]33size_t keyframed_mesh::get_max_frames() const
[158]34{
[239]35        return m_frame_count;
[158]36}
37
[287]38transform keyframed_mesh::get_node_transform( uint32 node_id ) const
[158]39{
[239]40        NV_ASSERT( m_tag_map, "TAGMAP FAIL" );
[287]41        NV_ASSERT( node_id < m_tag_map->get_count(), "TAGMAP FAIL" );
42        const key_data* data = m_tag_map->get_node( node_id )->data;
[285]43        NV_ASSERT( data, "TAG FAIL" );
44        transform last = data->get_raw_transform( m_last_frame );
45        transform next = data->get_raw_transform( m_next_frame );
46        return interpolate( last, next, m_interpolation  );
[158]47}
48
[287]49mat4 keyframed_mesh::get_node_matrix( uint32 node_id ) const
50{
51        return get_node_transform( node_id ).extract();
52}
53
[223]54void nv::keyframed_mesh::set_frame( uint32 frame )
55{
56        m_last_frame    = frame;
57        m_next_frame    = frame;
58        m_active        = false;
59        m_interpolation = 0.0f;
60}
61
[288]62void nv::keyframed_mesh::update_animation( animation_entry* anim, uint32 a_anim_time )
[158]63{
64        if ( m_active )
65        {
[288]66                float tick_time = ( (float)a_anim_time * 0.001f ) * anim->get_frame_rate();
67                float duration  = anim->is_looping() ? anim->get_duration() + 1.0f : anim->get_duration();
68                if ( tick_time >= duration )
[158]69                {
[288]70                        if ( anim->is_looping() )
[158]71                        {
[288]72                                tick_time = fmodf( tick_time, duration );
[158]73                        }
74                        else
75                        {
76                                m_active     = false;
[288]77                                m_last_frame = (uint32)anim->get_end();
78                                m_next_frame = m_last_frame;
79                                m_interpolation = 0.0f;
80                                return;
[158]81                        }
82                }
[288]83                m_last_frame    = (uint32)( glm::floor( tick_time ) + anim->get_start() );
[283]84                m_next_frame    = m_last_frame + 1;
[288]85                if ( m_next_frame > (uint32)anim->get_end() ) m_next_frame = (uint32)anim->get_start();
86                m_interpolation = tick_time - glm::floor( tick_time );
[158]87        }
88}
89
[283]90
[251]91void nv::keyframed_mesh::update( program* a_program ) const
[158]92{
[230]93        a_program->set_opt_uniform( "nv_interpolate", m_interpolation );
[223]94}
95
96nv::keyframed_mesh::~keyframed_mesh()
97{
98        delete m_va;
99}
100
[230]101void nv::keyframed_mesh::run_animation( animation_entry* a_anim )
102{
[252]103        if ( a_anim )
104        {
[288]105                m_active        = true;
106                m_last_frame    = 0;
107                m_next_frame    = 0;
108                m_interpolation = 0.0f;
[252]109        }
110        else
111        {
112                m_active = false;
113        }
[230]114}
115
[287]116nv::keyframed_mesh_gpu::keyframed_mesh_gpu( device* a_device, const mesh_data* a_data, const mesh_nodes_data* a_tag_map, program* a_program )
[275]117        : keyframed_mesh( a_device, a_data, a_tag_map )
[223]118        , m_loc_next_position( 0 )
119        , m_loc_next_normal( 0 )
120        , m_gpu_last_frame( 0xFFFFFFFF )
121        , m_gpu_next_frame( 0xFFFFFFFF )
122{
[230]123        m_loc_next_position = a_program->get_attribute( "nv_next_position" )->get_location();
124        m_loc_next_normal   = a_program->get_attribute( "nv_next_normal" )->get_location();
[281]125        m_va = a_device->create_vertex_array( a_data, STATIC_DRAW );
126        vertex_buffer* vb = m_va->find_buffer( slot::POSITION );
127        m_va->add_vertex_buffer( m_loc_next_position, vb, FLOAT, 3, 0,              sizeof( vertex_pn ), false );
128        m_va->add_vertex_buffer( m_loc_next_normal,   vb, FLOAT, 3, sizeof( vec3 ), sizeof( vertex_pn ), false );
[239]129}
[223]130
131
[230]132void nv::keyframed_mesh_gpu::update( uint32 ms )
[223]133{
[283]134        animated_mesh::update( ms );
[230]135
[158]136        if ( m_gpu_last_frame != m_last_frame )
137        {
[239]138                m_va->update_vertex_buffer( slot::POSITION, m_last_frame * m_vertex_count * sizeof( vertex_pn ) );
139                m_va->update_vertex_buffer( slot::NORMAL,   m_last_frame * m_vertex_count * sizeof( vertex_pn ) + sizeof( vec3 ) );
[158]140                m_gpu_last_frame = m_last_frame;
141        }
142        if ( m_gpu_next_frame != m_next_frame )
143        {
[239]144                m_va->update_vertex_buffer( m_loc_next_position, m_next_frame * m_vertex_count * sizeof( vertex_pn ) );
145                m_va->update_vertex_buffer( m_loc_next_normal,   m_next_frame * m_vertex_count * sizeof( vertex_pn ) + sizeof( vec3 ) );
[158]146                m_gpu_next_frame = m_next_frame;
147        }
148}
149
[287]150nv::keyframed_mesh_cpu::keyframed_mesh_cpu( device* a_device, const mesh_data* a_data, const mesh_nodes_data* a_tag_map )
[275]151        : keyframed_mesh( a_device, a_data, a_tag_map )
[158]152{
[280]153        m_vb = a_device->create_vertex_buffer( nv::STATIC_DRAW, m_vertex_count * sizeof( vertex_pn ), (void*)m_mesh_data->get_channel<vertex_pn>()->data );
154        m_va->add_vertex_buffers( m_vb, m_mesh_data->get_channel<vertex_pn>() );
[223]155
[280]156        nv::vertex_buffer* vb = a_device->create_vertex_buffer( nv::STATIC_DRAW, m_vertex_count * sizeof( nv::vec2 ), (void*)m_mesh_data->get_channel<vertex_t>()->data );
157        m_va->add_vertex_buffers( vb, m_mesh_data->get_channel<vertex_t>() );
[223]158
[280]159        nv::index_buffer* ib = a_device->create_index_buffer( nv::STATIC_DRAW, m_mesh_data->get_index_channel()->size(), (void*)m_mesh_data->get_index_channel()->data );
160        m_va->set_index_buffer( ib, m_mesh_data->get_index_channel()->desc.slots[0].etype, true );
[223]161
[239]162        m_vertex.resize( m_vertex_count );
[158]163}
[223]164
165void nv::keyframed_mesh_cpu::update( uint32 ms )
166{
[283]167        animated_mesh::update( ms );
[223]168
[280]169        const vertex_pn* data = m_mesh_data->get_channel_data<vertex_pn>();
[239]170        const vertex_pn* prev = data + m_vertex_count * m_last_frame;
171        const vertex_pn* next = data + m_vertex_count * m_next_frame;
[223]172
[239]173        for ( size_t i = 0; i < m_vertex_count; ++i )
[223]174        {
[239]175                m_vertex[i].position = glm::mix( prev[i].position, next[i].position, m_interpolation );
176                m_vertex[i].normal   = glm::mix( prev[i].normal,   next[i].normal,   m_interpolation );
[223]177        }
178
[239]179        m_vb->bind();
180        m_vb->update( m_vertex.data(), 0, m_vertex_count * sizeof( vertex_pn ) );
181        m_vb->unbind();
[223]182}
Note: See TracBrowser for help on using the repository browser.