« 标准MFC在OpenGL子类调用父类的纯虚函数之问题 »

视锥类CFrustum .zwqxin ver

闲着没事,把之前做CASCADE SHADOWMAP时弄的一个视锥类放上来,若有更闲者点评点评,感激。——ZwqXin.com

这个类其实作用更在于把场景中的真实视锥在渲染窗口里画出来。这样在调试一些与摄象机相关的效果时挺有用的。譬如shadowmap中,光源视觉下“光源所看到的世界”,通过画出其视锥就一清二楚了。

 本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/my-frustum-class.html
  1. #include "Vector3.h"
  2.  
  3. #define PI 3.1415926
  4.  
  5. class CFrustum  
  6. {
  7. public:
  8.     CFrustum();
  9.     CFrustum(GLfloat _fov, GLfloat _ratio, GLfloat d_near, GLfloat d_far);
  10.     ~CFrustum();
  11.  
  12.     inline void ReshapeFov(GLfloat _fov){fov = _fov;};
  13.     inline void ReshapeRatio(GLfloat _ratio){ratio = _ratio;};
  14.     inline void ResightNear(GLfloat d_near){distance_near = d_near;};
  15.     inline void ResightFar(GLfloat d_far){distance_far = d_far;};
  16.  
  17.     void UpdateFrustum(CVector3 &viewpos, CVector3 &viewdir, CVector3 &viewupvec);
  18.     void DrawFrustum(bool linemode, Color col, CVector3 &viewpos, bool nearPlane = false, bool farPlane = false);
  19.  
  20.     inline GLfloat GetFov() {return fov;           };
  21.     inline GLfloat GetRatio(){return ratio;         };
  22.     inline GLfloat GetNear(){return distance_near; };
  23.     inline GLfloat GetFar() {return distance_far;  };
  24.     CVector3 GetPoint(GLuint index);
  25.  
  26. private:
  27.  
  28.     GLfloat distance_near;
  29.     GLfloat distance_far;
  30.     GLfloat fov;
  31.     GLfloat ratio;
  32.     CVector3 point[8];
  33.  
  34. };

成员变量除了point[8]指示作图相关的8个点外,都是gluPerspective的参数一致的。在初始化实例的时候指定。成员函数基本都是自解释的,UpdateFrustum用于在每帧末尾更新视锥,DrawFrustum则是把视锥画出来。

  1. void CFrustum::UpdateFrustum(CVector3 &viewpos, CVector3 &viewdir, CVector3 &viewupvec)
  2. {
  3.    CVector3 rightvector = viewdir.CrossProd(viewupvec);
  4.    rightvector = rightvector.normalize();
  5.  
  6.    CVector3 new_upvector = rightvector.CrossProd(viewdir);
  7.    new_upvector = new_upvector.normalize();
  8.  
  9.    GLfloat radian_fov = GLfloat(fov * PI/180.0f) ;
  10.  
  11.     GLfloat Half_near_height = distance_near * (GLfloat)tan(radian_fov/2.0f);
  12.     GLfloat Half_near_width  = Half_near_height * ratio;
  13.     GLfloat Half_far_height  = distance_far  * (GLfloat)tan(radian_fov/2.0f);
  14.     GLfloat Half_far_width   = Half_far_height *  ratio;
  15.  
  16.  
  17.     CVector3 near_clip_center = viewpos + viewdir * distance_near;
  18.     CVector3 far_clip_center = viewpos + viewdir * distance_far;
  19.  
  20.     point[0] = near_clip_center - new_upvector*Half_near_height - rightvector*Half_near_width;
  21.     point[1] = near_clip_center - new_upvector*Half_near_height + rightvector*Half_near_width;
  22.     point[2] = near_clip_center + new_upvector*Half_near_height + rightvector*Half_near_width;
  23.     point[3] = near_clip_center + new_upvector*Half_near_height - rightvector*Half_near_width;
  24.  
  25.     point[4] = far_clip_center - new_upvector*Half_far_height - rightvector*Half_far_width;
  26.     point[5] = far_clip_center - new_upvector*Half_far_height + rightvector*Half_far_width;
  27.     point[6] = far_clip_center + new_upvector*Half_far_height + rightvector*Half_far_width;
  28.     point[7] = far_clip_center + new_upvector*Half_far_height - rightvector*Half_far_width;
  29.  
  30. }

UpdateFrustum的输入参数也就是相机的那几个参数了——如果更新相机,则视锥也应该要更新。输出的是用于作图的几个关键点位置。

  1. void CFrustum::DrawFrustum(bool linemode, Color col, CVector3 &viewpos, bool nearPlane, bool farPlane)
  2. {
  3.     glEnable(GL_BLEND);
  4.     glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  5.     glDisable(GL_LIGHTING);
  6.     if(linemode)glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  7.     else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  8.  
  9.     glPushMatrix();
  10.         glColor4f(col.r, col.g, col.b, 0.3f);
  11.         glLineWidth(1.0);
  12.         glPointSize(10);
  13.  
  14.     if(nearPlane)
  15.     {
  16.         glBegin(GL_QUADS);
  17.         for(int j=0; j<4; j++)
  18.             glVertex3d(point[j].x, point[j].y, point[j].z);
  19.         glEnd();
  20.     }
  21.     if(farPlane)
  22.     {
  23.         glBegin(GL_QUADS);
  24.         for(int i=4; i<8; i++)
  25.             glVertex3d(point[i].x, point[i].y, point[i].z);
  26.         glEnd();
  27.     }
  28.  
  29.         for(int k=0; k<3; k++)
  30.         {
  31.             glBegin(GL_QUADS);
  32.                 glVertex3d(point[k].x, point[k].y, point[k].z);
  33.                 glVertex3d(point[k+4].x, point[k+4].y, point[k+4].z);
  34.                 glVertex3d(point[k+5].x, point[k+5].y, point[k+5].z);
  35.                 glVertex3d(point[k+1].x, point[k+1].y, point[k+1].z);
  36.             glEnd();
  37.         }
  38.             glBegin(GL_QUADS);
  39.                 glVertex3d(point[3].x, point[3].y, point[3].z);
  40.                 glVertex3d(point[7].x, point[7].y, point[7].z);
  41.                 glVertex3d(point[4].x, point[4].y, point[4].z);
  42.                 glVertex3d(point[0].x, point[0].y, point[0].z);
  43.             glEnd();
  44.  
  45.         for(int l=0; l<4; l++)
  46.         {
  47.             glBegin(GL_LINES);
  48.             glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
  49.             glVertex3d(viewpos.x, viewpos.y, viewpos.z);
  50.             glVertex3d(point[l+4].x, point[l+4].y, point[l+4].z);
  51.             glEnd();
  52.         }
  53.     glPopMatrix();
  54.  
  55.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  56.     glDisable(GL_BLEND);
  57. }

画出来的视锥会有一定透明度,是否画线框,颜色,是否画近/远平面(一般不需要了吧这个)是可调的,另外输入“相机”位置是为了通过画图指示相机所在,这个还是必须的吧......

CFrustum类byzwqxin.rar

 本文来源于 ZwqXin (http://www.zwqxin.com/), 转载请注明
      原文地址:http://www.zwqxin.com/archives/opengl/my-frustum-class.html

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

IE下本页面显示有问题?

→点击地址栏右侧【兼容视图】←

日历

Search

网站分类

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Walle Build 100427

Copyright 2008-2013 ZwqXin. All Rights Reserved. Theme edited from ipati.