日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

复杂多边形光栅化算法

發(fā)布時間:2025/3/19 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 复杂多边形光栅化算法 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

雖然已經(jīng)一年多沒有維護gbox這個圖形庫項目了,最近確實時間不夠用。。。

今年的重點是把xmake徹底正好,至少在架構(gòu)和大功能(包依賴管理)上,要完全落實下來,后期就是零散的維護和插件功能擴展了。。

tbox我會陸陸續(xù)續(xù)一直進行一些小規(guī)模更新,明年上半年稍微重構(gòu)一些模塊后,就開始重點重新搞gbox了,這才是我一直最想做,也是最喜歡做的項目了

所以我寧愿開發(fā)的慢點,也要把它做精,做到最好。。

好了,回歸正題,雖然現(xiàn)在gbox還處于早期開發(fā)中,并不能用到實際的項目中去,但是里面的一些算法,還是很有參考學習價值的。。

我這兩天沒事就拿出來分享下,如果有感興趣的同學,可以直接閱讀源碼:monotone.c

畢竟這個算法我陸陸續(xù)續(xù)花了整整一年的時間,才把它徹底搞透,并且實現(xiàn)出來。。

為什么會花這么久呢,也許是我太笨了哈。。嘿嘿。。當然也有工作原因哈。。

我先簡單講講研究和實現(xiàn)這個復雜多邊形光柵化算法的背景:

我的gbox目前有兩套渲染設備,一套是直接純算法渲染,其核心算法就是掃描多邊形填充算法,這個算法已經(jīng)算是很普遍了,也很成熟,效率也很高
但是在我的另外一套基于opengl es渲染設備中(為了能夠利用gpu進行加速渲染),在渲染復雜多邊形時,就遇到了問題:opengl不支持復雜多邊形的填充

后來我想了很多辦法,也去google了下,發(fā)現(xiàn)可以通過opengl的模板來實現(xiàn),然后我就開寫了。。

寫到一半,整體效果也出來了,自以為搞定了,卻又遇到一個很難跨過的瓶頸,效率太低了,用這種方式渲染一個老虎頭,幀率只有:15 fps

比我用純算法的實現(xiàn)還慢,后來就思考為什么這么慢呢,一個原因就是模板確實很慢。。。

第二個原因就是:我要實現(xiàn)通用的渲染接口,要支持各種填充規(guī)則,裁剪規(guī)則,這些復雜性,也使得基于模板的方式整體不太好優(yōu)化。。

就這樣折騰了半年,最后決定,還是整體重構(gòu)gbox吧,徹底不用模板實現(xiàn)了,采用另外一種方式:

先在上層對復雜多邊形根據(jù)各種填充規(guī)則和裁剪,進行預處理,核心算法呢就是:對復雜多邊形進行三角化分割,并且合并成凸多邊形
再送到opengl中進行快速渲染。。。

那問題來了,如果才能高效分割多邊形呢,而且還要支持各種填充規(guī)則?

繼續(xù)google,最后發(fā)現(xiàn)libtess2的光柵化代碼里面的算法是可以完全做到的,但是我不可能直接用它的代碼,一個原因是維護不方便
另外一個原因是,它里面的實現(xiàn),很多地方效率不是很高,而我要實現(xiàn)的比他更高效,更穩(wěn)定。。。

那就必須要先看透它的實現(xiàn)邏輯,然后再去改進和優(yōu)化里面的算法實現(xiàn)。。。

雖然里面代碼不多,但是我光看透,就又花了半年時間,最后陸陸續(xù)續(xù)寫了半年,終于才完全搞定。。

最后效果嗎,還是不錯的,至少在我的mac pro上用opengl渲染老虎頭,幀率可以達到:60 fps

當然,里面肯定還是有很多問題在里面的,不做最近確實沒時間整了,只能先擱置下來了,等以后在優(yōu)化優(yōu)化。。。

先曬曬,三角化后的效果:



然后再曬張老虎頭效果:

接著我再對分割算法做些簡要描述:

gbox中實現(xiàn)算法跟libtess2算法中的一些不同和改進的地方:

  • 整體掃描線方向從縱向掃描,改成了橫向掃描,這樣更符合圖像掃描的席位邏輯,代碼處理上也會更方便
  • 我們移除了3d頂點坐標投影的過程,因為我們只處理2d多邊形,所以會比libtess2更快
  • 處理了更多交點情況,優(yōu)化了更多存在交點誤差計算的地方,因此我們的算法會更穩(wěn)定,精度也更高
  • 整體支持浮點和定點切換,在效率和精度上可以自己權(quán)衡調(diào)整
  • 采用自己獨有的算法實現(xiàn)了活動邊緣比較,精度更高,穩(wěn)定性更好
  • 優(yōu)化了從三角化的mesh合并成凸多邊形的算法,效率更高
  • 對每個區(qū)域遍歷,移除了沒必要的定點計數(shù)過程,因此效率會快很多

整個算法總共有四個階段:

  • 從原始復雜多邊形構(gòu)建DCEL mesh網(wǎng)(DCEL雙連通邊緣鏈表, 跟quad-edge類似,相當于是個簡化版).
  • 如果多邊形是凹多邊形或者復雜多邊形,那么先把它分割成單調(diào)多邊形區(qū)域(mesh結(jié)構(gòu)維護)
  • 對基于mesh的單調(diào)多邊形進行快速三角化處理
  • 合并三角化后的區(qū)域到凸多邊形
  • 其中光柵化算法實現(xiàn)上分有七個階段:

  • 簡化mesh網(wǎng),并且預先處理一些退化的情況(例如:子區(qū)域退化成點、線等)
  • 構(gòu)建頂點事件列表并且排序它 (基于最小堆的優(yōu)先級排序).
  • 構(gòu)建活動邊緣區(qū)域列表并且排序它(使用局部區(qū)域的插入排序,大部分情況下都是O(n),而且量不多).
  • 使用Bentley-Ottman掃描算法,從事件隊列中掃描所有頂點事件,并且計算交點和winding值(用于填充規(guī)則計算)
  • 如果產(chǎn)生交點改變了mesh網(wǎng)的拓撲結(jié)構(gòu)或者活動邊緣列表發(fā)生改變,需要對mesh的一致性進行修復
  • 當我們處理過程中,發(fā)生了一些mesh face的退化情況,那么也需要進行處理
  • 將單調(diào)區(qū)域的left face標記為”inside”,也就是最后需要獲取的輸出區(qū)域
  • 如果你想要了解更多算法細節(jié),可以參考: libtess2/alg_outline.md

    光柵化接口的使用例子,來自源碼:gbox/gl/render.c:

    更詳細的算法實現(xiàn)細節(jié),請參考我的實現(xiàn): monotone.c

    static tb_void_t gb_gl_render_fill_convex(gb_point_ref_t points, tb_uint16_t count, tb_cpointer_t priv){// checktb_assert(priv && points && count);// apply itgb_gl_render_apply_vertices((gb_gl_device_ref_t)priv, points);#ifndef GB_GL_TESSELLATOR_TEST_ENABLE// draw itgb_glDrawArrays(GB_GL_TRIANGLE_FAN, 0, (gb_GLint_t)count); #else// the device gb_gl_device_ref_t device = (gb_gl_device_ref_t)priv;// make crc32tb_uint32_t crc32 = 0xffffffff ^ tb_crc_encode(TB_CRC_MODE_32_IEEE_LE, 0xffffffff, (tb_byte_t const*)points, count * sizeof(gb_point_t));// make colorgb_color_t color;color.r = (tb_byte_t)crc32;color.g = (tb_byte_t)(crc32 >> 8);color.b = (tb_byte_t)(crc32 >> 16);color.a = 128;// enable blendgb_glEnable(GB_GL_BLEND);gb_glBlendFunc(GB_GL_SRC_ALPHA, GB_GL_ONE_MINUS_SRC_ALPHA);// apply colorif (device->version >= 0x20) gb_glVertexAttrib4f(gb_gl_program_location(device->program, GB_GL_PROGRAM_LOCATION_COLORS), (gb_GLfloat_t)color.r / 0xff, (gb_GLfloat_t)color.g / 0xff, (gb_GLfloat_t)color.b / 0xff, (gb_GLfloat_t)color.a / 0xff);else gb_glColor4f((gb_GLfloat_t)color.r / 0xff, (gb_GLfloat_t)color.g / 0xff, (gb_GLfloat_t)color.b / 0xff, (gb_GLfloat_t)color.a / 0xff);// draw the edges of the filled contourgb_glDrawArrays(GB_GL_TRIANGLE_FAN, 0, (gb_GLint_t)count);// disable blendgb_glEnable(GB_GL_BLEND); #endif}static tb_void_t gb_gl_render_fill_polygon(gb_gl_device_ref_t device, gb_polygon_ref_t polygon, gb_rect_ref_t bounds, tb_size_t rule){// checktb_assert(device && device->tessellator);#ifdef GB_GL_TESSELLATOR_TEST_ENABLE// set modegb_tessellator_mode_set(device->tessellator, GB_TESSELLATOR_MODE_TRIANGULATION); // gb_tessellator_mode_set(device->tessellator, GB_TESSELLATOR_MODE_MONOTONE); #endif// set rulegb_tessellator_rule_set(device->tessellator, rule);// set funcgb_tessellator_func_set(device->tessellator, gb_gl_render_fill_convex, device);// done tessellatorgb_tessellator_done(device->tessellator, polygon, bounds);}

    個人主頁:TBOOX開源工程
    原文出處:http://tboox.org/cn/2016/07/21/tessellate-polygon-algorithm/

    與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的复杂多边形光栅化算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。