【目标】
AnimDynamic继续
【思路】
1 之前运行效果
2 FAnimPhys.CalculateNextPose 会去更新每块骨骼位置
s2 = s1+ vt
3
4 计算流程
5 实验
FAnimPhys.CalculateNextPose
不更新NextPosition
效果如下:
因为FAnimPhys.CalculateNextPose没屏蔽旋转计算,所以有一部分变化
6
【步骤】
1 添加相关绘制盒子函数USkelControlAnimDynamic
INT USkelControlAnimDynamic::GetNumBodies() const
{
return Bodies.Num();
}
const FAnimPhysRigidBody& USkelControlAnimDynamic::GetPhysBody(INT BodyIndex) const
{
return Bodies(BodyIndex).RigidBody.PhysBody;
}
void USkelControlAnimDynamic::DrawSkelControl3D(const FSceneView* View, FPrimitiveDrawInterface* PDI, USkeletalMeshComponent* SkelComp, INT BoneIndex)
{
// If we want to preview the live node, process it here
if(bPreviewLive)
{
for(INT BodyIndex = 0 ; BodyIndex < GetNumBodies() ; ++BodyIndex)
{
const FAnimPhysRigidBody& Body = GetPhysBody(BodyIndex);
FBoneAtom BodyTransform(Body.Pose.Orientation, Body.Pose.Position);
//for(const FAnimPhysShape& Shape : Body.Shapes)
for (INT BodyIdx = 0; BodyIdx < Body.Shapes.Num(); BodyIdx++)
{
const FAnimPhysShape& Shape = Body.Shapes(BodyIdx);
//for(const FIntVector& Triangle : Shape.Triangles)
for (INT TriangleIdx = 0; TriangleIdx < Shape.Triangles.Num(); TriangleIdx++)
{
const FIntVector& Triangle = Shape.Triangles(TriangleIdx);
for(INT Idx = 0 ; Idx < 3 ; ++Idx)
{
INT Next = (Idx + 1) % 3;
FVector FirstVertPosition = BodyTransform.TransformPosition(Shape.Vertices(Triangle(Idx)));
FVector SecondVertPosition = BodyTransform.TransformPosition(Shape.Vertices(Triangle(Next)));
PDI->DrawLine(FirstVertPosition, SecondVertPosition, FLinearColor::Yellow, SDPG_Foreground, ShapeLineWidth);
}
}
const INT BoneIndex = SkelComp->MatchRefBone(BoundBone);
if(BoneIndex != INDEX_NONE)
{
FBoneAtom BodyJointTransform = SkelComp->SpaceBases(BoneIndex);
FBoneAtom ShapeOriginalTransform = BodyJointTransform;
// Draw pin location
FVector LocalPinOffset = BodyTransform.Rotator().RotateVector(GetBodyLocalJointOffset(BodyIndex));
PDI->DrawLine(Body.Pose.Position, Body.Pose.Position + LocalPinOffset, FLinearColor::Green, SDPG_Foreground, ShapeLineWidth);
// Draw basis at body location
FVector Origin = BodyTransform.GetTranslation();
FVector XAxis(1.0f, 0.0f, 0.0f);
FVector YAxis(0.0f, 1.0f, 0.0f);
FVector ZAxis(0.0f, 0.0f, 1.0f);
XAxis = BodyTransform.TransformVector(XAxis);
YAxis = BodyTransform.TransformVector(YAxis);
ZAxis = BodyTransform.TransformVector(ZAxis);
PDI->DrawLine(Origin, Origin + XAxis * TransformBasisScale, FLinearColor::Red, SDPG_Foreground, TransformLineWidth);
PDI->DrawLine(Origin, Origin + YAxis * TransformBasisScale, FLinearColor::Green, SDPG_Foreground, TransformLineWidth);
PDI->DrawLine(Origin, Origin + ZAxis * TransformBasisScale, FLinearColor::Blue, SDPG_Foreground, TransformLineWidth);
if(bShowLinearLimits)
{
DrawLinearLimits(PDI, BodyJointTransform);
}
if(bShowAngularLimits)
{
FBoneAtom AngularLimitsTM(BodyJointTransform.GetRotation(), BodyTransform.GetTranslation() + LocalPinOffset);
DrawAngularLimits(PDI, AngularLimitsTM);
}
if(bShowCollisionSpheres && Body.CollisionType != AnimPhysCollisionType::CoM)
{
// Draw collision sphere
DrawWireSphere(PDI, BodyTransform, FLinearColor(FColor::Cyan), Body.SphereCollisionRadius, 24, SDPG_Foreground);
}
}
}
}
}
}
void USkelControlAnimDynamic::DrawAngularLimits(FPrimitiveDrawInterface* PDI, const FBoneAtom& JointTransform) const
{
FVector XAxis = JointTransform.GetUnitAxis(0);
FVector YAxis = JointTransform.GetUnitAxis(1);
FVector ZAxis = JointTransform.GetUnitAxis(2);
const FVector& MinAngles = ConstraintSetup.AngularLimitsMin;
const FVector& MaxAngles = ConstraintSetup.AngularLimitsMax;
FVector AngleRange = MaxAngles - MinAngles;
FVector Middle = MinAngles + AngleRange * 0.5f;
UMaterialInterface* LimitMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("EditorMaterials.PhAT_JointLimitMaterial"), NULL, LOAD_None, NULL);
if (AngleRange.X > 0.0f && AngleRange.X < 180.0f)
{
FBoneAtom XAxisConeTM(YAxis, XAxis ^ YAxis, XAxis, JointTransform.GetTranslation());
XAxisConeTM.SetRotation(FQuat(XAxis, DegreesToRadians(-Middle.X)) * XAxisConeTM.GetRotation());
DrawCone(PDI, FScaleMatrix(30.0f) * XAxisConeTM.ToMatrix(), DegreesToRadians(AngleRange.X / 2.0f), 0.0f, 24, false, FLinearColor::White, LimitMaterial->GetRenderProxy(false), SDPG_World);
}
if (AngleRange.Y > 0.0f && AngleRange.Y < 180.0f)
{
FBoneAtom YAxisConeTM(ZAxis, YAxis ^ ZAxis, YAxis, JointTransform.GetTranslation());
YAxisConeTM.SetRotation(FQuat(YAxis, DegreesToRadians(Middle.Y)) * YAxisConeTM.GetRotation());
DrawCone(PDI, FScaleMatrix(30.0f) * YAxisConeTM.ToMatrix(), DegreesToRadians(AngleRange.Y / 2.0f), 0.0f, 24, false, FLinearColor::White, LimitMaterial->GetRenderProxy(false), SDPG_World);
}
if (AngleRange.Z > 0.0f && AngleRange.Z < 180.0f)
{
FBoneAtom ZAxisConeTM(XAxis, ZAxis ^ XAxis, ZAxis, JointTransform.GetTranslation());
ZAxisConeTM.SetRotation(FQuat(ZAxis, DegreesToRadians(Middle.Z)) * ZAxisConeTM.GetRotation());
DrawCone(PDI, FScaleMatrix(30.0f) * ZAxisConeTM.ToMatrix(), DegreesToRadians(AngleRange.Z / 2.0f), 0.0f, 24, false, FLinearColor::White, LimitMaterial->GetRenderProxy(false), SDPG_World);
}
}
void USkelControlAnimDynamic::DrawLinearLimits(FPrimitiveDrawInterface* PDI, const FBoneAtom& ShapeTransform) const
{
// Draw linear limits
FVector LinearLimitHalfExtents(ConstraintSetup.LinearAxesMax - ConstraintSetup.LinearAxesMin);
// Add a tiny bit so we can see collapsed axes
LinearLimitHalfExtents += FVector(0.1f);
LinearLimitHalfExtents /= 2.0f;
FVector LinearLimitsCenter = ConstraintSetup.LinearAxesMin + LinearLimitHalfExtents;
FBoneAtom LinearLimitsTransform = ShapeTransform;
LinearLimitsTransform.SetTranslation(LinearLimitsTransform.GetTranslation() + LinearLimitsTransform.TransformVector(LinearLimitsCenter));
UMaterialInterface* LimitMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("EditorMaterials.PhAT_JointLimitMaterial"), NULL, LOAD_None, NULL);
DrawBox(PDI, LinearLimitsTransform.ToMatrix(), LinearLimitHalfExtents, LimitMaterial->GetRenderProxy(false), SDPG_Foreground);
}
FVector USkelControlAnimDynamic::GetBodyLocalJointOffset(INT BodyIndex) const
{
if (JointOffsets.IsValidIndex(BodyIndex))
{
return JointOffsets(BodyIndex);
}
return FVector::ZeroVector;
}
使用兽人模型前飘带测试
目测骨骼位置反了?
旋转计算的问题
FAnimPhysAngularLimit.Iter
实验:去掉FAnimPhysAngularLimit.Iter 计算
qun02 和qun09 骨骼位置弄反了
应该qun02固定 qun09飘动的
会不会是 计算结果列表顺序 和应用上去的列表顺序 不一致
USkelControlAnimDynamic.CalculateNewBoneTransforms
USkelControlAnimDynamic.GetAffectedBones
2 修改USkelControlAnimDynamic.GetAffectedBones
//INT BoneIndex = Component->MatchRefBone(ChainEnd);
//OutBoneIndices.AddItem(ChainEndBoneIdx);
OutBoneIndices.InsertItem(ChainEndBoneIdx,0);
...
while(ParentBoneIndex != 0)
{
FName ParentBoneName = SkelComp->GetBoneName(ParentBoneIndex);
//OutBoneIndices.AddItem(ParentBoneIndex);
OutBoneIndices.InsertItem(ParentBoneIndex,0);
.......
}
}
else
{
//OutBoneIndices.AddItem(BoneIndex);
OutBoneIndices.InsertItem(BoneIndex,0);
}
【运行】
顺序对了
效果有待调整
【运行】
3