Table of Contents
This tutorial is about how to move objects around. It will introduce new shader techniques.
The simplest way one might think to move a triangle or other object around is to
            simply modify the vertex position data directly. From previous tutorials, we learned
            that the vertex data is stored in a buffer object. So the task is to modify the vertex
            data in the buffer object. This is what CPUPositionOffset.cpp
            does.
The modifications are done in two steps. The first step is to generate the X, Y offset
            that will be applied to each position. The second is to apply that offset to each vertex
            position. The generation of the offset is done with the
                ComputePositionOffset function:
Example 3.1. Computation of Position Offsets
void ComputePositionOffsets(float &fXOffset, float &fYOffset)
{
    const float fLoopDuration = 5.0f;
    const float fScale = 3.14159f * 2.0f / fLoopDuration;
    
    float fElapsedTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
    
    float fCurrTimeThroughLoop = fmodf(fElapsedTime, fLoopDuration);
    
    fXOffset = cosf(fCurrTimeThroughLoop * fScale) * 0.5f;
    fYOffset = sinf(fCurrTimeThroughLoop * fScale) * 0.5f;
}
        This function computes offsets in a loop. The offsets produce circular motion, and the
            offsets will reach the beginning of the circle every 5 seconds (controlled by
                fLoopDuration). The function
                glutGet(GLUT_ELAPSED_TIME) retrieves the integer time in
            milliseconds since the application started. The fmodf function
            computes the floating-point modulus of the time. In lay terms, it takes the first
            parameter and returns the remainder of the division between that and the second
            parameter. Thus, it returns a value on the range [0, fLoopDuration),
            which is what we need to create a periodically repeating pattern.
The cosf and sinf functions compute the
            cosine and sine respectively. It is not important to know exactly how these functions
            work, but they effectively compute a circle of diameter 2. By multiplying by 0.5f, it
            shrinks the circle down to a circle with a diameter of 1.
Once the offsets are computed, the offsets have to be added to the vertex data. This
            is done with the AdjustVertexData function:
Example 3.2. Adjusting the Vertex Data
void AdjustVertexData(float fXOffset, float fYOffset)
{
    std::vector<float> fNewData(ARRAY_COUNT(vertexPositions));
    memcpy(&fNewData[0], vertexPositions, sizeof(vertexPositions));
    
    for(int iVertex = 0; iVertex < ARRAY_COUNT(vertexPositions); iVertex += 4)
    {
        fNewData[iVertex] += fXOffset;
        fNewData[iVertex + 1] += fYOffset;
    }
    
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertexPositions), &fNewData[0]);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}
        This function works by copying the vertex data into a std::vector, then applying the offset to the X and Y coordinates of each vertex. The last three lines are the OpenGL-relevant parts.
First, the buffer objects containing the positions is bound to the context. Then the
            new function glBufferSubData is called to transfer this data to the
            buffer object.
The difference between glBufferData and
                glBufferSubData is that the SubData function does not
                allocate memory. glBufferData specifically
            allocates memory of a certain size; glBufferSubData only transfers
            data to the already existing memory. Calling glBufferData on a
            buffer object that has already been allocated tells OpenGL to
                reallocate this memory, throwing away the previous data and
            allocating a fresh block of memory. Whereas calling glBufferSubData
            on a buffer object that has not yet had memory allocated by
                glBufferData is an error.
Think of glBufferData as a combination of
                malloc and memcpy, while glBufferSubData
            is just memcpy.
The glBufferSubData function can update only a portion of the
            buffer object's memory. The second parameter to the function is the byte offset into the
            buffer object to begin copying to, and the third parameter is the number of bytes to
            copy. The fourth parameter is our array of bytes to be copied into that location of the
            buffer object.
The last line of the function is simply unbinding the buffer object. It is not strictly necessary, but it is good form to clean up binds after making them.
            Buffer Object Usage Hints. 
            Every time we draw something, we are changing the buffer object's data. OpenGL has
                a way to tell it that you will be doing something like this, and it is the purpose
                of the last parameter of glBufferData. This tutorial changed
                the allocation of the buffer object slightly, replacing:
        
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
with this:
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STREAM_DRAW);
GL_STATIC_DRAW tells OpenGL that you intend to only set the data in
            this buffer object once. GL_STREAM_DRAW tells OpenGL that you intend
            to set this data constantly, generally once per frame. These parameters do not mean
                anything with regard to the API; they are simply hints to the
            OpenGL implementation. Proper use of these hints can be crucial for getting good buffer
            object performance when making frequent changes. We will see more of these hints
            later.
The rendering function now has become this:
Example 3.3. Updating and Drawing the Vertex Data
void display()
{
    float fXOffset = 0.0f, fYOffset = 0.0f;
    ComputePositionOffsets(fXOffset, fYOffset);
    AdjustVertexData(fXOffset, fYOffset);
    
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    
    glUseProgram(theProgram);
    
    glBindBuffer(GL_ARRAY_BUFFER, positionBufferObject);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
    
    glDrawArrays(GL_TRIANGLES, 0, 3);
    
    glDisableVertexAttribArray(0);
    glUseProgram(0);
    
    glutSwapBuffers();
    glutPostRedisplay();
}
        The first three lines get the offset and set the vertex data. Everything but the last
            line is unchanged from the first tutorial. The last line of the function is there to
            tell FreeGLUT to constantly call display. Ordinarily,
                display would only be called when the window's size changes or
            when the window is uncovered. glutPostRedisplay causes FreeGLUT to
            call display again. Not immediately, but reasonably fast.
If you run the tutorial, you will see a smaller triangle (the size was reduced in this tutorial) that slides around in a circle.