笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:《手把手教你架构3D游戏引擎》电子工业出版社和《Unity3D实战核心技术详解》电子工业出版社等。

射线检测在游戏中使用的非常广泛,我们利用射线开发时,开发者只是调用引擎的接口即可实现,但是我们要了解其内部实现原理,这样我们也可以自己封装射线检测算法,射线检测算法利用程度非常高,不论是使用鼠标还是触摸屏,都需要用到射线检测,比如在虚拟仿真中,导弹追踪物体时,它需要通过从导弹上发出的射线一直朝向物体,角色寻路也可以通过在身体发出的射线检测与物体自身的碰撞盒接触后,用于查看物体是否发生了碰撞。射线检测还用于对物体身上的材质处理,比如墙体的遮挡关系,使用摄像机发出的射线方向指向角色,如果它们之间的射线检测到物体比如墙体,可以编写逻辑改变角色的材质进行透明处理,效果如下图所示:

当然我们也可以使用对墙体进行透明设置,这也是一种处理方式,是将墙体进行透明设置效果如下图所示:

其在程序中表现的效果如下所示:

从相机发出两条射线,射线与墙体的碰撞体发生接触,程序会改变墙体的Shader,替换其材质,让其透明。以下是Unity3D引擎使用案例,核心代码如下所示:

 if (Physics.Linecast(pos, transform.position, out hit)){last_obj = hit.collider.gameObject;int length = last_obj.transform.childCount;string name_tag = last_obj.tag;if (name_tag == "wall"){Material mat = new Material(Shader.Find("Transparent/Diffuse"));curr_obj = last_obj;for (int i = 0; i < length; i++){Transform child = last_obj.transform.GetChild(i);child.GetComponent<Renderer>().material = mat;mat.mainTexture = (Texture)Resources.Load("Atlas/test_pub_tm");}}
}

射线也可以用于物体的拾取操作,拾取物体时从触摸点发出一条射线与要拾取的物体的包围盒发生碰撞,表示物体被拾取到。

下面给开发者介绍一下,射线碰撞的原理,把一个物体放到场景中做了一个局部坐标到世界坐标变换,效果如下图所示:

将物体投影后,假设红的表示X轴,绿的表示Y轴,中间表示物体的碰撞盒,一条射线穿过后效果如下所示:

射线穿过我们要计算其是否与碰撞盒发生碰撞,主要是通过射线与碰撞盒相交值的大小进行判断,效果如下图所示:

射线与碰撞体发生碰撞后的判定效果图如下所示:

根据以上的判断我们可以写下代码,对于3D物体,我们要分别判断X,Y,Z三个轴。核心代码如下所示:

bool TestRayOBBIntersection(glm::vec3 ray_origin,        // Ray origin, in world spaceglm::vec3 ray_direction,     // Ray direction (NOT target position!), in world space. Must be normalize()'d.glm::vec3 aabb_min,          // Minimum X,Y,Z coords of the mesh when not transformed at all.glm::vec3 aabb_max,          // Maximum X,Y,Z coords. Often aabb_min*-1 if your mesh is centered, but it's not always the case.glm::mat4 ModelMatrix,       // Transformation applied to the mesh (which will thus be also applied to its bounding box)float& intersection_distance // Output : distance between ray_origin and the intersection with the OBB
){// Intersection method from Real-Time Rendering and Essential Mathematics for Gamesfloat tMin = 0.0f;float tMax = 100000.0f;glm::vec3 OBBposition_worldspace(ModelMatrix[3].x, ModelMatrix[3].y, ModelMatrix[3].z);glm::vec3 delta = OBBposition_worldspace - ray_origin;// Test intersection with the 2 planes perpendicular to the OBB's X axis{glm::vec3 xaxis(ModelMatrix[0].x, ModelMatrix[0].y, ModelMatrix[0].z);float e = glm::dot(xaxis, delta);float f = glm::dot(ray_direction, xaxis);if ( fabs(f) > 0.001f ){ // Standard casefloat t1 = (e+aabb_min.x)/f; // Intersection with the "left" planefloat t2 = (e+aabb_max.x)/f; // Intersection with the "right" plane// t1 and t2 now contain distances betwen ray origin and ray-plane intersections// We want t1 to represent the nearest intersection, // so if it's not the case, invert t1 and t2if (t1>t2){float w=t1;t1=t2;t2=w; // swap t1 and t2}// tMax is the nearest "far" intersection (amongst the X,Y and Z planes pairs)if ( t2 < tMax )tMax = t2;// tMin is the farthest "near" intersection (amongst the X,Y and Z planes pairs)if ( t1 > tMin )tMin = t1;// And here's the trick :// If "far" is closer than "near", then there is NO intersection.// See the images in the tutorials for the visual explanation.if (tMax < tMin )return false;}else{ // Rare case : the ray is almost parallel to the planes, so they don't have any "intersection"if(-e+aabb_min.x > 0.0f || -e+aabb_max.x < 0.0f)return false;}}// Test intersection with the 2 planes perpendicular to the OBB's Y axis// Exactly the same thing than above.{glm::vec3 yaxis(ModelMatrix[1].x, ModelMatrix[1].y, ModelMatrix[1].z);float e = glm::dot(yaxis, delta);float f = glm::dot(ray_direction, yaxis);if ( fabs(f) > 0.001f ){float t1 = (e+aabb_min.y)/f;float t2 = (e+aabb_max.y)/f;if (t1>t2){float w=t1;t1=t2;t2=w;}if ( t2 < tMax )tMax = t2;if ( t1 > tMin )tMin = t1;if (tMin > tMax)return false;}else{if(-e+aabb_min.y > 0.0f || -e+aabb_max.y < 0.0f)return false;}}// Test intersection with the 2 planes perpendicular to the OBB's Z axis// Exactly the same thing than above.{glm::vec3 zaxis(ModelMatrix[2].x, ModelMatrix[2].y, ModelMatrix[2].z);float e = glm::dot(zaxis, delta);float f = glm::dot(ray_direction, zaxis);if ( fabs(f) > 0.001f ){float t1 = (e+aabb_min.z)/f;float t2 = (e+aabb_max.z)/f;if (t1>t2){float w=t1;t1=t2;t2=w;}if ( t2 < tMax )tMax = t2;if ( t1 > tMin )tMin = t1;if (tMin > tMax)return false;}else{if(-e+aabb_min.z > 0.0f || -e+aabb_max.z < 0.0f)return false;}}intersection_distance = tMin;return true;}

射线与碰撞盒的判定就结束了,虽然市面上的各个引擎都提供了接口,我们可以直接使用,但是如果我们能明白其原理,更有助于我们理解射线碰撞算法。

射线检测算法在游戏中应用相关推荐

  1. 排序算法在游戏中的应用,你确定你了解吗?(详细的图解带你实战)

    排序算法在游戏中的应用,你确定你了解吗?(详细的图解带你实战) 目录 排序算法在游戏中的应用,你确定你了解吗?(详细的图解带你实战) 1. 归并排序 1.1 作为一种典型的分而治之思想的算法应用,归并 ...

  2. java 寻路算法_游戏中的寻路算法解析

    游戏角色的自动寻路,已经是游戏中一个历史比较悠久的领域,较为成熟也有很多种实现.这里摘录一句后面所提的参考资料中的描述:"业内AI开发者中有一句话:"寻路已不是问题."我 ...

  3. 机器学习算法在游戏中的一些具体应用

    Unite Beijing 2018国家会中心,Unity AI与机器学习副总裁Danny Lange分享了ML-Agents的新进展. 谈到了机器学习在游戏中的一些应用 具体游戏场景中,可以有以下应 ...

  4. bresenham算法模拟游戏中的追踪路线

    游戏AI中我们的怪物需要追击我们的玩家,那么怎么样的追击方法更好呢? 对于一般的3D游戏,基本都是动态改变start到target的朝向,然后对转向做一些平滑的插值或者调整,最后再对这个朝向施加相应的 ...

  5. 利用 Yolo V3 算法对游戏进行目标检测(DNF 为例)

    本 Chat 分享了 Python 及深度学习过程中的一个实战案例,详细讲述了利用目标检测算法识别游戏关键信息的实现过程. 本 Chat 不重复算法原理讲解,主要讲述编程思路,具体包括: 基于 Lab ...

  6. 小程序[渲染层网络层错误] failed to load image_游戏中水的渲染技术

    水的渲染一直是图形学需要解决的问题,本篇博客主要介绍用傅里叶变换算法实现的水反射,也是一种假反射效果,目的是优化效率.实现的效果如下图所示: 使用傅里叶系数来表示地形高度的假反射效果,在我们开发的游戏 ...

  7. 算法与游戏实战技术-姜雪伟-专题视频课程

    算法与游戏实战技术-5404人已学习 课程介绍         游戏开发者需要具有能解决实际问题的能力也就是算法能力.这需要开发者能将算法与实际项目开发完美的结合起来.算法是支撑项目开发的灵魂,在游戏 ...

  8. 3D射线拾取算法揭秘

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  9. 在线试玩,在体感游戏中打败泰森,这位小哥破解了任天堂「拳无虚发」

    视学算法报道 编辑:张倩.陈萍 加入体感控制,这位小哥破解了原版任天堂的拳击格斗游戏「拳无虚发」. 在经典红白机上玩拳击游戏是很多人的童年回忆,其中就包括任天堂 1987 年发布的拳击格斗游戏--「P ...

最新文章

  1. 一个有趣的算法问题:如何定义一个分数类
  2. SpringBoot 定制化原理
  3. .NET Core 2.1 容器镜像将从 Docker Hub 中删除
  4. 【原创】jpgraph中文乱码问题的解决
  5. mybatis自动生成代码只有insert()和insertSelective()
  6. 日本媒体称东芝敲定收购富士通硬盘业务
  7. stl:string:将str中的oldstr替换为newstr
  8. [转]centos7下yum安装mysql
  9. Servlet教程第7讲笔记
  10. pppoe服务器账号和密码是什么,小米路由器pppoe账号密码是什么你知道吗
  11. 忆典s1Android,忆典S1四核(RK3128)官方固件+安卓4.4.4已Root权限精简固件+刷机教程
  12. vue的props父向子传值
  13. where 引导从句
  14. 积微——荀子《强国篇》,给每个职场人士推荐
  15. CentOS 8 上配置 FTP 服务器详细步骤,附截图
  16. 微信小程序性能,行为收集探针实现
  17. Meth | git 常用命令
  18. 有感于“中国居里夫人”何泽慧院士逝世
  19. STM32看门狗简述
  20. 我和sql有个约会 - sql总结(三)

热门文章

  1. error: expected initializer before ‘’ token
  2. PTA(每日一题)7-75 某校几人
  3. 【渝粤题库】陕西师范大学151214 纳税筹划 作业(专升本)
  4. 浅谈IT行业加班现象
  5. 元宇宙厂商产品布局思路
  6. wordpress设置超级管理员以及修改管理后台用户列表显示(一)
  7. pytorch set seed
  8. [OpenAirInterface实战-4] :OAI支持的4G LTE功能集
  9. windows Folder Size 显示文件夹目录大小
  10. php输入银行卡判断所属银行,PHP实现根据银行卡号判断银行,php银行卡判断银行_PHP教程...