2010-08-03 39 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

我會做的第一件事情就是畫一個圓圈,並將其存儲在顯示列表中(您可以使用緩衝區對象,但這些建議的其餘部分都不依賴於順便說一下,你現在處於即時模式,所以我們會堅持最簡單的改進)。繪製你的分割圓,把紋理座標放在每個對應於完成百分比的地方。應用一個很無聊的着色器,但爲了完整性而使用統一的顏色;三角形紋理座標< =完整性變亮。其餘的保持灰色。然後你的繪圖包括設置制服,並調用顯示列表。快多了。