标签:api surface epo com false 精度 如何 位置 分享
需求来源:
UE4.15版本
我们的VR项目中,需要实现护盾的功能,玩家的左手柄方向的延长线与玩家周围的一个圆柱体相交的位置,即为护盾的位置,而护盾的方向,与圆柱体相切,如下图所示.
绿色为护盾,红色的为圆柱体,蓝色的线从左手柄射出.
玩家的左手一定会在圆柱体内,那么要解决的问题就变为,求解线段与圆柱体的交点.
如何使用迭代的方式求解呢,思路如下:
在玩家的左手柄方向的延长线上选择一点,此点的位置要在圆柱体外.设为PointOut.玩家左手柄位置为PointIn,求出两个点的中点:PointMiddle.那么交点一定位于[PointIn, PointMiddle] 或者[PointIn, PointOut]之间,以此类推,就可以不断逼近交点.
1 UCLASS() 2 class SHOOTERGAME_API UShooterBlueprintFunctionLibrary : public UBlueprintFunctionLibrary 3 { 4 GENERATED_UCLASS_BODY() 5 //求解一个点是否在圆柱体内 6 //LowCircleCenter:圆柱体底面的圆心位置 7 //HightCircleCenter:圆柱体的顶面的圆心位置 8 //R:圆柱体的半径 9 //TestPoint需要测试的点 10 UFUNCTION(BlueprintPure, Category = "Math") 11 static bool IsInCylinder(FVector LowCircleCenter, FVector HighCircleCenter, float R, FVector TestPoint); 12 13 //线段与圆柱的交点 采用迭代逼近的方式 14 //两个点必须一个在圆柱体内,一个在圆柱体外 15 //LowCircleCenter:圆柱体底面的圆心位置 16 //HightCircleCenter:圆柱体的顶面的圆心位置 17 //R:圆柱体的半径 18 //StartPoint:线段起始点 19 //EndPoint:线段终点 20 //Tolerance:迭代精度 21 //HasIntersection:是否有交点 22 //InSurface:交点的位置,在柱面上 0,在底面 -1,在顶面 1 23 UFUNCTION(BlueprintPure, Category = "Math") 24 static FVector LineAndCylinderIntersection(FVector LowCircleCenter, FVector HighCircleCenter, float R, FVector StartPoint, FVector EndPoint, float Tolerance, bool& HasIntersection, int32& InSurface); 25 }
1 //求解一个点是否在圆柱体内 2 //LowCircleCenter:圆柱体底面的圆心位置 3 //HightCircleCenter:圆柱体的顶面的圆心位置 4 //R:圆柱体的半径 5 //TestPoint需要测试的点 6 7 bool UShooterBlueprintFunctionLibrary::IsInCylinder(FVector LowCircleCenter, FVector HighCircleCenter, float R, FVector TestPoint) 8 { 9 FVector MiddlePoint = (LowCircleCenter + HighCircleCenter) / 2; 10 11 FVector CylinderDir = (HighCircleCenter - LowCircleCenter); 12 13 float Height = CylinderDir.Size(); 14 15 CylinderDir.Normalize(); 16 17 FVector StartDir = TestPoint - MiddlePoint; 18 19 float StartProj = FVector::DotProduct(StartDir, CylinderDir); 20 //判断此点是否在圆柱体的高度范围内 21 if (FMath::Abs(StartProj) > Height / 2) 22 { 23 return false; 24 } 25 26 //判断此点是否在圆柱体的横向距离内 27 float TestDist = FMath::PointDistToLine(TestPoint, CylinderDir, MiddlePoint); 28 29 return TestDist <= R; 30 31 }
1 //求解线段与圆柱体的交点,两个点必须一个在圆柱体内,一个在圆柱体外 2 //LowCircleCenter:圆柱体底面的圆心位置 3 //HightCircleCenter:圆柱体的顶面的圆心位置 4 //R:圆柱体的半径 5 //StartPoint:线段起始点 6 //EndPoint:线段终点 7 //Tolerance:迭代精度 8 //HasIntersection:是否有交点 9 //InSurface:交点的位置,在柱面上 0,在底面 -1,在顶面 1 10 FVector UShooterBlueprintFunctionLibrary::LineAndCylinderIntersection(FVector LowCircleCenter, FVector HighCircleCenter, float R, FVector StartPoint, FVector EndPoint, float Tolerance, bool& HasIntersection, int32& InSurface) 11 { 12 Tolerance = Tolerance <= 0.1f ? 0.1f : Tolerance; 13 //两个点必须一个在圆柱体内,一个在圆柱体外 14 if (!(IsInCylinder(LowCircleCenter, HighCircleCenter, R, StartPoint) ^ IsInCylinder(LowCircleCenter, HighCircleCenter, R, EndPoint))) 15 { 16 HasIntersection = false; 17 return FVector::ZeroVector; 18 } 19 20 HasIntersection = true; 21 22 FVector Point1 = StartPoint; 23 FVector Point2 = EndPoint; 24 25 FVector MiddlePoint = (Point1 + Point2) / 2; 26 27 float DiffSize = (Point1 - Point2).SizeSquared(); 28 29 int32 Times = 0; 30 //迭代算法 31 while (DiffSize > Tolerance) 32 { 33 //选择下一个迭代点 34 if (IsInCylinder(LowCircleCenter, HighCircleCenter, R, Point1) ^ IsInCylinder(LowCircleCenter, HighCircleCenter, R, MiddlePoint)) 35 { 36 Point2 = MiddlePoint; 37 } 38 else 39 { 40 Point1 = MiddlePoint; 41 } 42 43 MiddlePoint = (Point1 + Point2) / 2; 44 45 DiffSize = (Point1 - Point2).SizeSquared(); 46 47 Times++; 48 49 if (Times >= 40) 50 { 51 break; 52 } 53 } 54 55 FVector CircleCenterMiddlePoint = (LowCircleCenter + HighCircleCenter) / 2; 56 FVector CircleCenterDir = (HighCircleCenter - LowCircleCenter); 57 CircleCenterDir.Normalize(); 58 59 float TestDist = FMath::PointDistToLine(MiddlePoint, CircleCenterDir, CircleCenterMiddlePoint); 60 //交点在侧面,那么交点与圆柱体中心线的距离小于Tolerance 61 if ((TestDist - R) * (TestDist - R) <= Tolerance) 62 { 63 InSurface = 0; 64 } 65 else 66 { 67 //可以依据交点与中心点的方向来判断交点在底面还是顶面 68 if (FVector::DotProduct(MiddlePoint - CircleCenterMiddlePoint, CircleCenterDir) >= 0.0f) 69 { 70 InSurface = 1; 71 } 72 else 73 { 74 InSurface = -1; 75 } 76 } 77 78 return MiddlePoint; 79 }
标签:api surface epo com false 精度 如何 位置 分享
原文地址:http://www.cnblogs.com/sichuanke/p/7731511.html