Final IK——VRIK使用方法和一些小技巧
Posted love_c_s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Final IK——VRIK使用方法和一些小技巧相关的知识,希望对你有一定的参考价值。
目录
2.Spine——脊柱变量,包括 头、盆骨、胸、脊柱点、根旋转
一、背景
- 需求:接收VR端输入 头(最好是眼睛的位置)、两个手(wrist)、有需要可以再多加两个跟踪器在脚上,我这里没有。
- 输出:反解算出来的其他姿态。
- 难点:人物模型身高和现实真人身高不匹配导致相机位置异常、相机位置和头部位置的偏差。
二、实现过程
1.环境
unity2019.4.28+steam vr 2.7.3+unity商店的Kazuko人物模型
2.基操
1.给模型添加VRIK组件
一般会添加后自动解析好骨骼。
打开References检查一下,可以看到自动引用好了。 不放心就点开检查一下。
2.指定输入Transform(头、左手、右手)
①从steamvr插件里拖出[Camera Rig]预制体。
②复制一下 头、左右手的位置,只需要位置即可,下面的网格mesh要删掉。
③将复制出来的子物体拖放到 [Camera Rig]下对应的位置作为子物体。作为子物体是为了后面运行的时候能够调节跟踪点和模型的相对位置,就是这个微调很麻烦。
④将复制下来的副本的position清0。保留旋转。
坐标清零是为了对齐跟踪手柄和摄像机的原点,保持旋转接合原模型。
⑤将这几个位置作为输入,进而可以控制vr模型。
⑥运行即可看到效果,肯定很不理想。
二、发现问题
以上是传统的基操,但是会存在以下几个问题:
1.摄像机位置不对,具体表现为被脸或者头发挡住,因为摄像机和输入的头部位置重合,从脸内往脸外看,根本看不见外面。一般就会利用作为子物体的头部位置进行偏移校准。先运行,手动调位置,再复制,停止运行,再粘贴值。
但是可能还是不能很好解决问题。
因为还有问题是,如果真人的身高比模型的高,那么摄像机位置会移出去而不是固定在模型眼睛上,所以需要后面的其他设置。
2.摄像机在一定高度移动时不会移动模型(相机游走于眼睛外),超过范围后,模型才跟着动。
3.手柄位置不对。这里可以偏移两个手的追踪位置。同上。
三、参数功能
弄明白参数效果是很重要的,不然不知道出问题去哪里调节,一顿操作猛如虎,一看战绩0-5.
1.分块
这个组件有三块。
Fix Transforms—— 默认一般都勾选的,能提升解析性能。如果为真,将在每次更新中将求解器使用的所有变换修复为其初始状态。这可以以很小的性能成本防止未动画骨骼和Animator culling的潜在问题。
References——对原模型主要关节的引用,骨骼映射。如果不是人形角色,则右键单击组件标题并选择手动填写的“自动检测引用”。胸部、颈部、肩部和脚趾骨是可选的。
VRIK 还支持无腿和无臂角色。如果您不想使用腿/手臂,将所有腿/手臂参考留空。·
Solver——解算器,输入跟踪的头和双手。对原模型关节进行驱动。
2.Solver
1.几个全局解算参数。
- IK Position Weight:求解器的权重,可以解释为多大程度按照求解器得出的结果进行驱动。
- LOD:
0,全质量求解
1:肩部求解,拉伸植物脚(plantFeet)禁用,脊柱解决质量降低。这提供了大约 30% 的性能增益。
2:剔除,但如果启用了运动,则会更新根位置和旋转。
- plantFeet - 如果为 true,即使头部目标遥不可及,也会保持脚趾着地,因此如果头部目标太高而模型无法到达,这可能会导致相机退出头部。启用此功能会增加求解器的成本,因为必须多次求解腿。
Spine——脊柱变量,包括 头、盆骨、胸、脊柱点、根旋转:
Head:
引用:VRIK.solver.spine.headTarget……
headTarget-头部目标。这不应该是相机变换本身,而是作为其父级的子游戏对象(说白了就是相机为父,头骨为子),因此您可以调整其位置/旋转以匹配头骨的方向。然后将副本分配给此插槽。
positionWeight - 头部目标的位置权重。如果您已将 headTarget 设为空,则头部仍将被拉到 headTarget 的最后一个位置,直到您将此值设置为 0。
rotationWeight - 头部目标的旋转权重。
headClampWeight - 夹紧头部旋转。值 0.5 允许头部相对于 headTarget 旋转 90 度。值 0 允许 180 度,值 1 表示头部旋转将锁定到Target。
minHeadHeight - 头部距离角色根部的最小高度。(根在地板,相当于弯腰极限)
useAnimatedHeadHeightWeight - 在头部目标高度接近头部骨骼高度时,从动画继承垂直头部摆动运动,允许第三人网络化身的更自然的运动动画。
useAnimatedHeadHeightRange - 如果 abs(head target height - head bone height) < 这个值,将使用 head bone height 作为 head target Y。(如果想让相机贴着动而不是超过范围才跟着动,就设置为0)
useAnimatedHeadHeightBlend - 上面“useAnimatedHeadHeightRange”效果的衰减范围。如果头部目标高度与头部骨骼高度的距离大于 useAnimatedHeadHeightRange + animatedHeadHeightBlend,那么头部将再次垂直锁定到头部目标。(很绕,默认吧)
Pelvis——盆骨
pelvisTarget- 骨盆目标(可选),适用于坐着的装备,或者如果您的背包或腰带上有额外的跟踪器。设置的最佳实践是复制虚拟形象的骨盆骨骼并将其作为父项到骨盆跟踪器。然后将副本分配给此插槽。
pelvisPositionWeight - 骨盆目标的位置权重。请注意,如果您已将 pelvisTarget 设为空,骨盆仍将被拉到 pelvisTarget 的最后一个位置,直到您将此值设置为 0。
pelvisRotationWeight - 骨盆目标的旋转权重。同上head。
maintainPelvisPosition - 骨盆将保持其动画位置多少?
Chest
chestGoal- 如果 chestGoalWeight 大于 0,胸部将转向这个 Transform。
chestGoalWeight - 将胸部转向 chestGoal 的权重。
chestClampWeight - 夹紧胸部旋转。值 0.5 允许胸部相对于头部旋转 90 度。值 0 允许 180 度,值 1 表示胸部将相对于头部锁定。
rotateChestByHands - 基于手部位置应用于胸部的旋转量。
Spine
bodyPosStiffness - 确定身体跟随头部位置的程度。
bodyRotStiffness - 确定身体跟随头部旋转的程度。
neckStiffness - 确定胸部旋转到头部旋转的程度。
moveBodyBackWhenCrouching - 当玩家蹲下时,身体沿 -character.forward 轴水平移动该值。
Root Rotation
maxRootAngle - 如果头部目标转过这个角度,将自动旋转角色的根。
rootHeadingOffset - 根航向的角度偏移。调整此值以围绕垂直轴相对于 HMD 转动根。对于有时希望头像以倾斜姿势站立的格斗或射击游戏很有用。
Left Arm 手臂变量
bendGoal - 弯曲目标。如果 'Bend Goal Weight' > 0,肘部将朝着这个变换弯曲。
shoulderRotationMode - 肩骨旋转的不同技术。
shoulderRotationWeight - 肩部旋转的权重
shoulderTwistWeight - 当手臂抬起时向后扭转肩膀的权重。
bendGoalWeight - 如果大于 0,则将肘部朝向“弯曲目标”变换弯曲。
swivelOffset - 肘部弯曲方向的角度偏移。
wristToPalmAxis - 从手腕指向手掌的手骨局部轴。用于定义手骨方向。如果您从另一个具有不同骨骼方向的化身复制了 VRIK 组件,请右键单击 VRIK 标题并从上下文菜单中选择“猜测手部方向”。
palmToThumbAxis - 从手掌指向拇指的手骨局部轴。用于定义手部骨骼方向如果您从另一个具有不同骨骼方向的化身复制了 VRIK 组件,请右键单击 VRIK 标题并从上下文菜单中选择“猜测手部方向”。
Stretching 拉伸部分
armLengthMlp - 使用它来使手臂更短/更长。通过手和前臂局部位置的位移来工作。
stretchCurve - 通过相对于手臂长度的目标距离评估手臂的拉伸。时间 1 处的值表示到目标的距离等于臂长的点处的拉伸量。时间 2 处的值表示到目标的距离为臂长两倍处的拉伸量。值表示拉伸量。线性拉伸将通过上升 45 度的线性曲线来实现。通过将最后一个键向上和向右移动相同的量来增加拉伸范围。曲线平滑有助于减少肘部折断(在目标距离达到手臂长度之前稍微伸展手臂)。要获得该曲线的最佳最佳值,请转到“VRIK (Basic)”演示场景并从 Pilot 角色复制拉伸曲线。
Leg也是一样
Locomotion
引用:VRIK.solver.locomotion.mode……
Procedural模式:
footDistance - 尝试保持双腿之间的距离。
stepThreshold - 仅当步数目标位置至少离当前足迹这么远或脚不再到达当前足迹或足迹角度超过“角度阈值”时才迈出一步。
angleThreshold - 仅当步距目标位置至少距离当前足迹的“步距阈值”或脚不再到达当前足迹或足迹角度超过此值时才迈出一步。
comAngleMlp - 将质心的角度相乘 - 压力矢量的中心。如果失去平衡,较大的值会使角色更快地迈出一步。
maxVelocity - 用于预测的头部/手部目标速度的最大值。
velocityFactor - 头/手目标速度预测量。
maxLegStretch - 一条腿在被迫走到另一个位置之前可以伸展多少?1 表示完全拉伸。
rootSpeed - 将角色的根部拉向脚步的水平中点的速度。
stepSpeed - 将一只脚移动到下一个位置的速度。
stepHeight - 归一化步长(0 - 1)的脚的高度。
heelHeight - 归一化步长 (0 - 1) 后跟的高度偏移。
relaxLegTwistMinAngle - 如果理想的旋转超过此角度,则在腿不踩踏时旋转脚以放松腿的扭转旋转。
relaxLegTwistSpeed - 腿部不踩踏时脚的旋转速度,以放松腿部的扭转旋转。
stepInterpolation - 步的插值模式。
offset - 近似质心的偏移量。
Animated模式
weight - 用于混入/混出程序或动画运动。
Move Threshold - moveThreshold - 开始移动(到 HMD 的水平距离 + HMD 速度)阈值。
minAnimationSpeed - 最小运动动画速度。
maxAnimationSpeed - 最大运动动画速度。
animationSmoothTime - Vector3.SmoothDamping 'VRIK_Horizontal' 和 'VRIK_Vertical' 参数的平滑时间。较大的值使动画更流畅,但响应性较差。
standOffset - X 和 Z 站立偏离 HMD 的水平位置。
.rootLerpSpeedWhileMoving - 移动时以该速度将根移向 HMD 的水平位置。
rootLerpSpeedWhileStopping - 在从运动状态过渡到空闲状态时,以这个速度向 HMD 的水平位置移动根。
.rootLerpSpeedWhileTurning - 在原地转动时以这个速度将根移向 HMD 的水平位置。
maxRootOffset - 从根到 HMD 的最大水平距离。
maxRootAngleMoving - 移动时从头部向前的最大根角 (ik.solver.spine.maxRootAngle)。
maxRootAngleStanding - 站立时从头部向前的最大根角 (ik.solver.spine.maxRootAngle.
四、解决问题
主要是解决相机问题。
plantFeet 的勾去掉,使得模型能够跟随头,离地。
对于比较矮的模型,需要拉长腿,能够着地。这个要看模型调节。
相机要求贴近眼睛位置,所以要
五、总结
参数非常之多,而且细微的参数意思还特别难理解,需要常运行的时候调试才知道。
Java-小技巧-003-staticfinalstatic final的区别
final可以修饰:属性,方法,类,局部变量(方法中的变量)
final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变,jvm会将其分配到常量池中,程序不可改变其值;
final修饰的属性跟具体对象有关,在运行期初始化的final属性,不同对象可以有不同的值。
final修饰的属性表明是一个常数(创建后不能被修改)。
final修饰的方法表示该方法在子类中不能被重写,final修饰的类表示该类不能被继承。
对于基本类型数据,final会将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能再将句柄指向另一个对象。但是,对象的本身是可以修改的。这一限制也适用于数组,数组也属于对象,数组本身也是可以修改的。方法参数中的final句柄,意味着在该方法内部,我们不能改变参数句柄指向的实际东西,也就是说在方法内部不能给形参句柄再另外赋值)。
static可以修饰:属性,方法,代码段,内部类(静态内部类或嵌套内部类)
当定义一个static的变量的时候jvm会将将其分配在内存堆上,所有程序对它的引用都会指向这一个地址而不会重新分配内存;
static修饰的属性的初始化在编译期(类加载的时候),初始化后能改变。
static修饰的属性所有对象都只有一个值。
static修饰的属性强调它们只有一个。
static修饰的属性、方法、代码段跟该类的具体对象无关,不创建对象也能调用static修饰的属性、方法等
static和“this、super”势不两立,static跟具体对象无关,而this、super正好跟具体对象有关。
static不可以修饰局部变量。
当修饰一个程序块的时候(也就是直接将代码写在static{...}中)时候,虚拟机就会优先加载静态块中代码,这主要用于系统初始化;
static final和final static没什么区别,一般static写在前面。
static修饰的属性强调它们只有一个,final修饰的属性表明是一个常数(创建后不能被修改)。static final修饰的属性表示一旦给值,就不可修改,并且可以通过类名访问。
static final也可以修饰方法,表示该方法不能重写,可以在不new对象的情况下调用。
以上是关于Final IK——VRIK使用方法和一些小技巧的主要内容,如果未能解决你的问题,请参考以下文章
Java-小技巧-003-staticfinalstatic final的区别