2010-08-03 126 views
0

我正在研究一个应用程序,在这个应用程序中,我绘制了一个循环的进度指示器,它慢慢变得“充满”,在这里您可以看到a couple of images。我正在使用中间模式,并且我只通过在每个帧更新时绘制顶点来绘制该圆形(请参阅下面的代码)。当圆圈填满白色和灰色之间的边界线时有点闪烁,我想知道如何让它更平滑。如何使用openGL获得真正流畅的移动对象

这是一个具体的例子,但总的来说,我想知道如何获得最平滑的运动,即使使用非常简单的lineair插值?当我在iphone上浏览页面时看到动作时,它非常平滑,这让我想知道如何在我的(快速)mac上实现这一点?

感谢
Roxlu

PhotoBoothCountdown::PhotoBoothCountdown(float fMillisDuration) 
    :duration(fMillisDuration) 
    ,start_time(0) 
{ 
    setActionCommand("take_picture"); 
} 

void PhotoBoothCountdown::update() { 
    if(start_time != 0) { 
     float cur = ofGetElapsedTimeMillis(); 
     perc = (cur-start_time)/duration; 

    } 
} 

void PhotoBoothCountdown::draw() { 
    float resolution = 150; 
    int parts_filled = resolution * perc; 
    int parts_unfilled = (resolution - parts_filled); 
    float part_angle = TWO_PI/resolution; 
    //printf("filled: %i/%i/%i\n", parts_filled, parts_unfilled, (parts_filled+parts_unfilled)); 
    float radius = 300.0f; 
    float width = 100; 
    float radius_inner = radius-width; 
    float center_x = ofGetWidth()/2; 
    float center_y = ofGetHeight()/2; 
    float angle = 0; 

    glBegin(GL_TRIANGLE_STRIP); 
     glColor4f(0.2f, 0.2f, 0.2f,0.9f); 
     for(int i = 0; i <= parts_filled; ++i) { 
      float cosa = cos(angle); 
      float sina = sin(angle); 
      glVertex2f(center_x + cosa * radius,center_y + sina * radius); 
      glVertex2f(center_x + cosa * radius_inner,center_y + sina * radius_inner); 
      angle += part_angle; 
     } 
    glEnd(); 
    glBegin(GL_TRIANGLE_STRIP); 
     glColor4f(1.0f, 1.0f, 1.0f,0.9f); 
     angle -= part_angle; 
     for(int i = 0; i <= parts_unfilled; ++i) { 
      float cosa = cos(angle); 
      float sina = sin(angle); 
      glVertex2f(center_x + cosa * radius,center_y + sina * radius); 
      glVertex2f(center_x + cosa * radius_inner,center_y + sina * radius_inner); 
      angle += part_angle; 
     } 
    glEnd(); 

    if(perc >= 1) { 
     printf("should fire"); 
     fireEvent(); 
     reset(); 
    } 
} 



void PhotoBoothCountdown::start() { 
    start_time = ofGetElapsedTimeMillis(); 
    end_time = start_time + duration; 
} 

void PhotoBoothCountdown::reset() { 
    start_time = 0; 
    end_time = 0; 
    perc = 0; 
} 

回答

1
+0

OpenGL默认为双缓冲 – doc 2010-08-03 16:37:11

+0

@doc:OpenGL对单一缓冲区和双缓冲区的了解不多 - 这就是窗口系统接口的工作,比如wgl或glx。这就是为什么人们通常会调用'glutSwapBuffers',而不是神话般的'glSwapBuffers', – 2010-08-04 02:52:50

+0

@doc:不是,它取决于你初始化它的方式。 @Eric:+1 – Calvin1602 2010-08-04 07:15:27

0

看看这是很难猜测你问什么 - 一个flickery,走样,运动平稳或绘图假象。看你的代码后,自由思想

  • 你认为如果float part_angle = TWO_PI/resolution;然后通过(angle += part_angleresolution次总结,你会得到TWO_PI。不幸的是,在浮点算术中这不是真的。此外,sin(TWO_PI)cos(TWO_PI)将不会必然返回精确的0.01.0值。

  • 为了提高绘图精度,我会绘制完整的灰色圆圈,然后将其作为必要的白色圆圈。这将带来全灰圈100%

  • 浮动操作可能会给你一个错误,这个错误可能会影响转换后的整数值。可能你可能永远不会得到所有填充的部分,通过从这样的表达式计算它们,如int parts_filled = resolution * perc;。你可以转换你的百分比倒计时,以便它将使用整数类型或至少通过打印出百分比值来检验它是否达到100%。
  • Additionaly可以
    • 使用抗锯齿使图像边缘平滑
    • 更高的帧率(这取决于你如何更新图)垂直同步
    • 转到删除页面撕裂
+0

嗨医生,谢谢你的回复。也许,我展示的例子不是一个好的选择。假设我只是一个具有纹理的GL_QUAD,并且我想要平滑地旋转它,即使增加角度(即+ 0.1),每次更新都不会给我很好的平滑线条/图像。 vsync /增加帧率是可能很重要的事情。虽然我不确定frameync在将vsync设置为true时是否会执行任何操作... – pollux 2010-08-03 17:50:37

+1

@pollux您必须严格。是不是太光滑(跳跃)动画的问题还是不太平滑的外观(锯齿状,扭曲)? – doc 2010-08-03 18:17:25

+0

动画不顺畅 – pollux 2010-08-04 12:05:21

0

我会做的第一件事情就是画一个圆圈,并将其存储在显示列表中(您可以使用缓冲区对象,但这些建议的其余部分都不依赖于顺便说一下,你现在处于即时模式,所以我们会坚持最简单的改进)。绘制你的分割圆,把纹理坐标放在每个对应于完成百分比的地方。应用一个很无聊的着色器,但为了完整性而使用统一的颜色;三角形纹理坐标< =完整性变亮。其余的保持灰色。然后你的绘图包括设置制服,并调用显示列表。快多了。