3D模型下的鼠标拣选和碰撞检测-射线与圆的相交算法

3D射线拾取算法揭秘 笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,优快云社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。         射线在现实生活中使用的非常广泛,现实生活中经常使用各种射线检测金属表面的瑕疵。游戏开发或者说虚拟实现开发中也经常使用射线拾取,比如游戏中拾取掉落物品,点击某个建筑物 阅读详情

在实际应用中,常常使用包围球或者包围盒代替物体与拾取射线进行相交测试,假设拾取射线与包围盒或者包围球相交,就认为拾取射线与物体相交了,其实,在3d世界中有很多的计算都是不精确的,只是简单的模拟,近似的操作。因为确实也不需要必须要完全精确。

 

以包围球为例子,包围球可以用球心o与半径r来表示,假设点p在包围球上,即满足条件:

||p-o|| = r

即点p到球心o的距离等于球体半径r,

射线方程为:

p(t)=po+tu

po表示射线的起点,u表示射线的方向,t表示一个标量。因此,可以用这两个向量来定义射线的结构体,

定义如下结构:

struct ray

{

    D3DXVECTOR3 _origin;//射线起点

    D3DXVECTOR3 _derction;//射线方向   

};

假设射线与球体相交,必然存在一个点pt既在射线上又在球面上,将射线方程带入球面方程即可得到:

||pt-o|| = r  //pt在圆面上 那么pt到圆心o的距离等于r

 

||po+tu||-r=o//如果p(t)=po+tu在圆面上,那么满足||po+tu||=r  用这个方程求到的射线上的点pt满足在圆上

显然,要满足这个条件,就是求解方程中t的值,把公式进行转换:

(po+tu-o)2=r2

 

 

 

将最后的公司转化为一元二次方程:

A=u2

B=2u(p0-0)

C=(po-o)2-r2

At2+Bt+c=0

由于射线的方向u是单位向量,因此A=1,对上面的方程求解可以得到以下两个答案:

t0 =(-B+(B2-4c)的开平方)/2           

 

 

 

 

 

t1 =(-B-(B2-4c)的开平方)/2  

 

 


void CGame::HandleMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 switch (message)
 {
 case WM_LBUTTONDOWN:
  {
   POINT pt;
   GetCursorPos(&pt);
   ScreenToClient(hWnd, &pt);
   
   Ray ray = CalculateRay(pt.x, pt.y);
   D3DXMATRIX mat;
   m_pDevice->GetTransform(D3DTS_VIEW, &mat);
   D3DXMatrixInverse(&mat, NULL, &mat);
   ray = TransformRay(ray, &mat);

   for(int i=0; i<2; ++i)
   {
    if( CheckIntersection(&ray, &m_boundSphere[i]) )
     m_bRotate[i] = true;
    else
     m_bRotate[i] = false;
   }
  
  }
  break;
 }
}

CGame::Ray CGame::CalculateRay(int x, int y)
{
 float px=0.0f;
 float py=0.0f;
 //获取视口大小
 D3DVIEWPORT9 vp;
 m_pDevice->GetViewport(&vp);
 //获取投影矩阵
 D3DXMATRIX proj;
 m_pDevice->GetTransform(D3DTS_PROJECTION,&proj);
 
 //计算拾取射线
 px=(((2.0f*x)/vp.Width)-1.0f)/proj._11;
 py=(((-2.0f*y)/vp.Height)+1.0f)/proj._22;
 Ray ray;
 ray._origin = D3DXVECTOR3(0.0f,0.0f,0.0f);
 ray._dirction = D3DXVECTOR3(px,py,1.0f);
 return ray;
}

CGame::Ray CGame::TransformRay(Ray ray, D3DXMATRIX* T)
{
 Ray transRay;
 //转换射线的起点
 D3DXVec3TransformCoord(&transRay._origin,&ray._origin,T);
 //转换射线的方向
 D3DXVec3TransformNormal(&transRay._dirction,&ray._dirction,T);
 D3DXVec3Normalize(&transRay._dirction,&transRay._dirction);
 return transRay;
}

BOOL CGame::CheckIntersection(Ray* ray, BoundSphere* sphere)
{
 //计算t0与t1的值
 D3DXVECTOR3 v = ray->_origin-sphere->_center;
 float b = 2.0f*D3DXVec3Dot(&ray->_dirction,&v);
 float c = D3DXVec3Dot(&v,&v)-(sphere->radius*sphere->radius);

 float n = (b*b)-(4.0f*c);
 if (n<0.0f)
 {
  return false;
 }
 n = sqrtf(n);
 float t0 = (-b+n)/2.0f;
 float t1 = (-b-n)/2.0f;
 //判断是否相交
 if (t0>=0||t1>=0)
 {
  return true;
 }
 return false;
}

【信息科学与工程学】计算机科学与自动化——第八十六篇 各类应用上云计算 01 数字孪生:核心是实时性不等式(Δ<Δt)与带宽-精度权衡。数学上归结为带约束的非线性优化。预测性维护:从物理退化方程(Paris 定律)出发,结合贝叶斯推断,云端训练用深度时序模型,边缘推理用轻量模型。机器人协同:本质是多商品流 + 动态障碍物,需用图论(冲突检测)+ 最优控制(轨迹平滑)。工业视觉:延迟由四个环节组成,需用排队论分析流水线瓶颈,量化感知是降低延迟的关键。液压/气动系统上云(涉及流体力学、热力学、控制)机械臂力控/阻抗控制上云(涉及动力学、力/位混合控制) 阅读详情

相关推荐

ray-sphere-intersection:测试射线是否与球体相交

射线球相交 测试射线是否与球体相交。 var intersect = require ( 'ray-sphere-intersection' ) var origin = [ 0 , 0 , 4 ] , direction = [ 0 , 0 , - 1 ] , center = [ 0 , 0 , 0 ] , radius = 1 var hit = intersect ( [ ] , origin , direction , center , radius ) if ( hit ) { console . log ( hit ) // [0, 0, 1] } 改编自 。 PR的优化/等欢迎。 用法 out = intersect(out, origin, direction, center, radius) 确定3D射线(origin, dir

《3D 数学基础》几何检测-相交性检测

以c_m为原点,d为移动的方向向量,t为自变量的射线p(t) = c_m + td。因为移动是相对的,所以可以将左边的球设置为静止的,右边的移动方向就变成d,如下。如果两个都在运动,则换成一个静止,一个做相对运动(如上面的两个圆或者球是否相交)两个球在分别移动d1和d2的过程中是否会相交的,如下,d1和d2是移动向量。静止相交性检测是简单的,需要在每个维度上单独检测他们的相交性即可。其实是求t,知道相交点的t值,利用射线公式就知道相交点坐标。球心运动t时,会与平面相交。交点p,以向量表示(x,y,z)。

一千零一夜的博客 1584

CCC数字钥匙3.0标准解读(22)

介绍设备制造商服务器和车辆制造商服务器之间的通信协议.

weixin_41738640的博客 1748

射线与圆、球相交检测

射线与圆、球相交检测 本篇讨论2D中射线和圆的相交检测,本方法同样适用于3D中射线和球的相交检测,这是因为可以在包含射线和球心的平面中进行检测,从而将3D问题转化为2D问题。如果射线穿过球心,那么平面不是唯一的,但是不影响问题的解。 下面直接降阶为 2D讨论射线与圆的相交检测。 射线与圆的三种关系:相交、相切、相离 其中相切是相交的特殊情况 看下图, 如何判断射线与圆是否相交? 如果相交,如何计算交点坐标? 下图中是射线与圆相交的一般情形。交点为E,其实相交时交点是两个,行切时交点是一个,我们只讨论第一个

lq 2651

本地部署大模型 vs 网页版大模型区别

fill:#333;color:#333;color:#333;fill:none;本地服务器/工作站硬件资源私有化部署GPU集群高速存储模型文件训练框架推理引擎。

Ds-Rag的博 1712

从收音机到Arduino:手把手教你用BJT三极管搭建一个简易音频放大器(附电路图与元件清单)

本文详细介绍了如何使用BJT三极管搭建简易音频放大器,涵盖电路原理、元件选择、设计步骤及调试技巧。通过实践项目帮助电子爱好者深入理解BJT的放大特性,并提供与Arduino结合的扩展应用方案,适合创客和DIY玩家。

aitie1479的博客 439

使用OpenGL实现三维坐标的鼠标拣选

一、简介(Introduction)        OpenGL是一种比较“纯粹”的3D图形API,一般仅用于三维图形的渲染,对于特定领域的开发者(如游戏开发者)而言,如果选择使用 OpenGL进行开发,类似碰撞检测的机制就都需要自行编写了。但是由于鼠标在图形程序中的应用非常非常之广泛(例如现在已经很少有PC游戏能完全地脱离鼠标),OpenGL在图形库的基础上添加了选择与反馈机制(Sele

Y___Y的专栏 7150

XC95144XL-10TQG144I Xilinx XC9500XL 高性能 CPLD

XC95144XL-10TQG144I 属于 Xilinx 的 XC9500XL 高性能 CPLD 家族,是一颗面向 3.3V 低电压系统的可编程逻辑器件。该器件以小封装、高速响应和良好的系统兼容性为设计目标,常用作系统控制/ glue-logic、I/O 缓冲、状态机、总线桥接与接口协议前端等场景中的可重编程逻辑单元。产品支持现场(in-system)编程与 IEEE-1149.1 JTAG 边界扫描,能在系统板上直接更新逻辑。

2403_90082736的博客 1060

计算几何实践2.2:3D窗口的拾取操作

2018-02-25 在三维CAD 软件和3D游戏中,都有目标的拣选操作。通常有两种方式来实现这个功能:一是通过手工计算从屏幕发出的射线与场景内的物体求交,二是使用Vulkan/OpenGL的拾取机制(Selection Mode)。 即使是自己实现三维选择操作,也有多种方式。简单的拾取操作分为两类:点选和框选。点选非常简单,就是求解一条射线和场景内物体的相交。框选则需要按照投影模式分一下:...

know yourself 959

如何运用好DeepSeek为自己服务:智能增强的范式革命 || 目录

1.1 认知增强的三次浪潮1.2 DeepSeek认知增强模型1.3 人机认知耦合协议1.4 认知增强的数学基础。

𝓓𝓸𝓶𝓲𝓷𝓪𝓽𝓲𝓷𝓰 𝓐𝓵𝓵 𝓣𝓱𝓲𝓷𝓰𝓼 1220

SOME/IP协议详解「1.0·概述」

主要讲解什么是someip,

雪云飞星的博客 5367

使用OpenGL实现三维坐标的鼠标拣选(一 )

<br />使用OpenGL实现三维坐标的鼠标拣选<br /> Implementation of RIP(Ray-Intersection-Penetration)<br /> 3D Coordinates Mouse Selection Using OpenGL <br /> 顾 露 (武汉理工大学 计算机系 中科院智能设计与智能制造研究所 湖北武汉 430070)<br /> 摘要(Abstract):<br /> 本文提出并实现一种用于三维坐标拣选的RIP(Ray-Intersection

大美妞苏小菲 3537

SimSwap复现指引及代码分析【2023有更新】

我的环境!!!😚😚😚 之后会遇到:还会遇到至此环境配置完毕!下面是所需要的checkpoint。至此环境准备结束。先试试环境是否有问题,图片是代码包中给的。我用的是512的checkpoint,无水印,a是源脸,b是目标脸。输出到./output/result_whole_swapsingle.jpg 如图是可以成功换脸的:(为了方便查看将图像裁剪到了128x128) 表示图像预处理,相应的改为也是一样。不加就是对已经面部对齐的图像进行简单的面部交换。 加上就是无水印。 交换一张图片中的所有面孔。

zik的博客 2047

Unity3d 鼠标拣选小功能集合

最近在做一些优化工具,把鼠标拣选的功能单独抽出来。 可遍历所有选中的某类型资源,会递归文件夹 可编译所有prefab的某个Component,也是递归的 using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; using System....

weixin_30332705的博客 135

汇川AM系列ethercat控制伺服的使用说明(含转矩模式)

本文以一个实际例子,介绍ethercat伺服驱动器的工作原理,以及在汇川AM系列PLC中,如何点动、定位、速度、转矩控制ethercat伺服。

qq_34047402的博客 5111

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

射线和球相交的判断

本文主要介绍如何判定一条线和一个球面相交,即射线和球碰撞的判定

weixin_40301728的博客 2005

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

【unity3d游戏开发之基础篇】unity3d射线的原理用法以及一个利用射线实现简单拾取的小例子...

最近开始研究U3D,它的强大就不多说了, 今天研究了研究射线相关东西,总结了些东西放上来,一来做个笔记,二来和大家分享分享!嘿嘿~ 如果有不对的地方希望指出哈 !- _ - 进入正题 射线:射线是3D世界中一个点向一个方向发射的一条无终点的线,在发射轨迹中与其他物体发生碰撞时,它将停止发射。 用途:射线应用范围比较广,多用于碰撞检测(如:子弹飞行是否击中目标)、角色移动等...

weixin_30815469的博客 710

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

OpenGL—射线拾取(ray pick)

简介: OpenGL中鼠标射线拾取,就是通过鼠标点击屏幕

virwin的专栏 1万+

项目记录 : 射线与球的相交

射线与球的相交 从图形来说 射线与圆相交.origin 是射线的起点. dir 是射线的方向向量. P0 和 P1 是两个交点. center 是圆心, R 是半径. d 为圆心到射线的距离. 我们先以2D切面图来说明,当射线和圆相交的时候,可以看到,球心 center 到射线 ray 的距离 d &lt;= R,这个即为相交的条件。那么射线与球相切就转化为了球心到射线的距离d的判断。先求出d:...

【黑键】 1744

《Ray Tracing in One Weekend》阅读笔记 - 3、ray类

定义三维空间中的射线方程:P(t)=A+tb,这里的A表示射线的原点,b表示射线的方向,P表示这条射线所在的直线上的位置。t是一个实数(在代码中是double),加上不同的t的值,可以表示直线上的不同位置的点。(下面是书上的图片) (1)类中用orig表示原点A,dir表示方向b,类中拥有的方法是: 初始化函数 获得A,b 获得某一t对应的坐标 (2)射线与场景求交 计算从眼睛到像素的射线 找出相交的物体 计算射线与物体交点处的颜色 作者说,当第一次开发的时候,他总是做一个简单的摄像头来启动和运行

weixin_40773388的博客 441

unity基础开发 1. 射线&碰撞器的原理和用法

一. Unity3d 碰撞器与触发器 1. 要产生碰撞必须为游戏对象添加刚体(Rigidbody)和碰撞器, 刚体可以让物体在物理影响下运动。碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体会彼此相互穿过。物体发生碰撞的必要条件两个物体都必须带有碰撞器(Collider)

Chunix的专栏 6599

碰撞检测算法:点和矩形碰撞、点和圆形碰撞、矩形碰撞、圆形碰撞

点和矩形碰撞 [java] view plaincopyprint? /**       *        * @param x1 点       * @param y1 点       * @param x2 矩形view x       * @param y2 矩形view y       * @param w  矩形view 宽

2万+

OpenGL鼠标拾取的实现:终于搞定(包括细节问题)

void OpenGL::pickRects(){ /* GetCursorPos(&mouse); ScreenToClient(hWnd,&mouse); GLuint pickBuffer [32]; GLint nPicks,vpArray[4]; glRenderMode(GL_SELECT); glSelectBuffer(32,pickBuffer);

daojin505的专栏 2453
上一篇: OSG绘制空间凹多边形并计算其面积
下一篇: Qt5 QOpenGLWidget类
HelloEarth_
博客等级 码龄9年 38粉丝 49原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值