当前位置:网站首页>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);
}
}
边栏推荐
猜你喜欢
null == undefined
Unity3d click events added to 3D objects in the scene
爬虫(17) - 面试(2) | 爬虫面试题库
Binary search tree (features)
Prediction - Grey Prediction
Spark Tuning (III): persistence reduces secondary queries
模仿企业微信会议室选择
spark调优(三):持久化减少二次查询
Imitate the choice of enterprise wechat conference room
1亿单身男女“在线相亲”,撑起130亿IPO
随机推荐
运算符
Personal notes of graphics (3)
JS modularization
Unity3d click events added to 3D objects in the scene
【DesignMode】享元模式(Flyweight Pattern)
os、sys、random标准库主要功能
偶然升职的内心独白
laravel怎么获取到public路径
[hcsd celebrity live broadcast] teach the interview tips of big companies in person - brief notes
谎牛计数(春季每日一题 53)
Cesium(3):ThirdParty/zip. js
47_ Contour lookup in opencv cv:: findcontours()
[designmode] flyweight pattern
修改配置文件后tidb无法启动
How does laravel run composer dump autoload without emptying the classmap mapping relationship?
Have fun | latest progress of "spacecraft program" activities
【Android -- 数据存储】使用 SQLite 存储数据
记一次项目的迁移过程
【医学分割】attention-unet
删除 console 语句引发的惨案