0

Using GLFW3, I currently made a bvh file parser which reads the file in and converts it to a human model I made in opengl. However, whenever I launch it, the movement is so fast that the animation cannot be seen in the eye. So I want to tone the animation speed a little down. Here is my render loop

while (!glfwWindowShouldClose(window))
    {
        // per-frame time logic
        // --------------------
        float currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // input
        // -----
        processInput(window);

        // render
        // ------
        glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        (Some Shader Settings)

        glm::mat4 model = glm::mat4(1.0f);

        if (moveFlag == true) {
            bvh.clearVISITED();
            bvh.setMotionPerFrame(bvh.root, 0);
        }
        if (resetMatrices == true) {
            bvh.clearVISITED();
            bvh.resetMatrices(bvh.root);
        }

        drawBones(shader, bvh.root, model);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

The function inside the if statement bvh.setMotionPerFrame(bvh.root, 0) is where the animation reads in the JOINT configurations per Frame data inside the file, and sets each joint's rotation matrix and translation matrix accordingly. (moveFlag and resetMatricesare flags that are set if spacebar and r button are hit respectively)

Since reading the channel data per frame in each render loop unchangeable, I want to come up with a way that I can slower the render loop speed itself. Any suggestions?

genpfault
  • 51,148
  • 11
  • 85
  • 139
Peter
  • 460
  • 6
  • 23
  • 2
    You need a timer. Or at least a time-difference. See an example in [this SO answer](https://stackoverflow.com/a/41273081/3871028) – Ripi2 Oct 14 '18 at 16:28

1 Answers1

1

You need to add timing to your code. while you are parsing BVH MOTION like this:

MOTION
Frames:     20
Frame Time: 0.033333

you should extract the Frame Time value which is the time between frames in seconds. Now depending on the code architecture of yours you need to properly time your rendering. I am used to have some

bool _redraw=false;

telling whole app to redraw on next possible occasion (like timer) which is set by anything from mouse/keyboard events changing view or scene to resizing of window etc...

For time changing stuff I also usually have a function:

void update(double dt);

periodically called from app handling interpolation/simulation and stuff for dt time elapsed from last call. Now the dt can be timer interval that calls this or in case I need better accuracy I measure dt directly using windows PerformanceCounter. In case you just got endless loop you still can use:

Sleep(dt*1000.0);

which is not precise but will work.

More on animation and timing topic can be found in here and the sublinks:

Now getting back to BVH here is how my C++ update method for it looks like:

void bvh::update() // call periodically to animate
 {
 if ((_play)&&(dt>1e-6))
  { 
  int f=frame;
  t+=tper(&t0);
  while (t>=dt)
   {
   t-=dt;
   frame++;
   if (frame>=frames)
    {
    frame=0;
    if (!_loop){ stop(); break; }
   }
  }
  if (f!=frame) setframe(frame);
 }
}

here some selected stuff from my BVH class:

List<int> root;             // root bones ix
List<bvh_bone> bone;        // HIERARCHY bvh
List<double> data;          // MOTION data
int frames;                 // MOTION frames
double dt;                  // MOTION delta time [ms]
int channels;               // channels/frame
// render
bool _redraw;               // out redraw needed?
// animation
bool _loop;                 // in loop playback?
bool _play,_pause,_stop;    // out animation buttons state?
int frame;                  // actual set frame
double t,t0;                // time elapsed from start of actual frame, measurement start time
void play() { tper(&t0); t=0.0; if (!_pause) frame=0; _play=1; _pause=0; _stop=0; setframe(frame); _redraw=true; }
void stop() { tper(&t0); t=0.0;                       _play=0; _pause=0; _stop=1; frame=0; setframe(frame); _redraw=true; }
void pause(){ tper(&t0); t=0.0; if (_stop) return;    _play=_pause; _pause=!_pause; }
void setframe(int frame);   // compute bones from frame data

And tper function measures time between its subsequent calls taken from my timing lib:

const int   performance_max=64;                 // push levels
double      performance_Tms=-1.0,               // counter period [ms]
            performance_tms=0.0,                // measured time after tend [ms]
            performance_t0[performance_max];    // measured start times [ms]
int         performance_ix=-1;                  // actual time stack index

double tper(double *t0=NULL)    // return duration [ms] between tper() calls
    {
    double t,tt;
    LARGE_INTEGER i;
    if (performance_Tms<=0.0)
        {
        for (int j=0;j<performance_max;j++) performance_t0[j]=0.0;
        QueryPerformanceFrequency(&i); performance_Tms=1000.0/double(i.QuadPart);
        }
    QueryPerformanceCounter(&i); t=double(i.QuadPart); t*=performance_Tms;
    if (t0) { tt=t-t0[0]; t0[0]=t; performance_tms=tt; return tt; }
    performance_ix++;
    if ((performance_ix>=0)&&(performance_ix<performance_max))
        {
        tt=t-performance_t0[performance_ix];
        performance_t0[performance_ix]=t;
        }
    else { t=0.0; tt=0.0; };
    performance_ix--;
    performance_tms=tt;
    return tt;
    }

Now in main app loop/timer just call periodicaly the update and if _redraw is true set it to false and repaint your app. Beware my bvh::dt was converted to [ms] !!!

Spektre
  • 49,595
  • 11
  • 110
  • 380
  • Thank you Mr. Spektre! I'm the same person that asked how I can parse the bvh file to a given model in opengl. I was able to make a parser successfully during the weekends :) Thank you for the final advice! – Peter Oct 15 '18 at 12:21
  • 1
    @Peter glad to be of help and good to know you are progressing... inbetween I rewrited my old BVH class from ~6 Kb to ~18KB of C++ code adding more accurate timing (code is in here), some mesh computations and editor for dissecting single object mesh into sub-meshes if topology allows it ... – Spektre Oct 15 '18 at 13:15