当前位置:网站首页>Ray and OBB intersection detection
Ray and OBB intersection detection
2022-07-07 16:41:00 【[struggling]】
In the last article Radiation and AABB Intersection detection
Radiation and OBB3D The principle of intersection detection is similar to that of ray and AABB The principle of intersection detection is the same , This article will not explain the principle
The previous article infers : The distance between the intersection point of the ray and the plane and the starting point of the ray t The distance formula of is t = (d - Dot(p, n)) / Dot(rayDir, n)
OBB3D And AABB Differences in attributes
AABB The three axis vectors are fixed : (1, 0, 0), (0, 1, 0), (0, 0, 1)
OBB3D The three axis vectors vary with rotation
AABB The expression of can be used min, max Coordinate point representation
OBB3D There is no min, max Coordinates
therefore AABB Coordinate points and fixed axes used in calculation logic , Need to be replaced with OBB3D Properties of ,
Use axially _axisX,_axisY, _axisZ
take OBB3D Two vertices , Each vertex is the intersection of three faces, or vertex
_vertexs[0] = center + (axisX * size.x + axisY * size.y + axisZ * size.z) * 0.5f;
_vertexs[5] = center + (-axisX * size.x - axisY * size.y - axisZ * size.z) * 0.5f;
The logic code is as follows
public class OBB3D
{
/// <summary>
/// X Axis direction vector
/// </summary>
public Vector3 _axisX;
/// <summary>
/// Y Axis direction vector
/// </summary>
public Vector3 _axisY;
/// <summary>
/// Z Axis direction vector
/// </summary>
public Vector3 _axisZ;
/// <summary>
/// Center point coordinates
/// </summary>
public Vector3 _center;
/// <summary>
/// Length of three sides
/// </summary>
public Vector3 _size;
/// <summary>
/// Eight vertex coordinates
/// </summary>
public Vector3[] _vertexs;
public OBB3D(){
}
public void Set(Vector3 axisX, Vector3 axisY, Vector3 axisZ, Vector3 center, Vector3 size)
{
_axisX = axisX;
_axisY = axisY;
_axisZ = axisZ;
_center = center;
_size = size;
_vertexs = new Vector3[8];
_vertexs[0] = center + (axisX * size.x + axisY * size.y + axisZ * size.z) * 0.5f;
_vertexs[1] = center + (axisX * size.x - axisY * size.y + axisZ * size.z) * 0.5f;
_vertexs[2] = center + (axisX * size.x + axisY * size.y - axisZ * size.z) * 0.5f;
_vertexs[3] = center + (axisX * size.x - axisY * size.y - axisZ * size.z) * 0.5f;
_vertexs[4] = center + (-axisX * size.x + axisY * size.y - axisZ * size.z) * 0.5f;
_vertexs[5] = center + (-axisX * size.x - axisY * size.y - axisZ * size.z) * 0.5f;
_vertexs[6] = center + (-axisX * size.x - axisY * size.y + axisZ * size.z) * 0.5f;
_vertexs[7] = center + (-axisX * size.x + axisY * size.y + axisZ * size.z) * 0.5f;
}
}
/// <summary>
/// Radiation and AABB Intersection detection
/// The following method is Radiation and 3D AABB Calculation of intersection
/// If you want to calculate Radiation and 2D AABB The intersection , The following is about z Delete part of the coordinates
/// </summary>
public class RayOBBCollision
{
/// <summary>
/// Judge the ray and AABB Whether it intersects
/// </summary>
/// <param name="raySource"> Ray starting point </param>
/// <param name="rayDir"> The direction of the ray </param>
/// <param name="aabb">AABB</param>
/// <param name="point"> Radiation and AABB Intersection coordinates </param>
/// <returns></returns>
public bool IsCollision(Vector3 raySource, Vector3 rayDir, OBB3D obb3D, ref Vector3 point)
{
float length = 0;
bool collision = IsCollision(raySource, rayDir, obb3D, ref length);
point = raySource + rayDir * length;
return collision;
}
/// <summary>
/// Judge the ray and AABB Whether it intersects
/// </summary>
/// <param name="raySource"> Ray starting point </param>
/// <param name="rayDir"> Ray direction vector </param>
/// <param name="obb3D">OBB3D</param>
/// <param name="length"> Distance from ray starting point to intersection point </param>
/// <returns></returns>
public bool IsCollision(Vector3 raySource, Vector3 rayDir, OBB3D obb3D, ref float length)
{
float t1 = 0;
float t2 = 0;
bool collision = Calculate(raySource, rayDir, obb3D, obb3D._axisX, ref t1, ref t2);
if (!collision || !CheckValue(ref t1, ref t2))
{
return false;
}
float t3 = 0;
float t4 = 0;
collision = Calculate(raySource, rayDir, obb3D, obb3D._axisY, ref t3, ref t4);
if (!collision || !CheckValue(ref t3, ref t4))
{
return false;
}
float t5 = 0;
float t6 = 0;
collision = Calculate(raySource, rayDir, obb3D, obb3D._axisZ, ref t5, ref t6);
if (!collision || !CheckValue(ref t5, ref t6))
{
return false;
}
float entryT1 = Math.Max(Math.Max(t1, t3), t5);
float entryT2 = Math.Min(Math.Min(t2, t4), t6);
length = entryT1;
return (entryT1 < entryT2);
}
/// <summary>
/// Calculation of intersection of ray and plane
/// </summary>
/// <param name="raySource"> Ray starting point </param>
/// <param name="rayDir"> Ray direction vector </param>
/// <param name="obb3D">aabb</param>
/// <param name="normal"> Plane normal vector </param>
/// t = (d - Dot(raySource, normal)) / Dot(rayDir, normal)
/// d = Dot(planePoint, normal)
/// t = (Dot(planePoint, normal) - Dot(raySource, normal)) / Dot(rayDir, normal)
/// t = Dot((planePoint - raySource), normal) / Dot(rayDir, normal)
private bool Calculate(Vector3 raySource, Vector3 rayDir, OBB3D obb3D, Vector3 normal, ref float t1, ref float t2)
{
float p_sub_r_dot_n1 = Vector3.Dot(obb3D._vertexs[0] - raySource, normal);
float p_sub_r_dot_n2 = Vector3.Dot(obb3D._vertexs[5] - raySource, normal);
float r_dot_n = Vector3.Dot(rayDir, normal);
if (Math.Abs(r_dot_n) <= float.Epsilon) // The ray is perpendicular to the plane normal vector , So the ray is parallel to the plane
{
float dot1 = Vector3.Dot(obb3D._vertexs[0] - raySource, normal);
float dot2 = Vector3.Dot(obb3D._vertexs[5] - raySource, normal);
if (dot1 * dot2 > 0)
{
return false;
}
}
t1 = p_sub_r_dot_n1 / r_dot_n;
t2 = p_sub_r_dot_n2 / r_dot_n;
return true;
}
private bool CheckValue(ref float value1, ref float value2)
{
if (value1 < 0 && value2 < 0)
{
return false;
}
value1 = Mathf.Clamp(value1, 0, value1);
value2 = Mathf.Clamp(value2, 0, value2);
if (value1 > value2)
{
float temp = value1;
value1 = value2;
value2 = temp;
}
return true;
}
}
The test code is as follows
using System;
using UnityEngine;
public class RayOBBController : MonoBehaviour
{
// Cube Cube A
public Transform cube;
// Define two OBB3D Cube
private OBB3D obb3D;
// Intersection detection logic
private RayOBBCollision rayOBBCollision;
void Start()
{
// Instantiation
obb3D = new OBB3D();
rayOBBCollision = new RayOBBCollision();
}
private bool result = false;
// Create a small ball , When ray and AABB When we meet , Set the intersection coordinates to the ball
private GameObject go;
void Update()
{
// Put two Cube The data of are assigned to OBB3D
SetOBB(cube, obb3D);
Vector3 point = Vector3.zero;
// Judge whether it intersects
bool isCollision = rayOBBCollision.IsCollision(transform.position, transform.forward, obb3D, ref point);
if (result != isCollision)
{
result = isCollision;
// If the assumption is similar to AABB The intersection , take AABB The object is set to red
cube.GetComponent<Renderer>().material.color = result ? Color.red : Color.gray;
}
if (result)
{
// If the ray and AABB The intersection , Set the spherical coordinates to the intersection point
if (!go)
{
go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.transform.localScale = Vector3.one * 0.2f;
}
go.transform.position = point;
}
}
private void SetOBB(Transform tr, OBB3D obb)
{
// OBB3D The three axes of are used separately Cube.transform:right、up、forward
// OBB3D Use the coordinates of Cube.transform.position
// OBB3D Of size Use Cube.transform.localScale
obb.Set(tr.right, tr.up, tr.forward, tr.position, tr.localScale);
}
}
边栏推荐
- Asyncio concept and usage
- 模仿企业微信会议室选择
- [hcsd celebrity live broadcast] teach the interview tips of big companies in person - brief notes
- Tragedy caused by deleting the console statement
- MySQL中, 如何查询某一天, 某一月, 某一年的数据
- Three. JS series (3): porting shaders in shadertoy
- PHP中exit,exit(0),exit(1),exit(‘0’),exit(‘1’),die,return的区别
- 爬虫(17) - 面试(2) | 爬虫面试题库
- [Android -- data storage] use SQLite to store data
- 【DesignMode】享元模式(Flyweight Pattern)
猜你喜欢
华东师大团队提出,具有DNA调控电路的卷积神经网络的系统分子实现
Vs tool word highlight with margin
Xcode Revoke certificate
Imitate the choice of enterprise wechat conference room
低代码(lowcode)帮助运输公司增强供应链管理的4种方式
Binary search tree (basic operation)
二叉搜索树(基操篇)
AutoLISP series (3): function function 3
Lecturer solicitation order | Apache seatunnel (cultivating) meetup sharing guests are in hot Recruitment!
Statistical learning method -- perceptron
随机推荐
Three. JS series (3): porting shaders in shadertoy
Three. JS series (1): API structure diagram-1
二叉搜索树(特性篇)
Imitate the choice of enterprise wechat conference room
Lecturer solicitation order | Apache seatunnel (cultivating) meetup sharing guests are in hot Recruitment!
ByteDance Android gold, silver and four analysis, Android interview question app
[Android -- data storage] use SQLite to store data
AutoLISP series (2): function function 2
Binary search tree (basic operation)
Personal notes of graphics (3)
Vs2019 configuration matrix library eigen
Deep listening array deep listening watch
The difference and working principle between compiler and interpreter
【C 语言】 题集 of Ⅹ
Usage of config in laravel
【Android -- 数据存储】使用 SQLite 存储数据
掌握这个提升路径,面试资料分享
Prediction - Grey Prediction
应用在温度检测仪中的温度传感芯片
Power of leetcode-231-2