第三章 图 形 对 象.doc_第1页
第三章 图 形 对 象.doc_第2页
第三章 图 形 对 象.doc_第3页
第三章 图 形 对 象.doc_第4页
第三章 图 形 对 象.doc_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第三章 图 形 对 象即使人们不知道苹果和梨是怎么种植的,也可以吃掉它们。那么能否不必知道构造细节,也可以绘制出复杂的图形呢?可以,图形对象就干这种事情。Intra3D的图形对象隐藏了几何造型与绘制的细节,用户使用简单的几个接口函数就可以绘制出图形。Intra3D 2.0版提供了三类图形对象:(1)常用几何对象,如长方体、锥体、圆柱体、球体、圆环体、Swept形体等对象;(2)多边形模型对象,用于绘制Autodesk公司.3ds模型和Wavefront公司的.obj模型;(3)商业统计图形对象,如柱形图、带状图、条形图、折线图、面积图、饼图、塔形图、曲线图、曲面图、进程图、股票图等对象。Intra3D 将“图形对象”和“形体节点”(见第四章)分层设计。图形对象负责绘制,形体节点则处理3D交互。形体节点可以动态地引用图形对象,从而实现交互式绘制。这种分层设计可使Intra3D核心库具有良好的可扩展性,并使交互式3D应用程序的开发更加灵活。3.1 图形对象的基类与COM接口图形对象的基类为 GraphicalObject,相应的COM接口为IGraphicalObject。在C+类库中,几何图形对象如BoxObject、ConeObject、CylinderObject、SphereObject与TorusObject,多边形模型对象如Model3DS与ModelOBJ,商业统计图形对象如ColumnChart3D、RibbonChart3D、LineChart2D与BartChar2D等,均为GraphicalObject的派生类。在COM库中,上述对象均继承接口IGraphicalObject。C+类库中GraphicalObject是Container的派生类,应使用AddRef与Release函数来管理内存。源程序见Intra3D-DLLIncludeLayer2GraphicalObject.h。其定义如下:class GraphicalObject : public Containerpublic:virtual void Draw(void) / 图形绘制函数/ 获取对象的包围盒,(dx,dy,dz) 为长方体的幅值,(cx,cy,cz) 为中心坐标,virtual void GetBoundBox(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz) *dx=*dy=*dz=0; *cx=*cy=*cz=0; / 获取对象的包围球,(cx,cy,cz) 为中心坐标,radius 为半径virtual void GetBoundSphere(float *radius, float *cx, float *cy, float *cz) *cx=*cy=*cz=0; *radius=0; / 获取对象的最小坐标值(minx,miny,minz)与最大坐标值(maxx, maxy, maxz)virtual void GetMinMax( float *minx, float *miny, float *minz, float *maxx, float *maxy, float *maxz) *minx=*miny=*minz=-0; *maxx=*maxy=*maxz= 0; ;其中公有函数Draw、GetBoundBox、GetBoundSphere与GetMinMax均为虚函数,具体行为由派生类定义。COM接口IGraphicalObject的定义如下(见Intra3D-COMIntra3D.idl文件):interface IGraphicalObject : IDispatchHRESULT Draw();HRESULT GetMinMax( out float *minX, out float *minY, out float *minZ, out float *maxX, out float *maxY, out float *maxZ) ;HRESULT GetBoundSphere( out float *radius, out float *cx, out float *cy, out float *cz);HRESULT GetBoundBox( out float *dx, out float *dy, out float *dz, out float *cx, out float *cy, out float *cz);3.2 常用几何图形对象Intra3D 2.0 C+类库与COM库中的常用几何图形对象有BoxObject、ConeObject、CylinderObject、SphereObject与TorusObject。由于这几种图形对象的设计非常相似,本节仅以SphereObject为例讲述程序设计。程序的重点是 AddRef、Release与FinalRelease的使用。3.2.1 类 SphereObject的程序C+类库中的SphereObject程序见Intra3D-DLLIncludeLayer2SphereObject.h 和Intra3D-DLLLayer2 SphereObject.cpp。类SphereObject的定义如下:class SphereObject : public GraphicalObjectpublic:SphereObject(void);/ 构造函数void SetSphere(float radius, int slices=32); / 设置球体参数void SetDrawMode(int mode);/ 设置绘制模式void SetMaterial(Material *pMat); / 设置材质void SetTexture(Texture2D *pTex); / 设置纹理/- 以下为基类GraphicalObject的虚函数 -virtual void Draw(void);virtual void GetMinMax( float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ);virtual void GetBoundSphere( float *radius, float *cx, float *cy, float *cz);virtual void GetBoundBox(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz);protected:virtual void FinalRelease(void);/ 基类Container 的虚函数protected:floatm_fRadius;/ 球体半径intm_iSlices;/ 球体经纬等份数intm_iDrawMode;/ 绘制模式,取 SOLID 或者 WIREMaterial*m_pMaterial;/ 引用材质Texture2D*m_pTexture;/ 引用纹理;构造函数用于初始化成员变量:SphereObject:SphereObject(void)m_fRadius= 1.0;m_iSlices= 32;m_iDrawMode= SOLID;m_pMaterial= NULL;m_pTexture= NULL;SetMaterial函数用于引用外部定义的材质对象:void SphereObject:SetMaterial(Material *pMat)/ 1if(m_pMaterial != NULL)m_pMaterial-Release();/ 2m_pMaterial=pMat;/ 3if(pMat != NULL) m_pMaterial-AddRef();SetTexture函数用于引用外部定义的纹理对象:void SphereObject:SetTexture(Texture2D *pTex)/ 1if(m_pTexture != NULL)m_pTexture-Release();/ 2m_pTexture= pTex;/ 3if(pTex != NULL)m_pTexture-AddRef();当SphereObject:Release在删除自身时,应先消除对材质对象和纹理对象的引用。此工作由SphereObject:FinalRelease函数实现:void SphereObject:FinalRelease(void)if(m_pMaterial != NULL)m_pMaterial-Release();if(m_pTexture != NULL)m_pTexture-Release();SetSphere函数用于设置球体的参数。SetDrawMode用于设置球体的绘制模式,绘制模式有两种,可取SOLID 或WIRE模式。void SphereObject:SetSphere(float radius, int slices)m_fRadius = radius;m_iSlices = slices;void SphereObject:SetDrawMode(int mode)m_iDrawMode=mode;Draw函数用于绘制球体。当绘制模式为WIRE时,一般应将光照明关闭,否则由于光照明计算使得线框图时明时暗。如果关闭光照明则导致材质不起作用,此时可将材质的Diffuse颜色作为线框图的颜色。void SphereObject:Draw(void)if(m_pMaterial != NULL) / 如果关闭光照明则材质不起作用,此时可将材质的Diffuse颜色作为当前颜色float color3;m_pMaterial-GetDiffuseColor(color);glColor3fv(color);m_pMaterial-Apply();if(m_pTexture != NULL)glEnable(GL_TEXTURE_2D);m_pTexture-Apply();if(m_iDrawMode=SOLID)DrawSolidSphere(m_fRadius, m_iSlices);else if (m_iDrawMode=WIRE)int flag;glGetIntegerv(GL_LIGHTING, &flag);if(flag) glDisable(GL_LIGHTING);DrawWireSphere(m_fRadius, m_iSlices);if(flag) glEnable(GL_LIGHTING);if(m_pTexture != NULL)glDisable(GL_TEXTURE_2D);GetBoundBox、GetBoundSphere与GetMinMax函数的程序如下:void SphereObject:GetBoundBox(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz)*cx=*cy=*cz=0;*dx = *dy = *dz = m_fRadius*2.0f;void SphereObject:GetBoundSphere(float *radius, float *cx, float *cy, float *cz)*radius=m_fRadius;*cx=*cy=*cz=0;void SphereObject:GetMinMax( float *minx, float *miny, float *minz, float *maxx, float *maxy, float *maxz)*minx=*miny=*minz=-m_fRadius;*maxx=*maxy=*maxz= m_fRadius;3.2.2 COM 对象 SphereObject的程序COM库中的SphereObject程序见Intra3D-COMLayer2SphereObject.h和SphereObject.cpp。SphereObject有两个接口:ISphereObject 与IGraphicalObject。ISphereObject的定义如下:interface ISphereObject : IDispatchHRESULT SetSphere(float radius, defaultvalue(32) int slices);HRESULT SetMaterial(IMaterial *pMat);HRESULT SetTexture(ITexture2D *pTex);HRESULT SetDrawMode(EnumDrawMode mode);枚举类型EnumDrawMode定义如下:typedef enumSOLID=1,WIRE =2,EnumDrawMode;SphereObject的两个接口ISphereObject 与IGraphicalObject是由类CSphereObject实现的:class CSphereObject : public CComObjectRootEx,public CComCoClass,public IDispatchImpl,public IDispatchImplpublic:CSphereObject();DECLARE_REGISTRY_RESOURCEID(IDR_SPHEREOBJECT)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(CSphereObject)COM_INTERFACE_ENTRY(ISphereObject)COM_INTERFACE_ENTRY2(IDispatch, ISphereObject)COM_INTERFACE_ENTRY(IGraphicalObject)END_COM_MAP()public:/- ISphereObject 接口 -STDMETHOD(SetSphere)(float radius, /*defaultvalue(32)*/ int slices);STDMETHOD(SetDrawMode)(EnumDrawMode mode);STDMETHOD(SetMaterial)(IMaterial *pMat);STDMETHOD(SetTexture)(ITexture2D *pTex);/- IGraphicalObject 接口 -STDMETHOD(Draw)();STDMETHOD(GetBoundBox)(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz);STDMETHOD(GetBoundSphere)(float * radius, float *cx, float * cy, float * cz);STDMETHOD(GetMinMax)( float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ);virtual void FinalRelease(void);/ 类CComObjectRootEx的虚函数protected:floatm_fRadius;/ 球体半径intm_iSlices;/ 球体经纬等份数intm_iDrawMode;/ 绘制模式,取 SOLID 或者 WIREIMaterial*m_pMaterial;/ 引用材质ITexture2D*m_pTexture;/ 引用纹理;注意此处的成员变量m_pMaterial是IMaterial接口指针,m_pTexture是ITexture接口指针,FinalRelease是基类CComObjectRootEx的虚函数。CSphereObject:CSphereObject(void)m_fRadius= 1.0;m_iSlices = 32;m_iDrawMode = SOLID;m_pMaterial =NULL;m_pTexture=NULL;STDMETHODIMP CSphereObject:SetMaterial(IMaterial *pMat)AFX_MANAGE_STATE(AfxGetStaticModuleState()if(m_pMaterial != NULL)m_pMaterial-Release();m_pMaterial=pMat;if(pMat != NULL)m_pMaterial-AddRef();return S_OK;STDMETHODIMP CSphereObject:SetTexture(ITexture2D *pTex)AFX_MANAGE_STATE(AfxGetStaticModuleState()if(m_pTexture!=NULL)m_pTexture-Release();m_pTexture=pTex;if(pTex != NULL)m_pTexture-AddRef();return S_OK;void CSphereObject:FinalRelease(void)if(m_pMaterial != NULL)m_pMaterial-Release();if(m_pTexture != NULL)m_pTexture-Release();STDMETHODIMP CSphereObject:SetSphere(float radius, int slices)AFX_MANAGE_STATE(AfxGetStaticModuleState()m_fRadius = radius;m_iSlices = slices;return S_OK;STDMETHODIMP CSphereObject:SetDrawMode(EnumDrawMode mode)AFX_MANAGE_STATE(AfxGetStaticModuleState()m_iDrawMode=mode;return S_OK;STDMETHODIMP CSphereObject:Draw(void)AFX_MANAGE_STATE(AfxGetStaticModuleState()if(m_pMaterial != NULL) float color3;m_pMaterial-GetDiffuseColor(color+0, color+1, color+2);glColor3fv(color);m_pMaterial-Apply();if(m_pTexture != NULL)glEnable(GL_TEXTURE_2D);m_pTexture-Apply();if(m_iDrawMode=SOLID)DrawSolidSphere(m_fRadius, m_iSlices);else if(m_iDrawMode=WIRE)int flag;glGetIntegerv(GL_LIGHTING, &flag);if(flag) glDisable(GL_LIGHTING);DrawWireSphere(m_fRadius, m_iSlices);if(flag) glEnable(GL_LIGHTING);if(m_pTexture != NULL)glDisable(GL_TEXTURE_2D);return S_OK;STDMETHODIMP CSphereObject:GetMinMax( float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ)AFX_MANAGE_STATE(AfxGetStaticModuleState()*minX=*minY=*minZ=-m_fRadius;*maxX=*maxY=*maxZ= m_fRadius;return S_OK;STDMETHODIMP CSphereObject:GetBoundSphere(float * radius, float *cx, float * cy, float * cz)AFX_MANAGE_STATE(AfxGetStaticModuleState()*radius=m_fRadius;*cx=*cy=*cz=0;return S_OK;STDMETHODIMP CSphereObject:GetBoundBox(float *dx,float *dy,float *dz,float *cx,float *cy,float *cz)AFX_MANAGE_STATE(AfxGetStaticModuleState()*dx = *dy = *dz = m_fRadius*2.0f;*cx=*cy=*cz=0;return S_OK;3.2.3 其它几何图形对象C+类库中BoxObject、ConeObject、CylinderObject与TorusObject程序分别见Intra3D-DLLIncludeLayer2目录下的BoxObject.h、ConeObject.h、CylinderObject.h与TorusObject.h,以及Intra3D-DLLLayer2目录下的BoxObject.cpp、ConeObject.cpp、CylinderObject.cpp与TorusObject.cpp。COM库中BoxObject、ConeObject、CylinderObject与TorusObject程序分别见Intra3D-COMLayer2目录下的BoxObject.h、ConeObject.h、CylinderObject.h与TorusObject.h,以及BoxObject.cpp、ConeObject.cpp、CylinderObject.cpp与TorusObject.cpp。长方体的参数由函数SetBox设置:SetBox(float dx, float dy, float dz, float cx=0, float cy=0, float cz=0);圆锥体参数由函数SetCone设置:void SetCone(float radius, float height);圆柱体参数由函数SetCylinder设置:void SetCylinder(float radius, float height);圆环体参数由函数SetTorus设置:void SetTorus(float innerRadius, float outerRadius);在C+类库中还定义了TubeObject和SwaptObject,如图3.1所示。详细说明请参考Intra3D 2.0 类库手册和示例程序。 BoxObject ConeObject SphereObject CylinderObject TorusObject TubeObject SweptObject示例图3.13.3 多 边 形 模 型Intra3D 2.0 提供两种图形对象用于绘制多边形模型,一是用于绘制Wavefront公司.obj 模型的ModelOBJ对象;二是用于绘制Autodesk公司.3ds 模型的Model3DS对象。3.3.1 绘制OBJ模型C+类库中的ModelOBJ程序见Intra3D-DLLIncludeLayer2ModelOBJModelOBJ.h和Intra3D-DLLLayer2ModelOBJModelOBJ.cpp。COM库中的程序见Intra3D-COM Layer2ModelOBJ.h和ModelOBJ.cpp。类ModelOBJ是GraphicalObject的派生类,其公有函数如表2.1所示。COM对象ModelOBJ提供接口IModelOBJ和IGraphicalObject来调用表2.1的函数。.obj模型的示例数据存放于DataModelOBJ目录下,SOLID模式与WIRE模式的 .obj模型如图2.2所示。图2.2 SOLID模式与WIRE模式的 .obj模型BOOL LoadModel(char *strFile);功能:读 .obj 模型输入:strFile 为 .obj 格式的模型文件名返回:成功返回TRUE,否则返回FALSEvoid SetDrawMode(int mode);功能:设置绘制模式输入:mode 可选SOLID或WIRE以下函数的说明可参考类GraphicalObject或者IGraphicalObject接口void Draw(void);void GetMinMax(float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ);void GetBoundSphere( float *radius, float *cx, float *cy, float *cz);void GetBoundBox(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz);表2.1 ModelOBJ 的公有函数3.3.2 绘制3DS模型Autodesk 公司的.3ds模型在PC平台最常见,但其数据格式比较复杂,直接用OpenGL编写绘制.3ds模型的程序也显得很复杂。有一种免费软件View3DS.exe可以将 .3ds格式转化为一种简单的 .bmf格式。Intra3D 的Model3DS对象并不直接绘制 .3ds模型,而是绘制 .bmf模型(因此将类命名为 class Model3DSBMF)。C+类库中的程序见Intra3D-DLLIncludeLayer2Model3DS-BMFModel3DSBMF.h和Intra3D-DLLLayer2Model3DS-BMFModel3DSBMF.cpp。COM库中的程序见Intra3D-COM Layer2 Model3DS.h和Model3DS.cpp。类Model3DSBMF是GraphicalObject的派生类,其公有函数如表2.2所示。COM对象Model3DS提供接口IModel3DS和IGraphicalObject来调用表2.2的函数。BOOL LoadModel(char *strFile);功能:读 .bmf 模型输入:strFile 为 .bmf 格式的模型文件名返回:成功返回TRUE,否则返回FALSEvoid SetDrawMode(int mode);功能:设置绘制模式输入:mode 可选SOLID或WIRE以下函数的说明可参考类GraphicalObject或者IGraphicalObject接口void Draw(void);void GetMinMax(float *minX, float *minY, float *minZ, float *maxX, float *maxY, float *maxZ);void GetBoundSphere( float *radius, float *cx, float *cy, float *cz);void GetBoundBox(float *dx, float *dy, float *dz, float *cx, float *cy, float *cz);表2.2 Model3DS 的公有函数Intra3D 2.0提供的View3DS.exe以及.3ds 和 .bmf示例模型存放于DataModel3DS-BMF目录下。SOLID模式与WIRE模式的 .3ds模型如图2.3所示。图2.2 SOLID模式与WIRE模式的 .3ds模型3.3 商 业 统 计 图 形绘制这类图形并不难,但是为了得到美观的图形,程序的细节就比较多,如坐标轴标注、网格线、图例的设置等。Intra3D 最初设计了十余个商业统计图形对象:柱形图、带状图、饼图、塔形图、折线图、面积图、进程图、股票图、曲面图、曲线图、散点图等。为了不使核心库变得太臃肿,2.0标准版仅仅保留了典型的4个商业统计图形对象:三维柱形图(ColumnChart3D)、三维带状图(RibbonChart)、二维折线图(LineChart2D)和二维条形图(BarChart2D)。用户可以参考上述4个商业统计图形对象的设计,自己扩展对象库。Intra3D 为商业统计图形对象定义了一种简单的数据文件格式:ChartTypenRownColumnColumn0Column1Column2.Row0data(0,0)data(0,1)data(0,2).Row1data(1,0)data(1,1)data(1,2).Row2data(2,0)data(2,1)data(2,2).例如ColumnChart3D类型的数据格式为:ColumnChart3D57Year1Year2Year3Year4Year5Year6Year7Product18755142531890222182281002089129623Product292387823107771053311526722612281Product34739498851324736446549015277Product4108921268172116192143891829310025Product54529699037663285645327813899商业统计图形对象由其protected 类型的成员对象ChartData来处理原始数据和属性。C+类库中的ChartData程序见Intra3D-DLLIncludeLayer2ChartChartData.h和Intra3D-DLL Layer2ChartChartData.cpp。COM库中的程序见Intra3D-COMLayer2ChartData.h和ChartData.cpp。类ChartData的主要函数声明如下:class ChartDatapublic:BOOLCheckDataType(char *strFile, char * strDataType);BOOLReadData(char *strFile);voidFindMinMax(int num, float *data, float *min, float *max);floatClampToLarger(float x);floatClampToSmaller(float x);voidFloatToString( float step, float x, char *stringX );intMaxLenOfRowLabels(void);intMaxLenOfColumnLabels(void);voidSetGridColor(float color3);voidSetLabelColor(float color3);voidSetLabelX(BOOL bVisibility, int step);voidSetLabelY(BOOL bVisibility, int step);voidSetLabelZ(BOOL bVisibility, int step);voidSetLegend(BOOL bVisibility);.;ChartData对象并不向用户公开接口,只是在商业统计图形对象内部默默地工作。这里仅讲述用于处理坐标轴标注的三个函数ClampToLarger、ClampToSmaller与FloatToString。ClampToLarger与ClampToSmaller函数可将浮点数裁剪为以0或5结尾的最接近的数值。例如:float x;/- ClampToLarger -x= ClampToLarger(3600);/ x = 4000x= ClampToLarger(3300);/ x = 3500x= ClampToLarger(-3600);/ x = -3500x= ClampToLarger(-3300);/ x = -3000x= ClampToLarger(0.36);/ x = 0.40x= ClampToLarger(0.33);/ x = 0.35x= ClampToLarger(-0.36);/ x = -0.35x= ClampToLarger(-0.33);/ x = -0.30/- ClampToSmaller -x= ClampToSmaller(3600);/ x = 3500x= ClampToSmaller(3300);/ x = 3000x= ClampToSmaller(-3600);/ x = -4000x= ClampToSmaller(-3300);/ x = -3500x= ClampToSmaller(0.36);/ x = 0.35x= ClampToSmaller(0.33);/ x = 0.30x= ClampToSmaller(-0.36);/ x = -0.40x= ClampToSmaller(-0.33);/ x = -0.35ClampToLarger与ClampToSmaller函数的程序如下:float ChartData:ClampToLarger(float x)if( x = 0) return 0 ;doubley = fabs(x) ;intn = (int)log10(y);doublebase = pow( 10, n );if(base=y)return x;double z = (long)(y/base)*base ;z += base/2 ;if( y z )if( x 0 )return float(-z+base/2) ;elsereturn float(z) ;elseif( x 0 )return float(-z) ;elsereturn float(z+base/2) ;float ChartData:ClampToSmaller(float x)if( x = 0 ) return 0 ;doubley = fabs(x) ;intn = (int)log10(y);doublebase = pow( 10, n );if(base=y)return x;double z = (long)(y/base)*base ;z += base/2 ;if( y z )if( x 0 )return float(-z) ;elsereturn float(z-base/2) ;elseif( x = 10 )sprintf( strX, %.0f, x ) ;else if( step = 1 )sprintf( strX, %.1f, x ) ;else if( step = 0.1 )sprintf( strX, %.2f, x ) ;else if( step = 0.01 )sprintf( strX, %.3f, x ) ;else if( step = 0.001 )sprintf( strX, %.4f, x ) ;else if( step = 0.0001 )sprintf( strX, %.5f, x ) ;else sprintf( strX, %.6f, x ) ;例如:char label16 ;float x=100.1234 ;float step1=20 , step2=2 , step3=0.2 ;Float

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论