void Plotter::Render() { if( track_front ) { const float d = int_x[1] - log->x; int_x[0] -= d; int_x[1] -= d; } ActivateScissorAndClear(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(int_x[0], int_x[1], int_y[0], int_y[1]); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushAttrib(GL_ENABLE_BIT); glEnable(GL_LINE_SMOOTH); glDisable(GL_LIGHTING); DrawTicks(); if( log && log->sequences.size() > 0 ) { if( plot_mode==XY ) { for( unsigned int s=0; s < log->sequences.size() / 2; ++s ) { if( (s > 9) || show[s] ) { glColor3fv(plot_colours[s%num_plot_colours]); DrawSequence(log->sequences[2*s],log->sequences[2*s+1]); } } } else if( plot_mode==TIME_SERIES) { for( unsigned int s=0; s < log->sequences.size(); ++s ) { if( (s > 9) || show[s] ) { glColor3fv(plot_colours[s%num_plot_colours]); DrawSequence(log->sequences[s]); } } } else if( plot_mode==STACKED_HISTOGRAM ) { DrawSequenceHistogram(log->sequences); } else { assert(false); } } if( mouse_state & MouseButtonLeft ) { if( plot_mode==XY ) { glColor3fv(colour_ms); glBegin(GL_LINE_STRIP); glVertex2f(mouse_xy[0],int_y[0]); glVertex2f(mouse_xy[0],int_y[1]); glEnd(); glBegin(GL_LINE_STRIP); glVertex2f(int_x[0],mouse_xy[1]); glVertex2f(int_x[1],mouse_xy[1]); glEnd(); stringstream ss; ss << "(" << mouse_xy[0] << "," << mouse_xy[1] << ")"; glColor3f(1.0,1.0,1.0); OpenGlRenderState::ApplyWindowCoords(); glRasterPos2f( v.l+5,v.b+5 ); glutBitmapString(font,(unsigned char*)ss.str().c_str()); }else{ int xu = (int)mouse_xy[0]; glColor3fv(colour_ms); glBegin(GL_LINE_STRIP); glVertex2f(xu,int_y[0]); glVertex2f(xu,int_y[1]); glEnd(); stringstream ss; glColor3f(1.0,1.0,1.0); ss << "x=" << xu << " "; OpenGlRenderState::ApplyWindowCoords(); int tx = v.l+5; glRasterPos2f( tx,v.b+5 ); glutBitmapString(font,(unsigned char*)ss.str().c_str()); tx += glutBitmapLength(font,(unsigned char*)ss.str().c_str()); for( unsigned int s=0; s<log->sequences.size(); ++s ) { if( (s > show_n || show[s]) && log->sequences[s].HasData(xu) ) { stringstream ss; ss << " " << log->sequences[s][xu]; glColor3fv(plot_colours[s%num_plot_colours]); glRasterPos2f( tx,v.b+5 ); glutBitmapString(font,(unsigned char*)ss.str().c_str()); tx += glutBitmapLength(font,(unsigned char*)ss.str().c_str()); } } } } float ty = v.h-15; for (size_t i=0; i<log->labels.size(); ++i) { glColor3fv(plot_colours[i%num_plot_colours]); OpenGlRenderState::ApplyWindowCoords(); glRasterPos2f( v.l+5,ty); glutBitmapString(font,(unsigned char*)log->labels[i].c_str()); ty -= 15; } glPopAttrib(); }
void Plotter::Render() { // Animate scroll / zooming UpdateView(); #ifndef HAVE_GLES glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_LINE_BIT); #endif glClearColor(colour_bg.r, colour_bg.g, colour_bg.b, colour_bg.a); ActivateScissorAndClear(); // Try to create smooth lines glDisable(GL_MULTISAMPLE); glLineWidth(1.5); glEnable(GL_LINE_SMOOTH); glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_LIGHTING); glDisable( GL_DEPTH_TEST ); const float w = rview.x.Size(); const float h = rview.y.Size(); const float ox = -rview.x.Mid(); const float oy = -rview.y.Mid(); const float sx = 2.0f / w; const float sy = 2.0f / h; ////////////////////////////////////////////////////////////////////////// // Draw ticks prog_lines.SaveBind(); prog_lines.SetUniform("u_scale", sx, sy); prog_lines.SetUniform("u_offset", ox, oy); prog_lines.SetUniform("u_color", colour_tk ); const float min_space = 80.0; int ta[2] = {1,1}; while(v.w * ta[0] *tick[0].val / w < min_space) ta[0] *=2; while(v.h * ta[1] *tick[1].val / h < min_space) ta[1] *=2; const float tdelta[2] = { tick[0].val * ta[0], tick[1].val * ta[1] }; const int tx[2] = { (int)ceil(rview.x.min / tdelta[0]), (int)ceil(rview.x.max / tdelta[0]) }; const int ty[2] = { (int)ceil(rview.y.min / tdelta[1]), (int)ceil(rview.y.max / tdelta[1]) }; for( int i=tx[0]; i<tx[1]; ++i ) { glDrawLine((i)*tdelta[0], rview.y.min, (i)*tdelta[0], rview.y.max); } for( int i=ty[0]; i<ty[1]; ++i ) { glDrawLine(rview.x.min, (i)*tdelta[1], rview.x.max, (i)*tdelta[1]); } prog_lines.Unbind(); ////////////////////////////////////////////////////////////////////////// // Draw axis prog_lines.SaveBind(); prog_lines.SetUniform("u_color", colour_ax ); glDrawLine(0, rview.y.min, 0, rview.y.max ); glDrawLine(rview.x.min,0, rview.x.max,0 ); prog_lines.Unbind(); ////////////////////////////////////////////////////////////////////////// // Draw Implicits for(size_t i=0; i < plotimplicits.size(); ++i) { PlotImplicit& im = plotimplicits[i]; im.prog.SaveBind(); im.prog.SetUniform("u_scale", sx, sy); im.prog.SetUniform("u_offset", ox, oy); glDrawRect(rview.x.min,rview.y.min,rview.x.max,rview.y.max); im.prog.Unbind(); } ////////////////////////////////////////////////////////////////////////// // Draw series static size_t id_size = 0; static float* id_array = 0; for(size_t i=0; i < plotseries.size(); ++i) { PlotSeries& ps = plotseries[i]; GlSlProgram& prog = ps.prog; ps.used = false; prog.SaveBind(); prog.SetUniform("u_scale", sx, sy); prog.SetUniform("u_offset", ox, oy); prog.SetUniform("u_color", ps.colour ); // TODO: Try to skip drawing of blocks which aren't in view. const DataLogBlock* block = ps.log ? ps.log->FirstBlock() : default_log->FirstBlock(); while(block) { if(ps.contains_id ) { if(id_size < block->Samples() ) { // Create index array that we can bind delete[] id_array; id_size = block->MaxSamples(); id_array = new float[id_size]; for(size_t k=0; k < id_size; ++k) { id_array[k] = (float)k; } } prog.SetUniform("u_id_offset", (float)block->StartId() ); } // Enable appropriate attributes bool shouldRender = true; for(size_t i=0; i< ps.attribs.size(); ++i) { if(0 <= ps.attribs[i].plot_id && ps.attribs[i].plot_id < (int)block->Dimensions() ) { glVertexAttribPointer(ps.attribs[i].location, 1, GL_FLOAT, GL_FALSE, (GLsizei)(block->Dimensions()*sizeof(float)), block->DimData(ps.attribs[i].plot_id) ); glEnableVertexAttribArray(ps.attribs[i].location); }else if( ps.attribs[i].plot_id == -1 ){ glVertexAttribPointer(ps.attribs[i].location, 1, GL_FLOAT, GL_FALSE, 0, id_array ); glEnableVertexAttribArray(ps.attribs[i].location); }else{ // bad id: don't render shouldRender = false; break; } } if(shouldRender) { // Draw geometry glDrawArrays(ps.drawing_mode, 0, (GLsizei)block->Samples()); ps.used = true; } // Disable enabled attributes for(size_t i=0; i< ps.attribs.size(); ++i) { glDisableVertexAttribArray(ps.attribs[i].location); } block = block->NextBlock(); } prog.Unbind(); } prog_lines.SaveBind(); ////////////////////////////////////////////////////////////////////////// // Draw markers glLineWidth(2.5f); for( size_t i=0; i < plotmarkers.size(); ++i) { const Marker& m = plotmarkers[i]; XYRangef draw_range = m.range; draw_range.Clamp(rview); prog_lines.SetUniform("u_color", m.colour ); if(draw_range.x.Size() == 0.0 || draw_range.y.Size() == 0.0) { // Horizontal or Vertical line glDrawLine(draw_range.x.min, draw_range.y.min, draw_range.x.max, draw_range.y.max ); }else{ // Region glDrawRect(draw_range.x.min, draw_range.y.min, draw_range.x.max, draw_range.y.max ); } } ////////////////////////////////////////////////////////////////////////// // Draw hover / selection glLineWidth(1.5f); // hover over prog_lines.SetUniform("u_color", colour_ax.WithAlpha(0.3f) ); glDrawLine(hover[0], rview.y.min, hover[0], rview.y.max ); glDrawLine(rview.x.min, hover[1], rview.x.max, hover[1] ); // range prog_lines.SetUniform("u_color", colour_ax.WithAlpha(0.5) ); glDrawLine(selection.x.min, rview.y.min, selection.x.min, rview.y.max ); glDrawLine(selection.x.max, rview.y.min, selection.x.max, rview.y.max ); glDrawLine(rview.x.min, selection.y.min, rview.x.max, selection.y.min ); glDrawLine(rview.x.min, selection.y.max, rview.x.max, selection.y.max ); glDrawRect(selection.x.min, selection.y.min, selection.x.max, selection.y.max); prog_lines.Unbind(); prog_text.SaveBind(); ////////////////////////////////////////////////////////////////////////// // Draw Key prog_text.SetUniform("u_scale", 2.0f / v.w, 2.0f / v.h); int keyid = 0; for(size_t i=0; i < plotseries.size(); ++i) { PlotSeries& ps = plotseries[i]; if(ps.used) { prog_text.SetUniform("u_color", ps.colour ); prog_text.SetUniform("u_offset", v.w-5-ps.title.Width() -(v.w/2.0f), v.h-15*(++keyid) -(v.h/2.0f) ); ps.title.DrawGlSl(); } } ////////////////////////////////////////////////////////////////////////// // Draw axis text prog_text.SetUniform("u_scale", 2.0f / v.w, 2.0f / v.h); prog_text.SetUniform("u_color", colour_ax ); for( int i=tx[0]; i<tx[1]; ++i ) { std::ostringstream oss; oss << i*tdelta[0]*tick[0].factor << tick[0].symbol; GlText txt = GlFont::I().Text(oss.str().c_str()); float sx = v.w*((i)*tdelta[0]-rview.x.Mid())/w - txt.Width()/2.0f; prog_text.SetUniform("u_offset", sx, 15 -v.h/2.0f ); txt.DrawGlSl(); } for( int i=ty[0]; i<ty[1]; ++i ) { std::ostringstream oss; oss << i*tdelta[1]*tick[1].factor << tick[1].symbol; GlText txt = GlFont::I().Text(oss.str().c_str()); float sy = v.h*((i)*tdelta[1]-rview.y.Mid())/h - txt.Height()/2.0f; prog_text.SetUniform("u_offset", 15 -v.w/2.0f, sy ); txt.DrawGlSl(); } prog_text.Unbind(); glLineWidth(1.0f); #ifndef HAVE_GLES glPopAttrib(); #endif }