// Copyright (C) 2014-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #include "nv/gfx/debug_draw.hh" #include "nv/interface/device.hh" #include "nv/core/logging.hh" static const char *nv_debug_draw_vertex_shader = R"( #version 330 in vec3 nv_position; in vec3 nv_color; out vec3 v_color; uniform mat4 nv_m_mvp; void main(void) { gl_Position = nv_m_mvp * vec4 (nv_position, 1.0); v_color = nv_color; }; )"; static const char *nv_debug_draw_fragment_shader = R"( #version 330 in vec3 v_color; out vec4 o_frag_color; void main(void) { o_frag_color = vec4( v_color, 1.0 ); } )"; nv::debug_data::debug_data( context* a_context ) : m_context( a_context ), m_program(), m_va() { m_program = m_context->create_program( nv_debug_draw_vertex_shader, nv_debug_draw_fragment_shader ); m_buffer_size = 0; } void nv::debug_data::update() { if ( !m_va.is_valid() || m_data.size() > m_buffer_size ) { if ( m_va.is_valid() ) m_context->release( m_va ); m_buffer_size = nv::max( m_data.size(), 4096U, m_buffer_size ); m_vb = m_context->create_buffer( VERTEX_BUFFER, nv::STREAM_DRAW, m_buffer_size * sizeof( debug_vtx ) ); vertex_array_desc va_desc; va_desc.add_vertex_buffers< debug_vtx >( m_vb, true ); m_va = m_context->create_vertex_array( va_desc ); } m_context->update( m_vb, m_data.data(), 0, m_data.size()* sizeof( debug_vtx ) ); } void nv::debug_data::reset() { m_data.clear(); } void nv::debug_data::push_line( const vec3& a, const vec3& b, const vec3& color ) { m_data.emplace_back( a, color ); m_data.emplace_back( b, color ); } void nv::debug_data::push_aabox( const vec3& a, const vec3& b, const vec3& color ) { vec3 corners[8] = { vec3( a.x, a.y, a.z ), vec3( b.x, a.y, a.z ), vec3( b.x, a.y, b.z ), vec3( a.x, a.y, b.z ), vec3( a.x, b.y, a.z ), vec3( b.x, b.y, a.z ), vec3( b.x, b.y, b.z ), vec3( a.x, b.y, b.z ), }; push_line( corners[0], corners[1], color ); push_line( corners[1], corners[2], color ); push_line( corners[2], corners[3], color ); push_line( corners[3], corners[0], color ); push_line( corners[0], corners[4], color ); push_line( corners[1], corners[5], color ); push_line( corners[2], corners[6], color ); push_line( corners[3], corners[7], color ); push_line( corners[4], corners[5], color ); push_line( corners[5], corners[6], color ); push_line( corners[6], corners[7], color ); push_line( corners[7], corners[4], color ); } void nv::debug_data::push_gizmo( const transform& tr, float length ) { vec3 s( 0.0f, 0.0f, 0.0f ); vec3 r( length, 0.0f, 0.0f ); vec3 g( 0.0f, length, 0.0f ); vec3 b( 0.0f, 0.0f, length ); s = s * tr; r = r * tr; g = g * tr; b = b * tr; push_line( s, r, vec3( 1.0f, 0.0f, 0.0f ) ); push_line( s, g, vec3( 0.0f, 1.0f, 0.0f ) ); push_line( s, b, vec3( 0.0f, 0.0f, 1.0f ) ); } void nv::debug_data::push_wire_capsule( const transform& tr, float radius, float height ) { vec3 p = tr.get_position(); quat o = tr.get_orientation(); vec3 dir = o * vec3( 0, 1, 0 ); vec3 ldir = o * vec3( 1, 0, 0 ); vec3 h1dir = o * normalize( vec3( 1, -1, 0 ) ); vec3 h2dir = o * normalize( vec3( 1, 1, 0 ) ); vec3 sp1[12]; vec3 sp2[12]; vec3 hsp1[12]; vec3 hsp2[12]; for ( uint32 i = 0; i < 12; ++i ) { sp1[i] = nv::math::rotate( ldir * radius, ( float( i ) / 12.0f ) * math::two_pi(), dir ); hsp1[i] = nv::math::rotate( h1dir * radius, ( float( i ) / 12.0f ) * math::two_pi(), dir ); } for ( uint32 i = 0; i < 12; ++i ) { sp2[i] = nv::math::rotate( ldir * radius + height * dir, ( float( i ) / 12.0f ) * math::two_pi(), dir ); hsp2[i] = nv::math::rotate( h2dir * radius + height * dir, ( float( i ) / 12.0f ) * math::two_pi(), dir ); } for ( uint32 i = 0; i < 12; ++i ) { push_line( p + sp1[i], p + sp1[( i + 1 ) % 12], vec3( 1.0f, 0.0f, 0.0f ) ); push_line( p + sp2[i], p + sp2[( i + 1 ) % 12], vec3( 0.0f, 1.0f, 0.0f ) ); push_line( p + sp1[i], p + sp2[i], vec3( 0.0f, 0.0f, 1.0f ) ); push_line( p + hsp1[i], p + sp1[i], vec3( 0.0f, 0.0f, 1.0f ) ); push_line( p + hsp1[i], p + hsp1[( i + 1 ) % 12], vec3( 1.0f, 0.0f, 0.0f ) ); push_line( p + hsp2[i], p + sp2[i], vec3( 0.0f, 0.0f, 1.0f ) ); push_line( p + hsp2[i], p + hsp2[( i + 1 ) % 12], vec3( 0.0f, 1.0f, 0.0f ) ); push_line( p + hsp1[i], p - radius * dir, vec3( 0.0f, 0.0f, 1.0f ) ); push_line( p + hsp2[i], p + ( height + radius ) * dir, vec3( 0.0f, 0.0f, 1.0f ) ); } } nv::debug_data::~debug_data() { m_context->release( m_va ); m_context->release( m_program ); }