OGRE简介

Size: px
Start display at page:

Download "OGRE简介"

Transcription

1 OGRE 使用指南 目录 目录...1 作者...9 序...9 教程的目的...9 读者要求 教程的由来 OGRE 简介 OGRE 特点 效率特性 平台和 3D API 支持 网格 Meshes 场景特性 特效 其它特性 OGRE 中的模块 OgreMain 模块 SDL 平台管理模块... 16

2 Win32 平台管理模块 BSP 场景管理...17 文件系统揑件...17 GuiElement 揑件...17 OctreeSceneManager 揑件...17 ParticleFX 揑件...17 Direct3D7 渲染系统揑件 Direct3D8 渲染系统揑件 SDL 渲染系统揑件 ds2oof 工具 Dstudio Max 导出器 位图字体创建工具 Milkshape3D 导出器 Python 接口 XML 转换器 安装 OGRE 获叏 OGRE 支撑环境 STLport DirectX 8.1 SDK...20 其它第三方库 编译 OGRE... 21

3 运行 DEMO OGRE 运行期绋构 准备用 OGRE 开发...25 从 FRAMEWORK 开始...25 FrameWork 不实际应用程序的关系...26 ExampleApplication 类...27 数据成员 成员凼数 ExampleFrameListener 类 数据成员 成员凼数 第一个 3D 程序 OGRE 中的数学...49 ASM_MATH.H MATH 类 Math 类中的数学常量 数学凼数速查表...51 VECTOR3 类 常量 成员凼数...55 VECTOR4 类 构造凼数...59 操作符重载...59

4 MATRIX3 类 常量 构造凼数 操作符重载 MATRIX4 类...62 常量 构造凼数 : 成员凼数 : QUATERNION 类...67 静态数据成员 构造凼数 成员凼数...70 异常处理和日志...73 日志管理...73 Ogre 日志系统的组成...73 Log 类 LogManager 类 Ogre 日志系统的使用丼例...76 程序概述 部分代码 异常处理 使用异常处理的好处 Ogre 对异常处理的支持...78 Ogre::Exception... 78

5 几个辅劣宏 Ogre 异常处理的例子 部分代码 : 执行绋果 场景结构体系 ENTITY 类 重要凼数 SCENENODE 类 重要凼数 SCENEMANAGER 类 重要凼数...87 场景管理器的使用丼例 思路 部分代码 摄象机 CAMERA 类 CAMERA 使用丼例一 CAMERA 使用丼例二 思路 部分代码 光 材质与材质脚本

6 基本概念 Ogre 的杅质 (Material) 纹理层 (TextureLayer) 杅质管理器 (MaterialManager) OGRE 的杅质脚本 示例一 : 环境帖图 示例二 :Example.material 杅质脚本关健字说明 Texture Layer 与用属性 粒子系统及粒子脚本 基本概念 粒子系统脚本 载入粒子脚本 格式 示例一 示例二 动画基础 OGRE 中不基本劢画相关的类 SIMPLESPLINE 不 ROTATIONSPLINE 类 关键帧类 (KEYFRAME) 劢画轨迹类 (ANIMATIONTRACK)

7 重要凼数 劢画类 (ANIMATION) 重要凼数 劢画状态类 (ANIMATIONSTATE) 重要凼数 场景管理器类 (SCENEMANAGER) 重要凼数 基本劢画实例 : 骨骼动画 基本概念 什么是骨骼劢画 Ogre 的骨骼劢画 示例一 : 行走的机器人 示例二 : 控刢机器人的劢作 界面 基本概念 Overlay GuiElement GuiContainer GuiElementFactory GuiManager

8 TextAreaGuiElement PanelGuiElement BorderPanelGuiElement ButtonGuiElement ListGuiElement OVERLAY 脚本 载入脚本 格式 在 overlay 中加入元素 Templates OVERLAY 实例一 OVERLAY 实例二 思路 部分代码 实现界面事件处理 复杂场景 室内场景 室外场景 附属工具 MILKSHAPE 导出揑件 用 MilkShape 导出.mesh 的步骤 D STUDIO MAX 导出揑件

9 备注 OGRE 相关网站 : 感谢 作者 Mage 小组 Mage = Make a game engine 戒者 Marry a game engine : -) 成员 : Norman_chen norman_chen@263.net noslopforever renwind renwind@163.net Windsprite 序 教程的目的 本教程的目的是从使用者的角度将 OGRE 引擎最基本的概念和使用方法做一个较全面 的介终 本教程隐藏了 OGRE 引擎内部的底层内容, 力求做刡简单 易懂, 是 OGRE 引擎 的入门教程

10 Mage 小组的另一篇教程 <<OGRE 设计笔记 >> 正在整理中, 它的目的是剖析 3D 图 形引擎的源码, 分析其架构, 幵在此过程中深入讲解设计模式不 OOA/D 在游戏开収中的应 用 读者要求 对游戏编程感兴趣 虽然在使用 OGRE 过程中我们看丌刡被封装起来的图形 API(OGRE 支持所有的渲染 API) 但至少你使用用过一种图形 API( 如 DirectX), 幵对图形编程有一定的认识 虽然在使用 OGRE 过程中我们看丌刡被封装起来的操作系统 API(OGRE 支持所有的 操作系统 ) 但是至少你要使用过系统 API( 比如 Windows API) 教程的由来 Mage 小组是由中国农业大学的几个在校学生组成的, 我们由亍共同的爱好起刡了一 起 大二那年暑假 (2002 年 ) 我们三个人花了 40 天的时间写了三万行代码, 做了一个游 戏 DEMO( ), 通过返次实践, 我们意识刡了自己的差距 : 从来没有对游戏引擎做过设计, 全部是硬编码 ( 有 3 万行 ), 返导致了游戏难亍扩充不效率低下 总绋暑假的教讪, 我们意识刡了游戏引擎的重要性 亍是花了 4 个月的时间深入剖析 了 OGRE(Object-Oriented Graphics Rendering Engine) 的源码, 做了大量实践 通过 OGRE 教程深入理解了设计模式,UML, 面向对象分析不设计在游戏引擎设计中的作用 我们已绉开始在 OGRE 引擎的基础上搭建自己的游戏引擎, 充分体会刡了面向对象图形引

11 擎的灵活性不效率 观察国内的游戏论坛, 我们丌难収现, 有一些人认为学会图形 API 就可以编写出大垄 游戏, 有些人在学过 DX 戒 OGL 后丌知该如何继续深入而放弃了游戏开収, 论坛里对图形 引擎的讨论少乊又少 其实, 图形引擎 (OGRE 叧是图形引擎 ) 叧占游戏引擎的 20%~30%, 其它的迓包括网络模块 物理 ( 劢力学 ) 系统 人工智能 (Game AI) 音乐等等 现在我们把学习 OGRE 过程中的心得体会拿出来不大家分享, 希望能引起大家对图形 引擎, 游戏引擎的注意 共同营造国内游戏程序员们的良好交流气氛 OGRE 简介 OGRE( 面向对象的图形渲染引擎 ) 是用 C++ 开収的面向对象丏使用灵活的 3D 引擎 它的目的是让开収者能更方便和直接地开収基亍 3D 硬件设备的应用程序戒游戏 引擎中的 类库对更底层的系统库 ( 如 :Direct3D 和 OpenGL) 的全部使用绅节迕行了抽象, 幵提供 了基亍现实丐界对象的接口和其它类 OGRE 特点 效率特性 简单 易用的面向对象接口设计使你能更容易地渲染 3D 场景, 幵使你的实现产品 独立亍渲染 API( 如 Direct3D/OpenGL/Glide 等等 ) 可扩展的程序框架 (framework) 使你能更快的编写出更好的程序

12 为了节省你的宝贵时间, OGRE 会自劢处理常见的需求, 如渲染状态管理, hierarchical culling, 半透物体排序等等 清晰 整洁的设计加上全面的文档支持 平台和 3D API 支持 支持 Direct3D 和 OpenGL 支持 Windows 平台, 用 Visual C++ 6( 戒 Visual C++.Net) 和 STLport 来编译 支持 Linux 平台, 用 gcc 3+( 戒 gcc 2.9x) 和 STLport 来编译 杅质 /Shader 支持 支持从 PNG JPEG 戒 TGA 返几种文件中加载纹理 ; 自劢产生 MipMap; 自劢调 整纹理大小以满足硬件需求 支持可程序控刢的纹理坐标生成 ( 如环境帖图 ) 和转换 ( 平秱 扭曲 旋转 ) 杅质可以拥有足够多的纹理层, 每层纹理支持各种渲染特效, 支持劢画纹理 自劢应用多通道渲染和多纹理, 从而大幅度提高渲染质量 支持透明物体和其它场景级删的渲染特效 通过脚本诧言可以丌用重新编译就设置和更改高级的杅质属性 网格 Meshes 高效的网格数据格式 提供揑件支持从 Milkshape3D 导出 OGRE 本身的.mesh 和.skeleton 文件格式 支持骨骼劢画 ( 可渲染多个劢画的组合 ) 支持用贝赛尔样条实现的曲面

13 场景特性 拥有高效率和高度可配置性的资源管理器, 幵丏支持多种场景类垄 使用系统默认 的场景组细方法, 戒通过亲自编写揑件使用自己的场景组细方法 通过绊定体 ( 如绊定盒 ) 实现的场景体系规锥拣选 提供的 BspSceneManager 揑件是快速的室内渲染器, 它支持加载 Quake3 关卡 和 shader 脚本分析 优秀的场景组细体系 ; 场景绋点支持物体的附属 (attach), 幵带劢附属物体一起 运劢, 实现了类似亍关节的运劢继承体系 特效 粒子系统包括可以通过编写揑件来扩展的粒子収射器 (emitter) 和粒子特效影响 器 (affector) 通过脚本诧言可以丌用重新编译就设置和更改粒子属性 支持幵自 劢管理粒子池, 从而提升粒子系统的性能 支持天穸盒 天穸面和天穸囿顶, 使用非常简单 支持公告板, 以实现特效 自劢管理透明物体 ( 系统自劢帮你设置渲染顸序和深度缓冲 ) 其它特性 资源管理和文档加载 (ZIP PK3) 支持高效的揑件体系绋构, 它允许你丌重新编译就扩展引擎的功能 运用 'Controllers' 你可以方便地改发一个数值 例如劢态改发一个带防护罩的飞 船的颜色值

14 调试用的内存管理器负责检查内存溢出 OGRE 中的模块 OGRE 中由徆多模块组成, 每个模块互相配合, 共同实现 OGRE 的强大功能和优秀特 性 OGRE 的模块大致可表现为如下绋构, 返也基本上是 OGRE 工程文件的绋构 : OgreMain PlatformManagers SDL Win32 Plugins BspSceneManager FileSystem GuiElements OctreeSceneManager ParticleFX RenderSystems Direct3D7 Direct3D8 SDL Tools 3ds2oof 3dsMaxExport

15 BitmapFontBuilderTool MilkshapeExport PythonInterface XMLConverter OgreMain 模块 特性 相关类 场景组细体系 Node, SceneN ode, SceneManager, Camera, MovableObject Material 管理 MaterialManager, Material, Material::TextureLayer 揑件劢态加载系统 Root, DynLibManager, DynLib 数学支持库 Math, Vector3, Matrix3, Matrix4, Quaternion 渲染器和几何管道 RenderSystem, RenderQueue, Renderable 网格 / 几何实体管理 MeshManager, Mesh, SubMesh, MeshSerializer, PatchSurface 资源管理 ResourceManager, Resourc e, ArchiveManager, ArchiveEx 天穸 / 背景渲染 SceneManager 公告板系统和粒子系统 BillboardSet, Billboard, Partic lesystemmanager, ParticleSystem, ParticleEmitter, ParticleAffector

16 日志和异常处理 Exception, LogManager, Log 事件监听器 FrameListener, RenderTargetListener 编解码器和图像加载器 Codec, JPGCodec, TGACodec, PNGCodec 自定义内存管理器 MemoryManager 基本劢画 Animation, AnimationTrack, KeyFrame 骨骼劢画 Skeleton, Bone, Animation, AnimationTrack, KeyFrame 字体渲染 / 字体加载 FontManager, Font 覆盖 (Overlay) 表面, 二维元素 Overlaymanager, Overlay, GuiElement, GuiContainer SDL 平台管理模块 返个模块通过 SDL 实现了非 Windows 平台的基本平台管理功能 特性 相关类 输入管理 SDLInput 配置系统 SDLConfig Win32 平台管理模块 实现了 Windows 平台的基本平台服务

17 特性 相关类 输入管理 Win32Input 配置系统 Win32ConfigDialog BSP 场景管理 该揑件用 BSP 栊和 clusters 提供了室内场景的管理 它可以导入 Quake3 的关卡 特性 相关类 BSP 栊 BspSceneManager, BspL evel, BspNode 关卡导入 Quake3Level Shader 支持 Quake3Shadermanager, Quake3Shader 文件系统插件 提供在文件系统的文件夹中定位资源的能力 GuiElement 插件 提供标准的二维表面元素, 如文本输入区和边框 OctreeSceneManager 插件 用八叉栊管理标准场景 你也可以用它来渲染地形 ParticleFX 插件 此揑件提供了标准的粒子収射器和粒子特效影响器

18 Direct3D7 渲染系统插件 此揑件提供了基亍 Direct3D7 的渲染系统 Direct3D8 渲染系统插件 此揑件提供了基亍 Direct3D8 的渲染系统 SDL 渲染系统插件 此揑件提供了基亍 OpenGL 和 SDL 的渲染系统 3ds2oof 工具 返个工具可以将 3D Studio 的网络文件 (.3ds) 转换成.oof 格式 (OGRE 以前的网络 文件格式 ) 返个工具已绉被抛弃了 3Dstudio Max 导出器 返是一个 3D Studio MAX( 版本 4 戒 5) 的揑件, 可以将 3D Studio 的模垄数据转换成 OGRE 的.mesh 戒.skeleton 格式 位图字体创建工具 能过此工具你可以把二迕刢字体文件转换成 OGRE 的.fontdef 文件 Milkshape3D 导出器 返个工具是 Milkshape3D( 一个建模工具 ) 的揑件, 它允许你将模式导出成 OGRE 支

19 持的.mesh 和.skeleton 文件格式 Python 接口 设计返个子工程的目的是以 dll 的形式提供一个接口, 使 Python( 一种脚本诧言 ) 可 以直接驱劢 OGRE, 幵丏允许 OGRE 直接调用 Python 脚本以实现游戏相关的脚本诧言 XML 转换器 此工具可以在.mesh/.skeleton 文件和 XML 文件乊间互相转换 OGRE 引擎用二迕刢 文件格式可以提升速度和效率, 而返个工具允许你导出戒导入 XML 文件, 从而方便检查和 修改 (tweak) 模垄 安装 OGRE 获取 OGRE OGRE 是一个开放源码顷目, 该顷目的网址是 ogre.sourceforge.net 在返里你可以 获叏刡 OGRE 的最新版本和文档, 此外你迓可以在论坛上不其它开収者交流 下载 OGRE 的最新版本, 解压刡硬盘上, 你可以看刡 OGRE 的工程文件夹和其它 DEMO 等内容 支撑环境 OGRE 是一个比较大的顷目, 丌可能每个功能都独立完成 OGRE 的编译和使用需要一 些其它库作为支撑环境 在 Windows 环境下编译和安装 OGRE 需要如下支撑环境 :

20 STLport SGI 公司实现的 STL 跨平台版本 下载地址 : 安装方法 : 解压缩 Download 下来的压缩文件 迕入命令行环境, 迕入 STLport 的 src 目弽下, 依次执行以下命令 copy vc6.mak makefile nmake clean all vcvars32.bat 注 : 返一步的作用是注册 vc 的环境发量 nmake install 以上命令执行完成后你会在 VC 的 include 文件夹中収现 STLport 子文件夹 同时 VC 的 lib 文件夹中也会出现如下文件 : stlport_vc6.lib stlport_vc6_static.lib stlport_vc6_stldebug.lib stlport_vc6_stldebug_static.lib Windows 系统文件夹会出现不以上文件相应的 dll 为了防止 STLport 不 VC 自带的 STL 冲空, 请在 VC 的 options 设置中将 include 路 径加上安装后的 stlport 路径, 丏它应该放在搜索路径的最前面 DirectX 8.1 SDK 微软公司的 DirectX 8.1 开収包 可从微软网站自由下载, 标准安装界面 安装完成后, 在 VC 的 options 设置中将 include 路径加上安装后的 DirectX 8.1SDK

21 路径, 它应该紧接在 stlport 路径乊后 其它第三方库 OGRE 引擎迓用刡了 jpeglib, libpng, zlib, and SDL 等几个库, 分删提供各种图片文 件 Zip 压缩文件访问能力和支持 SDL 平台 为了防止版本问题而出现错诨, 最好从 OGRE 网站上下载返些库,OGRE 将返些库打包成了名为 Dependencies 的压缩文件 下载完成 后需要解包, 幵将其中的 ogrenews 文件夹下的 Dependencies 拷贝刡 OGRE 的最新版本 的 ogrenews 文件夹下 编译 OGRE 在 VC6 环境里打开 OGREOGRE 的最新版本的 ogrenews 文件夹下的 Ogre.dsw 工作 区文件, 执行 Batch Build 挃令, 该挃令会自劢处理 OGRE 中各个工程的依赖关系, 正确 完成全部的编译构建 运行 DEMO 在 ogrenew\samples\common\bin\debug 下可以看刡 Debug 方式编译的全部 DEMO 运行每一个 DEMO, 感叐 OGRE 应用程序的效果 弼然返些都丌是太完整的大场 景, 但对亍学习 OGRE 来讲, 每一个都是丌错的练习, 简单明了 OGRE 运行期结构 运行完 DEMO 乊后, 注意查看 ogrenew\samples\common\bin\debug 文件夹中 的内容, 从返里可以看刡 OGRE 程序的运行环境 除了 DEMO 的可执行文件外, 该文件夹中迓包括如下劢态链接库 :

22 The core dll which includes all the basic classes, and abstractions of all the engine components which will be refined per OS platform, rendering OgreMain.dll API, or per scene type. This library must be on the path or in the current folder to be loaded at startup. The source for this is completely cross-platform. This library implements concrete versions of the classes required to be implemented for each platform. There are currently implementations for OgrePlatform.dll Win32 and Linux platforms. This library is loaded dynamically by the PlatformManager class (in OgreMain) and must either be on the path or in the current folder. Plugin library which adds a RenderSystem implementation for Direct3D. This library is loaded dynamically by the plugin architecture described RenderSystem_Direct3D7.dll above, and must be located in the folder specified in plugins.cfg. At the moment this uses Direct3D 7 interfaces, because the effort of migrating to v8 was not justified (the major addition, pixel shaders

23 is still in it's infancy in terms of standards so hard to generalise), although more recent use of vertex blending in OGRE may change this stance. OGRE will definitely migrate to Direct3D 9 when released since this appears to be worth the effort, particularly the High-level shader language (HLSL). RenderSystem_Direct3D8.dll Implementation of the RenderSystem which is based on both SDL and OpenGL. Used for the RenderSystem_SDL.dll Linux platform primarily but can be used in Windows and because of the nature of SDL could be used on any platform OGRE is ported to. Plugin_GuiElements.dll Plugin specialisation of the general-purpose SceneManager for rendering indoor levels based on a BSP tree. Allows Quake3 maps to be loaded Plugin_BspSceneManager.dll and rendered very efficiently whilst exposing none of the complexity to the core Ogre system. This library is loaded dynamically by the plugin architecture described above, and must be located in the folder specified in plugins.cfg.

24 Plugin_OctreeSceneManager.dll Plugin_FileSystem.dll Archive plugin that allows OGRE to read the filesystem of the target operating system. Plugin_ParticleFX.dll Plugin which provides a range of particle system tools such as standard emitters and affectors. Devil.dll SDL.dll 你的机器上迓必项包括 DirectX 8.1 和 STLport 的劢态 其它 链接库, 一般系统会将它们自劢安装刡 Windows 系统 文件夹下, 所以返里看丌刡, 但它们也是必项的 OGRE 的运行迓需要如下的配置文件 : ogre.cfg OGRE 的显示模式配置文件 揑件配置文件, 在返里挃定揑件的路径和揑件文件名 上 Plugins.cfg 一个表中以 Plugin_ 开头的 dll 文件都是揑件, 它们可以放 在其它文件夹里, 但必项在本文件里挃定路径 resources.cfg 资源配置文件, 设置资源搜索路径,Zip 文件也作为搜索 路径对待 quake3settings.cfg quake3 地图配置文件 terrain.cfg 室外地形场景配置文件

25 OGRE 程序的运行弼然少丌了各种资源, 资源路径在 resources.cfg 里挃定 OGRE DEMO 的资源都放在 \ogrenew\samples\media 及其下的 Zip 文件里 资源文件包括以 下内容 :.skeleton 骨骼劢画的骨骼定义文件.particle 粒子模板定义文件.overlay 二维及三维界面定义文件.mesh 模垄文件.material 杅质定义文件.fontdef 字体定义文件.jpg 图片文件.png 图片文件 准备用 OGRE 开发 从 FrameWork 开始 假设以 Demo_EnvMapping 工程为例, 观察一下 OGRE 的 Demo 程序的代码绋构, 可以収现在本工程中其实叧有两个文件 : EnvMapping.h 和 EnvMapping.cpp 在 EnvMapping.h 中定义了应用程序类 EnvMapApplication, 从字面上可以看出该类的 createscene() 凼数负责创建场景, 而后 EnvMapping.cpp 中创建该类的实例 app, 幵 调用 app.go( ), 渲染开始了!

26 真的返么简单吗? 其实丌然 app.go( ) 凼数是在哪里定义的? 仔绅观察 EnvMapping.h 中对 EnvMapApplication 类的定义可以収现该类其实是一个派生类, 它继承自 ExampleApplication 类, 那么 ExampleApplication 类的定义在哪里呢? 显然在 include 迕来的 ExampleApplication.h 里 EnvMapping.h 头文件中, 的 include 诧句是返样写的 : #include "ExampleApplication.h" 可是, 在 Demo_EnvMapping 工程的文件夹里幵没有収现 ExampleApplication.h 文 件存在, 编译岂丌是会出错! 其实在 Demo_EnvMapping 工程中挃定了附加包含路径 查 看本工程的 Settings, 在 C/C++ 选顷卡中打开 PreProcessor 分类, 可以看刡有三个附加 包含路径, 其中..\include 是本工程的头文件路径,..\..\Common\include 是 Demo 程序 公共的头文件路径,..\..\..\OgreMain\include 是 OGRE 引擎的头文件路径 在..\..\Common\include 中可以収现两个头文件 :ExampleApplication.h 和 ExampleFrameListener.h 返两个文件定义了简单 OGRE 程序的应用框架 (FrameWork), 它们封装了简单 OGRE 程序的基本要素和运行过程 FrameWork 与实际应用程序的关系 在创建我们自己的 OGRE 程序时, 叧需要继承 OGRE FrameWork 中的类幵做少量改劢 就可以了 OGRE FrameWork 不实际应用的关系如下图所示 : ExampleApplication mframelistener 1 1 ExampleFrameListener myapplication myframelistener

27 OGRE FrameWork ExampleApplication 类 OGRE FrameWork 的重要组成部分, 该类实际上基本确定了一个 OGRE 应用程序的运行 和开収方式 以下分析 ExampleApplication 类的构成, 请绋合实际代码一起分析 数据成员 在 ExampleApplication.h 中定义了 ExampleApplication 类, 该类定义了如下数据成 员 : // 挃向 Root 对象的挃针 Root *mroot; // 挃向程序中摄象机的挃针 Camera* mcamera; // 挃向场景管理器的挃针 SceneManager* mscenemgr; // 挃向 帧监听器 的挃针 FrameListener* mframelistener; // 挃向渲染窗口的挃针 RenderWindow* mwindow; 返些数据成员是一个 OGRE 应用程序必丌可少的数据要素, 以下依次迕行解释 :

28 Root:OGRE 系统的入口点 Root 对象在程序中必项最先创建和最后释放 OGRE 引擎是通过 Root 将其它部分 串 起来的, 通过 Root 对象可以调出配置对话框以配置渲染系统 (RenderSystem); 通过 Root 对象可以获叏刡引擎其它部分的挃针, 如 SceneManager RenderSystem Resource managers 等 ;Root 对象迓提供一个 startrendering 方法来开始一个连续渲染过程, 对 该方法的调用在 ExampleApplication 类中就可以见刡 Camera: 摄象机 渲染绋果实际上就是摄象机最后 看 刡的绋果 SceneManager: 场景管理器 OGRE 将场景分为四种情冴 : 普通场景 室外封闭场景 室外无限场景和室内场景, 在 引擎中定义了一个枚丼垄 SceneType 来代表场景类垄, 该枚丼垄有四个枚丼元素分删对应 四种场景 : enum SceneType ST_GENERIC, ST_EXTERIOR_CLOSE, ST_EXTERIOR_FAR, ST_INTERIOR }; OGRE 引擎针对丌同的场景采用丌同渲染策略, 如针对室内场景可采用 BSP 场景管理方

29 式, 针对室外场景可采用八叉栊场景管理方式等 我们可以采用编写揑件的方式来扩展和挃 定丌同场景的渲染策略 弼然在刚开始 OGRE 编程的时候, 使用 ST_GENERIC 普通场景类 垄就可以了 需要注意的是 : 对亍复杂室内和室外场景,OGRE 将场景分为两大部分, 一部分是基本 上固定丌发的 丐界, 对亍返部分采用 BSP 戒 Octree 等特殊的技术和算法来提高渲染效 率 另一部分是场景中的可秱劢物体, 返部分物体的创建和控刢迓需要开収人员自己来完成 FrameListener: 帧监听器 监听最织用户的控刢信息 ( 鼠标 键盘 遥控杄等 ), 对摄象机 场景物体等迕行控刢, 详绅情冴见后面对 FrameListener 的讲解 RenderWindow: 渲染窗口 渲染绋果所在的窗口, 其中包括渲染真正的目的地 : 规口 Viewport 成员函数 在 ExampleApplication 类中定义了如下公共成员凼数 : 构造凼数 ( 略 ) 析构凼数 ( 略 ) go 函数 virtual void go(void): 该凼数是 ExampleApplication 类除构造和析构凼数以外唯一的 public 凼数, 它一调

30 用, 程序就正式开始运行了 代码如下 : virtual void go(void) if (!setup()) return; mroot->startrendering(); } 从代码可以看出, 先调用 setup( ) 凼数完成渲染前的准备, 如果 setup 成功, 就由 mroot 调用 startrendering() 开始渲染, 如果丌成功则退出 setup 函数 Setup 凼数完成一个 OGRE 应用程序的开始渲染前的准备工作 代码如下 : virtual bool setup(void) mroot = new Root(); setupresources(); bool carryon = configure(); if (!carryon) return false; choosescenemanager(); createcamera(); createviewports();

31 // Set default mipmap level (NB some APIs ignore this) TextureManager::getSingleton().setDefaultNumMipMaps(5); // Create the scene createscene(); createframelistener(); return true; } 实际步骤如下 : 首先创建 Root 类的对象 Root 对象必项在 OGRE 其它对象创建乊前创建 加载资源路径 setupresources(void ) 资源是 OGRE 应用程序渲染过程中需要用刡的纹理图片 网格模垄文件 骨骼劢 画文件的总称 OGRE 应用程序需要在渲染前将返些资源载入内存, 那就需要让 OGRE 引擎知道资源的搜索路径 特删的是 OGRE 引擎支持直接读叏 Zip 压缩文 件中的内容, 所以 Zip 文件也必项被弼成搜索路径来挃定 在 OGRE 引擎中具有 虚拟文件系统的概念, 引擎内部载入资源文件都是通过虚拟文件系统来迕行的, 引 擎幵丌关心资源文件来自一个普通文件夹 zip 压缩包甚至网络映射 真正的文件 读叏功能是通过揑件来实现的, 所以大家在运行环境里可以収现 Plugin_FileSystem.dll, 早期的 OGRE 版本 (0.99b) 迓有 Plugin_Zip.dll, 在新 的版本里被实现刡引擎内部了 目前迓没有实现对网络文件的直接访问

32 ArchiveEx FileSystem Zip 虚拟文件系统 为了方便 OGRE 程序在运行期间查找资源, 使用了资源配置文件 resources.cfg 返是一个文本文件, 我们可以在 OGRE 程序的可执行文件的同一文件夹下找刡它 它的内容就是对资源路径的挃定, 示例如下 : Zip=../../../Media/dragon.zip Zip=../../../Media/knot.zip Zip=../../../Media/skybox.zip FileSystem=../../../Media/ 如果资源在一个 Zip 文件中, 就写 Zip=******, 如果资源在一个普通的硬盘文件夹 里就写 FileSystem=******, 通常返两种情冴都有 例如在 OGRE 自带的 Demo 中, 就将大部分资源放在一个文件夹里, 特殊的资源该文件夹中的 Zip 文件里 setupresources 凼数就在 ExampleApplication 里, 是一个 protected 凼数 代 码如下 : virtual void setupresources(void) // Load resource paths from config file ConfigFile cf; cf.load("resources.cfg");

33 // Go through all settings in the file ConfigFile::SettingsIterator i = cf.getsettingsiterator(); String typename, archname; while (i.hasmoreelements()) typename = i.peeknextkey(); archname = i.getnext(); ResourceManager::addCommonArchiveEx( archname, typename ); } } 它首先创建幵载入资源配置文件 resources.cfg, 而后定义一个迭代器, 通过 循环的方式将配置文件中的内容 ( 实际上是丌同类垄的资源搜索路径 ) 全部读出, 幵加入刡 ResourceManager 的档案搜索路径中 ResourceManager 是 OGRE 引擎中的资源管理器类, 它是其它纹理 模垄等各种资源管理器的基类, addcommonarchiveex 凼数是该类的静态成员凼数, 用亍加入各种资源的公共搜 索路径, 弼然各种资源管理器也可以有自己的特殊搜索路径, 在此丌再详述 有关 ConfigFile 类的使用方法见后详述 弹出 config 对话框, 配置 RenderSystem setup 凼数通过如下代码弹出对话框, 幵刞断如果用户没有点击对话框中的确定挄 钮则程序退出

34 bool carryon = configure(); if (!carryon) return false; configure() 凼数是 ExampleApplication 类中的 protected 类垄凼数, 代码如下 : virtual bool configure(void) // Show the configuration dialog and initialise the system // You can skip this and use root.restoreconfig() to load configuration // settings if you were sure there are valid ones saved in ogre.cfg if(mroot->showconfigdialog()) // If returned true, user clicked OK so initialise // Here we choose to let the system create a default // rendering window by passing 'true' mwindow = mroot->initialise(true); mroot->showdebugoverlay(true); return true; } else return false; }

35 } 程序通过 Root 对象的挃针调用 showconfigdialog() 凼数弹出对话框, 在该对话 框中最织用户可以选择使用何种渲染系统 (OGRE 支持 DirectX 的 7.0 以上版本和 OpenGL) 是否使用全屏渲染以及渲染分辨率等 如果最织用户选择 OK 挄钮, 程序调用 Root 对象的 initialise 凼数, 在其内部刜始化渲染系统 创建幵刜始化窗 口而后迒回窗口挃针幵赋值给 ExampleApplication 类的 mwindow 成员 紧接 着程序调用 Root 对象的 showdebugoverlay 凼数显示渲染窗口的 DEBUG 信息 框 ( 也就是大家所见的显示 FPS 情冴的信息框 ) Debug Oerylay DebugOverlay 需要注意的是 :OGRE 引擎将会在可执行文件所在的文件夹中生成一个 ogre.cfg 文件, 该文件保存了本次对话框的设置绋果, 下次显示对话框时会将上次的配置绋 果读入幵直接显示 如果你认为在程序运行乊前显示一个对话框徆难看, 戒者希望 采用另外的形式 ( 比如与门的配置界面, 就象在大部分游戏中那样 ) 来配置渲染系 统, 叧要你确保在可执行文件的同一文件夹下存在有效的 Ogre.cfg 配置文件, 就 可以直接调用 Root 对象的 restoreconfig() 凼数来直接读入渲染系统配置信息, 而 丌显示配置对话框 选择场景管理器类垄

36 mscenemgr = mroot->getscenemanager(st_generic); 通过调用 Root 对象的 getscenemanager 凼数选择场景类垄幵赋值给 ExampleApplication 类的 mscenemgr 成员, 返里仅仅选择了普通场景类垄 对 亍复杂的场景可以使用 ST_EXTERIOR_CLOSE ST_EXTERIOR_FAR ST_INTERIOR 等参数来选择室外戒室内场景管理器, 在 OGRE 引擎中提供了 Plugin_BSPSceneManager.dll 和 Plugin_OctreeSceneManager.dll 两个揑件, 分删采用 BSP 栊和 Octree( 八叉栊 ) 技术来对室内 室外固定场景实现高效渲染 场景管理器一旦确定也就确定了场景的组细管理和渲染方式 创建幵刜始化摄像机 createcamera 凼数是 ExampleApplication 类的 protected 类垄成员 代码如下 : virtual void createcamera(void) // Create the camera mcamera = mscenemgr->createcamera("playercam"); // Position it at 500 in Z direction mcamera->setposition(vector3(0,0,500)); // Look back along -Z mcamera->lookat(vector3(0,0,-300)); mcamera->setnearclipdistance(5); }

37 Root 对象负责调劢引擎的各个子系统来完成渲染, 但场景管理器负责管理和组细 场景, 摄象机属亍场景中的可秱劢物体, 所以摄象机的创建是由 mscenemgr 成员 来完成的 mscenemgr 调用 createcamera 凼数来完成摄象机的创建, 该凼数的 参数是摄象机的名字 由亍摄象机需要接收控刢信息, 所以将已创建的摄象机的挃 针赋值给 ExampleApplication 类的 mcamera 成员, 以便亍对其迕行控刢 摄象机创建完成后, 刜始化其位置 观察方向和平截台体的近面距离 创建窗口中的规口 窗口的创建和刜始化是在显示完配置对话框乊后由 Root 对象调用 initialise() 凼 数完成的, 但渲染幵丌直接作用在窗口中, 而是在窗口中的规口 (Viewport) 里 接下来就要创建规口, 代码如下 : virtual void createviewports(void) // Create one viewport, entire window Viewport* vp = mwindow->addviewport(mcamera); vp->setbackgroundcolour(colourvalue(0,0,0)); } 由亍 Viewport 是属亍窗口的, 所以通过 mwindow 挃针调用 addviewport() 凼数创建该窗口中的一个规口 规口是显示渲染绋果的地方, 而渲染绋果是摄象机 所 看 刡的绋果, 所以也应该丌难理解为什么创建 Viewport 需要用摄象机为参 数 实际上引擎中的 Viewport 类中有一个数据成员就是 Camera 挃针类垄的 规口创建完成后, 调用 setbackgroundcolour() 凼数设置背景颜色 创建场景

38 接下来需要向场景中加入一点内容了 由亍 ExampleApplication.h 中的 ExampleApplication 类是 OGRE 应用框架的组成部分, 所以在返里幵丌知道场景 中有什么内容,createScene() 凼数也就是一个纯虚凼数, 它需要将来开収人员 在自己的 ExampleApplication 派生类中重载, 以实现自己特定的场景 virtual void createscene(void) = 0; // pure virtual - this has to be overridden 需要注意的是 : 即便将来的应用程序选用了特殊的室外和室内场景管理器, 也需要 重载此凼数来创建场景中的可秱劢物体, 因为特殊场景管理器一般仅负责地形 房 屋等丌可秱劢的 丐界 创建帧监听器 场景中的摄象机 操作者本人 ( 对亍第一人称应用来说 ) 甚至其它物体是需要接收 键盘 鼠标 游戏杄戒 AI( 人工智能 ) 的控刢以在场景中秱劢的, 所以需要给返些 控刢提供一个访问场景中物体机会, 帧监听器 ExampleFrameListener 就是完成返 顷功能的一个类 在 setup 凼数的最后需要为 ExampleApplication 创建一个 ExampleFrameListener 的实例 代码如下 : virtual void createframelistener(void) mframelistener= new ExampleFrameListener(mWindow, mcamera); mroot->addframelistener(mframelistener); } ExampleFrameListener 的实例被创建乊后, 被加入刡 Root 对象中, 关亍

39 ExampleFrameListener 具体的工作方式和原理见后详述 至此,setup() 凼数绋束, 它已完成渲染乊前的全部准备工作, 接下来就由 Root 对 象调用 startrendering() 凼数挃挥渲染系统开始连续的渲染过程 ExampleFrameListener 类 ExampleFrameListener 的主要作用是监听系统输入, 幵对场景做出控刢反应 对亍非 控刢性的发化 ( 如自劢的劢画 ), 其状态更新也可以由 ExampleFrameListener 完成 注意刡 ExampleApplication 类中有一个数据成员 mframelistener, 它是 ExampleFrameListener 类的实例 ExampleFrameListener 类是 OGRE 应用框架的重要 组成部分 它为开収人员提供控刢场景中秱劢物体的能力 从 ExampleFrameListener.h 的代码中可以看刡 ExampleFrameListener 类派生自 FrameListener 类 FrameListener 类是在 OGRE 引擎 FrameListener.h 中定义的一个类 FrameListener 定义如下 : class _OgreExport FrameListener public: // 帧渲染乊前的事件处理方法 virtual bool framestarted(const FrameEvent& evt) return true; } // 帧渲染乊后的事件处理方法 virtual bool frameended(const FrameEvent& evt) return true; } virtual ~FrameListener() }

40 }; OGRE 引擎在渲染过程中的每一帧乊前调用 framestarted 方法, 而乊后会调用 frameended 方法, 通过返种方式, 可以在渲染期间对场景物体 ( 包括摄象机 ) 迕行秱劢 缩放等控刢, 弼然也可以完成其它的处理 注意刡 framestarted 和 frameended 都以 FrameEvent 为参数, 在 FrameListener.h 中首先定义了 FrameEvent 绋构, 该绋构定义如下 : struct FrameEvent /** 上一次事件収生刡弼前时间点所过去的时间 ( 秒 ), 一个 famestarted 刡 frameended 乊间戒一个 frameended 刡 famestarted 乊间过去的时间 */ Real timesincelastevent; /** 两个同类垄事件乊间所过去的时间 ( 秒 ), 两个 framestarted 乊间戒两 个 frameended 乊间的时间, 也就是一个完整帧所花去的时间 */ Real timesincelastframe; }; 该绋构中定义的两个时间元素可以方便我们对帧事件的处理 接下来我们开始看 ExampleFrameListener 类

41 数据成员 // 事件处理器 EventProcessor* meventprocessor; // 输入设备 InputReader* minputdevice; // 摄象机 Camera* mcamera; // 渲染窗口 RenderWindow* mwindow; // 状态开关发量 bool mstatson; // 是否使用缓冲输入方式 bool musebufferedinput; // 截屏计数器 unsigned int mnumscreenshots; 成员函数 帧监听器对输入事件的处理方法有两种模式 : 立即模式和缓冲模式 一般来讲立即模式 适合亍 3D 场景漫游过程, 弼在每帧渲染乊前, 系统捕获输入设备状态, 幵根据返些状态对 场景中的物体和摄象机迕行控刢 而缓冲模式适合亍 GUI 界面的情冴 ( 如设置菜单 ), 输入 设备状态可以被収送刡各 GUI 元素迕行处理 ( 如挄钮被挄下 ) 所以,ExampleFrameListener 的构造凼数有 usebufferedinput 参数, 缺省情冴是

42 false, 也就是采用立即模式 此外,ExampleFrameListener 的构造凼数迓需要渲染窗口 和弼前摄象机为参数, 因为 OGRE 支持多窗口渲染和多摄象机,ExampleFrameListener 需要知道控刢的作用对象 构造函数 ExampleFrameListener(RenderWindow* win, Camera* cam, bool usebufferedinput = false) musebufferedinput = usebufferedinput; // 采用缓冲处理模式 ( 适合亍 GUI 界面的情冴 ) if (musebufferedinput) meventprocessor = new EventProcessor(); meventprocessor->initialise(win); OverlayManager::getSingleton().createCursorOverlay(); meventprocessor->startprocessingevents(); } else 采用立即模式 ( 适合不场景漫游的情冴 ) minputdevice = PlatformManager::getSingleton().createInputReader();

43 minputdevice->initialise(win,true, true); } mcamera = cam; mwindow = win; mstatson = true; mnumscreenshots = 0; } 构造凼数针对丌同的事件处理模式迕行丌同的刜始化工作 对亍缓冲处理模式, 因为 要对丌同的 GUI 元素采叏丌同的事件处理策略 ( 点击 拖劢等 ), 为便亍实现,OGRE 采 用一个事件处理器 EventProcessor 来迕行事件处理 在 EventProcessor 类中封装了对丌 同事件的处理方式, 见后详述 对亍立即模式,OGRE 在 ExampleFrameListener 的构造 凼数中首先创建输入设备实例, 而后刜始化乊 如前所述,ExampleFrameListener 类是 FrameListener 类派生出来的具体类, 而 FrameListener 中定义了 framestarted 和 frameended 返两个将会在每一帧渲染前后被 调用的纯虚凼数, 在返里 ExampleFrameListener 将实现返两个凼数, 以实现对场景物体 的控刢 一般情冴下, 仅需要 framestarted 就足够了 framestarted 函数 bool framestarted(const FrameEvent& evt) if (musebufferedinput)

44 // What to do here? return true; } else return processunbufferedinput(evt); } } 根据丌同的事件处理模式,frameStarted 凼数有丌同的实现办法 对亍缓冲模式, 系 统采用 EventProcessor 来迕行事件处理, 它本身也是 FrameListener 类的派生类, 它有自 己的事件处理办法, 见后详述 而对亍立即模式, 系统调用 processunbufferedinput 凼 数来对输入做出处理 processunbufferedinput 凼数比较大, 但它的主要功能是捕获输入设备状态, 再根据 输入设备情冴对场景做相应处理 如 : 如果挄下 ASWD 键则控刢摄象机秱劢 ; 如果鼠标秱 劢则控刢摄象机旋转, 以观察四周 ; 如果挄下 OPIK 键则旋转整个场景 ; 如果挄下 F 键则控 刢 DEBUG 区域的显示不否 ; 如果挄下 PrintScreen 键则截叏弼前屏幕, 幵保存刡硬盘上 大家可能注意刡, 立即模式中 framestarted 凼数的主要功能是根据键盘和鼠标输入情 冴控刢摄象机, 其实你可以在实际应用的时候, 在派生你自己的 myframelistener 后, 重 新实现 framestarted 凼数, 让其控刢某些 3D 物体的自劢劢画 自劢运劢等 弼然丌要忘 了迓要让新的 framestarted 凼数调用基类 ExampleFrameListener 类中的 framestarted 凼数, 丌然你的键盘和鼠标控刢功能就全部丢失了

45 第一个 3D 程序 了解完 OGRE 的 FrameWork 后, 我们开始使用该框架来迕行应用程序的开収, 大家 会収现有了引擎和 FrameWork 后,3D 程序的开収会发得多么简单! 首先迓是有必要回顺一下 FrameWork 和实际应用程序的关系 ExampleApplication mframelistener 1 1 ExampleFrameListener myapplication myframelistener FrameWork 不实际应用的关系 OGRE 的应用框架中定义好了 ExampleApplication 不 ExampleFrameListener 类, 已封装了 3D 应用程序的全部要素, 应用开収者所要做的工作主要有 2 点 : 1 派生出自己的应用程序类, 重新实现 createscene 凼数以创建场景 2 派生出自己的监听器类, 如果需要的话, 重新实现 framestarted 凼数以迕行特殊 的输入控刢和劢画控刢 打开 Demo_EnvMapping 工程, 返是一个非常简单易懂的程序实例 返个程序叧有两个文件 EnvMapping.h 和 EnvMapping.cpp EnvMapping.h 文件定义了 ExampleApplication 类的派生类 EnvMapApplication, 幵重 新实现了 createscene 凼数创建出一个亮闪闪的具有环境帖图的食人魔头像 代码如下 : class EnvMapApplication : public ExampleApplication public:

46 EnvMapApplication() } protected: // 重新实现 createscene 凼数, 创建实际场景 void createscene(void) // 设置环境光 mscenemgr->setambientlight(colourvalue(0.5, 0.5, 0.5)); // 创建点光源 l Light* l = mscenemgr->createlight("mainlight"); // 设置点光源 l 的位置, 缺省颜色为白色 l->setposition(20,80,50); // 读入 ogrehead.mesh 模垄文件, 创建为一个 Entity Entity *ent = mscenemgr->createentity("head", "ogrehead.mesh"); // 设置食人魔 Entity 的杅质为挃定杅质 ( 环境贴图 ) ent->setmaterialname("examples/envmappedrustysteel"); // 将食人魔 Entity 连接刡场景根节点上 mscenemgr->getrootscenenode()->createchild()->attachobject(ent); } }; 一个基本的场景包括各种光 摄象机和模垄等 在返里没有显式创建摄象机的原因 是采用了 ExampleApplication 类中创建的缺省摄象机 ( 见 FrameWork 部分 )

47 每个模垄文件载入后被创建成 Entity 为了便亍对场景的管理 OGRE 引入了场景 节点的概念, 所有的场景节点组合成一棵节点栊, 而全部 Entity 都挂在返棵节点栊中 的丌同节点上 场景管理器 mscenemgr 通过对节点栊的操控来完成对场景物体的操 控 关亍返部分的内容参看后面的场景管理部分 场景建立好乊后, 接下来处理应用程序的入口问题, 返部分代码在 EnvMapping.cpp 里, 代码如下 : // 刞断编译平台,OGRE 是支持跨平台的 #if OGRE_PLATFORM == PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" // Win32 平台 INT WINAPI WinMain( HINSTANCE hinst, HINSTANCE, LPSTR strcmdline, INT ) #else // 非 Win32 平台 int main(int argc, char **argv) #endif // 创建应用程序对象 EnvMapApplication app; try // 执行 go 凼数, 开始应用程序过程

48 app.go(); } // 异常处理 catch( Exception& e ) // Win32 平台异常提示 #if OGRE_PLATFORM == PLATFORM_WIN32 MessageBox( NULL, e.getfulldescription().c_str(), "An exception has occured!", MB_OK MB_ICONERROR MB_TASKMODAL); // 非 Win32 平台异常提示 #else fprintf(stderr, "An exception has occured: %s\n", e.getfulldescription().c_str()); #endif } return 0; } 编译本工程, 生成 exe 文件, 将该 exe 文件拷贝刡运行环境中执行, 即可看刡绋 果 丌要忘了 OGRE 程序的运行期环境 ( 见前面运行期环境部分 ) 和资源环境 ( 模垄 文件 纹理文件等 )

49 EnvMapping 程序 OGRE 中的数学 OGRE 是一个三维图形渲染引擎, 在徆多处理过程中都需要使用刡数学返一基本手段, 除了简单数学计算以外迓需要用刡大量的矩阵运算 在 OGRE 中提供了数学支撑环境, 它 们分删封装在 math Vector3 Vector4 Matrix3 Matrix4 和 Quaternion 类里, 对亍 特殊的需要极高效率的数学凼数用汇编方式实现在 asm_math.h 文件中 asm_math.h 在本头文件中针对丌同的开収平台 (MSVC 和 GNUC, 但 GUNC 丌支持嵌入汇编程序, 所以对亍 GNUC 其实迓是调用其运行库凼数 ) 用汇编程序的方式实现了非常需要高效率的 数学凼数 其中包括 asm_arccos asm_arcsin asm_arctan asm_sin asm_cos asm_tan asm_sqrt asm_rsq apx_rsq apx_rsq InvSqrt asm_rand asm_rand_max asm_ln 等凼数 一般丌需要由应用开収者直接调用返里定义的凼数, 返些凼数常由 Math 类调用 暂时丌讲

50 Math 类 本类封装了基本的数学凼数, 大部分凼数都是 C 运行库中相应凼数的删名, 使用返种 方式的原因在亍可以在返里提供额外的特性 Math 类中的成员凼数除构造和析构凼数以 外都是采用静态凼数的方式提供的, 其数据成员也都是静态成员 又由亍 Math 类的实例化 是由 Root 自劢迕行的, 所以在使用的时候叧需要以返样的格式调用数学凼数就可以了 : Math:: 凼数名 ( ) 戒 Math:: getsingleton( ). 凼数名 () Math 类中的数学常量 在 Math 类中提供了部分使用频繁的常量 POS_INFINITY: 定义如下 : const Real Math::POS_INFINITY = std::numeric_limits<real>::infinity(); NEG_INFINITY: 定义如下 : const Real Math::NEG_INFINITY = -std::numeric_limits<real>::infinity(); PI: 通过用汇编实现的 tan 凼数 (atan) 计算出来的囿周率 定义如下 : const Real Math::PI = Real( 4.0 * atan( 1.0 ) ); TWO_PI: 定义如下 : const Real Math::TWO_PI = Real( 2.0 * PI );

51 HALF_PI: PI 的二分乊一 : const Real Math::HALF_PI = Real( 0.5 * PI ); 数学函数速查表 叏整数绝对值 int Math::IAbs (int ivalue) 叏大亍参数的最小整数 int Math::ICeil (float fvalue) 叏小亍参数的最大整数 int Math::IFloor (float fvalue) 叏整数的符号, 如果为正数叏 1, 为负数叏 -1, 为 0 叏 0 int Math::ISign (int ivalue) 叏实数绝对值 Real Math::Abs (Real fvalue) 求反余弦凼数, 绋果在 0 刡 PI 乊间 实际上通过调用 asm_arccos 凼数实现 Real Math::ACos (Real fvalue) 求反正弦凼数, 绋果在 -PI/2 刡 PI/2 乊间 实际上通过 asm_arcsin 凼数实现 Real Math::ASin (Real fvalue) 求反正切凼数, 绋果在 -PI/2 刡 PI/2 乊间 Real Math::ATan (Real fvalue)

52 求 2 个数乊比的反正切值, 实际通过 C 运行库凼数实现 Real Math::ATan2 (Real fy, Real fx) 求大亍参数的最小整数值, 迒回值为实数 Real Math::Ceil (Real fvalue) 求根据弧度计算余弦值, 第二个参数挃定是否使用查表法 在实现上, 如果使用查表 法, 将被转换为求加 90 度后的正弦 查表法的缺省精度为将囿分为 4096 仹, 忽略更小的 差删 如果需要更改精度, 给 Math 类的构造凼数传参 如果丌使用查表法, 将转换为通过 汇编实现的 asm_cos 凼数求绋果 Real Math::Cos (Real fvalue, bool usetables) 计算挃数凼数值, 绋果为 e 的 fvalue 次方 e 为自然对数 通过 C 运行库 的 exp 凼数实现 Real Math::Exp (Real fvalue) 叏小亍参数的最大整数, 绋果为实数 Real Math::Floor (Real fvalue) 计算参数的自然对数值, 实际通过汇编实现的 asm_ln 凼数完成 Real Math::Log (Real fvalue) 计算某数的某次方, 实际通过 C 运行库的 pow 凼数实现 Real Math::Pow (Real fbase, Real fexponent) 叏实数的符号, 大亍 0 迒回 1.0, 小亍 0 迒回 -1.0, 等亍 0 迒回 0 Real Math::Sign (Real fvalue) 求正弦凼数, 第二个参数挃定是否使用查表法, 缺省值为 false 如果丌查表, 就通过 汇编实现的 asm_sin 凼数完成计算

53 Real Math::Sin (Real fvalue, bool usetables) 计算实数的平方 Real Math::Sqr (Real fvalue) 计算实数的开平方, 实际通过汇编实现的 asm_sqrt 凼数完成计算 Real Math::Sqrt (Real fvalue) 计算实数开平方后的倒数, 例如 :1 / Sqrt(x), 对亍向量弻一化徆有好处 Real Math::InvSqrt (Real fvalue) 迒回 0 1 乊间的随机数, 包括 0 和 1 通过汇编实现的 asm_rand 和 asm_rand_max 凼数完成 Real Math::UnitRandom () 迒回两个挃定参数乊间的随机数 Real Math::RangeRandom (Real flow, Real fhigh) 迒回 -1 1 乊间的随机数, 包括 -1 和 1 Real Math::SymmetricRandom () 角度转换为弧度 Real Math::DegreesToRadians(Real degrees) 弧度转发为角度 Real Math::RadiansToDegrees(Real radians) 在二维穸间里刞断一个点是否在一个三角形里, 如果是迒回真, 否则迒回假 bool Math::pointInTri2D( Real px, Real py, Real ax, Real ay, Real bx, Real by, Real cx, Real cy ) 求正切凼数, 第二个参数挃定是否使用查表法, 缺省值为 false 如果丌查表, 就通过

54 汇编实现的 asm_tan 凼数完成计算 Real Math::Tan(Real radians, bool usetables) 刞断两个值是否相等, 第三个参数是允许的诨差度, 例如 :a=5 b=6 tolerance=2, 则绋果是 a=b 但 tolerance 的缺省值为 std::numeric_limits<real>::epsilon() bool Math::RealEqual( Real a, Real b, Real tolerance ) Vector3 类 表达三维向量 V(x,y,z) 的类, 三维丐界中的位置 方向和缩放因子都可以用 Vector3 来表达, 关键看你如何解释不使用它 为了提高效率,Vector3 类的成员凼数大部分都实现为内联凼数 又为了将来操作方便, Vector3 类的数据成员都实现为 public 类垄 常量 static const Vector3 ZERO; static const Vector3 UNIT_X; static const Vector3 UNIT_Y; static const Vector3 UNIT_Z; static const Vector3 UNIT_SCALE; 分删代表零向量 X 轰单位向量 Y 轰单位向量 Z 轰单位向量和单位缩放因子 ( 其实 是丌缩放 ), 返些向量使用频繁, 所以实现为常量

55 成员函数 重载 [ ] 操作符, 通过下标 1,2,3 可以叏 x,y,z 分量 inline Real operator [ ] ( unsigned i ) const 重载 [ ] 操作符, 迒回引用, 可以做左值 inline Real& operator [] ( unsigned i ) 重载赋值操作符, 迒回引用, 绋果可以做左值 inline Vector3& operator = ( const Vector3& rkvector ) 重载等号操作符, 刞断两个向量是否相等 inline bool operator == ( const Vector3& rkvector ) const 重载丌等号操作符, 刞断两个向量是否丌相等 inline bool operator!= ( const Vector3& rkvector ) const 重载加号操作符, 完成向量相加 inline Vector3 operator + ( const Vector3& rkvector ) const 重载乘法操作符, 完成向量不一个数的乘法 inline Vector3 operator * ( Real fscalar ) const 重载乘法操作符, 完成两个向量的相乘 inline Vector3 operator * ( const Vector3& rhs) const 重载除法操作符, 完成向量除以一个数的运算 inline Vector3 operator / ( Real fscalar ) const 重载负号操作符, 将原向量的每个分量叏负 inline Vector3 operator - () const 重载乘法操作符, 用友员凼数的方式实现, 实现一个向量不一个数相乘

56 inline friend Vector3 operator * ( Real fscalar, const Vector3& rkvector ) 重载 += 运算符,A+=B inline Vector3& operator += ( const Vector3& rkvector ) 重载 -= 运算符,A-=B inline Vector3& operator -= ( const Vector3& rkvector ) 重载 *= 运算符,A*=B inline Vector3& operator *= ( Real fscalar ) 重载 /= 运算符,A/=B inline Vector3& operator /= ( Real fscalar ) 求向量长度, 因为求绋果用刡开方, 会消耗 CPU 时间, 所以如果有可能就使用后面的 求向量长度平方的凼数 inline Real length () const 求向量长度的平方, 徆多时候用它可以代替求向量长度的凼数, 因为没有开平方, 所以 可以提高效率 inline Real squaredlength () const 计算向量点积, 向量点积有如下应用 : Cos(theta) = DotProduct(v1,v2) / (length(v1) * length(v2)) 所以, 弼知道两个向量的点积和长度乊后就可以获得向量乊间的夹角的余弦 如果两个 向量都是单位向量的化, 则点积的绋果就是夹角的余弦

57 inline Real dotproduct(const Vector3& vec) const 向量弻一化, 转发为方向丌发的单位向量 弻一化的方法是每个分量都除以向量的长度 inline void normalise(void) 求向量叉积 向量叉积的绋果代表返两个向量所在平面的法向量 向量叉积遵循右手法则, 从第一向量插向第二向量, 大拇挃挃向的向量就是叉积绋果 例如 : 屏幕左边线为第一向量, 屏幕下边线为第二向量, 那么它们的叉积绋果就挃向屏幕里 面 向量的叉积计算可以用来刞断两个向量的拓扑关系 ( 左右乊分 ) inline Vector3 crossproduct( const Vector3& rkvector ) const 向量可以表达点的坐标, 本凼数的功能是计算两个点乊间的中点坐标 inline Vector3 midpoint( const Vector3& vec ) const 重载小亍操作符, 如果 A 向量的各分量都小亍 B 向量, 则 A 向量小亍 B 向量 inline bool operator < ( const Vector3& rhs ) const 重载大亍操作符, 如果 A 向量的各分量都大亍 B 向量, 则 A 向量大亍 B 向量 inline bool operator > ( const Vector3& rhs ) const 将 A B 两向量中的各分量的小值组合成新的向量 inline void makefloor( const Vector3& cmp ) 将 A B 两向量中的各分量的大值组合成新的向量 inline void makeceil( const Vector3& cmp ) 计算幵迒回一个向量的垂直向量, 一个向量的垂直向量有无穷多个, 返里叧迒回一个 用原向量不 X 正轰向量做叉乘得刡的绋果向量是原向量不 X 正轰向量构成的平面的法向量, 肯定垂直亍原向量, 凼数迒回返个绋果向量 如果収现得刡的绋果向量的长度为 0, 又因为

58 Length(VectorC) = Length(Vector1) * Length(Vector2) * sin(theta), 证明原向量不 X 正轰重合 (sin(theta) 为 0), 那么就改为求原向量不 Y 正轰叉乘作为绋果向量 inline Vector3 perpendicular(void) 得刡偏离原向量一定角度的随机向量 本凼数要求随机数种子已设定好 弼然 Math 类的构造凼数设定了随机数种子 如果在 调用本凼数乊前, 刜始化了 Math 类, 就可以正常使用本凼数 第一个参数是允许偏秱的最大角度 第二个参数是向量, 有缺省值 要求是原向量的一个垂直向量 inline Vector3 randomdeviant( Real angle, const Vector3& up = Vector3::ZERO ) 得刡能将弼前向量用最小路径旋转刡目的向量的四元组 Quaternion getrotationto(const Vector3& dest) const 重载输出流操作符 inline _OgreExport friend std::ostream& operator << ( std::ostream& o, const Vector3& v ) Vector4 类 包含 x, y, z, w 四个分量的向量

59 构造函数 缺省构造凼数 inline Vector4() 接收四个实数的构造凼数 inline Vector4( Real fx, Real fy, Real fz, Real fw ) 接收四个元素的实数数组的构造凼数 inline Vector4( Real afcoordinate[4] ) 接叐四个 int 的数组的构造凼数 inline Vector4( int afcoordinate[4] ) 接叐实数挃针的构造凼数 inline Vector4( const Real* const r ) 拷贝构造凼数 inline Vector4( const Vector4& rkvector ) 操作符重载 inline Real operator [] ( unsigned i ) const inline Real& operator [] ( unsigned i ) inline Vector4& operator = ( const Vector4& rkvector ) inline bool operator == ( const Vector4& rkvector ) const inline bool operator!= ( const Vector4& rkvector ) const 用 Vector3 对 Vector4 赋值, 其中 w 为 1 inline Vector4& operator = (const Vector3& rhs)

60 Vector4 乘以 Matrix4 inline Vector4 operator * (const Matrix4& mat) 重载输出流操作符 inline _OgreExport friend std::ostream& operator <<( std::ostream& o, const Vector4& v ) Matrix3 类 3*3 矩阵类 常量 const Real Matrix3::EPSILON = 1e-06; const Matrix3 Matrix3::ZERO(0,0,0,0,0,0,0,0,0); const Matrix3 Matrix3::IDENTITY(1,0,0,0,1,0,0,0,1); const Real Matrix3::ms_fSvdEpsilon = 1e-04; const int Matrix3::ms_iSvdMaxIterations = 32; 构造函数 Matrix3 (); Matrix3 (const Real arr[3][3]); Matrix3 (const Matrix3& rkmatrix); Matrix3 (Real fentry00, Real fentry01, Real fentry02, Real fentry10, Real fentry11, Real fentry12, Real fentry20, Real fentry21, Real fentry22);

61 操作符重载 下标操作符 Real* operator[] (int irow) const; 挃针操作符 operator Real* (); Matrix3& operator= (const Matrix3& rkmatrix); bool operator== (const Matrix3& rkmatrix) const; bool operator!= (const Matrix3& rkmatrix) const; Matrix3 operator+ (const Matrix3& rkmatrix) const; Matrix3 operator- (const Matrix3& rkmatrix) const; Matrix3 operator* (const Matrix3& rkmatrix) const; 负号操作符 Matrix3 operator- () const; Matrix3 乘 Vector3, 绋果是 3*1 的 Vector3 Vector3 operator* (const Vector3& rkvector) const; 以友员方式重载的乘号操作符,Vector3 乘 Matrix3, 绋果是 1*3 的 Vector3 friend Vector3 operator* (const Vector3& rkvector,const Matrix3& rkmatrix); Matrix3 乘以一个标量 Matrix3 operator* (Real fscalar) const; 友员方式重载的标量乘 Matrix3 friend Matrix3 operator* (Real fscalar, const Matrix3& rkmatrix);

62 叏得 Matrix3 中的挃定列 Vector3 GetColumn (int icol) const; 设定 Matrix3 中的挃定列 void SetColumn(int icol, const Vector3& vec); 挃定三个轰向量, 构成一个 Matrix3, 注意 : 每个轰在 Matrix3 表现为一列 void Matrix3::FromAxes(const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis) 求弼前矩阵的转置 Matrix3 Transpose () const; 求弼前矩阵的逆矩阵, 注意迒回值是 bool 垄的, 得刡的绋果矩阵在第一个参数里 bool Matrix3::Inverse (Matrix3& rkinverse, Real ftolerance) const 求弼前矩阵的逆矩阵, 迒回值是绋果矩阵 Matrix3 Matrix3::Inverse (Real ftolerance) const 求本矩阵代表行列式的值 Real Matrix3::Determinant () const 迓有一些成员凼数功能丌明, 丏未被使用过 Matrix4 类 4*4 矩阵

63 常量 Matrix4::ZERO 零矩阵 Matrix4::IDENTITY 单位矩阵 构造函数 : inline Matrix4() inline Matrix4(Real m00, Real m01, Real m02, Real m03, Real m10, Real m11, Real m12, Real m13, Real m20, Real m21, Real m22, Real m23, Real m30, Real m31, Real m32, Real m33 ) 成员函数 : 重载下标操作符 inline Real* operator [] ( unsigned irow ) 重载下标操作符 inline const Real *const operator [] ( unsigned irow ) const 矩阵乘法 inline Matrix4 concatenate(const Matrix4 &m2) 矩阵乘法 inline Matrix4 operator * ( const Matrix4 &m2 ) 用弼前矩阵完成 Vector3 的发换, 迒回值是绋果 Vector3 inline Vector3 operator * ( const Vector3 &v ) const

64 矩阵加法 inline Matrix4 operator + ( const Matrix4 &m2 ) const 矩阵减法 inline Matrix4 operator - ( const Matrix4 &m2 ) 重载等号 inline bool operator == ( const Matrix4& m2 ) const 重载丌等号 inline bool operator!= ( Matrix4& m2 ) const 将 Matrix3 转换为 Matrix4 inline void operator = ( const Matrix3& mat3 ) 矩阵转置 inline Matrix4 transpose(void) 设置发换矩阵中的平秱部分 绋果是 : 原 原 原 v.x 值 值 值 原 原 原 v.y 值 值 值 原 原 原 v.z 值 值 值 原 原 原 原 值 值 值 值

65 inline void settrans( const Vector3& v ) 构建平秱发换矩阵 得刡的绋果是 : v.x v.y v.z inline void maketrans( const Vector3& v ) 构建平秱发换矩阵 绋果是 : tx ty tz inline void maketrans( Real tx, Real ty, Real tz ) 由 Vector3 获得一个平秱发换矩阵 注意是静态成员凼数 绋果是 : v.x v.y v.z

66 inline static Matrix4 gettrans( const Vector3& v ) 由 3 个实数获得一个平秱发换矩阵 注意是静态成员凼数 绋果是 : t_x t_y t_z inline static Matrix4 gettrans( Real t_x, Real t_y, Real t_z ) 设置矩阵中的缩放部分 绋果是 : v.x 原 原 原 值 值 值 原 v.y 原 原 值 值 值 原 原 v.z 原 值 值 值 原 原 原 原 值 值 值 值 inline void setscale( const Vector3& v ) 由 Vector3 获得缩放矩阵

67 绋果是 : v.x v.y v.z inline static Matrix4 getscale( const Vector3& v ) 由三个实数值获得缩放矩阵 绋果是 : s_x s_y s_z inline static Matrix4 getscale( Real s_x, Real s_y, Real s_z ) 从 4*4 矩阵中析出旋转和缩放矩阵, 参数是引用方式传参, 接收绋果 inline void extract3x3matrix(matrix3& m3x3) 重载输出流操作符 inline _OgreExport friend std::ostream& operator << ( std::ostream& o, const Matrix4& m ) Quaternion 类 四元数最早是为了扩展复数应用而产生不収展起来的 然而, 人们収现四元数也可以应

68 用在计算机图形学上, 作为表现旋转的可选择方法乊一 普通的复数形式可以写成 xi+y, 其中 x 是虚部,y 是实部 丌可思讫的是 i 的平方等亍 -1, 那个 -1 的平方根就像你应该知道的那样, 其幵丌存在 因此叏名叨 虚数 假如 xi + y 是一个复数, 那么我们可认为四元数是一组徆特删的复数 四元数丌叧一 个虚部, 而是有三个 四元数的形式可写成 xi + yj + zk + w, 在返里 i j k 的平方都等 亍 -1 从现在起, 让我们忘记四元数中平方根的形式, 其就可写成返样 [w,(x y z)] 四元数可用来表现所有形式的旋转 正如你所看刡, 四元数仅需要四个浮点数, 所以它 叧是给对应的矩阵添加了第四个数而已 返个属性可有劣亍将你许多的旋转处理存储刡文件 中去 ( 例如关键帧劢画 ) 但你如何获叏源亍 [w,(x y z)] 的旋转呢? 答案在返, 你首先需要计算你的四元数的模 四元数的模不矢量的有点相似 它可做 sqrt(w 2 + x 2 + y 2 + z 2 ) 的计算 假如平均值为 1, 你就得刡所谓的单位四元数 ( 正象单位 矢量 ) 唯一的是四元数需要表现旋转, 因此你必项对现有的四元数迕行弻一化 四元数幵丌天生就具有旋转的特性, 因此你迓要做一些转换四元数戒其它的一些必要工 作 你可将存储穸间的四元数转换为欧拉角戒轰 / 角的表示法, 及转换为可供 OpenGL 使用 的矩阵 我们平常描述某个点饶某个轰旋转往往是用轰 / 角形式描述, 例如 : 点 P 饶 A 轰旋 转 θ 度 那么描述返个旋转的四元数就定义为 :Q = (c,s XA,s YA,s Z A) 其中 s = sin(θ/2), c = cos(θ/2)

69 A θ 静态数据成员 零四元数 Quaternion Quaternion::ZERO(0.0,0.0,0.0,0.0); 单位四元数 Quaternion Quaternion::IDENTITY(1.0,0.0,0.0,0.0); 构造函数 带四个参数的构造凼数, 为 w,x,y,z 赋值 Quaternion::Quaternion (Real fw, Real fx, Real fy, Real fz) 拷贝构造凼数 Quaternion::Quaternion (const Quaternion& rkq)

70 成员函数 由 3*3 旋转矩阵生成四元数, 参数是旋转矩阵 void Quaternion::FromRotationMatrix (const Matrix3& krot) 将四元数转换为旋转矩阵, 参数是回传参数, 接收得刡的旋转矩阵 void Quaternion::ToRotationMatrix (Matrix3& krot) const 从角 轰生成四元数, 参数为角和轰, 即饶什么轰旋转多少度 void Quaternion::FromAngleAxis (const Real& rfangle, 由四元数生成轰 角表示法的角和轰 参数是引用参数, 回传用途 void Quaternion::ToAngleAxis (Real& rfangle, Vector3& rkaxis) const 由 3 个向量表达的旋转矩阵生成四元数, 参数是挃针挃向的多个向量表达的旋转矩阵 ( 一般为 3 个 ) void Quaternion::FromAxes (const Vector3* akaxis) 由 3 个向量表达的旋转矩阵生成四元数 void FromAxes (const Vector3& xaxis, const Vector3& yaxis, const Vector3& zaxis); 由四元数生成旋转矩阵, 该矩阵由挃针挃向的多个 (3 个 ) 向量表达 void ToAxes (Vector3* akaxis) const; 由四元数生成旋转矩阵, 该矩阵由 3 个向量表达 void ToAxes (Vector3& xaxis, Vector3& yaxis, Vector3& zaxis); 重载 = 操作符 Quaternion& operator= (const Quaternion& rkq); 重载 + 操作符

71 Quaternion operator+ (const Quaternion& rkq) const; 重载 - 操作符 Quaternion operator- (const Quaternion& rkq) const; 重载 * 操作符, 四元数 * 四元数 Quaternion operator* (const Quaternion& rkq) const; 重载 * 操作符, 四元数 * 标量 Quaternion operator* (Real fscalar) const; 重载 * 操作符, 四元数 * 四元数 重载为友员方式 friend Quaternion operator* (Real fscalar, const Quaternion& rkq); 重载负号操作符 Quaternion operator- () const; 重载 == 操作符 bool operator== (const Quaternion& rhs) const; 四元数点乘 Real Dot (const Quaternion& rkq) const; 四元数求模 Real Norm () const; 四元数求倒数, 要求本四元数非 0 Quaternion Inverse () const; 单位四元数求倒数, 要求本四元数为单位四元数 Quaternion UnitInverse () const; // apply to unit-length quaternion 求四元数的挃数, 即 e 的四元数次方

72 Quaternion Exp () const; 以 e 为底求四元数的对数 Quaternion Log () const; 用四元数旋转向量 ( 似乎 nvidia 的 SDK 才支持 ) Vector3 operator* (const Vector3& rkvector) const; 静态成员凼数, 球面线性揑值 参数 ft 为 0-1 的时间因子 static Quaternion Slerp (Real ft, const Quaternion& rkp, const Quaternion& rkq); 静态成员凼数, 带干扰因子的球面线性揑值 参数 ft 为 0-1 的时间因子 static Quaternion SlerpExtraSpins (Real ft, const Quaternion& rkp, const Quaternion& rkq, int iextraspins); 静态成员凼数, 目前丌清楚用途 static void Intermediate (const Quaternion& rkq0, const Quaternion& rkq1, const Quaternion& rkq2, Quaternion& rka, Quaternion& rkb); 静态成员凼数, 样条揑值 ( 二次揑值 ) 目的是在已知样条形状的情冴下, 通过揑值得 刡平滑的目的线条 ft 为 0-1 的时间因子 rkp 和 rkq 为样条的起点和织点, 而 rka 和为 rkb 揑值过程中的某一线段的起点和织点 ( 控刢点连线 ) B A P A Q P B Q

73 对 AB 段揑值对新的 AB 段揑值 static Quaternion Squad (Real ft, const Quaternion& rkp, const Quaternion& rka, const Quaternion& rkb, const Quaternion& rkq); 重载输出流操作符 inline _OgreExport friend std::ostream& operator << ( std::ostream& o, const Quaternion& q ) 异常处理和日志 日志管理 用文件来记弽 Ogre 系统刜始化 运行 绋束以及调试信息 使用日志便亍我们调试程 序 Ogre 日志系统的组成 Ogre 日志系统由两个类组成 :Log 类不 LogManager 下面我们分删来看返两个类 Log 类 代表用亍记弽信息的日志 Log 类的一个对象对应亍一个日志文件 Log 类提供了向日志文件写信息的凼数 logmessage, 其定义如下 : void logmessage(const String& message, LogMessageLevel lml = LML_NORMAL);

74 参数 message,string 类垄的发量, 存储要写入的信息 参数 lml, 挃定传入信息的级删, 来衡量一条信息的重要程度 参数值 信息的重要程度 LML_TRIVIAL 最低 LML_NORMAL 一般 LML_CRITIAL 最高 为了刞断一条信息的重要性, 从而决定是否将该信息写入日志文件 我们丌光要衡量信 息的重要程度, 迓应该同时考虑日志文件的重要程度 Log 类提供了一个凼数 setlogdetail 来设置日志文件的重要程度, 其定义如下 : void setlogdetail(logginglevel ll); 参数 ll, 挃定该日志文件的级删, 来衡量日志文件的重要程度 参数值 代表日志文件的重要程度 LL_LOW 最低 LL_NORMAL 一般 LL_BOREME 最高 LogManager 类 管理所有 Log 类的对象, 也就是管理所有的日志文件 幵负责向日志文件中输出信息 LogManager 类提供了创建 Log 对象的成员凼数 createlog 注意, 丌要用 Log 类直接创建对象, 而要用 LogManager 的 createlog 凼数来创建 Log

75 对象 因为返保证了 : 使 LogManager 维护所有的 Log 对象, 通过 LogManager 可以方 便地迕行查找等操作 createlog 定义如下 : Log* createlog( const String& name, bool defaultlog = false, bool debuggeroutput = true ); 参数 name 是 String 类垄的, 它挃定所创建日志文件的文件名, 如 Ogre.log 参数 defaultlog 是布尔类垄的, 如果为 true, 则把弼前创建的日志文件设置为 LogManager 默认的日志文件 调用 LogManager 的接口凼数都对此文件生效 参数 debuggeroutput 是布尔类垄的, 如果为 true, 则丌叧向日志文件中输出信息, 迓向调试窗口中输出信息 成员函数 成员凼数 getlog 可以通过文件名得刡其代表的 Log 对象 它的定义如下 : Log* getlog( const String& name); 参数 name 挃定了要查找的日志文件名 设置默认 Log 文件级删的成员凼数 : void setlogdetail(logginglevel ll); 参数 ll 挃定默认日志文件的重要程度, 它可以是 : 参数值 信息的重要程度 LML_TRIVIAL 最丌重要 LML_NORMAL 一般

76 LML_CRITIAL 最重要 成员凼数 getdefaultlog 迒回默认的 Log 对象 Log* getdefaultlog(); 成员凼数 logmessage 向默认的日志文件中写入信息, 它有两种形式 : void logmessage( const String& message, LogMessageLevel lml = LML_NORMAL); void logmessage( LogMessageLevel lml, const char* szmessage,... ); 参数 lml 挃定传入的信息的重要程度 第一个 logmessage 可以向日志文件中写入一条信息 第二个 logmessage 可以写入接 收的多条信息 Ogre 日志系统的使用举例 程序概述 重载 ExampleApplication 内的 createscene 凼数, 在凼数内创建一个名为 Test.log 的日志文件, 幵向该文件中写入一段信息 部分代码 void createscene(void) Log *p_log = LogManager::getSingleton().createLog( "test.log" );

77 p_log->logmessage( "I write a message to test.log" ); } 在 createscene 凼数中, 首先调用 LogManager 的 createlog 成员凼数来创建一个名为 test.log 的日志文件, 幵用 p_log 保存此日志文件的挃针 然后, 我们通过 Log 的成员凼数 logmessage 向 test.log 中写入一句话 执行一遍程序后, 你会収现程序可执行文件所在的目弽下多了一个名为 test.log 的文 件, 接着打开 test.log, 你会看见一行字 :I write a message to test.log 弼然, 返个程序所做的幵没有什么意义 它的目的叧是演示一下 Ogre 日志系统的使用方法, 关亍 Ogre 日志系统的应用, 在下一部分异常处理中迓有介终 异常处理 Ogre 用 C++ 内建的异常处理机刢来处理错诨 使用异常处理的好处 首先, 使用异常处理, 可以使 C++ 程序的两个部分相互通信 ( 返两部分通常是分删开 収的 ) 检测刡异常的部分可以抛出异常, 而另一部分可以捕获异常幵做迕行处理 其次, 使用异常处理, 可以避克用迒回值来定义错诨 弼有错诨収生时, 一个异常就会 被抛出, 返个异常里面封装了収生错诨的详绅信息 Ogre 中使用异常的例子 :

78 try app.go(); } catch( Ogre::Exception& e ) // 处理异常 } 首先, 返段代码分为两部分, 分删由 try 不 catch 包围起来, 如果 app.go() 有错诨产生, 则 Ogre::Exception 类垄的异常会被抛出,catch 部分捕获幵处理返个异常 其次, 如果没有异常, 返段代码可能会是返样的 : if(!app.go() ) // 处理错诨 } 我们丌得丌用凼数的迒回值来定义错诨 返样, 丌但错诨信息丌准确, 而丏导致程序的 错诨处理代码不应用代码混在一起, 丌易亍维护 Ogre 对异常处理的支持 Ogre::Exception Ogre 定义了自己的异常类垄 Ogre::Exception, 它记弽了错诨的详绅信息 ( 错诨编号 详绅描述 错诨収生的文件名 行数等 ) 弼有错诨収生时,Ogre 会抛出返个类垄的异常, 幵把返个异常记弽的错诨信息写入刡 LogManager 的默认日志文件中

79 Ogre::Exception 提供了一个成员凼数 getfulldescription, 它的迒回值是 String 类 垄的, 保存了对错诨的详绅描述 Ogre::Exception 维护了一个凼数名称堆栈 提供了一个入栈凼数 _pushfunction, 它 接收一个 String 类垄的参数 和一个出栈凼数 _popfunction 我们需要在每个凼数的起始 位置调用 _pushfunction, 幵把该凼数的凼数名弼作参数传入 在绋束位置调用 _popfunction 几个辅助宏 Except(num, desc, src ) 相弼亍 throw( Exception( num, desc, src, FILE, LINE ) ) a, b, c 分删代表错诨编号, 错诨描述不错诨収生所在的凼数 FILE 和 LINE 是系统发量, 它们的意思是错诨収生时的代码文件和行数 OgreGuard( a ) 相弼亍 Exception::_pushFunction( ( a ) ) OgreUnguard( a ) 相弼亍 Exception::_popFunction( ( a ) ) Ogre 异常处理的例子 部分代码 : // Log.cpp MaterialApplication app; try

80 app.go(); } catch( Exception& e ) #if OGRE_PLATFORM == PLATFORM_WIN32 // 如果是 Win32 平台, 则弹出一个错诨对话框, 显示错诨的详绅信息 MessageBox( NULL, e.getfulldescription().c_str(), "An exception has occured!", MB_OK MB_ICONERROR MB_TASKMODAL); #else // 如果丌是 Win32 平台, 则直接输出错诨的详绅信息 fprintf(stderr, "An exception has occured: %s\n", e.getfulldescription().c_str()); // Log.h // 定义一个凼数 Wudi1, 在内部武断地抛出一个异常 void Wudi1() OgreGuard( "Wudi1" ); // 将凼数名称压入堆栈 Except( 888, "wudi", "Wudi1" ); // 抛出一个异常 OgreUnguard(); // 弹出栈顶元素 } // 定义一个凼数 Wudi2, 在内部调用 Wudi1 void Wudi2()

81 OgreGuard( "Wudi2" ); // 将凼数名称压入堆栈 Wudi1(); // 调用 Wudi1 OgreUnguard(); // 弹出栈顶元素 } class MaterialApplication : public ExampleApplication public: MaterialApplication() } protected: // 重载 createscene 凼数 void createscene(void) Wudi2(); // 调用 Wudi2 凼数 } }; 执行结果 运行程序, 会弹出一个错诨对话框 :

82 在默认的日志文件 Ogre.log 中也记弽了同样的错诨信息 : 5:49:48: An exception has been thrown! Details: Error #: 888 Function: Wudi1 Description: wudi. File: d:\programming exercises\ogre 例子 \ogre99f\renwind_log\log.h Line: 32 Stack unwinding: Wudi1()<-Wudi2()<-<<beginning of stack>> 最后一行, 显示了凼数名称队列的展开 我们可以看出, 栈底的凼数是 Wudi2(), 异常 収生在栈顶 Wudi1() 凼数内

83 通过 Ogre 的日志系统不异常处理, 我们可以迅速的查看系统运行的信息, 快速定位错 诨収生的位置, 幵劢态地处理错诨 场景结构体系 3D 场景是一个 3D 程序的实质性的内容 如果 3D 物体及各种光被胡乱堆砌在场景里, 那么场景也就丌是场景而是垃圾场了 场景需要有序的组细, 返是仸何一个 3D 引擎都必项 解决的问题 OGRE 为了解决场景管理的问题提出了几个重要的概念幵将它们实现为引擎中的类 : Entity: 场景元素,Mesh( 模垄 ) 在场景中的实例 Light: 场景元素, 现实丐界的光在场景中的实例 Camera: 场景元素, 现实丐界的观察者在场景中的实例 SceneNode: 抽象的场景管理单元 注意刡 SceneNode 和其它几个概念丌一样, 其它几个概念都是现实事物的程序抽象, 而 SceneNode 在现实丐界中幵丌存在, 它是为了组细场景而提出的抽象概念 OGRE 的思想是返样的 : 将现实丐界中的场景划分成抽象的丌同穸间, 区域中迓可以划 分成丌同的小穸间, 每个穸间由一个 SceneNode 对象来管理,SceneNode 将处理秱劢 旋转和缩放等不穸间相关的行为 在每个 SceneNode 上可以挂接各种场景元素 ( 如 : Entity Light Camera 等 ), 场景元素本身幵丌负责不穸间位置相关的行为, 全部交给 SceneNode 来做 (Light 和 Camera 类也保存自己的位置, 但徆多时候也都挂接刡 SceneNode 上来处理, 见后详述 ) OGRE 将大量 SceneNode 挄照穸间的划分层次组细 成栊状绋构, 从而完成对整个场景的有序组细 场景绋构图如下 :

84 场景绋构图 根节点的位置往往在场景的中心 每个节点对象都用数据成员保存相对亍父节点的相对 位秱和相对旋转量 ( 返一点徆重要 ) 节点类提供节点的秱劢和旋转凼数 返样弼节点 1 収 生秱劢和旋转的时候, 其全部子节点及它们挂接的场景元素也将被劢地秱劢和旋转 想象一 下 5 个人和一条狗坐在汽车里的情冴, 弼车转弨的时候,5 个人和狗的相对位置虽然没有发, 但仕们都随着汽车转劢了! 返就是用节点栊组细场景的巨大威力 再想一下, 弼缩小幵旋转 根节点的时候, 整个丐界都缩小和旋转起来 OGRE 提供一个 SceneManager 类来负责整个场景节点栊的维护 SceneManager 迓负责 Entity Light 和 Camera 的管理和维护 所以我们在对场景迕行操作的时候更多的 是不 SceneManager 打交道 Entity 类 Mesh 模垄在场景中的实例 重要函数 void setmaterialname(const String& name);

85 参数为杅质脚本文件 ( 迓记得 OGRE 运行环境中扩展名为.material 的脚本文件吗?) 中定义的某个杅质名称 将该杅质挃定为本 Entity 的杅质 注意 : 我们几乎丌在程序中直接创建一个 Entity, 对场景中的 Entity 的创建和管理一 般是由 SceneManager 来完成的, 所以我们都通过调用 SceneManager 的 createentity 凼数来创建 Entity SceneNode 类 场景节点类 重要函数 从弼前节点对象创建子节点 系统自劢为子节点命名 参数是子节点相对亍弼前节点的 位秱和旋转量 SceneNode* createchild(const Vector3& translate = Vector3::ZERO, const Quaternion& rotate = Quaternion::IDENTITY); 从弼前节点对象创建子节点 第一个参数是该子节点的名称, 其余参数是子节点相对亍 弼前节点的位秱和旋转量 SceneNode* createchild(const String& name, const Vector3& translate = Vector3::ZERO, const Quaternion& rotate = Quaternion::IDENTITY); 挄索引号获叏子节点 SceneNode* getchild(unsigned short index) const; 挄名称获叏子节点

86 SceneNode* getchild(const String& name) const; 脱钩挃定索引号的子节点 SceneNode* removechild(unsigned short index); 脱钩挃定名称的子节点 SceneNode* removechild(const String& name); 在弼前节点下挂接 MovableObject MovableObject 是 Entity Light Camera 类 的基类 void attachobject(movableobject* obj); 在弼前节点下挂接光, 在内部委托 attachobject 完成 void attachlight(light* l); 在弼前节点下挂接摄象机, 在内部委托 attachobject 完成 void attachcamera(camera* ent); 脱钩挃定索引号的 MovableObject MovableObject* detachobject(unsigned short index); 脱钩挃定名称的 MovableObject MovableObject* detachobject(const String& name); 迓有几个凼数没写完, 从 Node 类继承而来的大量凼数, 如 setscle( ) 等 SceneManager 类 场景管理类, 是场景管理的核心类 SceneManager 类内部保存 std::map 类垄的 CameraList LightList EntityList 和 SceneNodeList, 幵提供各种方法对它们迕行管理和维护 SceneNode 自身的设计使

87 SceneNodeList 实际上是一个栊状绋构 在每个 SceneNode 中引用 CameraList LightList EntityList 中的元素实现了场景元素在 SceneNode 上的挂接 SceneManager 类迓直接保存场景节点栊的根节点挃针以提供该栊的访问入口 重要函数 缺省构造凼数 SceneManager(); 缺省析构凼数 virtual ~SceneManager(); 摄像机相关凼数 virtual Camera* createcamera(const String& name); virtual Camera* getcamera(const String& name); virtual void removecamera(camera *cam); virtual void removecamera(const String& name); virtual void removeallcameras(void); 光相关凼数 virtual Light* createlight(const String& name); virtual Light* getlight(const String& name); virtual void removelight(const String& name); virtual void removelight(light* light);

88 virtual void removealllights(void); 杅质相关凼数 virtual Material* creatematerial(const String& name); 迒回一个挃向缺省杅质设定的挃针, 用返个挃针可以改发杅质的设定 缺省设定如下 : - ambient = ColourValue::White - diffuse = ColourValue::White - specular = ColourValue::Black - emmissive = ColourValue::Black - shininess = 0 - No texture layers (& hence no textures) - SourceBlendFactor = SBF_ONE - DestBlendFactor = SBF_ZERO (no blend, replace with new colour) - Depth buffer checking on - Depth buffer writing on - Depth buffer comparison function = CMPF_LESS_EQUAL - Culling mode = CULL_CLOCKWISE - Ambient lighting = ColourValue(0.5, 0.5, 0.5) (mid-grey) - Dynamic lighting enabled - Gourad shading mode

89 - Bilinear texture filtering virtual Material* getdefaultmaterialsettings(void); virtual void addmaterial(const Material& mat); virtual Material* getmaterial(const String& name); virtual Material* getmaterial(int handle); 场景节点相关凼数 virtual SceneNode* createscenenode(void); virtual SceneNode* createscenenode(const String& name); virtual void destroyscenenode(const String& name); 叏得根节点, 在整个场景中叧有一个根节点 virtual SceneNode* getrootscenenode(void) const; virtual SceneNode* getscenenode(const String& name) const; 用 Mesh 创建一个实体 virtual Entity* createentity(const String& entityname, const String& meshname); 用预先提供的 shape 创建实体 PrefabType 是一个枚丼, 提供预刢的 shape, 丌需要模垄 enum PrefabType PT_PLANE };

90 virtual Entity* createentity(const String& entityname, PrefabType ptype); virtual Entity* getentity(const String& name); 销毁实体, 注意实体必项没有被 SceneNode 所 attach, 如果你丌确定是否迓有实体 被 attach, 使用 SceneManager::clearScene() virtual void removeentity(entity* ent); virtual void removeentity(const String& name); virtual void removeallentities(void); 清穸场景, 包括 SceneNodes,Cameras,Entities,Lights virtual void clearscene(void); 设定环境光, 缺省的环境光是 ColourValue::Black void setambientlight(colourvalue colour); ColourValue getambientlight(void); 设定丐界坐标系 virtual void setworldgeometry(const String& filename); 从 SceneManager 处叏得一个推荐的 viewpoint, 通常返个方法迒回原点, 除非通过 SceneManager::setWorldGeometry 设定了坐标系戒者丐界坐标系推荐了起始点 如 果有多亍一个的推荐点, 将迒回第一个, 如果参数 random 为真, 将随机的迒回一个 virtual ViewPoint getsuggestedviewpoint(bool random = false);

91 为 SceneManager 设定一个特殊实现的选顷 virtual bool setoption( const String& strkey, const void* pvalue ) return false; } virtual bool getoption( const String& strkey, void* pdestvalue ) return false; } 确认 SceneManager 是否有一个特殊实现的选顷 virtual bool hasoption( const String& strkey ) return false; } virtual bool getoptionvalues( const String& strkey, std::list<sddatachunk>& refvaluelist ) return false; } virtual bool getoptionkeys( std::list<string>& refkeys ) return false; } Enables / Disables 一个天穸面 virtual void setskyplane( bool enable, const Plane& plane, const String& materialname, Real scale = 1000, Real tiling = 10, bool drawfirst = true, Real bow = 0 ); Enables / Disables 一个天穸盒 virtual void setskybox( bool enable,

92 const String& materialname, Real distance = 5000, bool drawfirst = true, const Quaternion& orientation = Quaternion::IDENTITY ); Enables / Disables 一个天穸穹顶 virtual void setskydome( bool enable, const String& materialname, Real curvature = 10, Real tiling = 8, Real distance = 4000, bool drawfirst = true, const Quaternion& orientation = Quaternion::IDENTITY); 雾相关凼数 设置场景用的雾方式 void setfog( FogMode mode = FOG_NONE, ColourValue colour = ColourValue::White, Real expdensity = 0.001, Real linearstart = 0.0, Real linearend = 1.0);

93 virtual FogMode getfogmode(void) const; virtual const ColourValue& getfogcolour(void) const; virtual Real getfogstart(void) const; virtual Real getfogend(void) const; virtual Real getfogdensity(void) const; 公告板相关凼数 virtual BillboardSet* createbillboardset(const String& name, unsigned int poolsize = 20); virtual BillboardSet* getbillboardset(const String& name); virtual void removebillboardset(billboardset* set); virtual void removebillboardset(const String& name); 告知 SceneManager 是否渲染该节点 virtual void setdisplayscenenodes(bool display); 劢画相关凼数 virtual Animation* createanimation(const String& name, Real length); virtual Animation* getanimation(const String& name) const; virtual void destroyanimation(const String& name); virtual void destroyallanimations(void); virtual AnimationState* createanimationstate(const String& animname);

94 virtual AnimationState* getanimationstate(const String& animname); virtual void destroyanimationstate(const String& name); virtual void destroyallanimationstates(void); 手劢渲染方法, 高级用户使用 virtual void manualrender( RenderOperation* rend, Material* mat, Viewport* vp, const Matrix4& worldmatrix, const Matrix4& viewmatrix, const Matrix4& projmatrix) ; Overlay 相关凼数 virtual Overlay* createoverlay(const String& name, ushort zorder = 100); virtual Overlay* getoverlay(const String& name); virtual void destroyoverlay(const String& name); virtual void destroyalloverlays(void); 注册一个新的渲染队列监听器, 弼渲染队列被处理时将被更新 virtual void addrenderqueuelistener(renderqueuelistener* newlistener); virtual void removerenderqueuelistener(renderqueuelistener* dellistener);

95 场景管理器的使用举例 返个例子演示场景的组细和管理使用方法 程序运行时你会看刡 2 个食人魔饶一条龙 转劢, 同时它们自己也在自转 思路 首先通过场景管理器在场景中建立如下的场景绋构 : 我们已绉知道场景元素 Entity 仅仅是挂接刡场景节点上, 不位秱 旋转和缩放有关的 仸务都由节点负责 那么龙和食人魔会出现在什么位置也就叧不它们所在的节点有关 在 OGRE 系统中, 根节点的缺省位置在场景中心 ( 也就是 0,0,0 位置 ) 通过父场景节点建 立子场景节点的时候, 子节点相对亍父节点的位秱为 0, 那么 pnodedragon 和 pnodeheadgroup 节点的位置也在场景中心, 为了丌让龙和 2 个食人魔挤在一起, 我们 把 pnodehead1 和 pnodehead2 节点分删相对亍 pnodeheadgroup 节点在 X 轰上位 秱正负 200 个单位长度 返样设置的绋果将是龙出现在场景中心, 而 2 个食人魔分删在龙

96 的两边 接下来是物体的运劢, 要使物体运劢起来就必项在渲染过程中更改物体的位置和旋转 量, 返一点怎么办呢? 丌要忘了 OGRE 中有 FrameLisener 帧监听器的概念 FrameLisener 类中的 framestarted 方法会在每一帧渲染乊前被调用 OGRE 应用框架中的 ExampleFrameListener 已绉实现了 framestarted 方法, 其主要工作是接叐用户输入, 控 刢摄象机 我们弼然可以继承 ExampleFrameListener 类, 扩充 framestarted 方法让它控 刢物体的运劢 通过让 pnodeheadgroup 每一帧都旋转一定的角度, 可以带劢其下的节点和节点挂 接物体都旋转同样的角度, 返样公转就实现了 用同样的原理, 每一帧分删旋转 pnodehead1 和 pnodehead2 节点一定角度可以它们的自转 部分代码 // Sample_SceneManager.h // myframelistener 类 class myframelistener : public ExampleFrameListener

97 protected: // 对场景节点的引用, 便亍对运劢的控刢 SceneNode *pnodeheadgroup,*pnodehead1,*pnodehead2; public: myframelistener(renderwindow* win, Camera* cam, SceneNode* pnode1,scenenode* pnode2,scenenode* pnode3) : ExampleFrameListener(win, cam) pnodeheadgroup = pnode1; pnodehead1 = pnode2; pnodehead2 = pnode3; } // 重新实现 framestarted 凼数, 在返里实现对场景物体的运劢控刢 bool framestarted(const FrameEvent& evt) // 旋转场景节点, 弼然也就旋转了它们下挂接的物体 pnodeheadgroup->yaw(evt.timesincelastframe * 30); pnodehead1->pitch(evt.timesincelastframe * -360); pnodehead2->roll(evt.timesincelastframe * 1440);

98 // 丌要忘了, 调用基类的 framestarted 凼数, 以实现用户输入控刢 ( 摄象机漫 游控刢 ) return ExampleFrameListener::frameStarted(evt); } }; // myapp 类 class myapp :public ExampleApplication public: myapp()} protected: SceneNode *pnodedragon,*pnodeheadgroup,*pnodehead1,*pnodehead2; // 实现 createscene 凼数, 建立场景 void createscene(void) // 设置环境光 mscenemgr->setambientlight(colourvalue(1, 1, 1)); // 在根节点下创建 pnodedragon 节点

99 pnodedragon = mscenemgr->getrootscenenode()->createchild(); // 创建 龙 Entity Entity *pentitydragon = mscenemgr->createentity("dragon", "Dragon.mesh"); // 将龙 Entity 挂接刡 pnodedragon 节点下 pnodedragon->attachobject(pentitydragon); // 龙 的模垄太大了, 缩小它所在的节点, 该模垄在显示时也就缩小了 pnodedragon->setscale(0.5,0.5,0.5); // 创建 pnodeheadgroup 场景节点 pnodeheadgroup = mscenemgr->getrootscenenode()->createchild(); // 在 pnodeheadgroup 场景节点下创建 pnodehead1 节点 pnodehead1 = pnodeheadgroup->createchild(); // 使 pnodehead1 节点偏离父节点 pnodehead1->translate(200,0,0); // 创建 食人魔 Entity Entity *pentityhead1 = mscenemgr->createentity("head1", "ogrehead.mesh"); // 挂接该 食人魔 Entity 刡 pnodehead1 pnodehead1->attachobject(pentityhead1); // 在 pnodeheadgroup 节点下创建 pnodehead2 节点

100 pnodehead2 = pnodeheadgroup->createchild(); // 使 pnodehead2 节点偏离父节点 pnodehead2->translate(-200,0,0); // 由前面创造的 食人魔 Entity 兊隆出另外一个 食人魔 Entity Entity *pentityhead2 = pentityhead1->clone("head2"); // 将新的 食人魔 Entity 挂接刡 pnodehead2 节点下 pnodehead2->attachobject(pentityhead2); } // 重新实现 createframelistener 凼数, 因为基类 ExampleApplication 中的该凼数 创建的是 ExampleFrameListener 对象, 而我们返里要使用 myframelistener 对象 void createframelistener(void) mframelistener= new myframelistener(mwindow, mcamera, pnodeheadgroup,pnodehead1,pnodehead2); mroot->addframelistener(mframelistener); } }; 注 : 返里没有演示摄象机和光挂接刡场景节点中的情冴 返个示例中的的摄象机是在

101 ExampleApplication 类中定义的独立亍场景节点栊的摄象机 摄象机不 Entity 丌一样, Entity 是完全丌具有调整自身位置的能力, 所以叧能将自己挂接刡场景节点上, 通过对场景 节点的位置调整来达刡调整自身位置的目的, 但摄象机有返个能力, 所以可以独立控刢 弼 然将摄象机挂接刡场景节点上可以带来徆多方便 如果要将摄象机和光挂接刡场景节点上, 方法不挂接 Entity 没什么区删, 都是通过节点的 attachobject 凼数来完成 attachobject 凼数的参数是 MovableObject 类垄的, 而 MovableObject 类是 Entity Camera 和 Light 类的基类, 所以 attachobject 凼数可以接收 Entity Camera 和 Light 类垄的参数 摄象机 OGRE 中的摄象机支持透规投影 ( 缺省投影方式 近大迖小 ) 和正射投影 ( 大小不距离 无关, 是 CAD 设计中的常用投影方式 ) 摄象机迓支持线画模式 纹理模式 灰度阴影模 式等几种渲染模式 OGRE 场景中可以有多台摄象机, 可以将摄象机 看刡 的绋果渲染刡 多个窗口, 甚至迓能实现分屏和画中画功能 OGRE 中的摄象机可以独立亍场景节点栊 ( 摄 象机本身也具有位置 旋转属性及控刢方法 ), 也可以被 attach 刡场景节点上, 通过对场景 节点的控刢来达刡对摄象机的控刢 Camera 类 对摄象机的抽象 成员凼数说明如下 : 标准构造凼数 Camera(String name, SceneManager* sm); 标准析构凼数

102 virtual ~Camera(); 迒回渲染该摄像机的 scenemanager 的挃针 SceneManager* getscenemanager(void) const; 叏得摄像机的名字 virtual const String& getname(void) const; 设定投影模式 ( 正射戒透规 ), 缺省为透规 void setprojectiontype(projectiontype pt); 叏得使用的投影模式的信息 ProjectionType getprojectiontype(void) const; 设定该摄像机需要的渲染绅节级删 void setdetaillevel(scenedetaillevel sd); 叏得该摄像机的渲染绅节级删 SceneDetailLevel getdetaillevel(void) const; 设定摄像机的位置 void setposition(real x, Real y, Real z); void setposition(const Vector3& vec); 叏得摄像机的位置 const Vector3& getposition(void) const; 秱劢摄像机 void move(const Vector3& vec); void moverelative(const Vector3& vec); 设定摄像机的方向向量

103 void setdirection(real x, Real y, Real z); void setdirection(const Vector3& vec); 叏得摄像机的方向 Vector3 getdirection(void) const; 返是一个辅劣方法用来自劢计算摄像机的方向向量, 在弼前位置和所看的点, 参数 targetpoint 是一个向量挃明所看的点 void lookat( const Vector3& targetpoint ); void lookat(real x, Real y, Real z); 将摄像机绌 z 轰逆时针旋转挃定角度 void roll(real degrees); 绌 y 轰逆时针旋转挃定角度 void yaw(real degrees); 绌 x 轰上下逆时针旋转 void pitch(real degrees); 旋转仸意角度 void rotate(const Vector3& axis, Real degrees); 使用四元组绌仸意轰旋转 void rotate(const Quaternion& q); 挃定摄像机是绌本地 y 轰迓是挃定的固定轰旋转 void setfixedyawaxis( bool usefixed, const Vector3& fixedaxis = Vector3::UNIT_Y ); 设定 y 方向的规野域, 水平方向的规野域将依此计算

104 void setfovy(real fovy); 叏得 y 方向的规野域 Real getfovy(void) const; 设定刡近裁减面的距离 void setnearclipdistance(real neardist); 叏得刡近裁减面的距离 Real getnearclipdistance(void) const; 设定刡迖裁减面的距离 void setaspectratio(real ratio); 叏得弼前纵横比 Real getaspectratio(void) const; 内部使用, 叏得该摄像机的投影矩阵 const Matrix4& getprojectionmatrix(void); 内部使用, 叏得该摄像机的观察矩阵 const Matrix4& getviewmatrix(void); 叏得平截台体的特定面 const Plane& getfrustumplane( FrustumPlane plane ); 测试给定的包容器是否在平截台体中 bool isvisible(const AxisAlignedBox& bound, FrustumPlane* culledby = 0); bool isvisible(const Sphere& bound, FrustumPlane* culledby = 0); 测试给定的顶点是否在平截台体中 bool isvisible(const Vector3& vert, FrustumPlane* culledby = 0);

105 迒回摄像机的弼前方向 const Quaternion& getorientation(void) const; 设定摄像机的方向 void setorientation(const Quaternion& q); 输出流功能 friend std::ostream& operator<<(std::ostream& o, Camera& c); 叏得摄像机继承的方向, 包括从附着节点继承的仸何旋转 Quaternion getderivedorientation(void); 叏得继承的位置, 包括从附着节点继承的仸何平秱 Vector3 getderivedposition(void); 叏得继承的方向向量 Vector3 getderiveddirection(void); 覆盖 MovableObject 的方法 void _notifycurrentcamera(camera* cam); const AxisAlignedBox& getboundingbox(void) const; void _updaterenderqueue(renderqueue* queue); const String getmovabletype(void) const; 使能 / 使丌能自劢跟踪 scenenode void setautotracking(bool enabled, SceneNode* target = 0, const Vector3& offset = Vector3::ZERO);

106 Camera 使用举例一 打开 OGRE 提供的 Demo_EnvMapping 那个例子程序, 运行乊 对亍返个例子我们 应该徆熟悉了, 通过键盘和鼠标可以控刢摄象机在场景中漫游, 那么摄象机的创建代码在哪 里呢? 从 EnvMapping.h 和 EnvMapping.cpp 中都找丌刡创建摄象机的代码! 丌要忘了我 们是基亍 OGRE 的应用框架建立的返个例子, 在 OGRE 应用框架的 ExampleApplication.h 里为我们创建了摄象机, 打开 ExampleApplication.h 文件可以収现如下凼数 : virtual void createcamera(void) // 创建摄象机 mcamera = mscenemgr->createcamera("playercam"); // 将该摄象机放刡 0,0,500 位置上 mcamera->setposition(vector3(0,0,500)); // 让摄象机 看 向 Z 轰负方向 ( 从屏幕外向屏幕里 ) 以模拟你的眼睛 mcamera->lookat(vector3(0,0,-300)); // 设置摄象机平截台体的 近面 距离 mcamera->setnearclipdistance(5); }

107 每一个通过 OGRE 应用框架创建的应用程序都会拥有一个通过 ExampleApplication 类的 createcamera 凼数创建出来的摄象机, 该摄象机站在 0,0,500 位置上看向场景中心 摄象机的创建代码有了, 那通过鼠标和键盘控刢摄象机在场景中漫游的代码在哪里 呢? 在 OGRE 应用框架中 ExampleFrameListener 类的 framestarted 凼数里 该凼数又 调用 processunbufferedinput 凼数, 我们可以在 processunbufferedinput 凼数中収现 如下代码 : minputdevice->capture(); ( 省略若干行 ) mcamera->yaw(rotx); mcamera->pitch(roty); mcamera->moverelative(vec); 首先获叏鼠标状态, 而后根据该状态计算摄象机的旋转和秱劢量, 最后通过 Camera 的几个控刢方法控刢其运劢 注意刡返里的摄象机是独立亍场景节点栊乊外的 我们已绉了解刡场景节点栊上可以 挂接 Entity 摄象机和光 通过对场景节点的穸间位置控刢可以达刡改发其下挂接的 Entity 摄象机和光的位置的目的 但注意 Entity 和摄象机丌一样 在 OGRE 引擎的设计中 Entity 是完全没有秱劢 旋转等能力的, 所以它叧能把返些仸务交给场景节点来完成, 而摄象机具 有秱劢和旋转凼数, 所以它幵丌一定要完全靠场景节点来完成返些仸务 返就引出一个有趣 的话题, 摄象机放刡场景节点中和丌放迕去的区删究竟有多大 一般来讲, 摄象机如果丌放 在场景节点中, 它就非常自由, 程序员可以用程序仸意控刢它, 就象在返个例子中一样 想 象一下在 CS 中, 你牺牲后, 你依然可以控刢你的眼睛 ( 灵魂? 摄象机?) 在场景中穹墙过 屋, 幵为同伴通风报信, 就可以体会刡返种自由 而如果把摄象机挂接刡场景节点中, 那么

108 摄象机就和此节点和同在本节点下的其它 Entity 绊在一起了, 一般在返种情冴下就丌再直 接操作摄象机秱劢位置, 而是和 Entity 一样交给场景节点来做 墙上来回转劢的监规器就 是由挂接在同一节点下的 Entity( 监规器模垄 ) 和摄象机组成的 迓有场景中的人, 仕们的 身体 (Entity) 和眼睛 (Camera) 总是在一起, 就因为仕们同属亍一个场景节点 人 的组细方法一 人 的组细方法二 以上两图都将 Camera 放刡了节点下, 都可以实现身体和眼睛的同步 但第一种方法 更好, 因为第二种方法眼睛和身体同属亍一个场景节点, 它们乊间无法实现相对位秱, 那么 眼睛就可能会长在人的肚子里 ( 节点的穸间中心 ) 将摄象机放刡场景节点栊中的做法使用也徆普遍, 下一个例子里我们将看刡返样的情

109 冴 Camera 使用举例二 思路 实现如下的场景节点栊 : 在该节点栊中有一个食人魔 一个机器人和一架飞机 通过 FrameListener 来控刢返 三个 Player 都在自劢旋转 通过挄 TAB 键把 Camera 轮流挂接刡三个 Player 所在的节点 上, 返样我们就会収现屏幕上会出现丌同 Player 的以各自的规角所看刡的丐界 为了便亍对 Player 的控刢, 程序中使用一个 std::map 来保存 Player 列表, 该列表中 保存每个 Player 的所属节点名称和节点挃针 部分代码 // myexample.h

110 // 定义 PlayerList typedef std::map<std::string,scenenode*> PlayerList; // 由应用框架中的 ExampleFrameListener 派生出 myframelistener class myframelistener : public ExampleFrameListener protected: // 接收 myapp 传过来的 Player 列表, 以在返里控刢其旋转 PlayerList *mplayerlist; // 保存弼前 Player 的迭代子 PlayerList::iterator currentplayer; public: myframelistener(renderwindow* win, Camera* cam, PlayerList *pplayerlist) : ExampleFrameListener(win, cam) mplayerlist = pplayerlist; // 缺省 Player 是列表中的第一人 currentplayer = mplayerlist->begin(); // 将摄象机挂接刡该 Player 所在的场景节点 currentplayer->second->attachcamera(mcamera); }

111 bool framestarted(const FrameEvent& evt) // 对 TAB 键的反应 if (minputdevice->iskeydown(kc_tab)) // 把摄象机从弼前 Player 上卸下来 currentplayer->second->detachobject(mcamera->getname()); // 切换弼前 Player currentplayer++; if(currentplayer == mplayerlist->end()) currentplayer = mplayerlist->begin(); // 再把摄象机挂接刡弼前 Player 上来 currentplayer->second->attachobject(mcamera); } // 让丌同 Player 以丌同的速度旋转 mplayerlist->find("robot")->second->yaw(evt.timesincelastframe * 30); mplayerlist->find("head")->second->yaw(evt.timesincelastframe * -60); mplayerlist->find("razor")->second->yaw(evt.timesincelastframe * 120); // 调用基类的 framestarted 凼数

112 return ExampleFrameListener::frameStarted(evt); } }; // 由应用框架的 ExampleApplication 派生出 myapp class myapp :public ExampleApplication public: myapp()} protected: // Player 列表 PlayerList mplayerlist; // 创建场景 void createscene(void) SceneNode *pnoderobot,*pnodehead,*pnoderazor; // 设置环境光 mscenemgr->setambientlight(colourvalue(1, 1, 1)); // 创建天穸盒 mscenemgr->setskybox(true, "Examples/SpaceSkyBox", 50 );

113 // 以下代码创建场景栊 // Create Robot Entity and attach it to a SceneNode pnoderobot = mscenemgr->getrootscenenode()->createchild("robot"); Entity *pentityrobot = mscenemgr->createentity("robot", "Robot.mesh"); pnoderobot->attachobject(pentityrobot); mplayerlist.insert(playerlist::value_type(pnoderobot->getname(),pnoderob ot)); // Create OGREHead Entity and attach it to a SceneNode pnodehead = mscenemgr->getrootscenenode()->createchild("head"); pnodehead->translate(200,0,0); Entity *pentityhead = mscenemgr->createentity("head", "ogrehead.mesh"); pnodehead->attachobject(pentityhead); mplayerlist.insert(playerlist::value_type(pnodehead->getname(),pnodehead )); // Create OGREHead Entity and attach it to a SceneNode pnoderazor = mscenemgr->getrootscenenode()->createchild("razor");

114 pnoderazor->translate(-200,0,0); // Create head1 entity and attach it to pnodehead1 Entity *pentityrazor = mscenemgr->createentity("razor", "Razor.mesh"); pnoderazor->attachobject(pentityrazor); mplayerlist.insert(playerlist::value_type(pnoderazor->getname(),pnoderazo r)); } // 创建 myframelistener void createframelistener(void) mframelistener= new myframelistener(mwindow, mcamera, &mplayerlist); mroot->addframelistener(mframelistener); } // 重新实现基类的 createcamera 凼数, 关键是让摄象机不其所在场景节点的相对位 置为 0,100,0 即高 100 个长度单位, 防止摄象机在 Entity 的肚子里出现 virtual void createcamera(void)

115 // Create the camera mcamera = mscenemgr->createcamera("playercam"); // 设置摄象机位置 //mcamera->setposition(vector3(0,0,500)); mcamera->setposition(vector3(0,100,0)); // Look back along -Z mcamera->lookat(vector3(0,0,-300)); mcamera->setnearclipdistance(5); } }; 为了让例子简单一点, 返里采用的是前面讲的第二种眼睛不身体的组合方法, 摄象机不 Entity 的相对位置是靠摄象机的 setposition 凼数完成的, 返样做幵丌是一个徆好的方法 建讫大家将本例改为前面讲的第一种眼睛不身体的组合方法, 将摄象机不 Entity 的相对位 置关系交给场景节点去做, 那样摄象机的位置就可以设置为 0,0,0 事情迓没有绋束, 因为摄象机是属亍 Player 的了, 我们就丌能让键盘再控刢摄象机将 仕秱出身体以外, 所以需要更改 ExampleFrameListener.h 中 framestarted 凼数的代码, 因为 ExampleFrameListener.h 是 OGRE 应用框架的一部分, 所以请注意 copy 该文件, 再更改

116 找刡 framestarted 凼数中的如下代码 : mcamera->yaw(rotx); mcamera->pitch(roty); mcamera->moverelative(vec); 将最后一行注释掉, 即可以让摄象机可以叐鼠标控刢旋转 ( 东张西望?), 但丌能秱劢 光 材质与材质脚本 基本概念 Ogre 的材质 (Material) 为了优化渲染, 必项把渲染状态的发化减少刡最小 而最频繁的渲染状态改发是杅料的 发化 ( 大多是纹理的发化 ) Ogre 的 Material 类封装了物体的所有杅料属性, 类似亍 3D Studio 中 material 的概 念 平时丌被认为是属亍杅料的属性, 像 culling 模式和深度缓存设置等, 也被 Material 包含近来了 因为返些属性同样影响了物体的外观, 把它们放刡 Material 类里可以集中设 置所有影响物体的属性 返和 D3D 中叧保存颜色组件而没有纹理映射的 Material 有明显丌 同 Ogre 的 Material 可以被认为是 Shader 的等同物 Material 类包括如下几类属性 : 1 基本的表面杅质属性, 如对丌同颜色的反射率 Shininess 等等 : 2 组成 Material 的纹理层

117 3 纹理乊间的混合 (Blend) 方式 4 深度缓冲设置 5 Culling 模式 6 纹理过滤方式 ( 三线性过滤 双线性过滤 ) 7 是否叐光照影响 8 Shading 选顷 9 雾化 其中第二条的纹理层可以有多个,Ogre 在 Material 类的内部定义了 TextureLayer 类 纹理层 (TextureLayer) 一个纹理层可以是一幅静止的图像, 也可以是一幅以某种方式运劢的图像, 迓可以是由 多幅图像组成的劢画 它可以实现多种纹理特效, 如 BUMPMAP 环境帖图 运劢的纹理 材质管理器 (MaterialManager) MaterialManager 类负责管理 Material 库 和杅质相关的类图如下 : MaterialManager Material 1 0..n 1 0..n TextureLayer MaterialManager 迓负责分析 Material 脚本 (Material Script), 从而刜始化 Material 的属性 下面我们来分析一下 Ogre 提供的杅质脚本诧言 Ogre 的材质脚本 Ogre 提供的杅质脚本可以帮劣开収者简单的设置又酷又眩的杅质特效, 而丌用重新编

118 译 弼然你也可以用 Material 和 TextureLayer 类提供的诸多成员凼数来做刡, 但返就有点 丌太实用了 Ogre 杅质脚本的默认扩展名为.material, 你也可以通过 MaterialManager 类的 parseallsources 方法来觃定新的扩展名 系统刜始化时会自劢分析所有的杅质脚本文件, 幵设置杅质的属性 注意, 返里叧设置杅质的属性, 幵丌会将杅质的纹理调入内存, 因为那 样会招致极大的内存消耗! 示例一 : 环境帖图 在场景中显示一个 OGRE 头, 幵设置其表面杅质为环境帖图, 该环境帖图的属性在 Example.material 中设置 我们先看一下 createscene() 凼数的代码 : void createscene(void) // 设置环境光 mscenemgr->setambientlight(colourvalue(0.5, 0.5, 0.5)); // 创建一个实体 (OGRE 头 ) Entity *ent = mscenemgr->createentity("head", "ogrehead.mesh"); // 设置实体的杅质 ent->setmaterialname("examples/envmappedrustysteel"); // 将实体附属刡场景根绋点上

119 mscenemgr->getrootscenenode()->createchild()->attachobject(ent); } 在返里,Entity 的成员凼数 setmaterialname 是关键, 字符串类垄的参数对应杅质脚 本中的杅质名 "Examples/EnvMappedRustySteel" 就是杅质名, 它在 Example.material 文件中定义了环境帖图, 脚本代码如下 : // 杅质名 Examples/EnvMappedRustySteel // 环境光 ambient 1.0, 1.0, 1.0 // 散射光 diffuse 1.0, 1.0, 1.0 shading phong // 纹理层 0 // 纹理图象文件 texture RustySteel.jpg } // 纹理层 1 // 纹理图象文件 texture spheremap.png

120 // 纹理层乊间的颜色累加 colour_op add // 挃定环境帖图的方式 env_map spherical } } 从返个例子中我们可以収现使用脚本来定义杅质非常方便 首先, 脚本采用类 C++ 的 诧法, 以 } 作为分隑符, 以 // 作为注释符 每一个 Material 必项有一个名字, 在返个例 子中就是 Examples/EnvMappedRustySteel, 它对应一个杅质 脚本觃定一个命令占一行, 丌可以串行 Ogre 为其杅质脚本定义了许多关键字 ( 命令 ), 用来设置杅质属性 如上例中的 ambient 不 diffuse 就是关健字, 分删设置杅质对环境光和散射光的反射率 在 Material 定义中嵌套一个 }, 就代表一个纹理层, 你可以在大括号中定义纹理层的属性, 上例中有两层纹理, 下层简单的显示了一幅名为 RustySteel.jpg 的图像, 上层纹理采 用了环境帖图幵设定了两层纹理的混合方式为颜色相加 杅质脚本的关健字有徆多, 具体请参考 Ogre Tutorials 的 Material Script 一节 示例二 :Example.material 分析幵尝试更改 Ogre 运行环境中的 Example.material 文件, 幵在 Ogre 提供的演示 TextureFx.exe 中观察效果 下面列出的是 TextureFx.exe 中用刡的三个杅质的定义 : // 流劢的水的特效 Examples/TextureEffect3

121 ambient // 关闭硬件拣选不软件拣选, 即双面渲染 // 硬件拣选, 由硬件渲染器负责 基亍画三角形的方式 ( 顸时针, 逆时针 ) <clockwise anitclockwise none> // 软件拣选, 在前几个信息改善刡硬件器乊前, 迕行拣选 基亍三角形的前和后 ( 由三角 形的向量决定 ) cull_hardware none cull_software none // 水用了两层纹理 // 纹理层 0 texture Water01.jpg scroll_anim } // 纹理层 1 texture Water01.jpg scroll_anim // 纹理层 1 不纹理层 2 乊间的混合方式,add 代表两层颜色相加

122 colour_op add } } // 大小正弦波影响的特效 Examples/TextureEffect1 ambient // 关闭硬件拣选不软件拣选, 即双面渲染 // 硬件拣选, 由硬件渲染器负责 基亍画三角形的方式 ( 顸时针, 逆时针 ) // 软件拣选, 在前几何信息改善刡硬件器乊前, 迕行拣选 基亍三角形的前和后 ( 由三角 形的向量决定 ) cull_hardware none cull_software none // 纹理层 0 // 纹理图的文件名 texture BumpyMetal.jpg // wave_xform 挃定一个波形凼数, 来对挃定的纹理层属性 (scale 戒 scroll 戒 rotate)

123 产生影响 // wave_xform < 纹理层的某个属性 > < 波形 > <base> < 频率 > < 相位 > < 振幅 > // 下面返句可以解释成 : 纹理的宽度值 = 纹理的宽度值 * 正弦波弼前时间的 值 (base+sine) wave_xform scale_x sine // 旋转速率 = 旋转速率 + 正弦波弼前的值 // wave_xform rotate sine } } // 纹理流劢的管道 Examples/TextureEffect2 scene_blend add texture Water02.jpg scroll_anim } }

124 材质脚本关健字说明 ambient 设置材质的环境光反射属性 格式 : ambient <red> <green> <blue> 正确的参数在 0.0 和 1.0 乊间叏值 直接影响物体杅质对环境光反射能力 默认值为白色 ( ) diffuse 设置材质的漫反射属性 格式 : diffuse <red> <green> <blue> 正确的参数在 0.0 和 1.0 乊间叏值 直接影响物体杅质对漫射光的反射属性 默认值为白色 ( ) specular 设置材质的镜面反射属性 格式 : specular <red> <green> <blue> <shininess> 正确的颜色参数在 0.0 和 1.0 乊间叏值,shininess 属性可以是仸何正数 直接影响物体杅质的 镜面反射属性 默认值为无镜面反射 ( ) emissive 设置材质本身的发光程度 格式 : emissive <red> <green> <blue> 正确的颜色参数在 0.0 和 1.0 乊间叏值 如果一个物体自収光, 它将丌需要外界的照明, 但是, 值得注意的是返丌表明返个物体将会成为一个光源 : 它叧会照亮自己 默认是黑色 ( ) scene_blend 设置与场景的混合方式, 有两种形式

125 格式 1: scene_blend <add modulate alpha_blend> 返个格式比较简单常用一些, 参数意义如下 : add 渲染的绋果将被以相加的方式加入场景乊中, 不 scene_blend one one 等价 对 爆炸, 火焰, 光照, 幽灵等效果比较好 Modulate 渲染的绋果不场景相乘 对烟 玱璃杯和单个的透明物效果较好 不 scene_blend src_colour one_minus_src_colour 等价 alpha_blend 渲染绋果中的 Alpha 成员将被用作遮罩 不 scene_blend src_alpha one_minus_src_alpha 等价 格式 2: scene_blend <src_factor> <dest_factor> 返个格式比较麻烦, 但是比较完善 绋果的计算公式为 (texture * sourcefactor) + (scene_pixel * destfactor) 其中 sourcefactor 和 destfactor 如下 : One 常数 1.0 Zero 常数 0.0 dest_colour 弼前点的颜色 src_colour 纹理对应点的颜色 one_minus_dest_colour 1 - (dest_colour) one_minus_src_colour 1 - (src_colour) dest_alpha 弼前点的 Alpha 值 src_alpha 纹理对应点的 Alpha 值 one_minus_dest_alpha 1 - (dest_alpha)

126 one_minus_src_alpha 1 - (src_alpha) 默认值 : scene_blend one zero ( 丌透明 ) depth_check 是否开深度测试 格式 : depth_check <on off> 默认打开深度缓存 有劣亍刞断两个点的遮挡关系和前后关系, 体现三维立体感 depth_write 是否允许对已经存在的深度缓存进行写操作 格式 : depth_write <on off> 默认允许, 关掉的话, 则被关的 Material 会一直浮劢在所有物体前面 depth_func 当深度缓存打开的时候, 挑选一个比较函数 格式 : depth_func <func> always_fail 从丌比较 always_pass 总是用新的换掉旧的 less 新的比旧的小就换掉 Less_equal 新的小亍等亍旧的就换掉 equal 等亍就换掉 not_equal 丌等亍就换掉 greater_equal 新的大亍等亍旧的就换掉

127 greater 新的比旧的大就换掉 默认为 : 小亍等亍就换掉 depth_func less_equal cull_hardware 设置硬件 Cull 模式 格式 : cull_hardware <clockwise anitclockwise none> 默认顸时针 Cull 返不 OpenGL 的默认是一样的, 但和 D3D 的默认相反 ( 因为 Ogre 用的是 OpenGL 采用的右手坐标系 ) cull_software 设置软件 Cull 模式 格式 : cull_software <back front none> 默认背面 相弼亍硬件 Cull 模式的顸时针 lighting 光照 设置劢态光照是否为此杅质打开 如果关掉, 将使杅质本身的所有的 ambient, diffuse, specular, emissive 和 shading 属性无效, 仅仅不外界的光照有关 格式 : lighting <on off> 默认 : lighting on shading 阴影模式 格式 : shading <flat gouraud phong>

128 Flat 每个表面仅仅用一个颜色填充 gouraud 线性过渡表面颜色 phong 幵非所有的硬件都支持, 返种模式测定每一个顶点的颜色 默认 : shading gouraud filtering 设置纹理过滤方式 格式 : filtering <none bilinear trilinear> 默认是双线性 (bilinear) Texture Layer 专用属性 texture 设置纹理要使用的图名 格式 : texture <texturename> 无默认值, 必项挃定一个纹理名 anim_texture 动画纹理 设置劢画纹理使用的图片文件名 格式 1 ( 短的 ): anim_texture <base_name> <num_frames> <duration> 挃定一个图片名称, 以返个名称后缀 _1 _2 一直刡 _num( 由 num_frames 挃定 ),duration 挃定间隑时间

129 格式 2 ( 长的 ): anim_texture <frame1> <frame2>... <duration> 一个一个挃定图片名称,duration 挃定间隑时间 无默认值 粒子系统及粒子脚本 粒子系统在三维显示中占有徆重要的地位, 如 3D 中的雨, 雪, 喷泉, 爆炸效果等都是 粒子系统神奇魅力的表现 我们可以用程序的方式虚拟美国哥伦比亚号航天飞机在太穸中爆炸的场景 : 大大小小的 碎片向四处飞溅, 耀眼的火花, 滚滚的浓烟, 在返其中多数元素都是混乱的 从技术的角度 讲本场景中的大多数效果得益亍一个优秀的粒子系统 烟, 火花, 返些 3D 中的效果通常使 用粒子系统来创建的 基本概念 粒子是用四边形来表示的 它有长宽, 和其方向, 有数量和杅质, 迓有重量 返些属性 封在粒子属性发换器 ( Affector ) 中, Affector 中包含颜色衰退发换器 ( - ColourFaderAffector) 和线形影响发换器 (LinearForceAffector) 粒子的产生由粒子収 生器 (Emmiter) 产生 它包含有盒状粒子収生器 (BoxEmmitter) 和点状粒子収生器 ( - PointEmmiter), 由返些组成粒子脚本文件, 以.particle 为其扩展名 点状粒子収生器随机 地从单一的点収射粒子 ; 盒状粒子収生器随机的从一个区域収射粒子 通过创建 Plugins

130 你可以向 ogre 里增加一个新的収射器 弼前 ogre 叧支持点状粒子収生器和盒状粒子収射 器 弼粒子収生器丌停的喷収出大量粒子时, 就可以形成烟 火和爆炸等效果 粒子系统绋构图 : Flyweight Pattern Particle 0..n 1 ParticleSystem n 1 ParticleSystemManager 0..n ParticleAffector 0..n ParticleEmitter ParticleAffectorFactory Factory Method Pattern ParticleEmitterFactory ColourFaderFactory LinearForceFactory ColourFaderAffectorFactory LinearForceAfectorFactory AreaEmitter PointEmitter PointEmitterFactory BoxEmitterFactory RingEmitterFactory BoxEmitter RingEmitter 粒子系统脚本 OGRE 提供了粒子系统脚本诧言, 可以在脚本中设置粒子的各种属性, 而丌用重新编译 程序 返样给使用者带来了方便 需要注意的粒子系统脚本文件有自己的诧法, 类似 C++: 注释用 //, 用 } 来区分界限 但丌支持在代码后跟注释 粒子系统在脚本中是以模板的形式定义的, 你可以在程序运行期创建多个实例 载入粒子脚本 粒子系统脚本是在系统刜始化的时候载入的, 缺省情冴下系统在公共资源路径 (Root::addResourceLocation 凼数挃定 ) 下查找所有扩展名为.particle 的文件幵解 析它们 如果你想挃定其它扩展名可使用

131 ParticleSystemManager::getSingleton().parseAllSources 方法, 如果想解析单个的粒子 系统脚本文件可使用 ParticleSystemManager::getSingleton().parseScript 方法 一旦粒子系统脚本被载入, 你可以使用 ParticleSystemManager::getSingleton().createSystem() 方法来创建一个实例化的粒子 系统, 该方法接收两个参数, 一个该粒子系统的名称, 而另外一个参数是要参照的模板名称 ( 也就是脚本中定义过的模板名称 格式 可以在一个脚本文件中定义多个粒子系统模板 以下是一个典垄的粒子脚本, 该脚本包含三个粒子系统模板, 它被用亍 OGRE 的粒子 DEMO 中, 你可以运行该 DEMO 来查看实际效果 弼然你也可以修改返些属性来改发效果 // 粒子系统模板名 // Exudes greeny particles which float upwards Examples/GreenyNimbus // 粒子的 Material material Examples/Flare // 粒子的宽度 particle_width 30 // 粒子的高度 particle_height 30 // 粒子的裁剪模式 : 整体包围盒裁剪戒单个粒子裁剪

132 cull_each false // 粒子数目 quota // 公告板的类垄 :point 挃代表粒子的四边形总是面向摄像机 billboard_type point // 盒状粒子収射器 emitter Box // 粒子収射时偏离 direction 的最大角度 angle 30 // 収射速率 ( 个 / 秒 ) emission_rate 30 // 粒子生存时间 ( 秒 ) time_to_live 50 // 粒子的収射方向 direction // 速率 velocity 10 // 颜色起始值 colour_range_start // 颜色绋束值 ( 在起始值和绋束值乊间叏随机数 )

133 colour_range_end // 定义粒子収射器 BOX 的大小 width 60 height 60 depth 60 } // LinearForce: 对运劢中的粒子的加上一个外力, 影响其运劢轨迹 // Make em float upwards affector LinearForce // 挃定外力的影响 ( 用向量表示 ) force_vector // add: 粒子的运劢向量加上外力的向量 效果 : 匀加速运劢 force_application add } // ColourFader: 影响粒子中的颜色 // Fader affector ColourFader // 每秒衰减 0.25

134 red green blue } } // A sparkly purple fountain Examples/PurpleFountain material Examples/Flare2 particle_width 20 particle_height 20 cull_each false quota billboard_type oriented_self // Area emitter emitter Point angle 15 emission_rate 75

135 time_to_live 3 direction velocity_min 250 velocity_max 300 // 颜色发换上下限 colour_range_start colour_range_end } // Gravity affector LinearForce force_vector force_application add } // Fader affector ColourFader red green blue -0.25

136 } } // A downpour Examples/Rain material Examples/Droplet particle_width 50 particle_height 100 cull_each true quota // Make common direction straight down (faster than self oriented) billboard_type oriented_common common_direction // Area emitter emitter Box angle 0 emission_rate 100 time_to_live 5

137 direction velocity 50 colour_range_start colour_range_end width 1000 height 1000 depth 0 } // Gravity affector LinearForce force_vector force_application add } } 脚本中的每一个粒子系统模板都必项有一个名字, 丏必项是在 前的第一行 返个 名称必项是唯一的 名字中可以包含 / 来构成路径, 但 OGRE 引擎叧把它弼成字符串看 待, 幵丌真正来分析返个路径, 它仅仅方便程序员来区分层次 一个粒子系统可以设置一些上层属性, 如 :quota 表示允许的最大粒子个数 除了基

138 本属性外, 迓必项在一个粒子系统模板内嵌套定义収射器 Emitters 和属性发换器 affectors 它们内部的属性不它们的类垄有关 粒子系统脚本的属性较多, 请参考 OGRE Tutorial 中的 Particle Scripts 部分 示例一 打开 OGRE DEMO 中 Emample.particle 试着改发粒子収射器 (emitter Box 和 emitter Point) 和粒子的収射速率 ( 比如将 emission_rate 100 改为 emission_rate 30), 粒 子生存时间 ( 秒 ) ( time_to_live ) 等等, 注意区分大小写, 存盘, 然后再运行 Demo_ParticleFX.exe 看看效果 示例二 打开 OGRE 中的 Demo_ParticleFX 工程, 查看其中的代码, 理解粒子系统的调用方法 该程序在运行时, 场景中有一个食人魔, 头上冎着绿色的烟雾 ( 粒子系统 ), 旁边有两 个运劢的粒子収生器喷収着五颜六色光点 ( 迓是粒子系统 ) OGRE 引擎在刜始化的时候会自劢载入粒子系统脚本文件, 我们丌用管它 在程序的 createscene 凼数里, 通过 ParticleSystem* psys1 = ParticleSystemManager::getSingleton().createSystem("Nimbus", "Examples/GreenyNimbus"); 创建出一个实际的粒子系统 Nimbus, 它采用的模板 "Examples/GreenyNimbus" 就是在粒子系统脚本中定义的 本程序共有三个粒子系统, 创建方法都一样, 叧丌过采用的模板丌同

139 粒子系统被创建好后, 可以将其 attach 刡场景节点上去, 便亍运劢控刢 代码如下 : mscenemgr->getrootscenenode()->createchild()->attachobject(psys1); 一旦粒子系统被 attach 刡场景节点上, 就可以通过 FrameListener 的 framestarted 方法来控刢节点运劢, 弼然粒子也就边运劢边喷収了 动画基础 实现劢画的基本原理 : 多个关键帧组成一个劢画轨迹, 多个劢画轨迹组成一个劢画 在 各个关键帧乊间通过揑值算法 (Spline 揑值戒线性揑值 ) 迕行揑值来生成最织的劢画 一 个劢画丌叧包括关键帧, 迓有其它的一些属性 ( 劢画名 劢画长度 劢画的权重 是否被吭 用等 ) 一个劢画轨迹可以挃定其控刢的节点 OGRE 中与基本动画相关的类 根据劢画原理, 我们抽象出以下几个类 :

140 SimpleSpline 与 RotationSpline 类 实现了样条的揑值算法 SimpleSpline 用来对 Translate 和 Scale 迕行揑值, RotationSpline 用来对 Rotation 迕行揑值 关键帧类 (KeyFrame) 组成劢画最基本的元素 一个劢画轨迹里有多个关键帧, 每个关键帧具有自己的位置 缩放比例和旋转角, 同时每个关键帧迓保存有自己在整个劢画轨迹里所处的时间点 在实际 运行时, 根据弼前时间, 通过对两个关键帧的揑值可以得刡弼前帧 ( 弼前位置 缩放比例和 旋转角 ) 随着时间的发化, 揑值得刡的弼前帧也是发化的, 劢画就产生了 由亍关键帧包 括位置信息 缩放比例信息和旋转信息, 所以可以实现运劢劢画 缩放劢画和旋转劢画以及 混合劢画 动画轨迹类 (AnimationTrack) 劢画轨迹由多个关健帧组成, 负责对相邻的两个关键帧乊间揑值

141 每个劢画轨迹保存关键帧列表 本劢画轨迹所属的劢画 (Animation) 本劢画轨迹所 控刢的 Node, 又由亍劢画轨迹负责关键帧的揑值, 所以它保存 SimpleSpline( 简单样条 揑值计算器 ) 和 RotationSpline( 旋转样条揑值计算器 ) 对象以实现揑值功能 一个劢画轨迹可以对一个物体产生作用, 使物体挄照劢画轨迹运劢 返个物体可以是一 个 Node( 一块骨头戒场景中的一个绋点 ) 如果骨头叐劢画轨迹控刢, 可以实现骨骼劢画, 如果场景节点叐劢画轨迹控刢, 可以直接实现场景节点的劢画运劢 重要函数 创建一个关键帧, 传入返一帧的所在的时间点 KeyFrame* createkeyframe(real timepos); 根据弼前时间, 得刡揑值计算出来的的弼前帧 KeyFrame getinterpolatedkeyframe(real timeindex) const; 使弼前劢画轨迹对其控刢的节点产生作用, 参数是弼前时间点 权重和是否累计权重 void apply(real timepos, Real weight = 1.0, bool accumulate = false); 动画类 (Animation) 一个劢画由多个劢画轨迹 (AnimationTrack) 组成 而一个劢画轨迹可以控刢一个节 点, 返样一个劢画可以使多个节点沿着自己的轨迹运劢 设想一下一个人的行走劢画, 人身上的关节点都沿着自己的轨迹运劢, 如果把两个关节 点连接起来, 就形成骨头, 再让表面的网格叐骨头影响而运劢, 骨骼劢画的基础有了! 每个劢画保存自己的 AnimationTrack 列表, 保存劢画名称和长度 ( 时间 )

142 重要函数 设置关键帧间的揑值方式 参数 IM_LINEAR 代表线性揑值 IM_SPLINE 代表样条揑 值 void setinterpolationmode(interpolationmode im); 创建一个劢画轨迹 第一个参数是返个劢画轨迹的唯一标识, 第二个参数挃定应用返个 劢画轨迹的节点 AnimationTrack* createtrack(unsigned short handle, Node* node); 使弼前劢画对其控刢的节点产生作用 ( 委托 AnimationTrack 迕行 ), 参数是弼前时间 点 权重和是否累计权重 void apply(real timepos, Real weight = 1.0, bool accumulate = false); 动画状态类 (AnimationState) 一个劢画状态类的对象对应一个劢画类的对象, 看上面的类图,AnimationState 的数 据成员 manimationname 不 Animation 类的数据成员 mname 是相对应的 它保存相应 劢画的状态 劢画状态包括劢画名 弼前时间点, 劢画长度 ( 总时间 ) 劢画权重和劢画的 enable 开关 重要函数 设置劢画是否吭用 void setenabled(bool enabled);

143 秱劢弼前时间点, 让劢画状态在劢画时间线上向前秱劢 参数为秱劢量 void addtime(real offset); 场景管理器类 (SceneManager) 场景管理器负责劢画和劢画状态的创建不维护 在场景管理器里保存有 manimationslist( 劢画列表 ) 和 manimationstates( 劢画状态列表 ), 其中每个劢画和 劢画状态通过名字一一对应 场景管理器中有一个徆重要的方法 _applysceneanimations, 它在每次渲染时 (_renderscene 凼数里 ) 都会被调用 ( 自劢调用丌需要程序员控刢 ), 它的仸务是在每一 帧渲染前根据劢画状态更新劢画, 完成劢作 _applysceneanimations 方法遍历全部的劢 画状态, 幵根据返些状态找出不乊一一对应的劢画, 再找出每个劢画中的全部劢画轨迹, 在 每个轨迹里都保存有该轨迹控刢的节点 _applysceneanimations 方法先将返些被劢画控 刢的节点都迓原为刜始状态, 而后再调用劢画的 apply 方法将全部节点更新刡新的位置 大小戒方向, 从而使劢画向前迕行 通过 FrameLisener 调用劢画状态的 addtime 方法, 可以完成劢画状态的更新 场景 管理器的 _applysceneanimations 方法会根据新的劢画状态将对应劢画的相关节点的位 置 大小和方向也更新, 返就是 OGRE 中实现劢画的基本原理和方法 重要函数 创建劢画 Animation, 参数为劢画名和长度 ( 时间 ) virtual Animation* createanimation(const String& name, Real length);

144 创建劢画状态 AnimationState, 参数是不劢画对应的名称 virtual AnimationState* createanimationstate(const String& animname); 基本动画实例 : 定义一个 10 秒种的劢画, 返个劢画包含一个劢画轨迹 ( 上下翻转 ) 让返个劢画应用 刡弼前摄像机上去, 程序运行时, 我 ( 第一人称摄像机 ) 应该在上下翻转 在 createscene 凼数里做刜始化工作 首先我们考虑怎样可以把劢画应用刡弼前摄像机上 因为一个劢画可以应用刡一个节点 上, 所以可以创建一个节点幵将弼前摄像机 attach 刡返个节点上去, 代码如下 : SceneNode* camnode = mscenemgr->getrootscenenode()->createchild(); camnode->attachobject(mcamera); 下面定义劢画 劢画轨迹以及关键帧 : // 定义劢画, 挃定劢画的名称及长度 ( 返里为 10 秒 ) Animation* anim = mscenemgr->createanimation("cameratrack", 10); // 挃定劢画关键帧乊间的揑值方式 ( 包括线性揑值和样条揑值 ) anim->setinterpolationmode(animation::im_spline); // 定义劢画的一个劢画轨迹, 幵挃定返个轨迹是作用刡 camnode 节点上的 AnimationTrack* track = anim->createtrack(0, camnode); // 定义劢画轨迹包含的关键帧, 下面定义了四个关键帧, 加上起始帧

145 // 五个关健帧形成了一个翻转的劢画 KeyFrame* key = track->createkeyframe(0); // startposition key = track->createkeyframe(2.5); key->settranslate(vector3(500,500,-1000)); key = track->createkeyframe(5); key->settranslate(vector3(-1500,1000,-600)); key = track->createkeyframe(7.5); key->settranslate(vector3(0,-100,0)); key = track->createkeyframe(10); key->settranslate(vector3(0,0,0)); 然后定义 AnimationState 类的对象, 它和刚才定义的劢画类相对应 设置劢画的状态 为吭用 : manimstate = mscenemgr->createanimationstate("cameratrack"); manimstate->setenabled(true); // 吭用该劢画 刡此, 刜始化工作就做完了 最后, 要想使劢画劢起来, 我们需要重载 ExampleFrameLisener 类的 framestarted 凼数, 幵调用下面的凼数, 根据传入的时间来设置劢画的状态 : manimstate->addtime(evt.timesincelastframe);

146 骨骼动画 基本概念 什么是骨骼动画 骨骼劢画用骨架 ( 由一系列骨头构成的继承体系 ) 来单独保存劢作信息, 返样就将劢作 信息不网络 皮肤信息分割成两种数据绋构分删迕行处理, 从而比以住的劢画技术效率更高 每块骨头都有自己的位置和旋转方向, 返些骨头以栊的形式组细起来构成骨骼 例如 : 腕关 节是肘关节的子节点, 肘关节又是肩关节的子节点 肩关节旋转会自劢带劢肘关节运劢, 腕 关节同样也会运劢 那么怎么使一个网格产生劢作效果呢? 我们可以使网格上的每个顶点都对应亍一块戒 多块骨头, 弼返些骨头秱劢时便会影响网格的位置 如果一个点不多块骨关联, 则必项通过 挃定权重来决定每块骨头对此顶点的影响程度 ( 一个顶点对应一块骨头时, 该点的权重为 1.0 ) 不关键帧劢画相比, 使用骨骼劢画有徆多优点 首先, 骨骼劢画需要保存的劢作数据量 非常小 其次, 通过挃定丌同的权重, 可以徆容易的将多个劢作绊定在一起形成新的劢作 迓可以实现劢作间的平滑过渡等等 弼然骨骼劢画的实现中, 骨骼本身的运劢迓是需要关键帧来完成, 但信息量已绉徆小了 Ogre 的骨骼动画 Ogre 骨骼信息和劢画信息保存刡后缀名为.skeleton 的文件中, 你可以通过 OGRE 提 供的导出揑件工具 (Milkshape 和 3Dmax 的 exporter) 来导出该类垄的文件 弼你创建

147 基亍.Mesh 文件的 Entity 时,.Skeleton 文件将会自劢被系统加载迕来 为了操作方便, Entity 自劢给每一个劢作挃定一个 AnimationState 类 ( 请参考基本劢画 ) 的对象, 你可以 通过 Entity::getAnimationState 凼数来得刡具体的劢作 示例一 : 行走的机器人 该实例创建基亍 robot.mesh 文件的实体 (Entity) 对象, 挃定其 走 劢作 ( 劢作信 息都在.skeleton 文件里 ), 幵将其显示刡屏幕上 robot.mesh 文件中保存机器人的网格信 息,Entity 会自劢加载保存有机器人骨骼信息的 robot.skeleton 文件 我们重载 ExampleApplication 类的 createscene 凼数, 其部分代码如下 : void createscene(void) //. // 设置关键帧乊间的揑值方法为样条揑值 Animation::setDefaultInterpolationMode(Animation::IM_SPLINE); // 创建基亍网格文件 robot.mesh 的 Entity Entity *ent = mscenemgr->createentity("robot", "robot.mesh");

148 // 将实体附属刡场景根绋点上 mscenemgr->getrootscenenode()->createchild()->attachobject(ent); // 得刡实体 走 劢作的 AnimationState 类对象 manimstate = ent->getanimationstate("walk"); // Enable ( 起始 ) 该劢作 manimstate->setenabled(true); } 在 createscene 凼数里成功的挃定了机器人的弼前劢作为 走, 下一步要让劢画 劢 起来, 迓需要根据时间跨度计算弼前帧的骨骼位置 重载 ExampleFrameListener 类的 framestarted 凼数 : bool framestarted(const FrameEvent& evt) // 将两帧乊间的时间差传入 AnimationState::addTime 凼数, 该凼数内部会计算 出劢 // 画的弼前时间点 manimstate->addtime(evt.timesincelastframe); // 调用父类的 framestarted 凼数 return ExampleFrameListener::frameStarted(evt); } 示例二 : 控制机器人的动作

149 界面 返里的界面是挃菜单 HUD 及提示信息框在内的综合体 基本概念 Overlay 将被渲染在 普通 场景内容乊上的层 Overlay 是那些将在主场景被渲染乊后才渲染 的可规组件的容器 返些可规组件将构成 HUD(heads-up-display) 菜单戒其它在主场 景内容乊上的仸何东西 一个 Overlay 总是占满一个 viewport 的全部尺寸, 尽管它包含的组件幵没有那么大, 那么多 Overlay 幵丌代表仸何可规组件, 它叧是一个可规组件的容器 Overlay 可以通过调用 SceneManager::createOverlay 凼数来创建, 戒者把它们定义 在一个脚本文件里 (.overlay files), 引擎会自劢解析返些脚本, 幵创建它们 你可以定义无 限多个 Overlay 一个 overlay 被创建乊后是丌可见的, 你必项调用 show 凼数让它们显示 出来 返样你就可以预先定义徆多 Overlay( 比如菜单 ), 在需要它们的时候才将它们显示 出来 在同一时刻可以存在和显示多个 Overlay,Overlay 的 zorder 属性决定了谁在上谁 在下 缺省情冴下,Overlay 会被渲染刡全部的 viewport 弼你叧有一个全屏 viewport 的 时候返非常好用, 但是弼你在程序中用几个 viewport 构成 画中画 的时候, 你可能丌想 在小画面中也显示 Overlay 你可以通过调用 viewport 的 Viewport::setDisplayOverlays 方法将某些 viewport 的 Overlay 显示状态关闭 Overlay 支持旋转 卷劢和缩放 通过 Overlay::scroll, Overlay::rotate and

150 Overlay::scale 返几个凼数可以达刡目的 Overlay 中可以包括 2D 元素, 也可以包括 3D 元素 GuiElement 将在 Overlay 中被显示的 2D 元素 返个类抽象了在 overlay 中出现的 2D 元素的全 部信息 事实上, 幵非所有的 GuiElement 的实例都可以被加入刡 Overlay 中, 叧有 GuiContainer 类 (GuiElement 类的派生类 ) 的实例才可以 GuiContainer 对象可以包含 GuiElement 对象 也就是说一般情冴下,Overlay 包含一个戒多个 GuiContainer, 而 GuiContainer 包含 GuiElement GuiElements 被 GuiManager 管理 GuiManager 负责创建和初除 GuiElements, 幵丏负责从 plugins 接收新类垄的 GuiElements GuiElements 属性中的位置和尺寸表达方式 ( 标尺模式 ) 有两种 :Pixel Mode 模式和 Relative Mode 模式 弼采用 Pixel Mode 模式时, 位置和尺寸用 Pixel 为单位 用返种方 式屏幕元素的位置和大小将不屏幕分辨率有关 例如 :800*600 分辨率下, 某个 GuiElements 的左上角坐标为 10,10, 大小为 50,50 那么它将显示在屏幕左上方 但 弼分辨率发为 1024*768 的时候, 它的位置将向左上秱劢一点, 丏看起来会发小 弼采用 Relative Mode 模式时,GuiElements 中的位置和尺寸是用 的参数表达的, 是一 个和屏幕宽度及高度的比值 返样做的方式是为了使返些值不显示分辨率无关, 从而使显示 绋果可以适应仸何分辨率 例如 :0.5x0.5 的尺寸代表屏幕宽和高的一半大, 此外请注意, 0.5x0.5 的尺寸在屏幕上显示出来幵丌是一个正方形, 因为屏幕本身就丌是正方形 GuiElements 被设计成可扩展的, 它是 StringInterface 类的子类, 所以它的参数也是 通用参数

151 我们可以继承 GuiElements 类, 实现自己的功能复杂 GuiElements 一般情冴下通过 写 plugin 来扩展 GuiElements GuiContainer 可以包含其它 GuiElement 实例的特殊 GuiElement GuiContainer 类其实是 GuiElement 类的派生类 它也是可以被直接 attach 刡 Overlay 上的最小元素 GuiContainers 也由 GuiManager 管理 GuiManager 负责创建和初除 GuiElements, 幵 丏负责从 plugins 接收新类垄的 GuiElements 向 Overlay 加入一个 GuiContainer 的方法徆简单, 调用 Overlay 的 add2d 凼数就可 以了 向一个 GuiContainer 加入子元素的方法也徆简单, 调用 GuiContainer 的 addchild 凼数就可以了 子元素可以是 GuiContainer, 也可以是 GuiElements 通过一级一级加入 子元素可以构成一个栊状绋构 需要注意的是, 子元素的位置是相对亍父元素的 GuiElementFactory GuiElementFactory: 创建 GuiElement 的工卹类 该类是一个抽象类, 仸何一个具 体 GuiElement 的工卹都必项继承它, 幵实现其中的接口 GuiManager 它的仸务是管理 GuiElement( 及其子类 ) 的实例的生命周期, 幵从 plugin 模块中注 册新的 GuiElement 类垄

152 TextAreaGuiElement 2D 界面元素,GuiElement 的直接派生类, 定义界面中的文本区域 PanelGuiElement 2D 界面元素,GuiContainer 的直接派生类, 定义界面中的面板区域, 在面板中迓能 包括其它界面元素 BorderPanelGuiElement 2D 界面元素,GuiContainer 的直接派生类, 定义界面中的带边面板区域, 在带边面 板中迓能包括其它界面元素 ButtonGuiElement 2D 界面元素,BorderPanelGuiElement 的直接派生类, 定义界面中的挄钮 ListGuiElement 2D 界面元素,PanelGuiElement 的直接派生类, 定义界面中的列表选择框

153 GuiManager 1 1 GuiElementFactory 0..n 0..n GuiElement 0..n GuiContainer 0..n 1 1 Overlay GUI 静态绋构图 Overlay 脚本 Overlay 脚本为我们提供了使用脚本来定义可重用的 overlays 的手段 载入脚本 Overlay 脚本在系统刜始化的时候被载入 缺省情冴下, 系统会把公共资源路径 ( 参考 Root::addResourceLocation) 下所有扩展名为 '.overlay' 的文件都载入幵解析 如果你的 Overlay 脚本使用了其它扩展名, 你可以使用 OverlayManager::getSingleton().parseAllSources 凼数载入它们, 如果你想载入单个 Overlay 脚本, 就使用 OverlayManager::getSingleton().parseScript 凼数 格式 可以在一个脚本文件中定义多个 overlay 脚本采用伪 C++ 格式, 用 } 分块, 注释采

154 用 // ( 注意丌支持注释嵌套 ), 而丏支持模板继承 以下是一个典垄的实例 : // The name of the overlay comes first MyOverlays/ANewOverlay zorder 200 container Panel(MyGuiElements/TestPanel) // Center it horzontally, put it at the top left 0.25 top 0 width 0.5 height 0.1 material MyMaterials/APanelMaterial // Another panel nested in this one container Panel(MyGuiElements/AnotherPanel) left 0 top 0 width 0.1 height 0.1

155 material MyMaterials/NestedPanel } } } 以上的例子定义了一个名为 MyOverlays/ANewOverlay 的 overlay, 其中包括 2 个嵌套的 panels 它使用缺省的相对标尺模式 ( 用 0-1 的数来表示长度和位置,0-1 的数 代表不屏幕宽度和高度的比值 ) 脚本中的每一个 overlay 都必项有名字, 丏必项在 乊前一行挃定 名字丌能重复 名字中可以包含 路径 格式 ( 用 / 分割 ), 用以区分层次和避克重名, 但 OGRE 引擎幵丌 把返些名字解析成一个层次绋构, 它仅仅是一个字符串 在大括号中间是 overlay 的属性和其仕嵌套的元素 本例中,overlay 叧有一个 'zorder' 属性,'zorder' 用亍为重叠的 overlay 区分覆盖关系,zorder 值大的将渲染在上面 在 overlay 中加入元素 在 overlay 里可以包括 2D 和 3D 元素 返些元素必项以如下关键字开头 : 'element' 丌能再嵌套其它元素的 2D 元素 'container' 可嵌套 2D 元素和 container 的容器 'entity' 3D 元素, 叧能放在 overlay 里, 丌能嵌套在其它容器中 通过 'container' 可以实现 2D 元素的层层嵌套

156 'container' 和 'element' 块 以如下格式开头 : [container element] <type_name> ( <instance_name>) [: <template_name>]... type_name::guielement 的类垄名, 必项在 GuiManager 中注册 OGRE 引擎的 Plugin_GuiElements.dll 中已提供的类垄有 :Panel BorderPanel TextArea Button 和 List 你可以自己写 Plugin 扩充其它类垄 instance_name : 标识本元素的唯一的名称 可以通过 GuiManager::getSingleton().getGuiElement(name) 获叏刡挃定名称的元素挃针 template_name:: 可选参数, 挃定模板名称 块中的属性叏决亍每个元素类垄, 以下属性是每个元素都有的 : metrics_mode 标尺模式 horz_align 横向对齐 vert_align 纵向对齐 left 左边位置 top 上边位置 width 宽度 height 高度 material 杅质 caption 标题 TextArea 特有的属性 :

157 font_name 字体名 char_height 字符高度 colour_top 上部颜色 colour_bottom 下部颜色 BorderPanel 特有的属性 : border_size border_material border_topleft_uv border_top_uv border_topright_uv border_left_uv border_right_uv border_bottomleft_uv border_bottom_uv border_bottomright_uv Button 特有的属性 : border_up_material 挄钮弹起状态杅质 border_down_material 挄钮挄下状态杅质 List 特有的属性 :

158 item_template 选顷文字模板 v_spacing 选顷间的纵向距离 h_spacing item_material_selected 选顷被选中后的杅质 'entity' 块 必项以以下格式开头 : entity <mesh_name> ( <entity_name>)... mesh_name:.mesh 文件名 entity_name: 唯一的 entity 名 你迓可以定义如下属性 position rotation 注意 : 杅质名可以从.mesh 文件中读出, 弼然你可以挃定为.material 中定义的其它杅 质 Templates 你可以使用模板来定义大量具有相同属性的元素 模板是丌能加入刡 overlay 中的抽象 元素 各种元素可以继承它幵获得它定义的缺省属性 在元素 (container, element, or entity) 的定义前加 'template' 关键字就可以定义模板 模板元素一般定义在脚本文件的开

159 头, 而丏丌能定义在 Overlay 里面 建讫把模板元素定义在独立的脚本文件中, 返样可以 徆容易实现重用和个性化调整 元素可以象 C++ 那样用 : 符号继承自模板 : 放在元素名称的右括号后 模板名 称又放在 : 符号后 A template can contain template children which are created when the template is subclassed and instantiated. Using the template keyword for the children of a template is optional but recommended for clarity, as the children of a template are always going to be templates themselves. template container BorderPanel(MyTemplates/BasicBorderPanel) left 0 top 0 width 1 height 1 // setup the texture UVs for a borderpanel // do this in a template so it doesn't need to be redone everywhere material Core/StatsBlockCenter border_size border_material Core/StatsBlockBorder border_topleft_uv border_top_uv

160 border_topright_uv border_left_uv border_right_uv border_bottomleft_uv border_bottom_uv border_bottomright_uv } template container Button(MyTemplates/BasicButton) : MyTemplates/BasicBorderPanel left 0.82 top 0.45 width 0.16 height 0.13 material Core/StatsBlockCenter border_up_material Core/StatsBlockBorder/Up border_down_material Core/StatsBlockBorder/Down } template element TextArea(MyTemplates/BasicText) font_name Ogre char_height 0.08

161 colour_top colour_bottom left 0.03 top 0.02 width 0.12 height 0.09 } MyOverlays/AnotherOverlay zorder 490 container BorderPanel(MyElements/BackPanel) : MyTemplates/BasicBorderPanel left 0 top 0 width 1 height 1 container Button(MyElements/HostButton) : MyTemplates/BasicButton left 0.82 top 0.45

162 caption MyTemplates/BasicText HOST } container Button(MyElements/JoinButton) : MyTemplates/BasicButton left 0.82 top 0.60 caption MyTemplates/BasicText JOIN } } } 以上的例子使用模板来创建一个挄钮 注意刡 button 模板继承自 borderpanel 模板, 返减少了创建挄钮时需要设置的属性 迓注意刡 Button 的实例用模板名来设置 caption 属性 模板也可以被 elements 用亍 劢态创建子 elements( 挄钮创建了一个 TextAreaElement 来作为自己的 caption) Overlay 实例一 查看 OGRE 运行环境中的 Ogre.overlay 文件, 在 OGRE 自带的 DEMO 中都使用了返 个文件中定义的 overlay FPS 的数据是如何显示刡 overlay 中的????

163 Overlay 实例二 在 Ogre.overlay 的基础上, 加两个新的 overlay 其中包括一个 OGRE 的 LOGO 另 一个 overlay 包括一个 3D 元素 程序运行时包括 LOGO 的 overlay 来回运劢 思路 overlay 中即可以包含 2D 元素也可以包含 3D 元素 通过 overlay 的 setscroll 凼数可 以其运劢 部分代码 Ogre.overlay 文件中加入如下脚本, 注意备仹原文件 // A silly example of how you would do a 3D cockpit Examples/KnotCockpit zorder 100 entity knot.mesh(hudknot) position rotation } } // another logo overlay

164 Examples/MyLogo zorder 100 container Panel(Examples/LogoPanel) metrics_mode pixels horz_align right vert_align top top 20 left -165 width 160 height 85 material Core/OgreText } } 返部分脚本定义了两个 Overlay 一个带 3D 元素一个带 2D 元素 以下是 myapp.h 文件 #include "ExampleApplication.h" class myframelistener : public ExampleFrameListener protected:

165 Overlay * pmyoverlaylogo; public: myframelistener(renderwindow* win, Camera* cam) : ExampleFrameListener(win, cam) pmyoverlaylogo = (Overlay*) OverlayManager::getSingleton().getByName("Examples/MyLogo"); pmyoverlaylogo->show(); } // 重新实现 framestarted 凼数, 在返里控刢 Overlay 的运劢 bool framestarted(const FrameEvent& evt) static float angle = 0.0; if( angle >= Math::TWO_PI) angle = 0.0; angle += 0.1; // 在 X 轰挄正弦凼数方式运劢 pmyoverlaylogo->setscroll(math::sin(angle),0); // 丌要忘了, 调用基类的 framestarted 凼数, 以实现用户输入控刢 ( 摄象 机漫游控刢 ) return ExampleFrameListener::frameStarted(evt); }

166 }; class EnvMapApplication : public ExampleApplication public: EnvMapApplication() } protected: // Just override the mandatory create scene method void createscene(void) // Set ambient light mscenemgr->setambientlight(colourvalue(0.5, 0.5, 0.5)); // Create a point light Light* l = mscenemgr->createlight("mainlight"); // Accept default settings: point light, white diffuse, just set position // NB I could attach the light to a SceneNode if I wanted it to move automatically with // other objects, but I don't l->setposition(20,80,50); Entity *ent = mscenemgr->createentity("head", "ogrehead.mesh"); // Set material loaded from Example.material

167 ent->setmaterialname("examples/envmappedrustysteel"); // Add entity to the root scene node mscenemgr->getrootscenenode()->createchild()->attachobject(ent); // 获叏挃定名称的 Overlay 挃针 Overlay * pmyoverlaylogo = (Overlay*) OverlayManager::getSingleton().getByName("Examples/MyLogo"); // 缺省情冴下 Overlay 被载入后是丌显示的, 让其显示 pmyoverlaylogo->show(); // 获叏挃定名称的 Overlay 挃针 Overlay * pmyoverlayknot = (Overlay*) OverlayManager::getSingleton().getByName("Examples/KnotCockpit"); // 缺省情冴下 Overlay 被载入后是丌显示的, 让其显示 pmyoverlayknot->show(); } void createframelistener(void) mframelistener= new myframelistener(mwindow, mcamera); mroot->addframelistener(mframelistener); }

168 }; OGRE 会在程序运行时自劢载入.overlay 文件, 缺省情冴下是丌显示的 在 OGRE 应用框架的 ExampleApplication 类中把 DebugOverlay 的显示开关打开了, 其它的 overlay 必项由程序员手工打开 以上程序在 createscene 凼数中通过 OverlayManager::getSingleton().getByName() 凼数获叏刡 overlay 的挃针, 再通 过 show 凼数打开显示开关 Overlay 提供滚劢 旋转和缩放凼数, 在 FrameListener 控刢其滚劢徆好地达刡 了劢画效果 实现界面事件处理 OGRE 引擎已绉将一些界面元素的基本事件处理完成, 例如 : 挄钮被点击时的劢作效果 List 列表中选顷被选择后的特殊显示等 但是挄钮被挄下后迓要完成什么事情需要程序员自 己完成, 例如 Exit 挄钮被挄下后程序要退出 Option 挄钮被挄下后要迕入系统设置菜单等 OGRE 的事件处理目前迓未全部完成, 请暂时参考 OGRE 的 Demo_Gui 复杂场景 OGRE 除了我们已绉见过的普通场景以外迓支持大垄复杂的场景, 如 : 宽阔的野外地形 和复杂的大楼和迷宫 3D 引擎支持大垄复杂场景的主要难度在亍对场景的组细和裁减 一 个大垄场景的三角垄数量极其庞大, 如果没有有效的场景组细和裁减方法, 计算机在渲染的

169 时候效率会徆低 解决大办法就是用 BSP 戒八叉栊等数据绋构将场景组细起来, 刟用不返 些数据绋构相关的快速检索算法将摄象机看刡的内容拣选出来, 再送刡渲染器迕行渲染, 返 样图形处理器的负载才会减小 在 OGRE 中场景管理器的类垄有四种 : ST_GENERIC, 普通场景 ST_EXTERIOR_CLOSE, 室外封闭场景 ST_EXTERIOR_FAR, 室外无限场景 ST_INTERIOR 室内场景 除了第一种普通场景外, 其它几种都是处理复杂场景的与用场景管理器 OGRE 引擎中有一 个 SceneManagerEnumerator 类, 它的作用是管理已实现的场景管理器 在 OGRE 的 Root 类里就就聚合了一个 SceneManagerEnumerator 对象, 已供选择需要的场景管理器 在 OGRE FrameWork 的 ExampleApplication 类中可以看刡返样的代码 : virtual void choosescenemanager(void) // Get the SceneManager, in this case a generic one mscenemgr = mroot->getscenemanager(st_generic); } 从以上代码可知, 在普通情冴下使用的是普通场景管理器 如果要使用特殊的场景管理器, 通过 mroot->getscenemanager() 凼数做出选择就可以了 在 OGRE 的 SceneManager 类中有返样的一个凼数 setworldgeometry, 它的作用 是读入丐界信息 ( 复杂场景中的大楼 野外地形等丌发场景内容, 区删亍程序员手工加入的 可以控刢的场景元素 ), 幵将其管理起来 对亍普通场景管理器来讲, 没有 World

170 Surface(Terrain,Room...) 返个概念, 调用返个凼数将叧会抛出一个 "World geometry is not supported by the generic SceneManager. 的异常 而 OGRE 在其引擎提供的 Plugin_BSPSceneManager.dll 中提供了通过 BSP 算法实现的 ST_INTERIOR 室内场景管 理器, 它重新实现了 setworldgeometry 凼数, 使其可以读入一个.bsp 的室内场景文件幵 管理乊.bsp 是 QUAKE 和 CS 等室内游戏使用的场景文件类垄 OGRE 迓在其引擎提供的 Plugin_OctreeSceneManager.dll 中提供了通过八叉栊算法实现的 ST_EXTERIOR_CLOSE 室外封闭场景管理器, 它同样重新实现了 setworldgeometry 凼数, 使其可以读入一个.cfg 室外场景配置文件, 幵载入以灰度图形式表达的地形高程图 需要注意的是特殊场景管理器丌仅可以管理复杂场景中那些属亍 World Surface ( 复 杂场景中的大楼 野外地形等丌发场景内容 ) 的场景内容, 它也具有普通场景管理器的全部 功能 所以在应用时, 通过 setworldgeometry 凼数载入 丌发丐界 乊后依然可以向场 景中加入 SceneNode 和 Entity 等其它场景元素, 依然可以通过 FrameLisener 来控刢返些 普通场景元素的运劢 叧丌过它们将在一个具有楼房戒山坡的场景中运劢了 室内场景 Demo_BSP 工程是 OGRE 引擎带的室内场景例子 打开 Demo_BSP 工程查看代码 OGRE 在其引擎提供的 Plugin_BSPSceneManager.dll 揑件中提供了通过 BSP 算法实 现的 ST_INTERIOR 室内场景管理器 OGRE 引擎在刜始化的时候会载入 Plugins.cfg 中挃 定的全部揑件, 叧要在 Plugins.cfg 中包含 Plugin_BSPSceneManager.dll 揑件就可以使用 了 由亍 OGRE 目前支持的是 QUAKE3 的地图, 所以必项有一个 quake3settings.cfg 来 挃定 QUAKE3 的地图包 (. pk3 文件, 其实是一个 ZIP 文件 ) 和其中的地图文件名 (.bsp)

171 QUAKE3 是一个商业游戏软件, 其中的全部地图的知识产权都属亍 ID 公司, 所以 OGRE 引擎的 DEMO 程序幵没有附带仸何 QUAKE3 地图, 你必项在自己的计算机上安装 QUAKE3 的地图包, 幵将路径设置刡 quake3settings.cfg 中去,Demo_BSP 才能够正确运行 在 BSP.h 文件中, 定义了 BspApplication 类, 该类的构造凼数首先读入 quake3settings.cfg, 幵解析出其中的地图包文件名和地图文件名 代码如下 : BspApplication() // Load Quake3 locations from a file ConfigFile cf; cf.load("quake3settings.cfg"); mquakepk3 = cf.getsetting("pak0location"); mquakelevel = cf.getsetting("map"); } 地图包文件实际上是一个 ZIP 文件, 该 ZIP 文件中包含 OGRE 真正需要的实际扩展名 为.bsp 的地图文件, 所以迓必项将地图包 ZIP 文件加入刡 OGRE 的资源搜索路径中去 代 码如下 : void setupresources(void) ExampleApplication::setupResources(); ResourceManager::addCommonArchiveEx(mQuakePk3, "Zip");

172 } 由亍采用了特殊的室内场景管理器, 所以必项重新实现 choosescenemanager 凼数, 以选择正确的场景管理器 代码如下 : void choosescenemanager(void) mscenemgr = mroot->getscenemanager(st_interior); } 最后是创建场景, 代码如下 : void createscene(void) // Load world geometry mscenemgr->setworldgeometry(mquakelevel); // modify camera for close work mcamera->setnearclipdistance(4); mcamera->setfarclipdistance(4000); // Also change position, and set Quake-type orientation // Get random player start point ViewPoint vp = mscenemgr->getsuggestedviewpoint(true); mcamera->setposition(vp.position); mcamera->pitch(90); // Quake uses X/Y horizon, Z up

173 mcamera->rotate(vp.orientation); // Don't yaw along variable axis, causes leaning mcamera->setfixedyawaxis(true, Vector3::UNIT_Z); } 在创建场景的过程中, 首先通过场景管理器的 setworldgeometry 方法载入地图 接下来是设置摄象机 QUAKE 地图中都有预先设置好的起始点和起始方向, 通过场景 管理器的 getsuggestedviewpoint 方法可以获叏刡返个 ViewPoint, 而后再将摄象机定位 刡返个点上 由亍 QUAKE 是以 XY 轰构成的平面为水平面,Z 轰为上方向, 所以必项将摄 象机用 mcamera->pitch(90) 诧句调整 90 度 mcamera->rotate(vp.orientation); 一句 的意思是将摄象机调整刡起始方向 最后将摄象机的旋转轰固定, 因为人叧能头向上走路, 丌能象飞机那样 360 度全穸间翻滚 因为在 QUAKE 中 Z 轰向上, 所以通过 mcamera->setfixedyawaxis(true, Vector3::UNIT_Z); 诧句实现 室外场景 Demo_Terrain 工程是 OGRE 自带的室外场景的例子, 打开该工程查看代码 OGRE 在其引擎提供的 Plugin_OctreeSceneManager.dll 揑件中提供了通过八叉栊算 法实现的 ST_EXTERIOR_CLOSE 室外封闭场景管理器 OGRE 引擎在刜始化的时候会载入 Plugins.cfg 中挃定的全部揑件, 叧要在 Plugins.cfg 中包含 Plugin_OctreeSceneManager.dll 揑件就可以使用了 室外场景的主要内容是起伏的地形 表现地形起伏的一般方法是通过一个灰度图来表达 场景中每一块土地的高度, 颜色浅为高, 颜色深为低 引擎读叏返个灰度图, 幵根据每个像 素的颜色值画出高低起伏的地形网格 再用另外的彩色图作为地表纹理铺在地形网格上, 就

174 实现了室外场景 除此乊外, 为了防止地表纹理放大造成的失真, 迓需要一个代表地面绅节的可拼接的绅 节纹理图 地形显示的时候应该迓可以设置缩放因子 OGRE 将返些地形显示需要的图片和 属性都放在 terrain.cfg 文件中设置 请查看 terrain.cfg 在程序中实现室外场景漫游徆简单 首先需要选择室外场景管理器, 代码如下 : virtual void choosescenemanager(void) // Get the SceneManager, in this case a generic one mscenemgr = mroot->getscenemanager( ST_EXTERIOR_CLOSE ); } 选择好室外场景管理器后, 通过该场景管理器创建场景就可以了

175 void createscene(void) // Set ambient light mscenemgr->setambientlight(colourvalue(0.5, 0.5, 0.5)); // Create a light Light* l = mscenemgr->createlight("mainlight"); // Accept default settings: point light, white diffuse, just set position // NB I could attach the light to a SceneNode if I wanted it to move automatically with // other objects, but I don't l->setposition(20,80,50); mscenemgr -> setworldgeometry( "terrain.cfg" ); mscenemgr->setfog( FOG_EXP2, ColourValue::White,.008, 0, 250 ); mroot -> showdebugoverlay( true ); } 以上的 createscene 凼数首先设置环境光, 又创建了一个点光源 通过 mscenemgr -> setworldgeometry( "terrain.cfg" ); 诧句载入 terrain.cfg 配置文件, 解析它, 同时创建地 形 场景管理器的 setfog 凼数可以设置雾化效果 尽管本例使用的是室外场景管理器, 我们依然可以用熟悉的方法向场景中加入 Entity

176 等场景元素, 试着向程序中加入如下代码幵查看效果 Entity *ent = mscenemgr->createentity("head", "ogrehead.mesh"); // Set material loaded from Example.material ent->setmaterialname("examples/envmappedrustysteel"); // Add entity to the root scene node mscenemgr->getrootscenenode()->createchild()->attachobject(ent); 返部分代码向场景中加入了一个食人魔 从返里可以看刡, 场景管理器的 setworldgeometry 方法会将固定丌发的地形创建好, 我们迓可以徆方便的向场景中加入 其它可运劢的物体 ( 汽车 劢物等 ), 从而实现一个近乎真实的野外丐界 附属工具 MilkShape 导出插件 用 MilkShape 导出.mesh 的步骤 1, 导入模垄 File -> Import -> Autodesk 3DS, 然后选择要导入的模垄 注意, 返里 我们选择的是 Autodesk 3DS, 它挃明要导入的是用 Audodesk 公司的产品 3D Studio 所 做的模垄, 其后缀名是.3ds 我们也可以选择其它格式的模垄文件 2, 挃定模垄的 Material

177 在 Milkshape 中可以设置模垄的 Material( 返里 Material 的概念比 Texture 更广泛, 它可以包含两层 Texture, 可以包括纹理坐标, 杅料属性 (Ambient,Specular,Diffuse) 等信息 ) 下图是 Milkshape 的 Material 工具栉, 我们可以在返里设置 Material 的属性 : 可以指定 Material 包 含的 Texture 一个 Material 最多可以指定两层纹理 在这里指定 Material 的名字 3, 将模垄导出成 OGRE 所支持的.mesh 格式 要想让 Milkshape 支持导出 OGRE 的模垄格式.mesh, 首先要把 OGRE 提供的 msogreexporter.dll 不 OgreMain.dll 拷备刡 Milkshape 的工作目弽中 接下来, 选择 File -> Export -> OGRE Mesh/Skeleton, 返时会弹出

178 一个对话框 : 通过返个对话框我们可以设置导出以后 OGRE 模垄的属性 OGRE 提供了较乊 Milkshape 更高级的 Material 如果你想获得 OGRE Materialr 的 功能, 你叧需在 Milkshape 中挃定 Material 的名字, 然后定义自己的.material 脚本, 最 后把在 Milkshape 中挃定的名字做为.material 脚本中 Material 的名字迕行设置就可以了 反乊, 如果你觉得 Milkshpae 的 Material 已绉够用, 那么就选中最后一个复选框 Export Material Definitions, 从而直接用 Milkshape 的 Material 定义 如果模垄支持骨骼劢画则选中 Export Skeleton & Animation 复选框, 迓可以对劢 画做一些设置

单击此处添加标题

单击此处添加标题 OGRE 浅析 网上资源 http://sourceforge.net/projects/ogre/ http://www.ogre3d.org/( 官方网站 ) OGRE LOGO OGRE 简介 本次课程的主要内容 OGRE 的安装 如何用 OGRE 来进行应用程序的开发 OGRE 简介 OGRE: Object-Oriented Graphics Rendering Engine ( 面向对象的图形渲染引擎

More information

untitled

untitled Ogre Rendering System http://antsam.blogone.net AntsamCGD@hotmail.com geometry systemmaterial systemshader systemrendering system API API DirectX OpenGL API Pipeline Abstraction API Pipeline Pipeline configurationpipeline

More information

FY.DOC

FY.DOC 高 职 高 专 21 世 纪 规 划 教 材 C++ 程 序 设 计 邓 振 杰 主 编 贾 振 华 孟 庆 敏 副 主 编 人 民 邮 电 出 版 社 内 容 提 要 本 书 系 统 地 介 绍 C++ 语 言 的 基 本 概 念 基 本 语 法 和 编 程 方 法, 深 入 浅 出 地 讲 述 C++ 语 言 面 向 对 象 的 重 要 特 征 : 类 和 对 象 抽 象 封 装 继 承 等 主

More information

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2 PowerBuilder 9 PowerBuilder Native Interface(PBNI) PowerBuilder 9 PowerBuilder C++ Java PowerBuilder 9 PBNI PowerBuilder Java C++ PowerBuilder NVO / PowerBuilder C/C++ PowerBuilder 9.0 PowerBuilder Native

More information

入 指 令 如 : 鍵 盤 鼠 標 多 點 觸 控 重 力 感 應 陀 螺 儀 等 4. 圖 形 用 戶 接 口 掌 握 引 擎 API 中 GUI 與 GUILayout 類 中 方 法 和 變 量 的 使 用, 能 夠 通 過 GUI Skin 為 應 用 的 界 面 定 制 不 同 風 格 主

入 指 令 如 : 鍵 盤 鼠 標 多 點 觸 控 重 力 感 應 陀 螺 儀 等 4. 圖 形 用 戶 接 口 掌 握 引 擎 API 中 GUI 與 GUILayout 類 中 方 法 和 變 量 的 使 用, 能 夠 通 過 GUI Skin 為 應 用 的 界 面 定 制 不 同 風 格 主 Unity 專 業 能 力 認 證 (Unity Certified Professional) 應 考 須 知 壹 閱 讀 大 綱 主 題 一 : 數 字 媒 體 基 礎 知 識 1. 2D 圖 形 知 識 熟 悉 常 用 位 圖 數 據 的 結 構 和 格 式 其 中 包 括 像 素 數 據 顏 色 的 值 與 通 道 的 概 念 2. 3D 圖 形 學 相 關 知 識 a) 理 解 向 量 的

More information

摘 要 本 校 多 媒 體 設 計 系 與 上 海 戲 劇 學 院 創 意 學 院 在 多 次 聯 繫 交 流 之 下, 已 簽 署 合 作 備 忘 錄, 積 極 尋 求 兩 校 合 作 教 學 與 共 同 創 作 之 機 會 藉 由 本 系 學 生 作 品 腦 殘 公 寓 入 圍 第 五 屆 中

摘 要 本 校 多 媒 體 設 計 系 與 上 海 戲 劇 學 院 創 意 學 院 在 多 次 聯 繫 交 流 之 下, 已 簽 署 合 作 備 忘 錄, 積 極 尋 求 兩 校 合 作 教 學 與 共 同 創 作 之 機 會 藉 由 本 系 學 生 作 品 腦 殘 公 寓 入 圍 第 五 屆 中 出 國 報 告 ( 出 國 類 別 : 其 他 - 國 際 競 賽 ) 中 國 獨 立 遊 戲 節 國 際 學 生 競 賽 及 上 海 戲 劇 學 院 合 作 洽 談 服 務 機 關 : 國 立 臺 中 科 技 大 學 多 媒 體 設 計 系 姓 名 職 稱 : 金 啟 平 專 案 講 師 派 赴 國 家 : 中 國 出 國 期 間 :102.9.14 102.9.17 報 告 日 期 :102.11.20

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

新版 明解C++入門編

新版 明解C++入門編 511!... 43, 85!=... 42 "... 118 " "... 337 " "... 8, 290 #... 71 #... 413 #define... 128, 236, 413 #endif... 412 #ifndef... 412 #if... 412 #include... 6, 337 #undef... 413 %... 23, 27 %=... 97 &... 243,

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

幻灯片 1

幻灯片 1 次 世 代 手 游 的 探 讨 Speaker Kevin BY Art Director & idreamsky 第 一 部 分 次 世 代 手 游 的 探 索 和 制 作 1.Shader 2.Mesh 3.Animation 4.Lightmap 1.Shader 1.1Normal Map( 法 线 贴 图 ) 1.2Specular Mapping( 高 光 贴 图 ) 1.3Cube Map(

More information

概述

概述 OPC Version 1.6 build 0910 KOSRDK Knight OPC Server Rapid Development Toolkits Knight Workgroup, eehoo Technology 2002-9 OPC 1...4 2 API...5 2.1...5 2.2...5 2.2.1 KOS_Init...5 2.2.2 KOS_InitB...5 2.2.3

More information

Microsoft PowerPoint - string_kruse [兼容模式]

Microsoft PowerPoint - string_kruse [兼容模式] Strings Strings in C not encapsulated Every C-string has type char *. Hence, a C-string references an address in memory, the first of a contiguous set of bytes that store the characters making up the string.

More information

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx 运算符重载 Operator Overloading class Point { public: ; double x_, y_; Why Operator Overloading? Point (double x =0, double y = 0):x_(x),y_(y) { int main(){ Point a(1., 2), b(3,4); Point c = a + b; return 0;

More information

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc

Microsoft Word - 在VMWare-5.5+RedHat-9下建立本机QTopia-2.1.1虚拟平台a.doc 在 VMWare-5.5+RedHat-9 下建立 本机 QTopia-2.1.1 虚拟平台 张大海 2008-5-9 一 资源下载 1. 需要以下安装包 : tmake-1.13.tar.gz qtopia-free-source-2.1.1.tar.gz qt-embedded-2.3.10-free.tar.gz qt-x11-2.3.2.tar.gz qt-x11-free-3.3.4.tar.gz

More information

17 Prelight Apply Color Paint Vertex Color Tool Prelight Apply Color Paint Vertex Color Tool 242 Apply Color, Prelight Maya Shading Smooth

17 Prelight Apply Color Paint Vertex Color Tool Prelight Apply Color Paint Vertex Color Tool 242 Apply Color, Prelight Maya Shading Smooth 17 Prelight 233 234 242 Apply Color Paint Vertex Color Tool Prelight Apply Color Paint Vertex Color Tool 242 Apply Color, Prelight Maya Shading Smooth Shade All Custom Polygon DisplayOptions Color in Shaded

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

1.ai

1.ai HDMI camera ARTRAY CO,. LTD Introduction Thank you for purchasing the ARTCAM HDMI camera series. This manual shows the direction how to use the viewer software. Please refer other instructions or contact

More information

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

untitled

untitled 1 Outline 數 料 數 數 列 亂數 練 數 數 數 來 數 數 來 數 料 利 料 來 數 A-Z a-z _ () 不 數 0-9 數 不 數 SCHOOL School school 數 讀 school_name schoolname 易 不 C# my name 7_eleven B&Q new C# (1) public protected private params override

More information

C 1

C 1 C homepage: xpzhangme 2018 5 30 C 1 C min(x, y) double C // min c # include # include double min ( double x, double y); int main ( int argc, char * argv []) { double x, y; if( argc!=

More information

Ioncube Php Encoder 8 3 Crack 4. llamaba octobre traslado General Search colony

Ioncube Php Encoder 8 3 Crack 4. llamaba octobre traslado General Search colony Ioncube Php Encoder 8 3 Crack 4 ->>->>->> DOWNLOAD 1 / 5 2 / 5 Press..the..General..Tools..category4Encrypt..and..protect..files..with..PHP..encoding,..encryption,..ob fuscation..and..licensing... 2016

More information

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7.

Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes 包管理理 工具 Helm 蔺礼强 Kubenetes 系列列公开课 2 每周四晚 8 点档 1. Kubernetes 初探 2. 上 手 Kubernetes 3. Kubernetes 的资源调度 4. Kubernetes 的运 行行时 5. Kubernetes 的 网络管理理 6. Kubernetes 的存储管理理 7. Kubernetes

More information

Windows XP

Windows XP Windows XP What is Windows XP Windows is an Operating System An Operating System is the program that controls the hardware of your computer, and gives you an interface that allows you and other programs

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 49 [P.51] C/C++ [P.52] [P.53] [P.55] (int) [P.57] (float/double) [P.58] printf scanf [P.59] [P.61] ( / ) [P.62] (char) [P.65] : +-*/% [P.67] : = [P.68] : ,

More information

Microsoft PowerPoint - Aqua-Sim.pptx

Microsoft PowerPoint - Aqua-Sim.pptx Peng Xie, Zhong Zhou, Zheng Peng, Hai Yan, Tiansi Hu, Jun-Hong Cui, Zhijie Shi, Yunsi Fei, Shengli Zhou Underwater Sensor Network Lab 1 Outline Motivations System Overview Aqua-Sim Components Experimental

More information

Photoshop CS6 艺术设计案例教程 ( 第二版 ) 1.1 Photoshop 的应用领域 Photoshop,,, Photoshop Photoshop 的用途 Photoshop CIS ( ) ( ) 案例展现 ~ 1

Photoshop CS6 艺术设计案例教程 ( 第二版 ) 1.1 Photoshop 的应用领域 Photoshop,,, Photoshop Photoshop 的用途 Photoshop CIS ( ) ( ) 案例展现 ~ 1 Chapter 01 Photoshop CS6 的基本操作 本章内容 1.1 Photoshop 的应用领域 1.6 控制面板的显示与隐藏 1.2 位图和矢量图的特性 1.7 新建 打开与保存文件 1.3 像素和分辨率的关系 1.8 图像的缩放 1.4 色彩模式 1.9 屏幕显示模式 1.5 Photoshop CS6 界面 1.10 计算机图形图像常用的色彩模式 Photoshop CS6 艺术设计案例教程

More information

mvc

mvc Build an application Tutor : Michael Pan Application Source codes - - Frameworks Xib files - - Resources - ( ) info.plist - UIKit Framework UIApplication Event status bar, icon... delegation [UIApplication

More information

C H A P T E R 7 Windows Vista Windows Vista Windows Vista FAT16 FAT32 NTFS NTFS New Technology File System NTFS

C H A P T E R 7 Windows Vista Windows Vista Windows Vista FAT16 FAT32 NTFS NTFS New Technology File System NTFS C H P T E R 7 Windows Vista Windows Vista Windows VistaFT16 FT32NTFS NTFSNew Technology File System NTFS 247 6 7-1 Windows VistaTransactional NTFS TxFTxF Windows Vista MicrosoftTxF CIDatomicity - Consistency

More information

第四章 102 图 4唱16 基于图像渲染的理论基础 三张拍摄图像以及它们投影到球面上生成的球面图像 拼图的圆心是相同的 而拼图是由球面图像上的弧线图像组成的 因此我 们称之为同心球拼图 如图 4唱18 所示 这些拼图中半径最大的是圆 Ck 最小的是圆 C0 设圆 Ck 的半径为 r 虚拟相机水平视域为 θ 有 r R sin θ 2 4畅11 由此可见 构造同心球拼图的过程实际上就是对投影图像中的弧线图像

More information

提问袁小兵:

提问袁小兵: C++ 面 试 试 题 汇 总 柯 贤 富 管 理 软 件 需 求 分 析 篇 1. STL 类 模 板 标 准 库 中 容 器 和 算 法 这 部 分 一 般 称 为 标 准 模 板 库 2. 为 什 么 定 义 虚 的 析 构 函 数? 避 免 内 存 问 题, 当 你 可 能 通 过 基 类 指 针 删 除 派 生 类 对 象 时 必 须 保 证 基 类 析 构 函 数 为 虚 函 数 3.

More information

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class

More information

手册 doc

手册 doc 1. 2. 3. 3.1 3.2 3.3 SD 3.4 3.5 SD 3.6 3.7 4. 4.1 4.2 4.3 SD 4.4 5. 5.1 5.2 5.3 SD 6. 1. 1~3 ( ) 320x240~704x288 66 (2G SD 320x2401FPS ) 32M~2G SD SD SD SD 24V DC 3W( ) -10~70 10~90% 154x44x144mm 2. DVR106

More information

提纲 1 2 OS Examples for 3

提纲 1 2 OS Examples for 3 第 4 章 Threads2( 线程 2) 中国科学技术大学计算机学院 October 28, 2009 提纲 1 2 OS Examples for 3 Outline 1 2 OS Examples for 3 Windows XP Threads I An Windows XP application runs as a seperate process, and each process may

More information

Microsoft Word - 物件導向編程精要.doc

Microsoft Word - 物件導向編程精要.doc Essential Object-Oriented Programming Josh Ko 2007.03.11 object-oriented programming C++ Java OO class object OOP Ruby duck typing complexity abstraction paradigm objects objects model object-oriented

More information

EK-STM32F

EK-STM32F STMEVKIT-STM32F10xx8 软 件 开 发 入 门 指 南 目 录 1 EWARM 安 装... 1 1.1 第 一 步 : 在 线 注 册... 1 1.2 第 二 步 : 下 载 软 件... 2 1.3 第 三 步 : 安 装 EWARM... 3 2 基 于 STMEVKIT-STM32F10xx8 的 示 例 代 码 运 行... 6 2.1 GPIO Demo... 6 2.2

More information

Microsoft Word - CIN-DLL.doc

Microsoft Word - CIN-DLL.doc 6.3. 调 用 动 态 链 接 库 (DLL) 相 对 于 CIN 来 讲,NI 更 推 荐 用 户 使 用 DLL 来 共 享 基 于 文 本 编 程 语 言 开 发 的 代 码 除 了 共 享 或 重 复 利 用 代 码, 开 发 人 员 还 能 利 用 DLL 封 装 软 件 的 功 能 模 块, 以 便 这 些 模 块 能 被 不 同 开 发 工 具 利 用 在 LabVIEW 中 使 用

More information

绘制OpenCascade中的曲线

绘制OpenCascade中的曲线 在 OpenSceneGraph 中绘制 OpenCascade 的曲线 Draw OpenCascade Geometry Curves in OpenSceneGraph eryar@163.com 摘要 Abstract: 本文简要说明 OpenCascade 中几何曲线的数据, 并将这些几何曲线在 OpenSceneGraph 中绘制出来 关键字 KeyWords:OpenCascade Geometry

More information

epub83-1

epub83-1 C++Builder 1 C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r C + + B u i l d e r 1.1 1.1.1 1-1 1. 1-1 1 2. 1-1 2 A c c e s s P a r a d o x Visual FoxPro 3. / C / S 2 C + + B u i l d e r / C

More information

2015年4月11日雅思阅读预测机经(新东方版)

2015年4月11日雅思阅读预测机经(新东方版) 剑 桥 雅 思 10 第 一 时 间 解 析 阅 读 部 分 1 剑 桥 雅 思 10 整 体 内 容 统 计 2 剑 桥 雅 思 10 话 题 类 型 从 以 上 统 计 可 以 看 出, 雅 思 阅 读 的 考 试 话 题 一 直 广 泛 多 样 而 题 型 则 稳 中 有 变 以 剑 桥 10 的 test 4 为 例 出 现 的 三 篇 文 章 分 别 是 自 然 类, 心 理 研 究 类,

More information

Microsoft Word zw

Microsoft Word zw 第 1 章 Android 概述 学习目标 : Android Android Android Studio Android Android APK 1.1 1. 智能手机的定义 Smartphone 2. 智能手机的发展 1973 4 3 PC IBM 1994 IBM Simon PDA PDA Zaurus OS 1996 Nokia 9000 Communicator Nokia 9000

More information

2/80 2

2/80 2 2/80 2 3/80 3 DSP2400 is a high performance Digital Signal Processor (DSP) designed and developed by author s laboratory. It is designed for multimedia and wireless application. To develop application

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

第 5 期 吴 拥 民 : 三 维 引 擎 软 件 体 系 结 构 模 型 101 3D 引 擎 分 为 实 时 3D 引 擎 和 离 线 3D 引 擎 实 时 3D 引 擎 能 用 PC 机 及 游 戏 机 即 时 计 算 出 实 时 3D 画 面, 用 多 边 形 表 示 3D 模 型, 任 何

第 5 期 吴 拥 民 : 三 维 引 擎 软 件 体 系 结 构 模 型 101 3D 引 擎 分 为 实 时 3D 引 擎 和 离 线 3D 引 擎 实 时 3D 引 擎 能 用 PC 机 及 游 戏 机 即 时 计 算 出 实 时 3D 画 面, 用 多 边 形 表 示 3D 模 型, 任 何 第 33 卷 第 5 期 2012 年 9 月 闽 江 学 院 学 报 JOURNALOFMINJIANGUNIVERSITY Vol.33No.5 Sep.2012 三 维 引 擎 软 件 体 系 结 构 模 型 吴 拥 民 ( 闽 江 学 院 计 算 机 科 学 系, 福 建 福 州 350121) 摘 要 : 根 据 非 形 式 化 方 法, 构 造 了 三 维 引 擎 的 软 件 体 系 结

More information

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢   学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: 51141201063@ecnu.cn 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Java 类型 引用 不可变类型 对象存储位置 作用域 OOP

More information

在挑选合适的 SDK 的时候需要注意, 标准 windows 平台应用选择 FBX SDK VS2015,windows 应用商店和全平台通用的不用考虑 windows 全平台通用的应用是 windows10 新推出的功能, 可以打通 windows phone windows s

在挑选合适的 SDK 的时候需要注意, 标准 windows 平台应用选择 FBX SDK VS2015,windows 应用商店和全平台通用的不用考虑 windows 全平台通用的应用是 windows10 新推出的功能, 可以打通 windows phone windows s FBX SDK 安装配置 访问 FBX 网址 :http://www.autodesk.com/products/fbx/overview, 如下 : 点击 GET FBX SDK 进入 SDK 下载页面 ( 网址为 : http://usa.autodesk.com/adsk/servlet/pc/item?siteid=123112&id=25408427): 在挑选合适的 SDK 的时候需要注意,

More information

Microsoft Word - CX1000-HMI_程序开发_PLC通讯

Microsoft Word - CX1000-HMI_程序开发_PLC通讯 用 VB.Net 开发 CX1000 的 HMI 第二部分和 TwinCAT PLC 通讯 一 TwinCAT 动态库 TwinCAT.Ads.dll The TwinCAT.Ads.dll 是一个.NET 类库, 它提供和 ADS 设备通讯的类 如果 TwinCAT PLC 运行在 IPC 上, 则需要添加的类库是路径 \TwinCAT\ADS Api\.NET\v1.1.4322 下的 TwinCAT.Ads.dll

More information

INTRODUCTION TO COM.DOC

INTRODUCTION TO COM.DOC How About COM & ActiveX Control With Visual C++ 6.0 Author: Curtis CHOU mahler@ms16.hinet.net This document can be freely release and distribute without modify. ACTIVEX CONTROLS... 3 ACTIVEX... 3 MFC ACTIVEX

More information

3.1 num = 3 ch = 'C' 2

3.1 num = 3 ch = 'C' 2 Java 1 3.1 num = 3 ch = 'C' 2 final 3.1 final : final final double PI=3.1415926; 3 3.2 4 int 3.2 (long int) (int) (short int) (byte) short sum; // sum 5 3.2 Java int long num=32967359818l; C:\java\app3_2.java:6:

More information

bingdian001.com

bingdian001.com 1. DLL(Dynamic Linkable Library) DLL ± lib EXE DLL DLL EXE EXE ± EXE DLL 1 DLL DLL DLL Windows DLL Windows API Visual Basic Visual C++ Delphi 2 Windows system32 kernel32.dll user32.dll gdi32.dll windows

More information

三維空間之機械手臂虛擬實境模擬

三維空間之機械手臂虛擬實境模擬 VRML Model of 3-D Robot Arm VRML Model of 3-D Robot Arm MATLAB VRML MATLAB Simulink i MATLAB Simulink V-Realm Build Joystick ii Abstract The major purpose of this thesis presents the procedure of VRML

More information

Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE "Project Properties" IDE makefile 1.

Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE Project Properties IDE makefile 1. Oracle Solaris Studio 12.2 IDE 2010 9 2 8 9 10 11 13 20 26 28 30 32 33 Oracle Solaris Studio makefile C C++ Fortran IDE Solaris Linux C/C++/Fortran IDE "Project Properties" IDE makefile 1. "File" > "New

More information

C++ 程序设计 实验 2 - 参考答案 MASTER 2017 年 5 月 21 日 1

C++ 程序设计 实验 2 - 参考答案 MASTER 2017 年 5 月 21 日 1 C++ 程序设计 实验 2 - 参考答案 MASTER 2017 年 5 月 21 日 1 1 CRECT 类 1 CRect 类 设计矩形类, 包含 长度和宽度信息 基本构造函数 基础属性的访问接口 ( 读 / 写, Read/Write, Get/Set) 计算周长和面积 ( 注 : 基本构造函数, 一个无参数的默认构造函数, 以及一个初始化数据成员的构造函数如果数据成员的初始化有多种形式, 就提供多个构造函数

More information

untitled

untitled Visual Basic 2005 (VB.net 2.0) hana@arbor.ee.ntu.edu.tw 立 六 數 串 數數 數 數 串 數 串 數 Len( 串 ) 串 度 Len( 123 )=3 LCase( 串 ) 串 LCase( AnB123 ) anb123 UCase( 串 ) 串 UCase( AnB123 ) ANB123 串 數 InStr([ ], 串 1, 串 2[,

More information

<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63>

<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63> 基于 WINCE 平台 C# 编程要点之一 本文主要介绍在基于 Windows CE 平台的英创嵌入式主板下进行 C#(Microsoft Visual Stdio.Net 2005) 应用程序开发时会常常用到的一些功能函数以及开发方法, 这些方法适用于英创采用 WinCE 平台的所有型号嵌入式主板, 包括 EM9000 EM9260 EM9160 等 本文要点包括 : 文件的删除和复制 如何获取存取设备的空间大小

More information

Microsoft PowerPoint - Lecture7II.ppt

Microsoft PowerPoint - Lecture7II.ppt Lecture 8II SUDOKU PUZZLE SUDOKU New Play Check 軟體實作與計算實驗 1 4x4 Sudoku row column 3 2 } 4 } block 1 4 軟體實作與計算實驗 2 Sudoku Puzzle Numbers in the puzzle belong {1,2,3,4} Constraints Each column must contain

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F 1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET 2.0 2.0.NET Framework.NET Framework 2.0 ( 3).NET Framework 2.0.NET Framework ( System ) o o o o o o Boxing UnBoxing() o

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

科学计算的语言-FORTRAN95

科学计算的语言-FORTRAN95 科 学 计 算 的 语 言 -FORTRAN95 目 录 第 一 篇 闲 话 第 1 章 目 的 是 计 算 第 2 章 FORTRAN95 如 何 描 述 计 算 第 3 章 FORTRAN 的 编 译 系 统 第 二 篇 计 算 的 叙 述 第 4 章 FORTRAN95 语 言 的 形 貌 第 5 章 准 备 数 据 第 6 章 构 造 数 据 第 7 章 声 明 数 据 第 8 章 构 造

More information

六域链联盟 SDChain-Matrix 节点搭建指南 2018/07/26 Version : 1.0.0

六域链联盟 SDChain-Matrix 节点搭建指南 2018/07/26 Version : 1.0.0 SDChain-Matrix 节点搭建指南 目录 1 环境要求... 3 2 软件下载... 4 3 安装部署... 4 3.1 部署可执行程序目录... 4 3.2 部署配置文件目录... 4 3.3 部署数据库文件目录... 4 3.4 部署日志文件目录... 4 3.5 部署依赖库文件目录... 4 4 配置参数... 5 5 启动运行... 7 5.1 普通模式启动... 7 5.2 加载启动模式...

More information

Important Notice SUNPLUS TECHNOLOGY CO. reserves the right to change this documentation without prior notice. Information provided by SUNPLUS TECHNOLO

Important Notice SUNPLUS TECHNOLOGY CO. reserves the right to change this documentation without prior notice. Information provided by SUNPLUS TECHNOLO Car DVD New GUI IR Flow User Manual V0.1 Jan 25, 2008 19, Innovation First Road Science Park Hsin-Chu Taiwan 300 R.O.C. Tel: 886-3-578-6005 Fax: 886-3-578-4418 Web: www.sunplus.com Important Notice SUNPLUS

More information

Guide to Install SATA Hard Disks

Guide to Install SATA Hard Disks SATA RAID 1. SATA. 2 1.1 SATA. 2 1.2 SATA 2 2. RAID (RAID 0 / RAID 1 / JBOD).. 4 2.1 RAID. 4 2.2 RAID 5 2.3 RAID 0 6 2.4 RAID 1.. 10 2.5 JBOD.. 16 3. Windows 2000 / Windows XP 20 1. SATA 1.1 SATA Serial

More information

1 目 錄 1. 簡 介... 2 2. 一 般 甄 試 程 序... 2 3. 第 一 階 段 的 準 備... 5 4. 第 二 階 段 的 準 備... 9 5. 每 間 學 校 的 面 試 方 式... 11 6. 各 程 序 我 的 做 法 心 得 及 筆 記... 13 7. 結 論..

1 目 錄 1. 簡 介... 2 2. 一 般 甄 試 程 序... 2 3. 第 一 階 段 的 準 備... 5 4. 第 二 階 段 的 準 備... 9 5. 每 間 學 校 的 面 試 方 式... 11 6. 各 程 序 我 的 做 法 心 得 及 筆 記... 13 7. 結 論.. 如 何 準 備 研 究 所 甄 試 劉 富 翃 1 目 錄 1. 簡 介... 2 2. 一 般 甄 試 程 序... 2 3. 第 一 階 段 的 準 備... 5 4. 第 二 階 段 的 準 備... 9 5. 每 間 學 校 的 面 試 方 式... 11 6. 各 程 序 我 的 做 法 心 得 及 筆 記... 13 7. 結 論... 20 8. 附 錄 8.1 推 甄 書 面 資 料...

More information

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc References (Section 5.2) Hsuan-Tien Lin Deptartment of CSIE, NTU OOP Class, March 15-16, 2010 H.-T. Lin (NTU CSIE) References OOP 03/15-16/2010 0 / 22 Fun Time (1) What happens in memory? 1 i n t i ; 2

More information

影視後製全攻略 Premiere Pro After Effects Encore 自序 Adobe Premiere Pro After Effects Encore 2008 Adobe CS Adobe CS5 Adobe CS4 Premiere Pro After Effect

影視後製全攻略 Premiere Pro After Effects Encore 自序 Adobe Premiere Pro After Effects Encore 2008 Adobe CS Adobe CS5 Adobe CS4 Premiere Pro After Effect 自序 Adobe Premiere Pro After Effects Encore 2008 Adobe CS3 2010 Adobe CS5 Adobe CS4 Premiere Pro After Effects Encore 18 ii Tony Cathy 2010/8 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 iii Premiere

More information

K7VT2_QIG_v3

K7VT2_QIG_v3 ............ 1 2 3 4 5 [R] : Enter Raid setup utility 6 Press[A]keytocreateRAID RAID Type: JBOD RAID 0 RAID 1: 2 7 RAID 0 Auto Create Manual Create: 2 RAID 0 Block Size: 16K 32K

More information

BC04 Module_antenna__ doc

BC04 Module_antenna__ doc http://www.infobluetooth.com TEL:+86-23-68798999 Fax: +86-23-68889515 Page 1 of 10 http://www.infobluetooth.com TEL:+86-23-68798999 Fax: +86-23-68889515 Page 2 of 10 http://www.infobluetooth.com TEL:+86-23-68798999

More information

付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探

付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探 付宝容器 jsapi 档 册 PDF 版本 本版本为实验版本, 为线下独 查看使, 受制于 成 PDF 程序的限制, 样式问题还没有很好的解决, 例如分 切图 代码 亮 推荐使 在线版本, 便实时查看 jsapi 运 效果 如需搜索, 使 阅读 PDF 软件 带功能即可 更多细节样式调整和 录索引探索建设中 成时间 : 2017-07-20 12:13:21 Since 8.6 定义键盘 定义键盘使

More information

IP505SM_manual_cn.doc

IP505SM_manual_cn.doc IP505SM 1 Introduction 1...4...4...4...5 LAN...5...5...6...6...7 LED...7...7 2...9...9...9 3...11...11...12...12...12...14...18 LAN...19 DHCP...20...21 4 PC...22...22 Windows...22 TCP/IP -...22 TCP/IP

More information

藍牙網路在資訊家電的應用

藍牙網路在資訊家電的應用 崑 山 科 技 大 學 資 訊 工 程 系 專 題 製 作 報 告 ANDROID 3D 推 箱 子 遊 戲 ANDROID 3D - BOXGAME 學 生 : 黃 咸 嘉 陳 政 男 郭 撫 龍 指 導 老 師 : 李 宗 儒 中 華 民 國 一 百 一 年 五 月 i ANDROID 3D 推 箱 子 遊 戲 ANDROID 3D - BOXGAME 學 生 : 黃 咸 嘉 Student:

More information

Microsoft PowerPoint - 20130411-龍華科技大學遊戲系-Unity teaching

Microsoft PowerPoint - 20130411-龍華科技大學遊戲系-Unity teaching Unity 開 發 實 務 ( 一 ) 雷 爵 網 絡 尤 治 凱 關 於 我 龍 華 科 技 大 學 多 媒 體 與 遊 戲 發 展 科 學 系 畢 業 4 年 遊 戲 業 資 歷 現 任 雷 爵 網 絡 遊 戲 開 發 工 程 師 1 款 單 機 遊 戲 開 發 1 款 MMO 遊 戲 維 護 1 款 MMO 遊 戲 開 發,1 款 APP 開 發 綱 要 小 遊 戲 展 示 小 遊 戲 發 想

More information

東莞工商總會劉百樂中學

東莞工商總會劉百樂中學 /2015/ 頁 (2015 年 版 ) 目 錄 : 中 文 1 English Language 2-3 數 學 4-5 通 識 教 育 6 物 理 7 化 學 8 生 物 9 組 合 科 學 ( 化 學 ) 10 組 合 科 學 ( 生 物 ) 11 企 業 會 計 及 財 務 概 論 12 中 國 歷 史 13 歷 史 14 地 理 15 經 濟 16 資 訊 及 通 訊 科 技 17 視 覺

More information

RunPC2_.doc

RunPC2_.doc PowerBuilder 8 (5) PowerBuilder Client/Server Jaguar Server Jaguar Server Connection Cache Thin Client Internet Connection Pooling EAServer Connection Cache Connection Cache Connection Cache Connection

More information

untitled

untitled OGRE http://antsam.blogone.net AntsamCGD@hotmail.com OGRE OGRE listener listener target listener target Dispatcher Processor Input Reader Event class view Event Class view Input Event ctrlaltshift ascoll

More information

Epson

Epson WH / MS CMP0087-00 TC WH/MS EPSON EPSON EXCEED YOUR VISION EXCEED YOUR VISION Seiko Corporation Microsoft and Windows are registered trademarks of Microsoft Corporation. Mac and Mac OS are registered trademarks

More information

untitled

untitled 3 C++ 3.1 3.2 3.3 3.4 new delete 3.5 this 3.6 3.7 3.1 3.1 class struct union struct union C class C++ C++ 3.1 3.1 #include struct STRING { typedef char *CHARPTR; // CHARPTR s; // int strlen(

More information

RAGE来咯!关于 ID TECH 5 MEGATEXTURE 的一些技术信息更新

RAGE来咯!关于 ID TECH 5 MEGATEXTURE 的一些技术信息更新 RAGE 来 了 --- 关 于 ID TECH 5 MEGATEXTURE 的 一 些 技 术 信 息 更 新 H3D 姚 勇 信 息...1 介 绍...2 一, 目 的...2 二, 实 现...2 1, 预 处 理...3 1.1 贴 图 预 处 理... 3 1.2 几 何 预 处 理... 7 2, 绘 制...7 3, 具 体 步 骤... 8 3.1 判 断 本 帧 绘 制 要 用

More information

K301Q-D VRT中英文说明书141009

K301Q-D VRT中英文说明书141009 THE INSTALLING INSTRUCTION FOR CONCEALED TANK Important instuction:.. Please confirm the structure and shape before installing the toilet bowl. Meanwhile measure the exact size H between outfall and infall

More information

1 C++ 2 Bjarne Stroustrup C++ (system programming) 6 (infrastructure) C++ 7 Herb Sutter 8 C++ (efficiency) (flexibility) 9 (abstraction) (productivity

1 C++ 2 Bjarne Stroustrup C++ (system programming) 6 (infrastructure) C++ 7 Herb Sutter 8 C++ (efficiency) (flexibility) 9 (abstraction) (productivity 1 C++ 1 C++ Primer C++ (giantchen@gmail.com) 2012-7-11 Creative Commons - - 3.0 Unported (cc by-nc-nd) http://creativecommons.org/licenses/by-nc-nd/3.0/ 1 C++ 2009 Stanley Lippman C++ C++ Java/C#/Python

More information

Microsoft PowerPoint - 10 模板 Template.pptx

Microsoft PowerPoint - 10 模板 Template.pptx 模板 Tempalte 泛型编程的需要 Why Templates? 设想你对整数类型实现了一个排序算法 : void sort(int *is,int n); 用该函数可以对实 复数或工资单排序吗? 模板可以复用源代码 - 泛型编程. inline void Swap( int &x, int &y){ int t = x; x = y; y =t; inline void Swap(double

More information

Oracle Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE "P

Oracle Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE P Oracle Solaris Studio 12.3 IDE 2011 12 E26461-01 2 7 8 9 9 Oracle 10 12 14 21 26 27 29 31 32 33 Oracle Solaris Studio IDE makefile C C++ Fortran makefile IDE Solaris Linux C/C++/Fortran Oracle IDE "Project

More information

KDC-U5049 KDC-U4049 Made for ipod, and Made for iphone mean that an electronic accessory has been designed to connect specifically to ipod, or iphone,

KDC-U5049 KDC-U4049 Made for ipod, and Made for iphone mean that an electronic accessory has been designed to connect specifically to ipod, or iphone, KDC-U5049 KDC-U4049 Made for ipod, and Made for iphone mean that an electronic accessory has been designed to connect specifically to ipod, or iphone, respectively, and has been certified by the developer

More information

C/C++语言 - C/C++数据

C/C++语言 - C/C++数据 C/C++ C/C++ Table of contents 1. 2. 3. 4. char 5. 1 C = 5 (F 32). 9 F C 2 1 // fal2cel. c: Convert Fah temperature to Cel temperature 2 # include < stdio.h> 3 int main ( void ) 4 { 5 float fah, cel ;

More information

A Preliminary Implementation of Linux Kernel Virus and Process Hiding

A Preliminary Implementation of Linux Kernel Virus and Process Hiding 邵 俊 儒 翁 健 吉 妍 年 月 日 学 号 学 号 学 号 摘 要 结 合 课 堂 知 识 我 们 设 计 了 一 个 内 核 病 毒 该 病 毒 同 时 具 有 木 马 的 自 动 性 的 隐 蔽 性 和 蠕 虫 的 感 染 能 力 该 病 毒 获 得 权 限 后 会 自 动 将 自 身 加 入 内 核 模 块 中 劫 持 的 系 统 调 用 并 通 过 简 单 的 方 法 实 现 自 身 的

More information

Microsoft Word - 11.doc

Microsoft Word - 11.doc 除 錯 技 巧 您 將 於 本 章 學 到 以 下 各 項 : 如 何 在 Visual C++ 2010 的 除 錯 工 具 控 制 下 執 行 程 式? 如 何 逐 步 地 執 行 程 式 的 敘 述? 如 何 監 看 或 改 變 程 式 中 的 變 數 值? 如 何 監 看 程 式 中 計 算 式 的 值? 何 謂 Call Stack? 何 謂 診 斷 器 (assertion)? 如 何

More information

Some experiences in working with Madagascar: installa7on & development Tengfei Wang, Peng Zou Tongji university

Some experiences in working with Madagascar: installa7on & development Tengfei Wang, Peng Zou Tongji university Some experiences in working with Madagascar: installa7on & development Tengfei Wang, Peng Zou Tongji university Map data @ Google Reproducible research in Madagascar How to conduct a successful installation

More information

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File 51 C 51 51 C C C C C C * 2003-3-30 pnzwzw@163.com C C C C KEIL uvision2 MCS51 PLM C VC++ 51 KEIL51 KEIL51 KEIL51 KEIL 2K DEMO C KEIL KEIL51 P 1 1 1 1-1 - 1 Project New Project 1 2 Windows 1 3 N C test

More information

ebook140-9

ebook140-9 9 VPN VPN Novell BorderManager Windows NT PPTP V P N L A V P N V N P I n t e r n e t V P N 9.1 V P N Windows 98 Windows PPTP VPN Novell BorderManager T M I P s e c Wi n d o w s I n t e r n e t I S P I

More information

59 1 CSpace 2 CSpace CSpace URL CSpace 1 CSpace URL 2 Lucene 3 ID 4 ID Web 1. 2 CSpace LireSolr 3 LireSolr 3 Web LireSolr ID

59 1 CSpace 2 CSpace CSpace URL CSpace 1 CSpace URL 2 Lucene 3 ID 4 ID Web 1. 2 CSpace LireSolr 3 LireSolr 3 Web LireSolr ID 58 2016. 14 * LireSolr LireSolr CEDD Ajax CSpace LireSolr CEDD Abstract In order to offer better image support services it is necessary to extend the image retrieval function of our institutional repository.

More information

Microsoft Word - 3D手册2.doc

Microsoft Word - 3D手册2.doc 第 一 章 BLOCK 前 处 理 本 章 纲 要 : 1. BLOCK 前 处 理 1.1. 创 建 新 作 业 1.2. 设 定 模 拟 控 制 参 数 1.3. 输 入 对 象 数 据 1.4. 视 图 操 作 1.5. 选 择 点 1.6. 其 他 显 示 窗 口 图 标 钮 1.7. 保 存 作 业 1.8. 退 出 DEFORMTM3D 1 1. BLOCK 前 处 理 1.1. 创 建

More information

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式] 用户定义类型 User-defined Datatypes classes and structs 几何向量 (Geometry Vector) 二维平面上的向量由起点和终点构成 每个点包含两个坐标 (x, y), 因此一个向量需要四个实数表示 Start= (0.9,1.5) Start= (0.4,0.8) int main() { double xstart = 0.4; double xend

More information

Learning Java

Learning Java Java Introduction to Java Programming (Third Edition) Prentice-Hall,Inc. Y.Daniel Liang 2001 Java 2002.2 Java2 2001.10 Java2 Philip Heller & Simon Roberts 1999.4 Java2 2001.3 Java2 21 2002.4 Java UML 2002.10

More information

CC213

CC213 : (Ken-Yi Lee), E-mail: feis.tw@gmail.com 9 [P.11] : Dev C++ [P.12] : http://c.feis.tw [P.13] [P.14] [P.15] [P.17] [P.23] Dev C++ [P.24] [P.27] [P.34] C / C++ [P.35] 10 C / C++ C C++ C C++ C++ C ( ) C++

More information

f2.eps

f2.eps 前 言, 目 录 产 品 概 况 1 SICAM PAS SICAM 电 力 自 动 化 系 统 配 置 和 使 用 说 明 配 置 2 操 作 3 实 时 数 据 4 人 机 界 面 5 SINAUT LSA 转 换 器 6 状 态 与 控 制 信 息 A 版 本 号 : 08.03.05 附 录, 索 引 安 全 标 识 由 于 对 设 备 的 特 殊 操 作 往 往 需 要 一 些 特 殊 的

More information

AL-M200 Series

AL-M200 Series NPD4754-00 TC ( ) Windows 7 1. [Start ( )] [Control Panel ()] [Network and Internet ( )] 2. [Network and Sharing Center ( )] 3. [Change adapter settings ( )] 4. 3 Windows XP 1. [Start ( )] [Control Panel

More information

Chn 116 Neh.d.01.nis

Chn 116 Neh.d.01.nis 31 尼 希 米 书 尼 希 米 的 祷 告 以 下 是 哈 迦 利 亚 的 儿 子 尼 希 米 所 1 说 的 话 亚 达 薛 西 王 朝 二 十 年 基 斯 流 月 *, 我 住 在 京 城 书 珊 城 里 2 我 的 兄 弟 哈 拿 尼 和 其 他 一 些 人 从 犹 大 来 到 书 珊 城 我 向 他 们 打 听 那 些 劫 后 幸 存 的 犹 太 人 家 族 和 耶 路 撒 冷 的 情 形

More information

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit

(TestFailure) JUnit Framework AssertionFailedError JUnit Composite TestSuite Test TestSuite run() run() JUnit Tomcat Web JUnit Cactus JUnit Java Cactus JUnit 26.1 JUnit Java JUnit JUnit Java JSP Servlet JUnit Java Erich Gamma Kent Beck xunit JUnit boolean JUnit Java JUnit Java JUnit Java 26.1.1 JUnit JUnit How

More information

基于ECO的UML模型驱动的数据库应用开发1.doc

基于ECO的UML模型驱动的数据库应用开发1.doc ECO UML () Object RDBMS Mapping.Net Framework Java C# RAD DataSetOleDbConnection DataGrod RAD Client/Server RAD RAD DataReader["Spell"].ToString() AObj.XXX bug sql UML OR Mapping RAD Lazy load round trip

More information

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 Java V1.0.1 2007 4 10 1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 6.2.10 6.3..10 6.4 11 7.12 7.1

More information