(提示:体素相关文章参考至http://gad.qq.com/article/detail/10014)
场景体素表示法
将场景按50CM
横竖分割成网格。
通过在网格上关联各种信息,以达成完整构建一个3D场景。
下面使用C(x, y),表示某个网格信息,主要包含以下内容:
静态体素层
C(x,y)={Hupward[H1,H2,...,Hn]layer0if voxel in layer1 - layerN C ( x , y ) = { H u p w a r d layer0 [ H 1 , H 2 , . . . , H n ] if voxel in layer1 - layerN
Hn=(Hdownward,Hupward) H n = ( H d o w n w a r d , H u p w a r d )
第0层,地表层,都有值
其他层,某C(x, y)有则储存之。
静态体素层的Mask
C(x,y)={M[M1,M2,...,Mn]layer0if voxel in layer1 - layerN C ( x , y ) = { M layer0 [ M 1 , M 2 , . . . , M n ] if voxel in layer1 - layerN
一些标志位,如2进制: 00000000 可行走;00000001 不可行走,等等。
1、2层可以合在一起。
即,每层上的C(x, y)都有属性: Hdownward H d o w n w a r d 、 Hupward H u p w a r d 、M。
第0层优化掉储存 Hdownward H d o w n w a r d ;其他层没有则优化掉储存这些属性。
静态体素的连通标志
C(x,y)={null[D0,D1,D2,D3,D4,D5,D6,D7]if no changeif have change C ( x , y ) = { n u l l if no change [ D 0 , D 1 , D 2 , D 3 , D 4 , D 5 , D 6 , D 7 ] if have change
有改变的地方保存信息。
《 <天涯明月刀>服务器端3D引擎设计与开发 》文中表述是4个方向。
4个方向还是8个方向,有待商榷。
简单动态体素层
C(x,y)=⎧⎩⎨⎪⎪null[H′1,H′2,...,H′n][M1,M2,...,Mn]if no dynamic voxelif have dynamic voxelif have dynamic voxel C ( x , y ) = { n u l l if no dynamic voxel [ H 1 ′ , H 2 ′ , . . . , H n ′ ] if have dynamic voxel [ M 1 , M 2 , . . . , M n ] if have dynamic voxel
H′=(dynamicId1,Hdownward,Hupward),...,(dynamicIdN,Hdownward,Hupward) H ′ = ( d y n a m i c I d 1 , H d o w n w a r d , H u p w a r d ) , . . . , ( d y n a m i c I d N , H d o w n w a r d , H u p w a r d )
a. 支持动态增加、删除体素(先增加好),改变地形。
b. 为了简单处理,动态体素不能与其他体素有重叠
c. 为了简单处理,动态体素的连通,要么是自身,要么是当前层的静态体素
第1、2、3点,构成静态3D场景信息,整个进程可以只有一份(或通过共享内存,一个机器只有1份)
第4点,每个副本一个,维护一些动态信息。
以上这些信息,即可完整表达一个3D场景。
3D场景信息完整表述
静态场景信息:
C(x,y)=⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪HupwardM[M1,M2,...,Mn][H1,H2,...,Hn][D0,D1,D2,D3,D4,D5,D6,D7]layer0layer0if voxel in layer1 - layerNif voxel in layer1 - layerNif have change C ( x , y ) = { H u p w a r d layer0 M layer0 [ M 1 , M 2 , . . . , M n ] if voxel in layer1 - layerN [ H 1 , H 2 , . . . , H n ] if voxel in layer1 - layerN [ D 0 , D 1 , D 2 , D 3 , D 4 , D 5 , D 6 , D 7 ] if have change
Hn=(Hdownward,Hupward) H n = ( H d o w n w a r d , H u p w a r d )
动态场景信息:
C(x,y)=⎧⎩⎨null[H1,H2,...,Hn][M1,M2,...,Mn]if no dynamic voxelif have dynamic voxelif have dynamic voxel C ( x , y ) = { n u l l if no dynamic voxel [ H 1 , H 2 , . . . , H n ] if have dynamic voxel [ M 1 , M 2 , . . . , M n ] if have dynamic voxel
动态场景信息,主要是为了支持:
没有这样的功能要求,则整个场景只需要静态场景。
行走
行走行为始终在体素表面。
行走需要的角色信息:
a. 角色位置信息: (x, y, layer, dynamicId)
b. 角色行走方向: dirX、dirY
获取当前体素信息 v0 v 0
Created with Raphaël 2.1.2 Start dynamicId == 0 通过 x、y、layer 从`静态场景信息`中获取当前体素信息 End 通过 x、y、layer、dynamicId 从`动态场景信息`中获取当前体素信息 yes no
获取目标体素信息 v1 v 1
Created with Raphaël 2.1.2 Start dynamicId == 0 通过 x+dirX、y+dirY、v0的连通信息 获取 layer1 通过 x+dirX、y+dirY、layer1 从`静态场景信息`中获取目标体素信息 End 通过 x+dirX、y+dirY、layer、dynamicId 从`动态场景信息`中获取目标体素信息 是否有目标体素信息 yes no yes no
行走的碰撞校验步骤为:
Created with Raphaël 2.1.2 Start 获取当前体素信息v0 获取目标体素信息v1 获取layer1所有动态体素信息d1(如果有的话) 获取layer1+1层静态体素信息v2(如果有的话) v1的mask检查通过 检查v1、v0高度差 检查角色与d1没有碰撞 检查角色与v2没有碰撞 行走 End yes no yes no yes no yes no
本图,忽略了3种情况:
a. 基于条件动态体素的连通,要么是自身,要么是当前层的静态体素
。不然获取v1逻辑更加复杂,还需要判断目标layer层上是否有动态体素,以及是否落在动态体素上等。
b. 上图忽略了玩家间的碰撞。不然还要增加遍历视野内玩家,检查碰撞,修正最终目的x、y值
第a特点殊情况出现不多,没有必要把行走逻辑写的很复杂。
因此,可以增加约束条件,限制上述情况出现。
第b点,看需求,加在之。可优化AOI,加多层AOI,如有2米大小的AOI,则可以快速检查碰撞
后续文章将对跳跃、飞行以及内存占用,做分析