14073102(CCDIKRecoil)
【目标】
CCDIKRecoil
【思路】
1 CCDIK和Recoil的结合
2 Recoil的回弹机制,逐渐回到原来位置
3 添加一个Recoil基类
【步骤】
1 将\Src\GameFramework\Classes\GameSkelCtrl_Recoil.uc复制到\Src\Engine\Classes\SkelControlRecoilBase.uc
修改一下名称 作为基类
2 其他相关类继承于SkelControlRecoilBase, \Engine\Classes\SkelControlLimbRecoil.uc
make一下
编译不通过
原因是USkeletalControlRecoilBase是在后面声明的
方案:
采取将派生类放GameFrameWork工程中
编译后发现
这里有语法错误
最后还是没有用继承方式,脚本目前很难使用双基类
所以目前还是重复写相同代码
3 添加一个继承类GameSkelCtrl_CCD_IK_Recoil_CCD_IK_Recoil.uc,放到GameFramework中,否则又牵扯到那些结构体声明的先后顺序问题
4 在GameSkelControls.cpp 中添加实现宏,及函数实现
IMPLEMENT_CLASS(UGameSkelCtrl_CCD_IK_Recoil);
/*-----------------------------------------------------------------------------
UGameSkelCtrl_CCD_IK_Recoil
-----------------------------------------------------------------------------*/
FVector2DUGameSkelCtrl_CCD_IK_Recoil::GetAim(USkeletalMeshComponent*InSkelComponent)
{
returnAim;
}
/** Is skeleton currently mirrored */
UBOOL UGameSkelCtrl_CCD_IK_Recoil::IsMirrored(USkeletalMeshComponent*InSkelComponent)
{
return FALSE;
}
// USkelControlBase interface
voidUGameSkelCtrl_CCD_IK_Recoil::TickSkelControl(FLOAT DeltaSeconds,USkeletalMeshComponent*SkelComp)
{
bApplyControl = FALSE;
if(ControlStrength> ZERO_ANIMWEIGHT_THRESH )
{
// if willing to play recoil, reset its state
if( bPlayRecoil != bOldPlayRecoil )
{
bPlayRecoil = bOldPlayRecoil;
Recoil.TimeToGo=Recoil.TimeDuration;
// ERS_Random == Start at random position along sine wave,
// ERS_Zero == Start at 0
const FLOAT TWO_PI =2.f*(FLOAT)PI;
Recoil.RotSinOffset.X =Recoil.RotParams.X == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.RotSinOffset.Y =Recoil.RotParams.Y == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.RotSinOffset.Z =Recoil.RotParams.Z == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.LocSinOffset.X =Recoil.LocParams.X == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.LocSinOffset.Y =Recoil.LocParams.Y == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.LocSinOffset.Z =Recoil.LocParams.Z == ERS_Random ? appFrand()* TWO_PI :0.f;
Recoil.RotOffset=FRotator(0,0,0);
Recoil.LocOffset=FVector(0.f);
}
if(Recoil.TimeToGo>DeltaSeconds)
{
Recoil.TimeToGo-=DeltaSeconds;
if(Recoil.TimeToGo>0.f)
{
bApplyControl = TRUE;
// Smooth fade out
const FLOAT TimePct=Clamp<FLOAT>(Recoil.TimeToGo/Recoil.TimeDuration,0.f,1.f);
const FLOAT Alpha=TimePct*TimePct*(3.f-2.f*TimePct);
const FLOAT AlphaTimesDelta=Alpha*DeltaSeconds;
// Recoil Bone Rotation, compute sin wave value for each component
if(!Recoil.RotAmplitude.IsZero())
{
if(Recoil.RotAmplitude.X !=0.f)
{
Recoil.RotSinOffset.X +=AlphaTimesDelta*Recoil.RotFrequency.X;
Recoil.RotOffset.Pitch= appTrunc(Alpha*Recoil.RotAmplitude.X * appSin(Recoil.RotSinOffset.X));
}
if(Recoil.RotAmplitude.Y !=0.f)
{
Recoil.RotSinOffset.Y +=AlphaTimesDelta*Recoil.RotFrequency.Y;
Recoil.RotOffset.Yaw= appTrunc(Alpha*Recoil.RotAmplitude.Y * appSin(Recoil.RotSinOffset.Y));
}
if(Recoil.RotAmplitude.Z !=0.f)
{
Recoil.RotSinOffset.Z +=AlphaTimesDelta*Recoil.RotFrequency.Z;
Recoil.RotOffset.Roll= appTrunc(Alpha*Recoil.RotAmplitude.Z * appSin(Recoil.RotSinOffset.Z));
}
}
// Recoil Bone Location, compute sin wave value for each component
if(!Recoil.LocAmplitude.IsZero())
{
if(Recoil.LocAmplitude.X !=0.f)
{
Recoil.LocSinOffset.X +=AlphaTimesDelta*Recoil.LocFrequency.X;
Recoil.LocOffset.X =Alpha*Recoil.LocAmplitude.X * appSin(Recoil.LocSinOffset.X);
}
if(Recoil.LocAmplitude.Y !=0.f)
{
Recoil.LocSinOffset.Y +=AlphaTimesDelta*Recoil.LocFrequency.Y;
Recoil.LocOffset.Y =Alpha*Recoil.LocAmplitude.Y * appSin(Recoil.LocSinOffset.Y);
}
if(Recoil.LocAmplitude.Z !=0.f)
{
Recoil.LocSinOffset.Z +=AlphaTimesDelta*Recoil.LocFrequency.Z;
Recoil.LocOffset.Z =Alpha*Recoil.LocAmplitude.Z * appSin(Recoil.LocSinOffset.Z);
}
}
}
}
}
Super::TickSkelControl(DeltaSeconds,SkelComp);
}
voidUGameSkelCtrl_CCD_IK_Recoil::GetAffectedBones(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<INT>&OutBoneIndices)
{
check(OutBoneIndices.Num()==0);
// Only process bone if there is something to do
if( bApplyControl )
Super::GetAffectedBones(BoneIndex,SkelComp,OutBoneIndices);
}
voidUGameSkelCtrl_CCD_IK_Recoil::CalculateNewBoneTransforms(INT BoneIndex,USkeletalMeshComponent*SkelComp,TArray<FBoneAtom>&OutBoneTransforms)
{
check(OutBoneTransforms.Num()==0);
// Current bone transform matrix in component space
FBoneAtomNewBoneTM=SkelComp->SpaceBases(BoneIndex);
if(bBoneSpaceRecoil)
{
if(!Recoil.LocOffset.IsZero()||!Recoil.RotOffset.IsZero())
{
FBoneAtomRecoilTM(Recoil.RotOffset,Recoil.LocOffset);
NewBoneTM=RecoilTM*NewBoneTM;
OutBoneTransforms.AddItem(NewBoneTM);
}
return;
}
// Extract Aim
Aim=GetAim(SkelComp);
// Actor to Aim transform matrix
constFRotatorAimRotOffset( appTrunc(Aim.Y*16384), appTrunc(Aim.X*16384),0);
FBoneAtomActorToAim(AimRotOffset,FVector::ZeroVector);
ActorToAim.RemoveScaling();
ActorToAim.SetOrigin(FVector(0.f));
constFBoneAtomAimToActor=ActorToAim.Inverse();
// Component to Actor transform matrix
FBoneAtomComponentToActor=SkelComp->CalcComponentToFrameMatrix(BoneIndex, BCS_ActorSpace, NAME_None);
ComponentToActor.RemoveScaling();
ComponentToActor.SetOrigin(FVector(0.f));
constFBoneAtomActorToComponent=ComponentToActor.InverseSafe();
// Add rotation offset in component space
if(!Recoil.RotOffset.IsZero())
{
FRotatorRotOffset=Recoil.RotOffset;
// Handle mirroring
if(IsMirrored(SkelComp))
{
RotOffset.Yaw=-RotOffset.Yaw;
}
FBoneAtomNewRotTM=NewBoneTM*(ComponentToActor*(AimToActor*FBoneAtom(RotOffset,FVector::ZeroVector)*ActorToAim)*ActorToComponent);
NewRotTM.SetOrigin(NewBoneTM.GetOrigin());
NewBoneTM=NewRotTM;
}
// Add location offset in component space
if(!Recoil.LocOffset.IsZero())
{
FVectorLocOffset=Recoil.LocOffset;
// Handle mirroring
if(IsMirrored(SkelComp))
{
LocOffset.Y =-LocOffset.Y;
}
constFVectorTransInWorld=ActorToAim.TransformNormal(LocOffset);
constFVectorTransInComp=ActorToComponent.TransformNormal(TransInWorld);
constFVectorNewOrigin=NewBoneTM.GetOrigin()+TransInComp;
NewBoneTM.SetOrigin(NewOrigin);
}
// OutBoneTransforms.AddItem(NewBoneTM);
EffectorLocation=NewBoneTM.GetOrigin();
EffectorLocationSpace= BCS_WorldSpace;
Super::CalculateNewBoneTransforms(BoneIndex,SkelComp,OutBoneTransforms);
}
5 运行
如果单独一根骨骼的Recoil
6
14073102(CCDIKRecoil)的更多相关文章
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- Angular2学习笔记(1)
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
- ASP.NET Core 之 Identity 入门(一)
前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OW ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Online Judge(OJ)搭建(第一版)
搭建 OJ 需要的知识(重要性排序): Java SE(Basic Knowledge, String, FileWriter, JavaCompiler, URLClassLoader, Secur ...
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
- 【.net 深呼吸】细说CodeDom(5):类型成员
前文中,老周已经厚着脸皮介绍了类型的声明,类型里面包含的自然就是类型成员了,故,顺着这个思路,今天咱们就了解一下如何向类型添加成员. 咱们都知道,常见的类型成员,比如字段.属性.方法.事件.表示代码成 ...
- 【.net 深呼吸】细说CodeDom(4):类型定义
上一篇文章中说了命名空间,你猜猜接下来该说啥.是了,命名空间下面就是类型,知道了如何生成命名空间的定义代码,之后就该学会如何声明类型了. CLR的类型通常有这么几种:类.接口.结构.枚举.委托.是这么 ...
随机推荐
- JS写随机数
使用JS编写一个方法 让数组中的元素每次刷新随机排列(不得使用sort方法:需注明步骤思路).例如:初始数组:a,b,c,d 每次刷新页面都会显示不同:b,c,d,a….a,d,c,b…等等 代码: ...
- LAMP环境搭建 (原创帖,转载请注明出处)
=============================说在前面的话==========================第一安装Mysql第二安装Apache-httpd第三安装PHP 第四配置PH ...
- 浮动div中的图片垂直居中
table-cell方法垂直水平居中 <!DOCTYPE html> <html> <head> <meta name="description&q ...
- Android应用的安全的攻防之战
一.前言 在前两篇破解的文章中,我们介绍了如何使用动态调试来破解apk,一个是通过调试smali源码,一个是通过调试so代码来进行代码的跟踪破解,那么今天我们就这两篇文章的破解方法,来看看Androi ...
- mysql实战之 批量update
mysql实战之批量update 现阶段我们的业务量很小,要对admin_user表中的relationship字段进行更新,指定id是409.已知409是公司内的一服务中心,需要把该服务中心放到区代 ...
- cocoapods使用一直Updating local specs repositories的解决方案
pod install 换成pod install --verbose --no-repo-update这个命令,前面的命令被墙了 ,<pre id="best-content-226 ...
- printf(),类型修饰符
%s, 将输出作为字符串,要一直找到结束符'\0',这样在内存访问中,如果访问的是char 类型的,就会出现,从起始位置一直访问把整个申请的内存空间都遍历没有找到'\0',就会出现segment fa ...
- Unity手撸2048小游戏——背景文字控制
今天继续昨天的计划吧 1.新建项目.场景命名啥的都不说了吧. 2.直接开始新建一个Image,顺便把Image改名成Chessman 3.选中Image新建一个Text对象,调整下大小位置.这样就算完 ...
- dsp28377控制DM9000收发数据——第二版程序,能够实现手术功能,但是容易掉帧;使用读取中断寄存器的方式判断中断
G:\controlSUITE\device_support\F2837xD\v180\F2837xD_examples_Cpu1\emif1_16bit_asram\cpu01\emif1_16bi ...
- HTML 在安卓手机端软键盘弹出顶起页面布局的解决办法
$('body').height($('body')[0].clientHeight); 以上是背景即BODY被顶起的解决办法. 如果是footer被顶起,则可以用判断解决, $('input').f ...