Skip to content
  • 首页
  • 留言
  • 关于

Share the joys of programming and technology

视锥体与AABB和OBB包围盒相交判断

视锥体与AABB和OBB包围盒相交判断

2022年7月27日 liyanliang Comments 0 Comment

1.视锥体与AABB包围盒相交判断

 template <class TYPE>
 class Frustum
 {
 public:
     Frustum(){
     }
     
     Frustum(const Frustum<TYPE>& rhs){
         for(int i=0; i<6; i++)
             planes[i] = rhs.planes[i];
     }
     
     bool ContainsPoint(const Vec3<TYPE>& v){
         
         for (int i = 0; i < 6; i ++ ) {
             
             if (planes[i].DistanceToPoint(v) < 0 ) {
                 
                 return false;
             }
         }
         
         return true;
     }
     
     CullStatus intersects(const Box3<TYPE>& box){
         // https://old.cescg.org/CESCG-2002/DSykoraJJelinek/
         
         CullStatus result = CullStatus::INSIDE;
         
         for (int i = 0; i < 6; i++) {
             
             const auto& plane = planes[i];
             
             Vec3<TYPE> p = box.vMin;
             if (plane.nx >= 0) p.x = box.vMax.x;
             if (plane.ny >= 0) p.y = box.vMax.y;
             if (plane.nz >= 0) p.z = box.vMax.z;
             
             Vec3<TYPE> n = box.vMax;
             if (plane.nx >= 0) n.x = box.vMin.x;
             if (plane.ny >= 0) n.y = box.vMin.y;
             if (plane.nz >= 0) n.z = box.vMin.z;
             
             TYPE nt = (plane.nx * p.x) + (plane.ny * p.y) + (plane.nz * p.z);
             if (nt < -plane.d)
             {
                 return CullStatus::OUTSIDE;
             }
             
             TYPE mt = (plane.nx * n.x) + (plane.ny * n.y) + (plane.nz * n.z);
             if (mt < -plane.d)
             {
                 result = CullStatus::INTERSECT;
             }
         }
         
         if(result == CullStatus::INTERSECT)
         {
             for (int axis = 0; axis < 3; axis++)
             {
                 TYPE projectedPoint = corners[0].m[axis] - box.vMin.m[axis];
                 TYPE projMin = projectedPoint;
                 TYPE projMax = projectedPoint;
                 
                 for (int p = 1; p < 8; p++) {
                     projectedPoint = corners[p].m[axis] - box.vMin.m[axis];
                     
                     projMin = Math::Min(projMin, projectedPoint);
                     projMax = Math::Max(projMax, projectedPoint);
                 }
                 
                 if (projMax < 0 || projMin > box.vMax.m[axis] - box.vMin.m[axis])
                     return CullStatus::OUTSIDE;
             }
             
         }
         return result;
     }
  
   
 public:
     Plane<TYPE> planes[6];
     Vec3<TYPE>  corners[8];
     
 };
 ​
 template <class TYPE>
 Frustum<TYPE> fromClipMatrix(const Mat4<TYPE>& clip, const Mat4<TYPE>& inv_clip)
 {
     Frustum<TYPE>  frustum;
   
     frustum.corners[0] = inv_clip.TransformCoord({-1, +1, -1});    // left top near
     frustum.corners[1] = inv_clip.TransformCoord({+1, +1, -1});    // right top near
     frustum.corners[2] = inv_clip.TransformCoord({+1, -1, -1});    // right bottom near
     frustum.corners[3] = inv_clip.TransformCoord({-1, -1, -1});    // left bottom near
     frustum.corners[4] = inv_clip.TransformCoord({-1, +1, +1});    // left top far
     frustum.corners[5] = inv_clip.TransformCoord({+1, +1, +1});    // right top far
     frustum.corners[6] = inv_clip.TransformCoord({+1, -1, +1});    // right bottom far
     frustum.corners[7] = inv_clip.TransformCoord({-1, -1, +1});    // left bottom far
 ​
      
     TYPE me0  = clip.m[0],  me1 =  clip.m[1],  me2  = clip.m[2],  me3  = clip.m[3];
     TYPE me4  = clip.m[4],  me5 =  clip.m[5],  me6  = clip.m[6],  me7  = clip.m[7];
     TYPE me8  = clip.m[8],  me9 =  clip.m[9],  me10 = clip.m[10], me11 = clip.m[11];
     TYPE me12 = clip.m[12], me13 = clip.m[13], me14 = clip.m[14], me15 = clip.m[15];
     
     frustum.planes[0].Set(me3 + me2, me7 + me6, me11 + me10, me15 + me14);   // near
     frustum.planes[1].Set(me3 - me2, me7 - me6, me11 - me10, me15 - me14);   // far
     frustum.planes[2].Set(me3 + me0, me7 + me4, me11 + me8,  me15 + me12);   // left
     frustum.planes[3].Set(me3 - me0, me7 - me4, me11 - me8,  me15 - me12);   // right
     frustum.planes[4].Set(me3 + me1, me7 + me5, me11 + me9,  me15 + me13);   // bottom
     frustum.planes[5].Set(me3 - me1, me7 - me5, me11 - me9,  me15 - me13);   // top
       
     for(int i=0; i<6; i++)
     {
         frustum.planes[i].Normalize();
     }
     
     return  frustum;
 }

2.视锥体与AABB包围盒相交判断

一般的做法是做保守的剔除,检测OBB是否都在视锥的六个平面之外。

遍历视椎体的6个面判断是否相交:

 CullingResult
 OrientedBoundingBox::intersectPlane(const Plane& plane) const noexcept {
   const glm::dvec3 normal = plane.getNormal();
 ​
   const glm::dmat3& halfAxes = this->getHalfAxes();
   const glm::dvec3& xAxisDirectionAndHalfLength = halfAxes[0];
   const glm::dvec3& yAxisDirectionAndHalfLength = halfAxes[1];
   const glm::dvec3& zAxisDirectionAndHalfLength = halfAxes[2];
 ​
   // plane is used as if it is its normal; the first three components are
   // assumed to be normalized
   const double radEffective = glm::abs(
                                   normal.x * xAxisDirectionAndHalfLength.x +
                                   normal.y * xAxisDirectionAndHalfLength.y +
                                   normal.z * xAxisDirectionAndHalfLength.z) +
                               glm::abs(
                                   normal.x * yAxisDirectionAndHalfLength.x +
                                   normal.y * yAxisDirectionAndHalfLength.y +
                                   normal.z * yAxisDirectionAndHalfLength.z) +
                               glm::abs(
                                   normal.x * zAxisDirectionAndHalfLength.x +
                                   normal.y * zAxisDirectionAndHalfLength.y +
                                   normal.z * zAxisDirectionAndHalfLength.z);
 ​
   const double distanceToPlane =
       ::glm::dot(normal, this->getCenter()) + plane.getDistance();
 ​
   if (distanceToPlane <= -radEffective) {
     // The entire box is on the negative side of the plane normal
     return CullingResult::Outside;
   }
   if (distanceToPlane >= radEffective) {
     // The entire box is on the positive side of the plane normal
     return CullingResult::Inside;
   }
   return CullingResult::Intersecting;
 }

Renference:

视锥体剔除AABB和OBB包围盒的优化方法

高效视锥体剔除

相关文章

  • OpenGL实现多光源-附项目源码OpenGL实现多光源-附项目源码
  • C++实现一个简单的语言解释器C++实现一个简单的语言解释器
  • 创建模态对话框绘制直线-ObjectARX开发视频创建模态对话框绘制直线-ObjectARX开发视频
  • 截面特性计算程序-附源码截面特性计算程序-附源码
  • 在mapbox中实现3dtiles的加载和绘制(移动端)在mapbox中实现3dtiles的加载和绘制(移动端)
  • LoadLibrary和GetProcAddress获取另一个项目中的函数LoadLibrary和GetProcAddress获取另一个项目中的函数

OpenGL

Post navigation

PREVIOUS
倾斜摄影在mapbox中的坐标转换
NEXT
在mapbox中实现3dtiles的加载和绘制(移动端)

发表回复 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

近期文章

  • IBL计算总结
  • Filament加载并渲染glTF模型
  • 在mapbox中实现3dtiles的加载和绘制(移动端)
  • 视锥体与AABB和OBB包围盒相交判断
  • 倾斜摄影在mapbox中的坐标转换
  • 解析3dTiles数据和提取b3dm模型文件
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (1,503)
  • Modern OpenGL绘制圆柱体 (703)
  • 提取最小封闭区域 (634)
  • 判断一个点是否在闭合区域内 (536)
  • 截面特性计算程序-附源码 (524)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (487)
  • OpenGL绘制旋转立方体 (435)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (411)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (375)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (350)
  • 解析3dTiles数据和提取b3dm模型文件 (345)
  • 土木想往土木软件开发方向发展,应该如何准备 (330)
  • #pragma message 编译时提示信息 (322)
  • midas XD2020的开发 (317)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (308)
  • 两跨连续梁影响线绘制-附源码 (300)
  • Midas W-满堂支架快速建模助手开发 (290)
  • 算法:寻找异常数字 (249)
  • OpenGL几何着色器实现贝塞尔曲线 (174)
  • 通过Spy++抓取窗口以查询对话框id (173)

分类

  • C# (3)
  • C++ (17)
  • Filament (1)
  • GIS (3)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (12)
  • Revit开发 (1)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2022年10月 (3)
  • 2022年7月 (2)
  • 2022年4月 (1)
  • 2022年3月 (1)
  • 2022年2月 (1)
  • 2022年1月 (5)
  • 2021年11月 (7)
  • 2021年6月 (3)
  • 2021年5月 (2)
  • 2021年3月 (2)
  • 2021年2月 (8)
  • 2021年1月 (18)

标签

3dtiles b3dm Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX filament fog GIS glTF json mapbox MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

  • 李燕良的CSDN
  • 崔济东的博客
  • C++爱好者博客
  • 陈学伟的博客
  • 贾苏的博客
  • 陈睦锋的博客
  • 孙勇的博客

统计

  • 0
  • 21
  • 6
  • 57
  • 23
  • 69,967
  • 21,748

实时访问地域

© 2023   liyanliang.net Copyright. All Rights Reserved.