当前位置: 首页 > article >正文

【UE5 C++】判断两点连线是否穿过球体

目录

前言

原理

代码

测试

结果


前言

       通过数学原理判断空间中任意两点的连线是否穿过球体,再通过射线检测检验算法的正确性。

原理

(1)设球体球心的坐标为O(C_{x},C_{y},C_{z}) ,半径为r;

(2)设线段AB中A点的坐标为A(x_{1},y_{1},z_{1}),B点的坐标为B(x_{2},y_{2},z_{2})

(3)计算\underset{OA}{\rightarrow}\underset{OB}{\rightarrow}\underset{AB}{\rightarrow}

(4)计算点O到 线段AB的最短距离d

d=\frac{|\underset{OA}{\rightarrow}\times \underset{AB}{\rightarrow}|}{|\underset{AB}{\rightarrow}|}

(5) 如果d\leq r,则线段AB穿过球体;如果d> r,则线段AB不穿过球体。

代码

        定义一个函数“IsCrossSphere”来判断线段AB是否穿过球体,函数需要传入点A、B的坐标以及球心坐标和球体半径。

再定义一个结构体作为函数返回值

函数“IsCrossSphere”的实现如下

头文件:

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "LineIsCrossSphere.generated.h"

USTRUCT(BlueprintType)
struct FStruct_Result_IsLineCrossSphere
{
	GENERATED_BODY();
public:
	UPROPERTY(BlueprintReadWrite)
	float distanceOfLineAndSphereCenter;
	UPROPERTY(BlueprintReadWrite)
	bool isCrossSphere;
};

UCLASS()
class STUDY_API ALineIsCrossSphere : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ALineIsCrossSphere();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UFUNCTION(BlueprintCallable)
	FStruct_Result_IsLineCrossSphere IsCrossSphere(FVector pointA, FVector pointB, FVector sphereOrginPoint, float sphereRadius);   //计算线段AB到球心的距离并判断AB是否穿过球体

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

};

源文件:

// Fill out your copyright notice in the Description page of Project Settings.


#include "Test/LineIsCrossSphere.h"

// Sets default values
ALineIsCrossSphere::ALineIsCrossSphere()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void ALineIsCrossSphere::BeginPlay()
{
	Super::BeginPlay();
	
}

FStruct_Result_IsLineCrossSphere ALineIsCrossSphere::IsCrossSphere(FVector pointA, FVector pointB, FVector sphereOrginPoint, float sphereRadius)
{
	bool isCrossSphere;

	FVector OA = pointA - sphereOrginPoint;
	FVector OB = pointB - sphereOrginPoint;
	FVector AB = OB - OA;
	FVector n = OA.Cross(AB);
	float D = n.Size() / AB.Size();

	if (D > sphereRadius)
	{
		isCrossSphere =  false;
	}
	else
	{
		isCrossSphere =  true;
	}

	FStruct_Result_IsLineCrossSphere result;
	result.isCrossSphere = isCrossSphere;
	result.distanceOfLineAndSphereCenter = D;
	return result;
}

// Called every frame
void ALineIsCrossSphere::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

测试

        在Tick中每帧去发射射线检测并调用函数 “IsCrossSphere”,通过观察射线碰撞结果以及函数 “IsCrossSphere”的打印是否相等来判断算法是否有误。(这里设置球体半径固定为50,球体坐标为(0,0,0))

结果

        可以看到不论是线段在球体表面,穿过球体,还是在球体外,函数 “IsCrossSphere”与射线检测的结果都是一致的。


http://www.kler.cn/a/418358.html

相关文章:

  • 深入研究:Vue.js 响应式系统的原理与优化
  • 【NLP 4、数学基础】
  • Flink常见面试题
  • 【操作文档】mysql分区操作步骤.docx
  • 【真正离线安装】Adobe Flash Player 32.0.0.156 插件离线安装包下载(无需联网安装)
  • 一体化数据安全平台uDSP 入选【年度创新安全产品 TOP10】榜单
  • Observability:如何在 Kubernetes pod 中轻松添加应用程序监控
  • k8s 架构详解
  • 虚拟列表遇上瀑布流布局
  • 基于Springboot开发的云野旅游平台
  • 机器学习与深度学习-2-Softmax回归从零开始实现
  • 模型 布鲁姆法则
  • 如何用一块香橙派Zero3打造你的HomeAssistant智能家居中心并实现远程管理
  • 华为机试HJ77 火车进站
  • 【docker】多阶段构建与基础构建,及企业案例展示
  • Vue 3 中实现页面特定功能控制
  • Ubuntu双系统20.04平稳升级至22.04
  • 代数拓扑学
  • 【热门主题】000073 探索云原生后端:开启高效应用开发新时代
  • 系统架构:MVVM
  • YOLOv8-ultralytics-8.2.103部分代码阅读笔记-files.py
  • LSTM神经网络时间序列
  • 使用Docker在Ubuntu 22.04上部署MySQL数据库的完整指南
  • 如何在 VPS 上设置 Apache 并使用免费签名的 SSL 证书
  • Uniapp 使用自定义字体
  • Linux下如何安装JDK