虚幻4 在Material中如何实现 车子压倒草的功能

上次发了篇介绍车子压倒草的博文

http://www.cnblogs.com/JinT-Hwang/p/8169146.html

中的2.部分。

不过存在一个问题,就是如果草很多,会有很多个碰撞体,虽然物理效果比较真实但是可能会导致性能问题。

这次介绍一下在草的材质中编码,实现车子压倒草的功能。

material中会用到一些数学的知识,还需要各位有一定的概念才能很好的理解。

关键词:unreal4、虚幻4、汽车、草、压倒、伏地、Material、材质编辑器、Shader

实现思路:通过求出草离车子的水平和垂直距离(如果只判断车子离草的距离,结果周围的草会成一个圆形倒地而不是一个长方形),再根据距离让草旋转不同的角度。

 

思路详解:

1.要实现的功能如下图。

2.O点是车子的中心坐标,A是草的中心坐标,只需求出AB和AC的长度,然后再跟自己设定的触发距离比较,符合就草根据距离做逐渐倒地的动作。(需要两个实现,一距离判断,二倒地动作)。

3.只有O、A两点的坐标还不足以求出AB和AC的距离,注意上图表示的是车子本地XY轴坐标系,车子不是在世界原点。

4.要求出BO(AC)的长度,至少要知道Cos∠AOB,此处可利用点乘(即数量积、点积),向量OA·向量OB=|向量OA|·|向量OB|·Cos∠AOB,求出Cos∠AOB后,即可求出OB的向量和OB长度。

5.求出OB长度后,用勾股定理即可求出AB的长度,第一个实现就完成了,第二个实现以及细节的请往下看。

 

一、虚幻4如何通过Material编程实现车子压倒草的功能

A.先创建一个MaterialParameterCollection(材质参数集合),因为material下的局限,只能通过调用MaterialParameterCollection来获取外部标量和矢量。具体介绍可参考下方官方文档。

https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/ParameterCollections/index.html?lang=zh-CN

创建后双击打开,Scalar Parameters下创建的是标量(0),Vector Parameters下创建的是矢量(0,0,0,0),此处先创建一个矢量的,命名为CarPosition,用来储存车子坐标,来传入Material使用的。

打开车子的蓝图,在EventTick事件引出一条线用于实时获取车子坐标。

车子的坐标有了,车子指向草的矢量(向量)就可得到了,还需要一个车子指向前方的矢量,此处车子的蓝图的component面板中添加一个空的组件,调整到车后底部并且对准车子的中心线。

在前面的MaterialParameterCollection中再添加一个表示车后坐标的矢量参数。

回到车子的蓝图中,从Event中再引一条线出来用来获取车子后面点的坐标。

B.将前面的MaterialParameterCollection拖动到草的Material里,点击该Material Parameter Collection,并在Details面板中的Parameter Name下拉框选到表示车子坐标矢量的参数,再复制一个,选到表示车子背后坐标矢量的参数。

两个坐标需要先用Mask去掉第四个坐标,将Float4转换为float3。在material里的参数、操作是以颜色RGBA码来表示的。

车尾坐标指向车中心坐标的向量,用车中心的坐标减去车尾的坐标即可得到(后面简称向量DO)。此处相减前都乘了(1,1,0),这是去掉Z轴坐标的干扰,计算的时候只要算XY轴平面的距离即可,只要2D向量即可满足。当然,也可以前面mask的时候只保留RG值组成为Float2坐标。

同理,车中心坐标指向草中心坐标的向量(后面简称向量OA)。下图的Object Position是指当前这个material的中心在世界坐标中的位置。

根据点乘的公式可得, Cos∠AOB=(向量OA·向量OB)÷(|向量OA|·|向量OB|),此处向量OB不知道,用向量DO代替Cos∠AOB=(向量OA·向量DO)÷(|向量OA|·|向量DO|),因为向量DO的指向和向量OB的指向相同,所以求出来的Cos∠AOB值是一样的。

向量的点积,用Dot接上两个向量即可求出,向量的绝对值可用Vector Length即可求出(前面是Float2的用V2,前面是Float3的用V3)。此处有两种做法,一种是用Normal将向量归一化然后再求Cos,或者直接用本身向量长度求也可以。

可以先求向量OB,再求向量OB的长度,或者直接向量OA的绝对值乘上Cos∠AOB直接得到OB的长度。

但是此处有一点要注意,向量OA和向量DO夹角大于90°时,Cos∠AOB的值时负值的,会导致车子的前面部分草有压倒的反应,但是后面部分草没有反应。

要求的是Cos∠AOB,但是当角度大于90°时,cos的值实际上是cos∠AOB’。当∠AOB’增大时,∠AOB在减小(由90°->0°),由上面的cos值变化图,可以看出当角度大于90°时,要求的cos∠AOB跟当前的cos值时相反的关系。

当cos∠AOB大于零时,仍使用当前的cos值,cos∠AOB小于零时,即乘以-1即可得到向量OB。

然后即可用勾股定理求出向量OB的长度,或者用向量OA=向量OB+向量BA,求出向量OB后再求向量OB的长度。到这里草在水平方向和垂直方向离车子的距离就都求出来了,分别是|向量OA|和|向量OB|。

C.接下来需要实现草旋转的部分。如下。RotationAngle的值需为0~1.

旋转是根据UV坐标系来旋转的,x轴向右,y轴向上,z轴垂直xy轴从屏幕出来。

(1,0,0)表示沿着本地X轴旋转,但我们需要在世界中,面向相机的方向倒下去,所以加上Transform Vector将本地的坐标空间转换成世界坐标,此处除了使用View Space也可以使用Camera Space,效果等同。

还需要自定义三个参数来做判断依据,CarLong和CarWidth两个参数用来判断是否在车子底下,OutSideWidth用来结合另外两个,来判断外圈草倒地动作的范围。

上面的自定义参数,carlong储存车子长,carwidth储存车子宽,outsidewidth储存草开始触发操作,离车子矩形边缘的距离。

判断草是否在触发范围内,如下图。第一个if,出口接material上的World Position Offset,当A>B时,如果有之前有别的代码连World Position Offset上,可连在此处,否则连一个0常量即可,第二个if当A>B时,相同,当A<B时,接旋转草代码。

草旋转倒地也要做判断,当草在车子底下时为倒地90°,在车子外但在+outsidewidth内时,根据距离由远及近0°->90°改变倒地的角度。

此处将90÷OutSideWidth得到每1单位OutSideWidth对应多少°,|向量OB|(即草竖直方向离车子中心的距离)减去CarLong得到草离车子边的距离L,然后L去乘上面得到的等分,得到L对应的角度,因为初始的角度时90°,即有这样的关系,草离车子边的距离L:OutSideWidth->0时,草的角度∠:0->90,90再减去乘出来度数可得到草应旋转的度数,然后除以360可以得到需要的浮点数。

此处还可以根据车子的前进后退,让草分别做出往前旋转还是往后旋转,在前面的MaterialParameterCollection中新增一个CarForwardSpeed,并在EventTick下实时获取车子的速度方向,然后根据CarForwardSpeed的值传+360或-360到上上图中。

判断草水平方向离车子边的如下图,同理。

完成后,大体结构如下。

如果需要HLSL代码,可以点击window->HLSL Code。

到此就完成了。

原文地址:https://www.cnblogs.com/JinT-Hwang/p/8370792.html

时间: 2024-10-13 13:26:30

虚幻4 在Material中如何实现 车子压倒草的功能的相关文章

MYSQL-实现ORACLE 和SQLserver数据中- row_number() over(partition by ) 分组排序功能

网上看见了好多例子都基本上是一样的,没有过多的解释,对于一个初学MySQL来说有点难,我把部分转摘过来如下 原文:http://www.cnblogs.com/buro79xxd/archive/2012/08/29/2662489.html 要求目标:1.确定需求: 根据部门来分组,显示各员工在部门里按薪水排名名次. 创建表格:2.来创建实例数据: drop table if exists heyf_t10; create table heyf_t10 (empid int ,deptid i

《Java中的自动装箱和拆箱功能.》

1 //Java中的自动装箱和拆箱功能. 2 class AutoboxingUnboxing 3 { 4 public static void main(String[] args) 5 { 6 //直接把一个基本类型变量赋给Interger对象. 7 Integer inObj = 5; 8 Object inObj1 = 6; 9 //直接把一个boolean类型的变量赋给一个Object类型的变量. 10 Object boolObj = true; 11 //直接把Integer对象赋

【翻译自mos文章】为什么在备份过程中rman不使用unused block 压缩功能

为什么在备份过程中rman不使用unused block 压缩功能? 来源于: Why is RMAN not using Unused Block Compression during backup? (文档 ID 798844.1) 适用于: Oracle Database - Enterprise Edition - Version 10.2.0.1 to 11.2.0.2 [Release 10.2 to 11.2] Information in this document applie

解决mac pro中三指轻按翻译的功能不起作用

mac pro中三指轻按翻译的功能不起作用了,这是为什么呢? 快捷键如下: command+contral+d 原因是pro和air不一样,air默认是开着的,pro需要设置 系统偏好设置-> 触控板 -> 取消"用力点按和触觉反馈" -> 选中"查找与数据监测器"(可以看到有用三个手指轻按) 然后用3个手指轻按了,就会翻译了,而无需用control+command+d快捷键了

在VC中,为图片按钮添加一些功能提示(转)

在VC中,也常常为一些图片按钮添加一些功能提示.下面讲解实现过程:该功能的实现主要是用CToolTipCtrl类.该类在VC  msdn中有详细说明.首先在对话框的头文件中加入初始化语句:public:下,加入:CToolTipCtrl    m_Mytip;然后在初始化对话框函数中加入:m_Mytip.Create(this);  m_Mytip.AddTool( GetDlgItem(IDC_BUTTON), "你想要添加的提示信息" ); //IDC_BUTTON为你要添加提示信

iOS开发中文件的上传和下载功能的基本实现-备用

感谢大神分享 这篇文章主要介绍了iOS开发中文件的上传和下载功能的基本实现,并且下载方面讲到了大文件的多线程断点下载,需要的朋友可以参考下 文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代码. 主控制器的关键代码: 复制代码代码如下: YYViewController.m#import "YYViewController.h" #define YYEnc

【性能分析】初探VS2010中的Profile(性能剖析)功能

VS2010中的Profile(性能剖析)功能十分实用,它可以协助程序员迅速锁定当前程序的性能瓶颈,为程序的优化做准备. 点击VS2010的Analyze菜单,选择Launch Performance Wizard,依照提示可以很方便地完成Profile的必需配置.可能你会碰到"Injection of runtime library failed"错误,这时就不要使用Wizard,而要选择Analyze下拉菜单中的Profiler->Attach/Detach...,将Prof

app刚开始启动时(即:appdelegate文件中)可以写的几个功能

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } p.p2 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px "Helvetica Neue"; color: #454545 } span.s1 { font: 12.0px "Helvetica Neue" } span.s2 {

.NET中string与StringBuilder在字符串拼接功能上的比较

来自森大科技官方博客 http://www.cnsendblog.com/?p=86 .NET中string与StringBuilder在字符串拼接功能上的比较string与StringBuilder的在字符串拼接时执行效率上有差异,因为StringBuilder类中用了一个技巧:它申请了两倍的内存空间存放字符串,在调用Append方法拼接字符串时,会先检查剩余的空间是否能放下要拼接的字符串,若能放下,则将要拼接的字符串Copy到剩余的空间中,若不能放下,则再申请拼接后的字符串两倍的长度空间,将