(转)DirectX下 Viewing Frustum 的详细实现

(转)DirectX下 Viewing Frustum 的详细实现

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章
原始出处 、作者信息和本声明。否则将追究法律责任。
http://xiaoxiang.blog.51cto.com/88051/26928
本文大部分内容翻译自Gil Gribb和Klaus Hartmann合写的《Fast Extraction of Viewing Frustum Planes from the World-View-Projection Matrix》这篇文章,有兴趣的朋友可以搜索看下原文,里面DirectX下和OpenGL下的实现过程都说的很清楚,这里只说DirectX部分。
 
这里介绍的算法,可以直接从世界、观察以及投影矩阵中计算出Viewing Frustum的六个面。它快速,准确,并且允许我们在相机空间(camera space)、世界空间(world space)或着物体空间(object space)快速确定Frustum planes。
 
我们先仅仅从投影矩阵(project)开始,也就是假设世界矩阵(world)和观察矩阵(view)都是单位化了的矩阵。这就意味着相机位于世界坐标系下的原点,并且朝向Z轴的正方向。
 
定义一个顶点v(x y z w=1)和一个4*4的投影矩阵M=m(i,j),然后我们使用该矩阵M对顶点v进行转换,转换后的顶点为v’= (x’ y’ z’ w’),可以写成这样:
(转)DirectX下 Viewing Frustum 的详细实现
转换后,viewing frustum实际上就变成了一个与轴平行的盒子,如果顶点 v’ 在这个盒子里,那么转换前的顶点 v 就在转换前的viewing frustum里。在Direct3D下,如果下面的几个不等式都成立的话,那么 v’ 就在这个盒子里。

                                                                    
-w’ < x’ < w’
-w’ < y’ < w’
0 < z’ < w’
 
可得到如下结论,列在下表里:
(转)DirectX下 Viewing Frustum 的详细实现
现在假设,我们要测试x’是否在左半空间内,根据上表,也就是判断
-w’ < x’ 是否成立。用我们开始提到的信息,可将不等式写成如下形式:
-( v * col4 ) < ( v * col1 )
即:
0 < ( v * col4 )  + ( v * col1 )
得到最后形式:
0 < v * ( col1 + col4 )
写到这里,其实已经等于描绘出了转换前的viewing frustum的左裁剪面的平面方程:
x * ( m14 + m11 ) + y * ( m24 + m21 )  + z * ( m34 + m31) + w * ( m44 + m41 ) = 0
当W = 1,我们可简单成如下形式:
x * ( m14 + m11 ) + y * ( m24 + m21 )  + z * ( m34 + m31) +  ( m44 + m41 ) = 0
这就给出了一个基本平面方程:
ax + by + cz + d = 0
其中
a = ( m14 + m11 ) , b = ( m24 + m21 ), c = ( m34 + m31) , d  =  ( m44 + m41 )
 
ok,到这里左裁剪面就得到了。重复以上几步,可推导出到其他的几个裁剪面,具体见下表:
(转)DirectX下 Viewing Frustum 的详细实现
需要注意的是:最终得到的平面方程都是没有单位化的(平面的法向量不是单位向量),并且法向量指向空间的内部。这就是说,如果要判断 v 在空间内部,那么6个面必须都满足ax + by + cz + d > 0
 
到目前为止,我们都是假设世界矩阵( world )和观察矩阵( view )都是单位化了的矩阵。但是,本算法并不想受这种条件的限制,而是希望可以在任何条件下都能使用。实际上,这也并不复杂,并且简单得令人难以置信。如果你仔细想一下就会立刻明白了,所以我们不再对此进行详细解释了,下面给出3个结论:
1. 如果矩阵 M 等于投影矩阵 P ( M = P ),那么算法给出的裁剪面是在相机空间(camera space)
 
2. 如果矩阵 M 等于观察矩阵 V 和投影矩阵 P 的组合( M = V * P ),那么算法给出的裁剪面是在世界空间(world space)
 
3.如果矩阵 M 等于世界矩阵 W,观察矩阵 V 和投影矩阵 P 的组合( M = W* V * P ),呢么算法给出的裁剪面是在物体空间(object space)
 
好,到此为止,理论知识就全部说完了,下面给出具体的实现代码:
===============================
Frustum.h==============================
 
#ifndef __FrustumH__

#define __FrustumH__
 
#include <d3dx9.h>
 
class Frustum

{

public:
     Frustum();

     ~Frustum();
    
// Call this every time the camera moves to update the frustum

     void CalculateFrustum( D3DXMATRIX ViewMatrix, D3DXMATRIX ProjectMatrix );
    
// This takes a 3D point and returns TRUE if it’s inside of the frustum
     bool PointInFrustum( D3DXVECTOR3 Point );
private:

   
  // This holds the A B C and D values for each side of our frustum.

     D3DXPLANE FrustumPlane[6];

};
#endif // __FrustumH
 
=============================Frustum.cpp============================
 
#include “Frustum.h”

#include <D3dx9math.h>

enum FrustumSide { RIGHT, LEFT, BOTTOM, TOP, FRONT, BACK };

Frustum::Frustum()

{

}
Frustum::~Frustum()

{

}
/ CALCULATE FRUSTUM
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
*
/
/ This extracts our frustum from the projection and view matrix.
/
/ CALCULATE FRUSTUM

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
*
void Frustum::CalculateFrustum( D3DXMATRIX ViewMatrix, D3DXMATRIX ProjectMatrix )

{

 D3DXMATRIX ComboMatrix;

 D3DXMatrixMultiply( &ComboMatrix, &ViewMatrix, &ProjectMatrix );
 
//right clipping plane
 FrustumPlane[RIGHT].a = ComboMatrix._14 – ComboMatrix._11;

 FrustumPlane[RIGHT].b = ComboMatrix._24 – ComboMatrix._21;

 FrustumPlane[RIGHT].c = ComboMatrix._34 – ComboMatrix._31;

 FrustumPlane[RIGHT].d = ComboMatrix._44 – ComboMatrix._41;

 


 //normalize

 D3DXPlaneNormalize( &FrustumPlane[RIGHT], &FrustumPlane[RIGHT] );
 
//left clipping plane

 FrustumPlane[LEFT].a = ComboMatrix._14 + ComboMatrix._11;

 FrustumPlane[LEFT].b = ComboMatrix._24 + ComboMatrix._21;

 FrustumPlane[LEFT].c = ComboMatrix._34 + ComboMatrix._31;

 FrustumPlane[LEFT].d = ComboMatrix._44 + ComboMatrix._41;
 
//normalize

 D3DXPlaneNormalize( &FrustumPlane[LEFT], &FrustumPlane[LEFT] );
 
//bottom clipping plane

 FrustumPlane[BOTTOM].a = ComboMatrix._14 + ComboMatrix._12;

 FrustumPlane[BOTTOM].b = ComboMatrix._24 + ComboMatrix._22;

 FrustumPlane[BOTTOM].c = ComboMatrix._34 + ComboMatrix._32;

 FrustumPlane[BOTTOM].d = ComboMatrix._44 + ComboMatrix._42;
 
//normalize

 D3DXPlaneNormalize( &FrustumPlane[BOTTOM], &FrustumPlane[BOTTOM] );
 
//top clipping plane

 FrustumPlane[TOP].a = ComboMatrix._14 – ComboMatrix._12;

 FrustumPlane[TOP].b = ComboMatrix._24 – ComboMatrix._22;

 FrustumPlane[TOP].c = ComboMatrix._34 – ComboMatrix._32;

 FrustumPlane[TOP].d = ComboMatrix._44 – ComboMatrix._42;
 
//normalize

 D3DXPlaneNormalize( &FrustumPlane[TOP], &FrustumPlane[TOP] );
 //near clipping plane

 FrustumPlane[FRONT].a = ComboMatrix._14 + ComboMatrix._13;

 FrustumPlane[FRONT].b = ComboMatrix._24 + ComboMatrix._23;

 FrustumPlane[FRONT].c = ComboMatrix._34 + ComboMatrix._33;

 FrustumPlane[FRONT].d = ComboMatrix._44 + ComboMatrix._43;
 
//normalize

 D3DXPlaneNormalize( &FrustumPlane[FRONT], &FrustumPlane[FRONT] );
 
//far clipping plane

 FrustumPlane[BACK].a = ComboMatrix._14 – ComboMatrix._13;

 FrustumPlane[BACK].b = ComboMatrix._24 – ComboMatrix._23;

 FrustumPlane[BACK].c = ComboMatrix._34 – ComboMatrix._33;

 FrustumPlane[BACK].d = ComboMatrix._44 – ComboMatrix._43;
 
//normalize

 D3DXPlaneNormalize( &FrustumPlane[BACK], &FrustumPlane[BACK] );

}


/ POINT IN FRUSTUM
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
*
/
/ This determines if a point is inside of the frustum
/
/ POINT IN FRUSTUM

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
*
bool Frustum::PointInFrustum( D3DXVECTOR3 Point )

{

 for( int i = 0; i < 6; i++ )

 {

  float x = D3DXPlaneDotCoord( &FrustumPlane[i], & Point );

  if( x < 0 )

   return false;

 }


 // The point was inside of the frustum (In front of ALL the sides of the frustum)

 return true;

}

本文出自 “小祥” 博客,请务必保留此出处http://xiaoxiang.blog.51cto.com/88051/26928

转载于:https://www.cnblogs.com/lancidie/archive/2010/10/11/1847764.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/110713.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 神经网络超参数有哪些_神经网络参数优化

    神经网络超参数有哪些_神经网络参数优化本节主要介绍了如何选择神经网络中的超参数。根据神经网络中超参数的特性对超参数进行分类,并给出了大致三种调整超参数的方法。首先根据机理确定激活函数的种类,代价函数的种类,权重初始化的方法,输出层的编码方式;其次根据宽泛策略给出一个结构较为简单神经网络,在这里可以确定网络层数,神经元个数;最后依次确定学习率,minibatch,lambda和回合数。

  • 股票 数据接口(股票行情数据接口)

    最近股票大跌,打算做点数据分析。转个数据接口,等我完成数据分析有具体结论再写出来吧。做了一点股票分析数据准备,做了个均线图:http://stock.chenpeng.info/randomone查询股票走势请移步:http://stock.chenpeng.info/,搜索请输入代码或者股票名称。Sina股票数据接口eg:http://hq.sinajs.cn/li…

  • linux查看全部环境变量_centos7环境变量配置

    linux查看全部环境变量_centos7环境变量配置一、查看环境变量 $env二、查看PATH $echo$PATH三、修改PATH 在Linux里设置环境变量的方法(exportPATH)一般来说,配置交叉编译工具链的时候需要指定编译工具的路径,此时就需要设置环境变量。例如我的mips-linux-gcc编译器在“/opt/au1200_rm/build_tools/bin”目录下,build_tools就是

  • 机器学习:准确率(Precision)、召回率(Recall)、F值(F-Measure)、ROC曲线、PR曲线

    机器学习:准确率(Precision)、召回率(Recall)、F值(F-Measure)、ROC曲线、PR曲线以下第一部分内容转载自:机器学习算法中的准确率(Precision)、召回率(Recall)、F值(F-Measure)是怎么一回事摘要:数据挖掘、机器学习和推荐系统中的评测指标—准确率(Precision)、召回率(Recall)、F值(F-Measure)简介。引言:在机器学习、数据挖掘、推荐系统完成建模之后,需要对模型的效果做评价。业内目前常常采用的评价指标有准确率(Precision)、召

  • js 彻底理解回调函数「建议收藏」

    一、前奏在谈回调函数之前,先看下下面两段代码:不妨猜测一下代码的结果。functionsay(value){alert(value);}alert(say);alert(say(‘hijs.’));如果你测试了,就会发现:只写变量名say返回的将会是say方法本身,以字符串的形式表现出来。而在变量名后加()如say()返回的就会使say方法调用后的结果,这里

  • 软件工程师待遇怎么样?软件工程师薪水到底有多高?「建议收藏」

    软件工程师待遇怎么样?软件工程师薪水到底有多高?「建议收藏」随着技术不断进步,行业对软件开发技能的需求急剧上升。在此情况下,软件工程师(程序员)薪水上涨便很正常。通常来说,个人薪水是高是低,则与自身积累的经验、所处的地点以及产业分不开。据国际调研机构IDC在报告中公开的数据:2018年,全球有2230万名的软件工程师;其中,全职程序员1165万名,兼职人员635万名,非专业人员430万名。美国拥有最多的软件工程师,651017人;其次是中国,183…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号