Request advice on strip chart concepts

Centos Linux, Qt and Open GL novice
With a search result I obtained what seems to be the version string: 2.1 Mesa 17.2.3

The goal is to create a strip chart to be used to observe various signals during system development and testing. I have created a Qt layout that has buttons and line edits needed to control the strip chart. A grid layout is used and a simple Open GL widget is placed nicely within the QT environment.

Now to replace that simple GL widget with the strip chart. It is a rectangle maybe 200 pixels high and 800 wide. It scrolls from right to left making time flow from left to right. Each time a measurement is received, the entire rectangle is moved left one pixel or one column width to the left opening a new column on the right. The new plotted point is placed in that column. The app then waits for the next measurement. It is a simple two dimensional construct. All B&W will be fine but one additional color would help.

Trying to keep this at a high level, what open GL functionality should be used to draw this strip chart? I presume a bit map is best but am unsure of the most efficient way to move it a column at a time. Are there any tools within OpenGL that might be suited to this goal?

glDrawArrays(GL_LINES).

You’ll want to store the values in a circular buffer, rather than shifting everything down when adding a new value. That means you’ll need two draw calls, with the first value of the second call equal to the last value of the first call. So when writing the last element in the array, you’d store the same value in the first element and set the update index to 1 rather than 0. You can store the x coordinates in the same array, or (if the samples are equally-spaced) derive the x coordinate from gl_VertexID in a vertex shader.

I am looking into glDrawArrays( GL_LINES)
The plotted points will not be lines, they will effectively be random points. Each will usually, but not always, be close to the previously plotted point vertically and one position over horizontally. GlDrawArrays has the option GL_POINTS. This appears to be a collection of points. As the chart moves for each time increment, every point must be visited and its X location updated. That will be a lot of work for the processor.
I was / am hoping for some type of primitive that begins with an image and moves it X pixels in a specified direction. Does any sort of beast such as that exist?

[QUOTE=mbkelly;1293300]
As the chart moves for each time increment, every point must be visited and its X location updated. That will be a lot of work for the processor.[/QUOTE]
That isn’t necessary. You can translate the points either in the vertex shader or using the model-view matrix.

I thought the Qt part was OK but wound up struggling with that more than expected. Now I am moving into the core of how to plot the points.
This is a 2D app with no shading, no color manipulation, or view changes so I would probably have never looked into the vertex shader or model-view. I am starting that now so thank you for taking the time to read and post.

Edit
With a quick look I don’t see how the vertex shader will be useful. The majority of what I have found with model-view matrix is far more than I need. However, I have picked out this phrase: translation.

A strip chart, as displayed on the monitor, is an X-Y array of bits. The only animation is to translate them along the X axis, adding new points to one end. In a tiny bit more detail, columns are added to the right end with all values being 0, except for one value in each column that is set to 1, the point plotted. I cannot envision the need to preform a full matrix translation, just shift the bits along one axis.

This will probably use less than 1% of Open GL’s capabilities. Might there be any need to elaborate on how simple the concept is? (Understanding that implementation is never as simple as concept.)

Do I seem to be on the right path?

[QUOTE=mbkelly;1293338]
With a quick look I don’t see how the vertex shader will be useful. The majority of what I have found with model-view matrix is far more than I need. However, I have picked out this phrase: translation.

A strip chart, as displayed on the monitor, is an X-Y array of bits. The only animation is to translate them along the X axis, adding new points to one end. In a tiny bit more detail, columns are added to the right end with all values being 0, except for one value in each column that is set to 1, the point plotted. I cannot envision the need to preform a full matrix translation, just shift the bits along one axis.

This will probably use less than 1% of Open GL’s capabilities. Might there be any need to elaborate on how simple the concept is? (Understanding that implementation is never as simple as concept.)

Do I seem to be on the right path?[/QUOTE]

Yes.

If you’re using “legacy” OpenGL, then the simplest way to apply the translation is via the model-view matrix, e.g.


glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-x_offset, 0, 0);

The offset will then be subtracted from the X coordinate of all vertices.

“Modern” OpenGL (3.1+ core profile) doesn’t have these functions; you’d do something similar using the vertex shader.

[QUOTE=GClements;1293346]Yes. …
[/QUOTE]

I am beginning to understand the problem and situation now. I suspect that a major part of the problem is my almost total lack of knowledge about matrix operations.

Now I am sensing that to move the numbers in a matrix over by some amount a matrix multiply is performed. That is an expensive operation as compared to a bit shift (as in a bit shift register). However, we are discussing graphics and how things are viewed, and that is done with a graphics/video adapter, and that generally has specialized hardware, therefore is not as expensive as when done with a standard processor programmed in what might be called a linear mode. (Doing things one at a time. Is there a better phrase?)

And as I look at the various GL commands I am not able to visualize what is done within the graphics processing hardware and what is done by the main CPU.

We have but one other person with any experience with Open GL and that is on Windows rather than Linux and it runs within an incredibly extensive display product called IADS (Interactive Analysis Display System). He has an app that is way more comprehensive than my needs. Its in C sharp so I find it difficult to read. I have now spent a couple of days looking that code.

Now I understand those three lines of code you posted. And am beginning to shift my perspective to that of Open GL.

This is way too much to post, and too much more to explain, but to keep it short your advice has modified my trajectory and I appreciate the time you spent reading my posts and writing back.

Thank you.

It’s not just the specialised hardware but also the fact that, with the fixed-function pipeline (i.e. when not using shaders), the hardware is probably going to perform the matrix multiply on every vertex anyhow. If you don’t modify the model-view matrix it will just be multiplying by an identity matrix, and that isn’t actually any cheaper.

It could optimise that case, but given that most modern OpenGL applications are performing far more complex computations for every pixel (and doing that for millions of pixels each frame), there wouldn’t be much point.

The CPU sends commands to the GPU. It also handles various housekeeping operations such as allocation and deallocation of objects. Anything which is done “in bulk” (for every vertex, every triangle or every pixel) will have the computation performed by the GPU.

I am working on getting adjusted to the concept that OpenGL does much or most of its work in the display adapter hardware. Thanks for those hints.

I made changes Qt part and returned to the OpenGL part. Function glOrtho(…) is very versatile. My theory is that the left and right clipping values of glOrtho can be continuously set to the moving time window. If the values are two seconds apart then only values with associated time values within that two second window will be displayed.

In the initial test a polygon is drawn within the QGLWidget. Good so far.

Problem 1: When the encompassing widget is resized the QGLWidget changes size as expected (within its enclosing Qt widget) but the polygon remains fixed in size and position with respect to the lower left corner of the QGLWidget. I expected it to resize along with the QGLWidget and to stay in the same relative position within the changing QGLWidget.

Problem 2: The second test was to put a call to glOrtho() within function paintGL(). I can show that this function is called for each step of the resize operation. The arguments were constants in the hope the polygon would be redrawn and keep the same size relative to its enclosing QGLWidget. That does not work. On each step of window resize, getting larger, the polygon loses half its width. Height is unchanged. After about eight resize steps it disappears. If the window is resized two steps larger and then back smaller, the polygon continues to get smaller until it disappears.

This is a 2D display and I am really weak on matrix operations and linear math.

A stackoverflow thread discusses glOrtho() and states that it is deprecated as of OpenGL 4.5. I cannot update now so is there some other method or concept that should be used?

Edit: I fixed problem 1 and think I understand it. Regarding problem 2, should I stop attempting to use the glOrtho() function and instead use glViewport() to accommodate the resizing? What about accommodating the ever changing time as the strip chart scrolls?

You should use both. At a minimum, you need to call glViewport() whenever the widget size changes, although you could just call it at the start of paintGL(). You should still use glOrtho() to scroll the data.

Vertex coordinates are subjected to three transformations: model-view, projection and viewport. glOrtho() modifies the model-view or projection transformation (depending upon the glMatrixMode() setting), glViewport() affects the viewport transformation. Clipping is performed between the projection and viewport transformations, so you can’t combine the two operations.

Also: note that glOrtho() concatenates a transformation with the current transformation, so you would normally call glLoadIdentity() first to reset the transformation.

I am struggling with glOrtho() and glViewport(). My current understanding is that glOrtho() sets how openGL will look at the artifacts to be displayed and calculate the display to present a orthographic projection (I think I understand those last two words). When a diagonal arrow is drawn glOrtho can be used to show that arrow with compass angles of 45, 135, 225, or 315 degrees. glOrtho() uses real world coordinates.

glViewport() defines the monitor limits of what is to be displayed. It sets the lower left corner in pixels along with the width and height in pixels. The only call to glViewport() is in resizeGL() and the only arguments changed are size and height.

The previous post that I should use glOrtho() to scroll the data makes sense. But there is something wrong in my simple test.

The QGLWidget, within an encompassing Qt widget, is given a minimum size of width 400 height 100. Within initializeGL(), call glOrtho( -4.0, 4.0, -1.0, 1.0, -1,0, 1.0 ) (those arguments are all defined constants). That looks good. I can swap some signs and see the image flip about the expected axis.

In resizeGL( width, height ) there is a call to glViewport( 0, 0, width, height ). The QGLWidget is resized along with the encompassing widget. For this app I suspect the first two arguments or glViewport(), left and bottom, will never change from 0.

In paintGL() a polygon is drawn within the QGLWidget and appears as expected. It resizes as expected.

In expectation of possibly using glOrtho() within paintGL() the call is copied from initializeGL() into paintGL(), unchanged, all arguments are constants.

The polygon is then reduced to about 10% of the original width but the height remains the same. On resize it is further reduced to a small line segment.
I cannot copy paste from my work computer, please try to accommodate typos, but the paintGL() looks mostly like this.

void C_GL_Strip_Chart:: paintGL()
{
// Used constants for glOrtho because nothing is changing, a static display.
/* glOrtho( LEFT_CLIP, RIGHT_CLIP, BOTTOM_CLIP, TOP_CLIP, NEAR_CLIP, BACK_CLIP ); */
GlClear( GL_COLOR_BUFFER_BIT );
GlColor3f( 1.0, 0.0, 0.0 );
glBegin( GL_POLYGON )
glVertex2f( -0.5, -0.5 );
glVertex2f( -0.5, 0.5 );
glVertex2f(  0.5, 0.5 );
glVertex2f(  0.5, -0.5 );  // rectangle,
glVertex2f( -0.4, -0.9 ); // with a little bump to show orientation
glEnd();
};

This indicates that glOrtho() does not belong in paintGL. But from other things I have seen and read, that appears to be a contradiction. I resolve that apparent contradiction by presuming there is something I don’t understand here. The bad behavior of goOrtho() might be a red herring, or something I have omitted.

As I wrote all this out I ran a few tests and confirmed the above concepts. Indeed, I learned and verified several things via the process of trying to pose a cogent question. There must be something wrong in how I have used glOrtho() within paintGL(). Or maybe somewhere else.

You need to call glLoadIdentity() before glOrtho(). Otherwise, each glOrtho() transformation is combined with the previous glOrtho() transformations.

Adding glLoadIdentity() looks good. Meanwhile I added some functions, slots, and connected two pushbuttons to some functions as follows:

const GLdouble FUDGE_IT = 1.0;
void C_GL_Strip_Chart::move_ortho_left()
{
std::cout << “called move left 
”;
ortho-left_clip -= FUDGE_IT;
ortho-right_clip -= FUDGE_IT;
glLoadIdentity( );
glOrtho( ortho_left_clip, 
             ortho_right_clip,
             ortho_bottom_clip,
             ortho_top_clip,
             ortho_near_clip,
             ortho_far_clip );
paintGL();
}  

Meaning the buttons were connected such that the shown function(s) gets called.

There is a move_ortho_right that does +=. In paintGL() there is now a little while loop just before exiting that calls glGetError() and outputs any error messages. It outputs messages to show that the loop ran and has discovered N errors. None have been discovered.

I expected that the changes to glOrtho() argument would cause the polygon to move within the QGLWidget display. I see no effect at all.
Is there a method to fetch/get the ortho and view values to be sure they contain the values expected?

Edit
Added a bit of code to get the clip plane values discovering that there are over 3000 of them.

for( i = 0; i <= 4; i ++ ) 
{ 
glGetClipPlane( i, ortho_clip_plane );  // arg 2 is array of 4 GLdouble
std::cout << “clip plane = “ << stuff to print each of four values << “
”
}

This runs right after one of the calls to glOrtho(…) where the arguments are changing. I looked at the first four of the the clip planes and none of the values get changed, nothing but zeroes. Is that indicating that my glOrtho(…) call is incorrect?
Note that the first call to glOrtho() seems to have the expected effect and the arguments are not not all zeroes.

Edit again: All the calls to glOrtho() have been prefixed and postfixed as follows:

glMatrixMode( GL_PROJECTION );
glLoadIdentity()
glOrtho( six_arguments );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

Those two calls before and two after produced no detectable effect.

Bonus Question: Is there a book or tutorial written for people that only need 2D displays? My searches for that were unproductive.

Just had a possible realization. From reading tutorials and forums I discovered the need to override method: paintGL().
My OOP is not well developed but I suspect that the original paintGL() code within openGL itself still gets called. However, when I create another function that requires a repaint, calling paintGL() directly calls my local code but it does not invoke the original openGL method paintGL().

Please help with the terminology. What is the code needed to invoke paintGL() at the openGL level?

EDIT:
With that idea I found than I cannot call the openGL original paintGL() because it is protected. So, additional searches discovered that I should use update();

and that gave me the moving ortho window that I want. On each interval of time I can set the window to show the desired time period, then plot the points using the received value along the Y axis and the recorded value along the X axis. There is more to it, but I now have the concept.

EDIT 2:
I work for the government and have discovered that some buttons in forums are not displayed. Is there a way to mark this thread as resolved. Or maybe change the title at the OP level to include the word Resolved.

GClements,
Thank you for the time you spent assisting me.