Ogre 界面(Overlay)

2023-10-26

2011-10-16 23:12  4725人阅读  评论(2)  收藏  举报
  分类:

这里的界面是指菜单、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 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.0 - 1.0的参数表达的,是一个和屏幕宽度及高度的比值。这样做的方式是为了使这些值与显示分辨率无关,从而使显示结果可以适应任何分辨率。例如:0.5x0.5的尺寸代表屏幕宽和高的一半大,此外请注意,0.5x0.5的尺寸在屏幕上显示出来并不是一个正方形,因为屏幕本身就不是正方形。
GuiElements被设计成可扩展的,它是StringInterface类的子类,所以它的参数也是通用参数。
我们可以继承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类型。
TextAreaGuiElement
2D界面元素,GuiElement的直接派生类,定义界面中的文本区域。
PanelGuiElement
2D界面元素,GuiContainer的直接派生类,定义界面中的面板区域,在面板中还能包括其它界面元素。
BorderPanelGuiElement
2D界面元素,GuiContainer的直接派生类,定义界面中的带边面板区域,在带边面板中还能包括其它界面元素。
ButtonGuiElement
2D界面元素,BorderPanelGuiElement的直接派生类,定义界面中的按钮。
ListGuiElement
2D界面元素,PanelGuiElement的直接派生类,定义界面中的列表选择框。


GUI静态结构图


Overlay脚本
Overlay脚本为我们提供了使用脚本来定义可重用的overlays的手段。
载入脚本
Overlay脚本在系统初始化的时候被载入。缺省情况下,系统会把公共资源路径(参考Root::addResourceLocation)下所有扩展名为'.overlay'的文件都载入并解析。如果你的Overlay脚本使用了其它扩展名,你可以使用OverlayManager::getSingleton().parseAllSources函数载入它们,如果你想载入单个Overlay脚本,就使用OverlayManager::getSingleton().parseScript函数。
格式
可以在一个脚本文件中定义多个overlay。脚本采用伪C++格式,用{ }分块,注释采用‘//’(注意不支持注释嵌套),而且支持模板继承。以下是一个典型的实例:
// 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 
             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元素的层层嵌套。
'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特有的属性:
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特有的属性:
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'关键字就可以定义模板。模板元素一般定义在脚本文件的开头,而且不能定义在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 0.05 0.05 0.06665 0.06665
    border_material Core/StatsBlockBorder
    border_topleft_uv 0.0000 1.0000 0.1914 0.7969
    border_top_uv 0.1914 1.0000 0.8086 0.7969
    border_topright_uv 0.8086 1.0000 1.0000 0.7969
    border_left_uv 0.0000 0.7969 0.1914 0.2148
    border_right_uv 0.8086 0.7969 1.0000 0.2148
    border_bottomleft_uv 0.0000 0.2148 0.1914 0.0000
    border_bottom_uv 0.1914 0.2148 0.8086 0.0000
    border_bottomright_uv 0.8086 0.2148 1.0000 0.0000
}
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
    colour_top 1 1 0
    colour_bottom 1 0.2 0.2
    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
            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中的????
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 0 0 -50
rotation 0 0 0 0
}

}
// another logo overlay
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:
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);
    }
};

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
        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);
}

};

OGRE会在程序运行时自动载入.overlay文件,缺省情况下是不显示的。在OGRE应用框架的ExampleApplication类中把DebugOverlay的显示开关打开了,其它的overlay必须由程序员手工打开。以上程序在createScene函数中通过OverlayManager::getSingleton().getByName()函数获取到overlay的指针,再通过show函数打开显示开关。
Overlay提供滚动、旋转和缩放函数,在FrameListener控制其滚动很好地达到了动画效果。
实现界面事件处理
OGRE引擎已经将一些界面元素的基本事件处理完成,例如:按钮被点击时的动作效果、List列表中选项被选择后的特殊显示等。但是按钮被按下后还要完成什么事情需要程序员自己完成,例如Exit按钮被按下后程序要退出、Option按钮被按下后要进入系统设置菜单等。
OGRE的事件处理目前还未全部完成,请暂时参考OGRE的Demo_Gui。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pizi0475/archive/2010/04/05/5451304.aspx

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ogre 界面(Overlay) 的相关文章

  • Ubuntu运行rviz报错:OGRE EXCEPTION(3:RenderingAPIException): Unable to create a suitable GLXContext

    写在前面 笔者的测试环境 xff1a Ubuntu20 04 xff0c ROS noteic 一 问题描述 运行rviz时出现报错 xff1a span class token punctuation span WARN span cla
  • 纹理(Textures)

    纹理 Textures 原文 Textures 作者 JoeyDeVries 翻译 Django 校对 Geequlim BLumia 我们已经了解到 我们可以为每个顶点使用颜色来增加图形的细节 从而创建出有趣的图像 但是 如果想让图形看起
  • 可编程渲染管线与着色器语言

    可编程渲染管线与着色器语言 Programming pipeline shading language Sampler Direct3D 9 asm ps A sampler is a input pseudo register for a
  • [OGRE]基础教程来四发:来谈一谈地形系统

    OGRE 基础教程来四发 来谈一谈地形系统 标签 OGRE 2013 10 09 17 22 2238人阅读 评论 1 收藏 举报 分类 OGRE 11 版权声明 本文为博主原创文章 未经博主允许不得转载 英文链接如下 http www o
  • 如果XML文件太大(10M),打开方式选择

    用UltraEdit打开 其他的例如Editplus和notepad 根本打不开上百M的文件 一打开就死了
  • tinyxml开发入门

    概述 tinyxml和xercesc一样 提供了完整的dom操作api tinyxml相对比较简单好用 编译连接也不容易出问题 xercesc比较麻烦 非常完整庞大 编译有点麻烦 有内存泄漏 我认为在一般需求完全可以使用tinyxml ti
  • 地形纹理Splatting技术(翻译)

    地形纹理Splatting技术 翻译 文章来源 http www gamedev net reference articles article2238 asp Texture Splatting in Direct3D Introducti
  • Axiom3D:Ogre地形代码解析

    Axiom3D Ogre地形代码解析 作者 天天不在 发布日期 2014 09 01 20 52 05 我来说两句 0 Tag标签 地形 代码 大致流程 这里简单介绍下 Axiom中采用的Ogre的地形组件的一些概念与如何生成地形 先说下大
  • Texture Format全解析

    Texture Format全解析 Texture Format全解析 What internal representation is used for the texture This is a tradeoff between size
  • VC 运行时库 /MD、/MDd 和 /MT、/MTd

    VC 运行时库 MD MDd 和 MT MTd 2013 01 24 18 42 11058人阅读 评论 2 收藏 举报 分类 C C 19 有段时间在写cuda程序是出现过 error LNK2005 exit 已经在 MSVCRTD l
  • 转:Ogre TerrainGroup地形赏析

    转 Ogre TerrainGroup地形赏析 1 1 参考 http www ogre3d org tikiwiki tiki index php page Ogre Terrain System http www ogre3d org
  • hlsl register

    https msdn microsoft com en us library dd607359 v VS 85 aspx register Optional keyword for assigning a shader variable t
  • 理解D3D—(2)最多混合几层texture

    理解D3D 2 最多混合几层texture 先提出问题 Q 要是模型有很多层贴图 再加上shadow map 还有ssao 岂不是会不够用了 A 参考资料 IDirect3DDevice9 SetTexture Assigns a text
  • DirectD3D-纹理映射

    DirectD3D 纹理映射 标签 Direct3Ddirectx游戏游戏开发 2014 11 12 14 03 321人阅读 评论 0 收藏 举报 分类 DirectX 8 版权声明 本文为博主原创文章 未经博主允许不得转载 纹理映射的概
  • OGRE动画

    动画是由若干静态画面 快速交替显示而成 因人的眼睛会产生视角暂留 对上一个画面的感知还末消失 下一张画面又出现 就会有动的感觉 计算机图形学中的动画也同样遵循着这一本质的原理 只不过不同于传统动画的手绘和拍摄 Ogre图形引擎可以通过自动或
  • 关于 Demo_Ocean 例子的分析

    关于 Demo Ocean 例子的分析 重要总结 1 该例主要类不再继承自ExampleApplication和ExampleFrameListener 重写驱动类和监听类 2 如何创建OIS的输入系统 1 创建OIS ParamList
  • 2021年11月6日-11月12日(ogre抄写+ue4视频,本周35小时,共1035小时,剩8965小时。)

    这周还不错 不但完成了本周学习任务 还完成了本月学习任务 方法就是 拼命抄源码 抄到吐时就再看看Ue4视频教程 内外兼修 可以在未来的日子里这么进行 每天5小时学习 还是进入状态的 5 7 35小时 共1035小时 剩8965小时 另外 去
  • 第十三章 公告板与粒子系统 标签: ogre公告板粒子系统ogre粒子系统

    Ogre编程入门与进阶 第十三章 公告板与粒子系统 标签 ogre公告板粒子系统ogre粒子系统 2015 07 05 14 41 1365人阅读 评论 1 收藏 举报 分类 Orge模块 16 版权声明 本文为博主原创文章 未经博主允许不
  • Ogre/Mogre:相机两点透视

    我正在显示一个场景 其中有一些立方体 相机采用的是透视法 一切都很好 但我希望垂直线是平行的 两点透视 http en wikipedia org wiki Perspective graphical 两点透视 从正面观察立方体时 我想要的
  • Ogre g++ 编译时错误

    在ubuntu上 我已经编译并安装了所有的ogre库 但是 当我尝试使用此命令编译教程时 g o otest ogre cpp I pkg config libs cflags OGRE OIS lOgreMain lOI 它输出 tmp

随机推荐