免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5728 | 回复: 9
打印 上一主题 下一主题

[算法] 其实, 我也不会脏矩形, 不知道论坛有没人贡献一份代码出来 [复制链接]

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
1 [报告]
发表于 2012-11-24 21:38 |显示全部楼层
你到底想实现什么功能?

如果是“有许多区域是脏的,我要逐个更新”这个,你可以考虑用region,我可以教你算法。

如果是“只有在单个长方形区域里面的内容,才会更新”这个,我可以教你clip算法。分为光栅clip和矢量clip两部分。看你用的什么样的引擎。

如果是“只有在某个多边形内部才会更新”这个,我可以给你一个gpc的源代码——不好意思,没法教你,因为我自己还没有看懂。GPC的意思是“通用多边形裁剪”,用处你懂的。

你得说明这个“脏矩形”到底是想实现啥功能= =

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
2 [报告]
发表于 2012-11-24 22:08 |显示全部楼层
本帖最后由 starwing83 于 2012-11-24 22:14 编辑

哦,就是把屏幕分成几个小块,然后仅仅绘制对应小块的技术?

何必呢。任意的脏矩形绘制不好么?而且根本就不难啊……

一块矩形脏了,将其加入脏矩形的数组,然后在绘制的时候,利用这个数组进行裁切嘛……矢量引擎里面,通常是对顶点进行裁切,因为顶点被裁,所以剩下所有顶点肯定能被绘制,因此不必每画一个点就判断,提高了效率。光栅绘制的话,恐怕就很麻烦了。基本上要各个情况各个分析,比如说画直线怎么个裁剪法儿,画矩形怎么个裁剪法儿等等了……但是也不难。

分屏幕的技术,在光栅时代应该没啥问题。进入矢量绘图时代以后,已经失去其时代意义了。

更新:屏幕分块的话还要一个作用。就是在屏幕上有大量物体的时候,少量物体的移动不会导致全部物体的重绘。这一点其实也不太需要屏幕分块了。移动的时候采用非常经典的AABB算法即可划分出需要重绘的块。然后 根据这些块的extents决定哪些物体必须重绘。

其实说白了,非确定性的离散算法,已经比确定性的划分算法要好了。搞过比赛的都知道这个。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
3 [报告]
发表于 2012-11-24 22:14 |显示全部楼层
回复 7# __BlueGuy__

Flash代码之渣你又不是没有看过= =
   

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
4 [报告]
发表于 2012-11-24 22:20 |显示全部楼层
回复 7# __BlueGuy__


    2D也能矢量绘图啊你不知道?

顶点源,顶点变换器,光栅器,像素变换器,像素排序,扫描线。

这些都是2D的矢量绘制技术啊。

在这里的几乎每一个部分,都支持矢量裁剪。后三个部分支持光栅裁剪。

云风这个的优势是:划分为块以后,小对象,不动的对象效率会很高。

缺点是:一个对象如果太大以至于横挎几个块,会导致重复绘制(当然实际上是不会真的重复绘制的,会做裁剪判断的,但是重复调用是跑不掉的)。另外对象的移动会导致它在块中相对位置变化,对于移动频繁的游戏这个开销是很沉重的。

我以前(大概两年以前吧)就写过这个算法,当时是公司项目,Game2D,用作飞机游戏的底层引擎,不过失败了= =原因就不提了,有自己的原因在里面吧。

现在如果让我重写的话,我不会再用脏矩形。在绘制之初就过滤一遍对象,然后直接令对象重绘,可能会更好一点。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
5 [报告]
发表于 2012-11-24 22:20 |显示全部楼层
回复 9# __BlueGuy__


    是你自己渣好不好?云风的代码非常好懂啊!你自己说说哪儿不好懂了?

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
6 [报告]
发表于 2012-11-24 22:27 |显示全部楼层
本帖最后由 starwing83 于 2012-11-24 22:37 编辑

回复 12# __BlueGuy__


    是这样的,云风的代码分为三个部分。

第一部分是canvas.[ch],这部分是整个脏矩形的实现的核心。整个canvas被划分为了多个block所谓“绘制”是把对象的绘制函数贴到canvas身上。canvas的draw里面做了二重循环,根据绘制对象的位置,将对象划分到对应的block身上,这部分是重点。

然后,redraw什么都不干,只是标记需要重新绘制了。而update函数则依次按block,调用object数组里面的函数,让覆盖了这个block的所有对象依次(从先到后)在实际的像素(第一个参数,那个pixel)上做绘制。object数组里面的每个绘制函数自己负责裁剪:而且仅仅是矩形裁剪。强调一下:update每绘制完一个block,就会将其中的对象清零,方便下次绘制。这个设计…………也不能说很不好吧,只是说比较适应某些场景而已。

这个核心就完了,仔细看,很好懂的。

第二个部分是box.[ch],这部分给出了一个实际的object的例子,即绘制矩形。这部分代码你要还不懂的话你还是转行吧。

第三部分是gdi.[ch]和test.c,前者负责提供一个兼容的函数,将前面绘制的像素pixel真正地放到屏幕上去(SetDIBitToDevice函数是核心),后者就是整体的程序了,注册窗口类啊什么的。这个应该很好懂,不懂的话你得补习Win32 SDK编程了。

有什么疑问?

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
7 [报告]
发表于 2012-11-24 22:37 |显示全部楼层
回复 14# __BlueGuy__


    做销售去吧,赚钱。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
8 [报告]
发表于 2012-11-24 22:47 |显示全部楼层
回复 16# __BlueGuy__


    要么,你就安安心心的当你的码农,老大要你写1+1,你就不要脑子里想a+b。

要么,你就刻苦学习算法和架构设计。云风的代码(就这份而言)架构上勉强过得去,但是风格很清新,你可以多学习。

就想坐着不动突然顿悟,哪那么好的时期?我学C到第八年才突然明白原来设计是这样的。虽然我走了很多弯路,但是也算是厚积薄发吧。(当然如果是OwnWaterloo肯定会说我是视野狭隘)如果你真的想快速提高眼界和设计水平,我强烈建议你通读Lua实现源代码,才2W行左右,通读应该很简单,云风的博客里面有Lua源码赏析的pdf(藏得很深……)有助于帮助你在Lua源代码里面找到路标= =(不过一间小教室就需要路标这个嘛……)难点的话,垃圾回收是一个,哈希表处理是一个,语法分析是一个,基本上就没了吧。哈希表处理我在论坛写过帖子。垃圾回收云风写过五篇的稿子,其实我推荐你看MikePall的“四色垃圾回收法”的文章,那个讲的非常明白,我就是看那个看懂的。语法分析我到现在都没看懂,也不需要看懂,反正我也不打算写个编译器,其中大部分(99%)的内容懂了就成。没懂的部分是关于back-patch和寄存器分配的,实在没什么需求看懂这个,我就放下了。

给自己一个月时间,看Lua源代码,学习设计,你再看看是不是这样。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
9 [报告]
发表于 2012-11-24 23:12 |显示全部楼层
回复 18# __BlueGuy__


    你不读,怎么知道读不懂?

Lua里面很多技巧是很有用的,比如内存管理,lmem就值得细品,还有关于longjmp/setjmp的用法也值得学习。Lua的链表用得出神入化,也可以观摩。基本上Lua源代码看明白了,写什么不行?

不能畏难啊,畏难就寸步难行。

论坛徽章:
5
狮子座
日期:2013-08-20 10:12:24午马
日期:2013-11-23 18:04:102015年辞旧岁徽章
日期:2015-03-03 16:54:152015亚冠之德黑兰石油
日期:2015-06-29 18:11:1115-16赛季CBA联赛之新疆
日期:2024-02-21 10:00:53
10 [报告]
发表于 2012-11-24 23:26 |显示全部楼层
回复 20# __BlueGuy__


    先试着用Lua,写点小游戏。我这里有个GraphApp,过个几天就准备开源(现在代码还在整理中,而且还没开发完)。你可以试着用它配合Lua写点小东西玩玩。然后你可能会想要让Lua调用C,你可以看一些简单的Lua C模块。这里推荐你去看Roberto写的struct模块。然后,看manual,全部都看,对Lua有一个主观上的了解。最后再去看Lua源代码。从lua.h开始看,理解每一个导出函数的含义和用法,然后看lapi.c和lauxlib.c,看看导出是如何实现的。最后你就可以去看l*lib.c系列文件了,看看标准库是如何实现的。

这一步过了,你基本上就已经是Lua专家了(切记,踏实。有一个函数没看就是没看完)。接下来你就可以专攻一项了,Lua几十个源文件,你专攻一个去看,推荐你第一个看的是基础件lmem.c,lzio.c,lstring.c,这些比较简单,容易上手,然后你配合我在论坛的帖子看ltable.c,这样基础件部分就搞完了。剩下的两个方向一个是lvm.c的虚拟机实现,配合Lcode.c,和lopcodes.c去看。另一个就是llex.c和lparser.c的编译器部分了。

最后,你就可以专攻遍及了整个Lua源代码的lgc.c垃圾回收了。看完了,这个,Lua对你来说就没有难度了。你可以从头开始,每个文件浏览一遍,从整体上体会Lua的设计。

我相信到了这一步,纯C开发对你来说就是举重若轻的事情了。而且你可以由此去推导C++开发的一些方法。接下来的事情,就是玩GraphApp,为其写一些Lua模块(protobuf协议啊,GUI系统啊等等),深入理解如何写Lua C模块。你会发现C的短板,然后你就可以对C++为何要提供那么多特性有了一个很清晰的认识。用C++的时候就不会茫然了。

这就是整个学习过程。算起来的话,一年肯定够了。我就是从去年这个时候开始这个过程的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP