首页 > 代码库 > 17020701(AnimDynamic继续)

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)


17020701(AnimDynamic继续)