17020701(AnimDynamic继续)

【目标】

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

来自为知笔记(Wiz)

时间: 2024-10-20 01:02:58

17020701(AnimDynamic继续)的相关文章