我所遭遇过的游戏中间件--Apex
我所遭遇过的游戏中间件--Apex
Apex是PhysX的扩展中间件,它是在PhysX的基础上封装了一层.用于实现布料,粒子,破碎这三种物理效果.我只研究其布料处理.使用Apex做物理最大的好处是:它的布料可以即受物理影响,又受骨骼蒙皮的影响.物理布料有很大的不确定性,你无法知道在做了一套动作后,布料的模拟还是否正常.然而有了骨骼蒙皮的影响,就给布料带来确定性.在PhysX的Max导出插件中,美工可以设置布料上每一个顶点受物理影响的范围.运算过程应该是先对布料上的点做骨骼蒙皮运算,再做物理模拟.
Apex是我碰到过的接口最难搞的中间件,它里面使用了大量的回调,接口十分晦涩难懂,官方文档也不够详细.好在有他们官方人员的帮助,才算搞定.但我对Apex有种很陌生的感觉,总觉得它不是我写的代码.每次出了问题维护起来都很纠结.
(1)Apex的对象属性设置
举个布料属性设置的例子.布料LOD的设置以如下的方式进行:
NxParameterized::setParamF32(*actorDesc, "lodWeights.maxDistance", 30.0f);
NxParameterized::setParamF32(*actorDesc, "lodWeights.distanceWeight", 100.0f);
NxParameterized::setParamF32(*actorDesc, "lodWeights.bias", 0.0f);
NxParameterized::setParamF32(*actorDesc, "lodWeights.benefitsBias", 0.0f);
这是对布料按摄像机距离设置LOD的配置.这几个参数是布料lod的设置,不要和布料自己的maxdistance搞混了。APEX自己有一套分析每个布料获得计算资源的系统,它自己会计算出这套布料获得的一个LOD的权重,称为benefit。benefit的计算有一个公式:
benefit=lodWeights.distanceweight*angularimportance( distancefromeye, assetRadius )+lodweights.benefitBias
lodWeights.maxdistance这个是说进行布料计算的最大距离,如果布料和视点的距离超出这个范围,benefit就是0,布料将回归全动画状态。
lodWeights.distanceWeight,这个就是根据布料和视点的距离计算benifit的一个scale。
lodWeights.benefitbias,这个是一个权重的偏移,比如你设置0.1,那么永远都不会出现0了,布料就会一直工作。
挺复杂的吧,我到现在也没完全搞懂.然而Apex的Lod的坑比想象中的还大:它有两种LOD的概念:Graphic LOD与Physics LOD.
Graphic LOD就是模型的LOD,具体的用法就是如果你在游戏中更新了模型的LOD,那么你可以把这个LOD等级同步到clothing上,clothing就会转而用相应的graphic lod对应的那个physics mesh来进行模拟。使用的前提是你要提供多个graphic LOD对应的physics mesh。
Physics LOD是物理上的LOD,根据镜头到布料的距离,场景里所有的布料,硬件状况等等等等作用因素,apex会自己给布料赋予一个LOD,这个LOD的设置是基于maxdistance的大小的,比如你做一个二级LOD,可以把所有maxdistance小于50%最大值的都忽略掉,那么在二级LOD中,那些maxdistnce小于50%最大值的顶点都输出纯动画,不参与布料的更新。
我发现Apex布料有个很奇怪的现象:不同的布料,LOD相关的参数设置相同,但发现它们物理布料开启时,与摄像机的距离不同.这个问题困扰了我好久,后来才意识到,这个距离还有布料的复杂程度有关,物理计算量小的布料其开启距离远,物理计算量大的布料其开启距离近.好智能的设计.
(2)Apex有很多属性设置与PhysX重复
这一点让人不知该调用哪个的好,比如按帧更新物理世界操作,代码如下:
void PhysicsSimulate(float fDeltaTime, bool finalStep)
{
if (m_pApexScene)
{
m_pApexScene->simulate(fDeltaTime, finalStep);// 如果使用了Apex则调用Apex的接口
}
else if (m_pNxScene)
{
m_pNxScene->simulate(fDeltaTime);// 如果没用Apex则调用PhysX的接口
if (finalStep)
{
m_pNxScene->flushStream();
}
}
}
获取物理运算结果的操作与按帧更新相似,其代码如下:
void CPhysicsScene::GetPhysicsResults(bool block)
{
if (m_pApexScene)
{
m_pApexScene->fetchResults(block, NULL);
}
else if (m_pNxScene)
{
m_pNxScene->fetchResults(NX_RIGID_BODY_FINISHED, block);
}
}
Apex有自己的一套调试图形显示接口,这让我总觉得无所是从.我曾经问过他们官方这样的问题:"我显示PhysX的Debug数据,发现PhysX和APEX各提供了一套接口,它们有什么关系?NxDebugRenderable和physx::apex::NxApexRenderDebug有什么关系?我的程序中只使用NxDebugRenderable也能将APEX创建的布料显示出来。"对方的回复是:"关于debugrender的两套接口。PHYSX的管physx的内容,APEX管apex的内容,具体你可以看一下render的那些可以打开的flag,内容上基本都是自己的特有的内容。需要注意的是两套接口的渲染输出是完全不一样的,所以你可以认为他们不是一套东西。关于为啥physx的接口也能看到cloth,这个要解释一下,因为apexclothing在clothing的底层solver一直是physx的cloth,所以你用physx的cloth里的debugrender一样可以看到例如布料骨骼,顶点之类的输出。"大体意思就是,Apex又实现了一套PhysX已经有的功能.然而,后来Apex又推出一种新的布料文件格式,3X版本.这种文件加载的布料则无法使用PhysX的NxDebugRenderable显示调试图形.
还提过一个问题:APEX的NxParameterized::setParamF32(*pDebugRenderParams, "VISUALIZATION_SCALE", 1.0f);和PHYSX的m_pNxPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 1.0f);是否是实现相同的功能?对于这个问题Nvidia的官方回复是:"两个scale的设置功能不同,apex的scale管apex的输出,physx的管physx."反正我是没明白.
(3)Apex的GPU硬件加速.
PhysX和Apex中有好多个与硬件加速相关的设置,我花费了好长时间才搞清楚.你需要设置:操作系统是否开启的PHYSX的GPU加速,NxPhysicsSDK是否有硬件加速,NxSceneDesc的模拟方式是否有硬件加速,physx::apex::NxApexSceneDesc的GPU处理方式,创建的布料对象是否要硬件加速.总之各是各的,但有一定的先后依赖关系.
NxPhysicsSDK创建时需要设定一个gpuHeapSize,当申请GPU加速的布料所使用的显存大于这个数时,将会崩溃.于是只好每次创建布料时判断一下当前PhysX对显存的使用情况,如果超过一个数值,则只能以CPU的形式创建.此外测试发现N卡440以下的显卡,使用GPU加速容易出现崩溃,所以只能强制关闭这种卡的硬件加速.
(4)多线程处理
我发现PhysXCore.dll会创建3个线程,ApexFramework_x86.dll会创建8个线程,我曾经问其官方这些线程具体是做什么用的,能否少创建几个?但没有明确答复.
(5)2X资源与3X资源
Apex1.2.3版本后,提出了3X资源的布料.他们官方极力推荐我们使用3X资源.并说了一大堆3X资源的优点,如性能提高,可支持本地模拟等.但如同去商场买东西一样,售货员极力推荐的往往都不是最好的,升级到3X问题重重.首先Navida没有提供一个2X到3X的转化工具,官方的解释是2X和3X本来就不是一个世界的东西,所以没办法转化.那么要升级只能重导.而后发现有些用2X导出正常的模型,改成3X导就出现异常,比较常见的是莫名其妙的抖动.因为MAX中的模型是Z轴向上的右手坐标系,而游戏中为Y轴向上的左手坐标系,所以我会对布料APB文件进行一个转化处理,大部分转化后的3X资源文件是没有问题的,只有极少数会有抖动,也找不到什么规律.
(6)布料与非布料的合并
如果有一件衣服,只有衣角的一部分需要做布料效果,那么没必要将整个衣服都做成布料.将其拆分开,非布料的用引擎自己的导出插件以普通模型的方式导出,布料的用PhysX的布料导出插件导出.碰到的问题是:布料与非布料在游戏中会看到一条明显的接缝,原因是PhysX的导出插件对顶点法线切线的导出方式与自己的导出插件方式不一致.虽然我寻问过Nvidia多次,PhysX的导出插件是如何处理法线切线的,但没有解决这个问题.最后的解决方法是:同时加载布料与非布料两个模型,遍历非布料模型上的顶点,如果顶点与布料上的某个顶点位置一致,则将非布料顶点的法线切线设置为布料上相应顶点的法线和切线值.
我所遭遇过的游戏中间件--Apex的更多相关文章
- 我所遭遇过的游戏中间件--PhysX
我所遭遇过的游戏中间件--PhysX PhysX现在是Nvidia的物理中间件.其特点是简练且功能强大.当我最初拿到PHYSX的SDK时,就发现这个物理中间件比Havok要小很多,但该有的功能都有,甚 ...
- 我所遭遇过的游戏中间件--Havok
我所遭遇过的游戏中间件--Havok Havok是我接触的第一款游戏中间件,那是在五,六年前,我刚刚毕业,对游戏开发还是个菜鸟.我记得先是对游戏场景中的地形和其他静态物体生成刚体,然后做角色的Ragd ...
- 我所遭遇过的游戏中间件---SpeedTree
我所遭遇过的游戏中间件---SpeedTree SpeedTree是一个专门用于渲染植被的中间件,并提供了一套完善的植物编辑工具.在它官方提供的DEMO中,你会看到高度逼真的树木和植物,在风的影响下树 ...
- 我所遭遇过的游戏中间件---nvDXTLib
我所遭遇过的游戏中间件---nvDXTLib nvDXTLib是Nvidia提供的一套用于DXT纹理压缩SDK.接口十分简洁,就是提供了几个纹理压缩的函数,其中我使用最多的函数是: DXTLIB_AP ...
- 我所遭遇过的游戏中间件---HumanIK
我所遭遇过的游戏中间件---HumanIK Autodesk HumanIK游戏中间件,为游戏创建更加可信.真实的角色动画.该中间件的全身逆向运动(FBIK)系统支持角色真实地与所在环境及其它角色进行 ...
- 我所遭遇过的游戏中间件--Kynapse
我所遭遇过的游戏中间件--Kynapse Autodesk Kynapse游戏中间件是一款面向游戏开发.非玩家控制角色实时模拟的领先的人工智能解决方案.Kynapse具有先进的路径查找功能,比如三维路 ...
- 我所遭遇过的游戏中间件--Scaleform
我所遭遇过的游戏中间件---Scaleform Scaleform帮助开发人员利用现代系统的三维硬件加速性能创建电影品质的菜单.游戏内HUD,动画纹理.迷你游戏以及移动游戏与应用.Scaleform作 ...
- 我所遭遇过的游戏中间件---Redux
我所遭遇过的游戏中间件---Redux 一.关于Redux Substance Redux 是一款纹理处理软件加中间件,专门用于纹理生成和压缩.具其用户指南介绍,它能够对纹理集进行优化,可以将现有压缩 ...
- 我所遭遇过的游戏中间件--FlashOcx
使用Flash做游戏界面的另一种方式是通过Abode提供flash.ocx处理Flash界面.将Flash图像通过GDI绘制出来后,再将图像数据拷贝到一个D3D的纹理结构中,最后由引擎的D3D接口进行 ...
随机推荐
- 8-2 Building for UN Uva1605
题意:你的任务是设计一个包含若干层的联合国大楼,其中每层都是一个等大的网络 由若干个国家需要在联合国大楼里面办公 你需要把每个格子分配给一个国家 使得任意两个不同的国家都有一对相邻的格子 (要没是同 ...
- JSP的学习二(指令与标签)
一:page指令 1.JSP的指令 放在<%@ 指令 属性=“值”%> 主要有page,include,tablib. 2.page指令 用于定义JSP页面的各种属性,作用于是JSP的整个 ...
- HandlerExceptionResolver统一异常处理 返回JSON 和 ModelAndView
统一异常处理类的两种方式一种是前后分离,一种是一整套集合返回指定到指定的错误页面显示错误信息 1.由于前后分离,是统一返回JSON的格式 自定义Exception public class Bussi ...
- rabbitmq学习之路-rabbitmqctl
rabbitmqctl使用 学习rabbitmq,原理之后第一个要掌握的就是rabbitmqctl这个命令的用法了,rabbitmq的管理功能最全的就是rabbitmqctl命令了,当然还有HTTP ...
- JAVA语言中的运算符和表达式
JAVA——运算符 按运算符要求的运算符个数可分为一元.二元.三元运算符: 一元运算符有一个操作数:如正数或者负数前面的“+”.“—”,和自增“++”.自减“- -”. 二元运算符有两个操作数:如除法 ...
- maven 发布jar包到远程仓库
有的时候我们需要发布一些自己写的相关jar包到maven私服,供项目组使用. 首先在setting.xml文件添加,这里 注意 要保证该账户有发布的权限 <servers> <ser ...
- 为什么要使用String
最近在培训课期间指导初学者.任务之一就是要大家完成一个类,要求这个类对key为String类型的map执行dwarwle操作.其中一位学员完成的类中,有如下方法: void dwarwle(HashM ...
- 为什么全部width:100%浏览器边缘存在留白?
一般浏览器都给body加了外边距,margin:0应该能解决你所遇到的问题.但你很可能又会遇到其他奇怪的现象,比如说p的行高,在不同浏览器上显示不一致,最根本的解决方案还是重置浏览器默认样式. 可以使 ...
- springboot配置多数据源mongodb
参考大佬的文章 https://juejin.im/entry/5ab304dd51882555825241b3
- 【BFS】【最小生成树】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem G. We Need More Managers!
题意:给你n个点,点带权,任意两点之间的边权是它们的点权的异或值中“1”的个数,问你该图的最小生成树. 看似是个完全图,实际上有很多边是废的.类似……卡诺图的思想?从读入的点出发BFS,每次只到改变它 ...