// Copyright (C) 2011 Kornel Kisielewicz // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh #include "nv/gfx/skeletal_mesh.hh" #include #include #include "nv/interface/context.hh" #include "nv/interface/device.hh" nv::skeletal_mesh::skeletal_mesh( device* a_device, md5_mesh_data* a_mesh_data ) : animated_mesh() , m_mesh_data( nullptr ) { m_mesh_data = a_mesh_data->spawn(); m_va = a_device->create_vertex_array( a_mesh_data, nv::STREAM_DRAW ); } void nv::skeletal_mesh::update_animation( animation_entry* a_anim, uint32 a_anim_time ) { if ( a_anim ) { skeletal_animation_entry * anim = (skeletal_animation_entry*)a_anim; float frame_duration = 1000.f / (float)anim->get_frame_rate(); uint32 anim_duration = uint32( frame_duration * (float)anim->get_frame_count() ); uint32 new_time = a_anim_time % anim_duration; anim->update_skeleton( m_transform.data(), (float)new_time * 0.001f ); m_mesh_data->apply( m_transform.data() ); vertex_buffer* vb = m_va->find_buffer( nv::slot::POSITION ); vb->bind(); vb->update( m_mesh_data->data(), 0, m_mesh_data->size() ); vb->unbind(); } } nv::skeletal_mesh::~skeletal_mesh() { delete m_va; delete m_mesh_data; } void nv::skeletal_mesh::run_animation( animation_entry* a_anim ) { if ( a_anim != nullptr ) { skeletal_animation_entry * anim = (skeletal_animation_entry*)(a_anim); m_transform.resize( anim->get_num_joints() ); update_animation( a_anim, 0 ); } } void nv::skeletal_animation_entry_gpu::update_skeleton( mat4* data, uint32 time ) { m_animation->animate( data, time ); } void nv::skeletal_animation_entry_gpu::prepare( const nmd_temp_model* m_model ) { m_animation->prepare( m_model ); } nv::skeletal_mesh_gpu::skeletal_mesh_gpu( device* a_device, const nmd_temp_model* a_model, uint32 index, bool primary ) : animated_mesh(), m_primary( primary ), m_model( a_model ) { const mesh_data* data = a_model->get_data( index ); m_va = a_device->create_vertex_array( data, nv::STATIC_DRAW ); m_index_count = data->get_count(); } void nv::skeletal_mesh_gpu::run_animation( animation_entry* a_anim ) { if ( m_primary && a_anim != nullptr ) { skeletal_animation_entry_gpu * anim = (skeletal_animation_entry_gpu*)(a_anim); m_transform.resize( m_model->get_bone_count() ); anim->prepare( m_model ); update_animation( a_anim, 0 ); } } void nv::skeletal_mesh_gpu::update_animation( animation_entry* a_anim, uint32 a_anim_time ) { if ( m_primary && a_anim ) { skeletal_animation_entry_gpu * anim = (skeletal_animation_entry_gpu*)a_anim; anim->update_skeleton( m_transform.data(), a_anim_time ); } } void nv::skeletal_mesh_gpu::update( program* a_program ) const { if (m_primary) a_program->set_uniform_array( "nv_m_bones", m_transform ); }