0

我正在开发一个应用程序,在该应用程序中我绘制了一个缓慢“填充”的圆形进度指示器,在这里您可以看到几张图像。我正在使用中间模式,我只是通过在每次帧更新时绘制顶点来绘制这个圆形(参见下面的代码)。当圆圈填满白色和灰色之间的边界线时,有点闪烁,我想知道如何使它更平滑。

这是一个具体的例子,但总的来说,我想知道即使使用非常简单的线性插值,如何获得最平滑的运动?当我在 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;
}
4

3 回答 3

1

看看双缓冲

于 2010-08-03T16:35:31.107 回答
0

我要做的第一件事就是简单地绘制一个圆圈,并将其存储在显示列表中(您可以使用缓冲区对象,但此建议的其余部分均不依赖于此,并且您处于即时模式,所以我们将坚持最简单的改进)。画出你的分割圆,将纹理坐标放在与那里的完成百分比相对应的每个圆上。应用一个很乏味的着色器,但为了完整性有一个统一的着色器;具有纹理坐标 <= 完整性的三角形会亮起。其余的保持灰色。然后你的绘图包括设置制服和调用显示列表。快多了。

于 2010-08-03T21:55:20.747 回答
0

很难猜出您要问的是什么 - 闪烁、锯齿、平滑运动或绘图伪影。查看您的代码后的自由想法

  • 您假设 if then 通过对 ( )次float part_angle = TWO_PI/resolution;求和,您将得到. 不幸的是,这在浮点算术中是不正确的。sin(TWO_PI) cos(TWO_PI) 也不一定会返回精确值和值。angle += part_angleresolutionTWO_PI0.01.0

  • 为了提高绘图精度,我会画一个完整的灰色圆圈,然后根据需要在上面画一个白色的圆圈。这将带来 100% 的全灰色圆圈

  • 对浮点数的操作可能会给您带来舍入错误,并且此错误可能会影响转换后的整数值。您可能永远无法通过像这样的表达式计算它们来获得所有填充的部分int parts_filled = resolution * perc;。您可以转换您的百分比倒计时,以便它使用整数类型,或者至少通过打印百分比值来测试它并检查它是否达到 100%。
  • 另外你可以
    • 使用抗锯齿使边缘更平滑
    • 提高帧速率(这取决于您如何更新绘图)
    • 打开垂直同步以消除页面撕裂
于 2010-08-03T17:12:07.870 回答