找回密码
 点一下
查看: 4886|回复: 12

附加模型的偏移与旋转

[复制链接]
发表于 2011-6-5 18:44:54 | 显示全部楼层 |阅读模式
前言
  好吧……既然有人都提到关于模型的旋转的问题了,四夕水觉得某些研究成果可以拿出来了。
  提示:本教程的行为比较生涩,需要一定的欧几里得几何基础和常识,同时,由于这是关于演算体的中阶使用技巧,需要一定的数据编辑(尤其是演算体使用)基础。


  特指词汇约定:当我们把模型B附加到模型A上去(例如,将大和炮充能的模型附加到战列巡航舰的模型上去)时,本教程默认称模型A及其演算体为“目标模型”,模型B及其演算体为“附加模型”。
  坐标系约定:一般来说一个模型的“中心”(Center)附加点的坐标系都是固定且与模型坐标系一致。其坐标系为:X轴正方向:朝向模型的左侧;Y轴正方向:朝向模型的后方;Z轴正方向:朝向模型的上方。(更为具体的说明请参见结尾部分的示意图)


第一部分:控制附加模型偏移与旋转的『部位运算演算体』

  『部位运算演算体(CActorSiteOp) 』是演算体中很大的一个分类,它本身并不负责具体的模型(Model)与音效(Sound)的控制,而是辅助其他演算体以便其能更好的工作。
本教程中需要接触的其子类有两个:
    [li]部位运算(局部偏移)(CActorSiteOpLocalOffset);[/li][li]部位运算(准确旋转)(CActorSiteOpRotationExplicit)。[/li]
  顾名思义,他们分别控制附加模型的偏移与旋转。

第二部分:『部位运算演算体』演算体的使用方法

  设置附加模型的演算体的时候(通常这个演算体都继承自『模型附加物(ModelAddition)』或其子类),通常都需要设置“动作者托管 – 主体部位运算 – 表达式”(CActorBearing_HostSiteOps_Ops)属性。在这个属性中填入相应的部位运算演算体就能将附加模型添加到目标模型正确的附加点上,同时,也是在这里填入更多相应的部位运算演算体来使附加模型偏移或者旋转。
  也就是说,如果想要附加模型在附加点上偏移或者旋转,需要自己新建对应的部位运算演算体,并且将其设置到附加模型演算体的表达式中。
  

  上图为一个具体的例子。按照填入顺序:SOpAttachTarget表示模型附着的附加点为“目标”(Target)附加点,其坐标系方向与“中心”(Center)附加点相同;PsiChargeSOpHigher内设置模型相对附加点的偏移;Sop90_Forward内设置模型相对自己中心点的旋转。

第三部分:『部位运算(局部偏移)』的设置方法

  新建一个演算体,动作者类型设置为“部位运算(局部偏移)”(CActorSiteOpLocalOffset),基于设置为“默认动作者基础”(CActorBase),装饰物类别设置为“非饰物”(NotDoodad)。这样就新建了一个负责模型偏移的部位运算演算体。
  

  属性方面,基本绝大部分的属性都可以使用父类的默认值。唯一需要设置的属性为:“动作者 – 局部偏移”(CActorSiteOpLocalOffset_LocalOffset),其XYZ三个值分别为附加模型在附加点坐标系下偏移向量的各坐标分量。
  

  如上图例,(0,0,0.5)表示附加模型相对附加点向Z轴正方向(一般的,该方向竖直向上)偏移0.5长度(关于单位长度的具体尺寸请自行测试)。
  特别提示:以上设置建立在附加模型只偏移不旋转或者先偏移后旋转的情况,如果附加模型的表达式设置为先旋转后偏移,则偏移坐标按照附加点坐标系旋转以后的新坐标系计算。如果无法驾驭这种情况或者压根就没看懂这条“特别提示”的以上部分,那就干脆记住:设置附加模型的表达式的时候,一定按照“附加点演算体,偏移演算体,旋转演算体”的顺序添加。

第四部分:『部位运算(准确旋转)』的设置方法

  新建演算体的步骤和新建部位运算(局部偏移)演算体的步骤大致相同。只需要将动作者类型设置为“部位运算(准确旋转)”(CActorSiteOpRotationExplicit)。
  同样,属性方面也绝大部分都不用处理。需要设置的属性有以下三项:
    [li]  “动作者 – 是局部的”(CActorSiteOpRotationExplicit_IsLocal)设置为“已启用”(True),这样保证了旋转坐标为的坐标系为主模型的附加点坐标系而不是全局坐标系;
      [/li][li] “动作者 – 前移”(CActorSiteOpRotationExplicit_Forward);[/li][li] “动作者 – 上”(CActorSiteOpRotationExplicit_Up)。[/li]
  其中,“动作者 – 向前”与“动作者 – 上”分别为附加模型在附加点坐标系下的朝向矢量和附加模型相对自己中心的旋转矢量。由于旋转本身的复杂性,将通过下面的例子来进行详细说明。

第五部分:例子

  为了直观起见,我们将一个战列巡航舰的模型附加在一个折跃棱镜的模型上去。
  

  
  新建所有需要的演算体,并写入相应的表达式。
  不进行任何偏移和旋转的情况下,模型附加的效果如截图左一。
  由于战列巡航舰的模型过大,所以基本把折跃棱镜盖住了。我们设置偏移向量为(0,0,2),让附加模型向上面偏一些,以便观察旋转。
  

  设置后的结果如截图左二。

  朝向部分:该部分使用“动作者 – 前移” 属性。
  该属性为实质为转向后新的单位朝向在旧的坐标系中的矢量的坐标。也就是说,设置为(0,-1,0)为模型的默认朝向,设置为该值将不会改变模型的朝向。
  按图中战列巡航舰模型的方向,如想要战列巡航舰转向180°朝向后边,按照附加点的坐标系,朝向矢量应该是(0,1,0)。注意:由于朝向矢量在运算的时候会被程序归一化,所以 (0,1,0)和(0,2,0)都是一样的。
  

  结果如截图右二。
  如果要在默认的基础上让战列巡航舰的机头向上抬45°,朝向矢量就是(0,-1,1)。同理,(0,-2,2)也可。
  

  结果如图右一。直观起见按住了Insert键是镜头旋转了45°,从侧面截图。
  


  旋转部分:该部分使用“动作者 – 上”属性。
  该属性实质为模型绕Y轴旋转后新坐标系中Z轴朝向在旧坐标系中的矢量坐标。由于绕Y轴旋转不会改变Y轴的去向,所以一般认为该属性的Y值为无效值。同时,(0,0,1)为模型的默认旋转矢量,设置为该值同样不会使模型的旋转发生任何变化。该矢量同样会被归一化。
  想要战列巡航舰的模型底朝天翻过来?设置(0,0,-1)即可。
  

  如截图左。
  其它:“前移”与“上”两个属性的结合方式
  按照“前移”(0,1,0),(控制战列巡航舰头向后屁股向前)“上”(1,0,0)(控制战列巡航舰向左侧身)的属性进行设置。根据实际结果就能判断两者的结合方式。
  

  如截图右。得出结合方式可以认为是先进行了“前移”属性的旋转,之后在旋转后的新坐标系进行“上”属性的旋转。
  




关于模型的坐标系
  我们一直认为模型坐标系中各坐标轴的方向为:X向前;Y向左;Z向上,也就是模型朝向在模型坐标系中的方向矢量为(1,0,0)。实际上个坐标轴的方向为:X向左;Y向后;Z向上,模型方向矢量(0,-1,0)。这也就是为什么恶火的火焰伤害的偏移量为(0,-y,0)。“向前”的偏移量在Y轴上确实是负值。
  以“战略巡航舰”的模型为例,坐标轴方向如下图所示。
  




PS:按惯例似乎四夕水应该在结尾提些问题的……
算了,既然最近没有什么过于困难的问题这次就不提问了~

点评

看不到图,还有就是坐标系描述有点混乱,不是很懂,其实附着点坐标是按三角来计算的,用顶点定位Z轴,用对角定位Y  发表于 2016-10-27 00:02

评分

参与人数 1威望 +6 收起 理由
oneonestar + 6 不错的教程

查看全部评分

发表于 2011-6-5 22:03:07 | 显示全部楼层
被rotation折腾大半天于是头目发现了bug

trigger中调用actor send message时会用到一个函数:SetRotation
此函数用以生成此类型的message

源码:
string libNtve_gf_SetRotation (fixed lp_forwardX, fixed lp_forwardY, fixed lp_forwardZ, fixed lp_upX, fixed lp_upY, fixed lp_upZ) {
    // Implementation
    return libNtve_gf_ActorMsg1("SetRotation", libNtve_gf_Convert3DRotationToString(lp_forwardX, lp_forwardY, lp_forwardZ, lp_upX, lp_upY, lp_upZ));
}

其中调用的函数:
string libNtve_gf_Convert3DRotationToString (fixed lp_forwardX, fixed lp_forwardY, fixed lp_forwardZ, fixed lp_upX, fixed lp_upY, fixed lp_upZ) {
    // Implementation
    return (libNtve_gf_Convert3DVectorToString(lp_forwardX, lp_forwardY, lp_forwardZ) + "," + libNtve_gf_Convert3DVectorToString(lp_upX, lp_upY, lp_upZ));
}

加红处的逗号会导致其后的3个up数值无效,此处应为" "
此为nativelib的一个bug
所以通过变量计算角度做连续旋转时
需要自己重写此函数
回复

使用道具 举报

发表于 2011-6-5 22:51:42 | 显示全部楼层
很好实现
回复

使用道具 举报

发表于 2011-6-5 23:40:48 | 显示全部楼层
附赠伪平滑旋转演示+自建rotation message函数
以前似乎没见过类似的演示呢



注意事项
游戏中许多单位带有的Host Site Operation的会覆盖掉trigger发送的message,所以需要在数据编辑器中做出修改

rotation.SC2Map

24 KB, 下载次数: 55

回复

使用道具 举报

发表于 2011-6-9 10:51:47 | 显示全部楼层
正好学习了旋转的问题
回复

使用道具 举报

发表于 2011-6-9 18:04:08 | 显示全部楼层
这个教程很好很强大。。。 支持一下。
回复

使用道具 举报

发表于 2011-6-9 18:05:54 | 显示全部楼层
小白考完试了?
回复

使用道具 举报

发表于 2011-6-10 10:40:53 | 显示全部楼层
很好很强大~
回复

使用道具 举报

发表于 2011-10-8 05:04:40 | 显示全部楼层
请问"动作者托管"在哪里添加? 找了一圈没找到
回复

使用道具 举报

发表于 2011-10-8 09:20:32 | 显示全部楼层
很实用的教程,谢谢收下了。
回复

使用道具 举报

 楼主| 发表于 2011-10-8 12:41:07 | 显示全部楼层

回 8楼(sindragosa) 的帖子

sindragosa:请问"动作者托管"在哪里添加? 找了一圈没找到 (2011-10-08 05:04)
繁体中文用户请按下Ctrl+D然后根据项目的ID寻找属性项目。
回复

使用道具 举报

发表于 2014-6-11 16:36:33 | 显示全部楼层
给目标模型添加附加模型 是在目标模型的哪个属性里改?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-11-24 07:41 , Processed in 0.127274 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表