Post on 24-Jul-2015
description
Introdução ao
Ogre3D
Maylson Gonçalves
@maylson
Outubro/2010
Belém, Pará
2
Índice de Figuras
Figura 1 - Download do OGRE SDK ................................................................................... 7
Figura 2 - Diretório para onde será extraído o OGRE SDK ............................................... 8
Figura 3 - Andamento da extração do OGRE SDK ............................................................ 8
Figura 4 - Conteúdo do diretório de instalação do OGRE SDK ......................................... 9
Figura 5 - Criação da variável de ambiente do OGRE ....................................................... 9
Figura 6 - Lista de variáveis de ambiente, com a nova variável criada .......................... 10
Figura 7 - Exemplos do OGRE SDK .................................................................................. 13
Figura 8 - Erro ao compilar o SampleBrowser ................................................................ 14
Figura 9 - Solução do erro no Pre-Link Event.................................................................. 14
Figura 10 - Janela de configuração do Ogre3D ............................................................... 15
Figura 11 - Screenshot do SampleBrowser ..................................................................... 16
Figura 12 - Criação de um novo projeto ......................................................................... 17
Figura 13 - Adicionando um arquivo ao projeto ............................................................ 18
Figura 14 - Criando o arquivo Main.cpp na subpasta Source ......................................... 18
Figura 15 - Configuração da guia General em modo Release ........................................ 19
Figura 16 - Configuração da guia C/C++ >>> General ..................................................... 20
Figura 17 - Configuração da guia Linker >>> General ..................................................... 21
Figura 18 - Configuração da guia Linker >>> Input ......................................................... 21
3
Sumário
Índice de Figuras ............................................................................................................... 2
Introdução ao Ogre3D ...................................................................................................... 5
Pré-requisitos ................................................................................................................ 5
Plataformas ................................................................................................................... 6
Instalação do Ambiente de Desenvolvimento ................................................................. 7
Estrutura de Diretórios do OGRE SDK ......................................................................... 10
bin ........................................................................................................................... 10
Docs ........................................................................................................................ 11
include .................................................................................................................... 11
lib ............................................................................................................................ 11
Samples ................................................................................................................... 12
media ...................................................................................................................... 12
Compilando os Exemplos do OGRE............................................................................. 12
Criando um Projeto no VC++ ...................................................................................... 16
Inicialização do OGRE ..................................................................................................... 23
Root ........................................................................................................................ 23
plugins.cfg ............................................................................................................... 23
ogre.cfg ................................................................................................................... 24
Ogre.log .................................................................................................................. 26
Render Window ...................................................................................................... 26
Scene Manager ....................................................................................................... 27
Render Loop............................................................................................................ 29
Frame Listener ........................................................................................................ 30
Main Rendering Loop ............................................................................................. 31
Gerenciamento dos Recursos de Media ........................................................................ 33
Gerenciamento de Recursos na Prática ................................................................. 33
Localização dos Recursos........................................................................................ 34
Inicialização dos Recursos ...................................................................................... 35
Descarregamento de Recursos ............................................................................... 36
Dispositivos de Entrada .................................................................................................. 37
4
Biblioteca de Input.................................................................................................. 37
Input Manager e Input Listener .............................................................................. 37
Materials ......................................................................................................................... 43
Scene Management ........................................................................................................ 43
Ferramentas de Produtividade ....................................................................................... 43
Animação ........................................................................................................................ 43
GUI com SdkTrays ........................................................................................................... 43
Estudo de Caso ............................................................................................................... 43
Hot tips ........................................................................................................................... 44
Dúvidas comuns .............................................................................................................. 44
Exportação com o Blender ............................................................................................. 44
5
Introdução ao Ogre3D
OGRE (Object Oriented Graphics Rendering Engine) é um motor de renderização
gráfica em tempo real, multiplataforma, escrito em C++ e de código aberto, construído
para abstrair as especificidades das APIs (Application Interface Programming) de
renderização gráfica de baixo nível, como o DirectX e o OpenGL. O OGRE é mantido por
um pequeno grupo de desenvolvedores que trabalham no núcleo do motor, mas que
também recebe contribuições de diversos usuários.
O OGRE também pode ser utilizado em outras linguagens de programação,
como Java, C# e Python, através de wrappers construídos pela comunidade, ou seja,
não suportados oficialmente pela equipe de desenvolvimento do OGRE, estando em
diversos graus de estabilidade e completude em relação ao OGRE oficial.
Um erro comum relacionado ao OGRE é devido a sua qualidade como Motor de
Jogos ou Game Engine. O OGRE não é, nem nunca teve a pretensão de ser uma
plataforma de desenvolvimento de jogos completa, sendo, ao invés disso, apenas uma
plataforma de renderização gráfica, podendo ser utilizada em diversas aplicações de
computação gráfica, inclusive games. Uma pergunta comum nos fóruns do OGRE é:
“Como eu rodo o OGRE?”. Bem, você não roda. OGRE não é um programa. Não existe
um executável do OGRE. O OGRE é um SDK (Software Development Kit), o que significa
que deve ser utilizado para desenvolver software.
Pré-requisitos
Este curso é destinado à iniciantes em Ogre3D e em computação gráfica em
geral, interessados em utilizar gráficos 3D acelerados por hardware em seus games
e/ou aplicações. Apesar de ser um curso para iniciantes, alguns pré-requisitos devem
ser cumpridos, como por exemplo, ser familiar com ISO Standard C++ e C++ STL, uma
vez que este curso utilizará a API em C++ nativa do OGRE, e todos os códigos e
exemplos estarão implementados em C++. Por exemplo, se você não entender o
código abaixo:
for (std::vector<int>::iterator it = m_myVec.begin();
it != m_MyVec.end(); it++) {
//Loop code here;
}
6
então você deve revisitar seus conceitos básicos de C++, pois iterar através de um
container STL é uma tarefa comum em programas C++, de modo que você terá uma
aprendizado mais confortável se entender o básico. Além disso, é necessário possuir
uma cópia e se sentir hábil para utilizar o Microsoft Visual C++ .Net 2008 SP1. É
necessário também que os drivers mais atuais da placa de vídeo do computador de
desenvolvimento estejam instalados e funcionando corretamente.
Plataformas
O desenvolvimento original do OGRE foi feito em Windows 32-bit. Esta ainda é
a principal plataforma de desenvolvimento para o OGRE, embora isso não signifique
que outras plataformas são desconsideradas. O time de desenvolvedores do OGRE tem
um responsável exclusivo para tratar da compatibilidade do OGRE com o Linux. Assim
como existe um encarregado exclusivo para Mac OS X, outro para iPhone/iPod etc.
Todas essas plataformas são igualmente suportadas a partir da mesma base de código.
Como OGRE tem suporte nativo ao OpenGL, é possível utilizar o OGRE em
qualquer plataforma na qual exista suporte aceleração por hardware em OpenGL,
como o Solaris da Sun. Entretanto, o núcleo de desenvolvedores do OGRE não suporta
diretamente plataforma não-Linux/UNIX, sendo qualquer “port” desta natureza apenas
esforço da comunidade.
7
Instalação do Ambiente de Desenvolvimento
Para ter um ambiente de desenvolvimento funcional, você precisa ter o OGRE
SDK e uma IDE (Integrated Development Environment). Neste curso usaremos o Visual
C++ .Net 2008 SP1. O método mais simples de obter esse ambiente é seguindo os
passos abaixo.
1. Fazer o download do OGRE SDK correto, de acordo com a IDE a ser utilizada;
2. Configurar sua IDE com os caminhos corretos para o OGRE SDK;
3. Compilar os exemplos do OGRE, garantindo que seu ambiente configurado.
Para efetuar o download do instalador do OGRE SDK, acesse a página de
downloads do OGRE: http://www.ogre3d.org/download/sdk. Escolha o OGRE 1.7.2
SDK for Visual C++ .Net 2008 (32-bit).
Figura 1 - Download do OGRE SDK
8
Ao executar o instalador, será necessário informar o caminho para onde o SDK
será extraído. Indique o caminho do diretório raiz do Windows, C:\.
Figura 2 - Diretório para onde será extraído o OGRE SDK
Acompanhe o andamento da extração e fique atento para quaisquer erros no
processo, que podem surgir por problemas de permissão de escrita no diretório, por
exemplo.
Figura 3 - Andamento da extração do OGRE SDK
Após o final da operação de extração, o seu diretório do OGRE SDK estará como
na Figura 4.
9
Figura 4 - Conteúdo do diretório de instalação do OGRE SDK
Agora é preciso criar uma variável de ambiente que faça referência ao diretório
do OGRE SDK. Vá ao Painel de Controle >>> Sistema >>> Configurações Avançadas do
Sistema >>> Propriedades do Sistema. Clique no botão “Variáveis de Ambiente...”. Na
janela que abrir, clique no botão “Novo”. Por fins de padronização, nomeie a variável
de ambiente como OGRE_HOME, indicando o diretório do OGRE SDK no campo Valor
da Variável. Clique em OK, e pronto. A nova variável irá aparecer na lista de variáveis.
Figura 5 - Criação da variável de ambiente do OGRE
10
Figura 6 - Lista de variáveis de ambiente, com a nova variável criada
Essa variável é extensivamente utilizada nos exemplos do OGRE. Ela será útil
para localizar a e para apropriadamente definir os diretórios de headers e de libraries
do OGRE, de modo a não haver preocupação relativa ao diretório onde o OGRE foi
instalado. Ela também será bastante utilizada nos exemplos deste curso.
Estrutura de Diretórios do OGRE SDK
Na Figura 4 podemos ver o conteúdo do diretório do OGRE SDK. Vamos analisar
os itens mais importantes para o prosseguimento deste curso.
bin
Esta pasta contém as DLLs padrão do OGRE SDK — OGRE e OIS (Object Oriented
Input System, biblioteca de input oficial do OGRE, embora seja um projeto separado).
11
As DLLs dessas bibliotecas existem tanto na pasta release quanto na pasta debug, e
cada uma contém seus respectivos tipos de DLL: a pasta debug contém DLLs não-
otimizadas que incorporam informações de debug, muito úteis ao fazer o debugging
de aplicações baseadas no OGRE. A pasta release contém DLLs otimizadas e enxutas
(no sentido de não possuírem qualquer informação para debugging), as quais são
utilizadas para distribuir o aplicativo baseado no OGRE.
Docs
Esta pasta contém as referências da API na forma CHM (Compiled Help), além
do Manual online do OGRE no formato HTML. A referência da API é gerada a partir do
código atual, utilizando uma ferramenta chamada doxygen, a qual realiza um parse nos
headers do OGRE e cria referências em hyperlinks a partir de seus conteúdos e
marcações especiais no código-fonte. É bastante útil para descobrir quais classes e
métodos estão disponíveis na API do OGRE, além de conter uma breve descrição de
uso de cada classe. É ainda mais útil se já houver familiaridade com a API e precisar
apenas de uma rápida referência. O Manual é um sumário condensado e conciso e
condensado das características e utilização de algum grande subsistema do OGRE, bem
como uma discussão a respeito do uso de algumas características avançadas do OGRE.
O Manual é escrito e mantido pela equipe de desenvolvimento do OGRE, e serve como
um bom complemento para as referências da API quando for necessária uma fonte
rápida fonte de informação sobre uma particular característica do OGRE.
include
Esta pasta contém os headers do OGRE, os quais serão referenciados no seu
código, bem como os headers da OIS. Esta pasta deve ser referenciada na configuração
de qualquer projeto que utilize o OGRE.
lib
Esta pasta contém as bibliotecas de importação do OGRE e da OIS, necessárias
para linkar as DLLs da pasta bin. Cada DLL tem uma correspondente .lib: *_d.lib para
*_d.dll e release *.lib para *.dll. Esta pasta deve ser referenciada na configuração de
qualquer projeto que utilize o OGRE.
12
Samples
Esta pasta contém os exemplos do OGRE, cada exemplo destacando uma
característica em particular do OGRE. Os exemplos são fornecidos com código-fonte e
podem ser facilmente compilados.
media
Esta pasta contém todos os materials, textures, meshes, etc., que os exemplos
do OGRE requerem para sua execução. Os subdiretórios desta pasta podem ser uma
ótima referência para aprender sobre a operação de vários sistemas do OGRE
(especialmente scripts de material e o sistema de efeitos de partícula).
Compilando os Exemplos do OGRE
Compilar os exemplos do OGRE é uma ótima maneira de validar o seu ambiente
de desenvolvimento. Além disso, os exemplos permitem analisar o uso e
implementação de diversos recursos do OGRE. Para compilá-los, vá ao diretório do
OGRE SDK, onde você encontrará o arquivo OGRE.sln. Ao abrir este arquivo, você verá
algo semelhante à Figura 7.
No Solution Explorer, você pode ver cada exemplo separadamente. Estes
exemplos foram implementados de forma que, ao serem compilados, será criada uma
DLL para cada exemplo (Sample_BezierPatch.dll, Sample_BSP.dll,.., Sample_Water.dll).
Ao final da lista de projetos no Solution Explorer, encontramos o SampleBrowser. Este
projeto será compilado na forma de um arquivo executável (SampleBrowser.exe), e
este será responsável por carregar as DLLs de cada exemplo do OGRE SDK.
Para compilar toda a “Solution”, no centro-superior da janela do VC++,
selecione o modo Release (o padrão ao abrir pela primeira vez é o modo Debug). Em
seguida, clique no menu Build >>> Build Solution (ou aperte F7).
13
Figura 7 - Exemplos do OGRE SDK
Caso o VC++ relate a ocorrência do erro mostrado na Figura 8, não se preocupe.
Esse erro é devido a ausência do programa CMake no seu computador. Sua instalação
não é necessária, no entanto, para remover o erro, no Solution Explorer, selecione o
projeto SampleBrowser e acesse o menu Project >>> Properties. Em Configuration,
selecione Release, na árvore lateral, selecione Build Events >>> Pre-Link Event,
conforme a Figura 9. Na direita, deixe o item Command Line em branco. Clique em
Aplicar e OK. Aperte F7 para compilar a Solution novamente.
14
Figura 8 - Erro ao compilar o SampleBrowser
Figura 9 - Solução do erro no Pre-Link Event
Se tudo correu normalmente, acesse o diretório do OGRE SDK, vá para a
subpasta bin\Release e execute o SampleBrowser.exe. Você irá ver a janela mostrada
na Figura 10.
15
Para o SampleBrowser, essa janela será exibida apenas na primeira vez em que
este for executado. Nela é possível escolher o subsistema de renderização (DirectX ou
OpenGL) e configurar opções como Full Screen, Video Mode etc.
A Figura 11 mostra a janela do SampleBrowser com as opções Video Mode (800
x 600) e Full Screen (No). As informações sobre a configuração escolhida serão
armazenadas no arquivo de texto ogre.cfg, a ser armazenado no Diretório de
Documentos do Usuário, na subpasta Ogre\Cthugha.
Figura 10 - Janela de configuração do Ogre3D
16
Figura 11 - Screenshot do SampleBrowser
Criando um Projeto no VC++
Este curso introdutório engloba a criação de um framework base para
rapidamente desenvolver aplicativos com o OGRE. Dessa forma, é necessário aprender
a criar e configurar corretamente um projeto que utilize o OGRE. Existem algumas
ferramentas, como o OgreAppWizard, que facilitam este processo, mas é sempre
importante conhecer os procedimentos.
Para criar um projeto novo no VC++, clique no menu File >>> New >>>
Project...; Em Project Types, selecione General. Em Templates, selecione Empty Project,
como mostrado na Figura 12.
Em Location, insira o diretório onde o projeto será armazenado, no exemplo, o
diretório é C:\MyProjects. Em Name, digite OgreFramework. O campo Solution Name
será automaticamente preenchido. Marque a opção Create directory for solution
(assim, será criada uma pasta dentro do diretório C:\MyProjects, com o nome do
projeto). Clique em OK.
17
Figura 12 - Criação de um novo projeto
Uma vez que o projeto foi criado, será necessário configurá-lo para fazer uso do
OGRE. Mas, antes, adicione um arquivo de extensão .cpp ao projeto (esse passo é
importante para habilitar algumas configurações do projeto).
Para criar o arquivo, no Solution Explorer, clique com o botão direito do mouse
no projeto OgreFramework (logo abaixo de Solution ‘OgreFramework’). Em seguida
clique em Add >>> New Item..., como mostrado na Figura 13. Na janela que aparecer
(Figura 14), em Categories selecione Code, em Templates selecione C++ file (.cpp). Em
Name digite Main.cpp. Atente para o fato de que o campo Location já aparece
preenchido no diretório do projeto, no entanto, por padronização deste curso, todos
os códigos-fontes (arquivos .h e .cpp) do projeto ficarão em uma subpasta chamada
Source. Crie a subpasta e referencie-a no campo Location, como mostrado na Figura 9.
Em seguida clique em OK.
O arquivo Main.cpp deverá aparecer no Solution Explorer, dentro do filtro
Source. Ainda não adicione qualquer código a este arquivo. Nós próximos capítulos
vamos fazer as implementações e a estrutura do framework base.
18
Figura 13 - Adicionando um arquivo ao projeto
Figura 14 - Criando o arquivo Main.cpp na subpasta Source
19
Agora podemos configurar o projeto apropriadamente. O termo “Configurar o
projeto” significa, em outras palavras, dizer ao VC++ onde ele deve procurar os
headers do OGRE, onde ele deve procurar as libs do OGRE, quais libs do OGRE ele deve
utilizar, onde ele deve gerar o executável, qual nome ele deve dar ao executável, onde
ele deve gerar os arquivos intermediários etc. Sem que você o ajude, o VC++ não pode
ajudar você. Lembrando que é necessário configurar o projeto duas vezes: uma para o
modo Release, outra para o modo Debug. Entender a diferença e o propósito dos
modos de compilação Release e Debug pode lhe poupar muitas dores de cabeça.
PASSO I: Clique no menu Project >>> Properties. Na janela que aparecer (Figura 15),
em Configuration selecione o item Release.
PASSO II: Na árvore lateral, no item Configuration Properties, selecione o item General.
Na direita, os itens Output Directory (diretório onde será gerado o executável) e
Intermediate Directory (diretório onde serão gerados os arquivos intermediários)
precisam ser preenchidos conforme abaixo:
Para o campo Output Directory: $(SolutionDir)\Bin\$(ConfigurationName)
Para o campo Intermediate Directory: $(SolutionDir)\Obj\$(ConfigurationName)
Figura 15 - Configuração da guia General em modo Release
20
PASSO III: Agora, na árvore lateral, selecione o item C/C++ >>> General (Figura 16). Na
direita, em Additional Include Directories, você precisar referenciar os diretórios onde
estão localizados os headers do OGRE e do BOOST (biblioteca utilizada pelo OGRE).
Clique no botão “...” para adicionar cada diretório separadamente. Os diretórios a
serem adicionados são:
$(OGRE_HOME)\include\OGRE
$(OGRE_HOME)\boost_1_44
Figura 16 - Configuração da guia C/C++ >>> General
PASSO IV: Na árvore lateral, selecione o item Linker >>> General (Figura 17). Na direita,
em Additional Library Directories, você precisar referenciar os diretórios onde estão
localizados os arquivos .lib do OGRE e do BOOST. Clique no botão “...” para adicionar
cada diretório separadamente. Os diretórios a serem adicionados são:
$(OGRE_HOME)\lib\release
$(OGRE_HOME)\lboost_1_44\lib
21
Figura 17 - Configuração da guia Linker >>> General
PASSO V: Na árvore lateral, selecione o item Linker >>> Input (Figura 18). Na direita,
em Additional Dependencies, você precisar referenciar os arquivos .lib do OGRE.
Apenas digite OgreMain.lib, pois é o único .lib necessário em nossos primeiros testes.
Figura 18 - Configuração da guia Linker >>> Input
22
Após isso, clique em Aplicar para finalizar a configuração do modo Release.
Agora é necessário configurar o modo Debug, que é muito semelhante ao modo
Release. Para fazer isso, é preciso repetir os 5 passos (um pouco modificados).
No PASSO I, ao invés de selecionar o item Release, selecione o item Debug. Em
seguida repita os PASSOS II e III. No PASSO IV, substitua $(OGRE_HOME)\lib\release
por $(OGRE_HOME)\lib\debug. No PASSO V, substitua OgreMain.lib por
OgreMain_d.lib. Após isso, clique em Aplicar, em seguida clique em OK. Pronto.
23
Inicialização do OGRE
Agora que temos o OGRE devidamente instalado e funcional, e já sabemos com
configurar um projeto corretamente para utilizar o OGRE, faremos um abatimento
geral sobre a inicialização do OGRE. A inicialização aqui mostrada segue apenas as
estruturas básicas de um programa OGRE, não se preocupando com outros detalhes
da implementação, de modo que vamos apenas utilizar enxertos de código a fim de
ilustrar as explicações. O corpo do código do framework base pode ser encontrado em
http://www.waveit.com.br/IntroOgre3D/aula01.rar. Faça o download do código e
adicione-o ao seu projeto. Se você criou o projeto corretamente, esse código deverá
compilar sem erros.
Vamos então à inicialização da engine!
Root
A primeira coisa a se fazer em qualquer aplicação OGRE é criar uma instancia do Root.
Você deve fazer isso antes de chamar qualquer outra operação do OGRE (exceto para
o LogManager, embora este não seja abortado neste curso introdutório). O construtor
do Root recebe algumas strings opcionais como parâmetro, todas são nomes de
arquivos.
Ogre::Root *mRoot =
new Ogre::Root(“plugins.cfg”,“ogre.cfg”,“ogre.log”);
plugins.cfg
Um plug-in do OGRE é qualquer código modular (.dll no Windows, .so no Linux)
que implementa uma das interfaces de plug-in, como SceneManager ou
RenderSystem. O arquivo plugins.cfg contém uma lista de plug-ins que o OGRE
carregará em sua inicialização, bem como a localização destes.
24
# Define plugin folder
PluginFolder=.
# Define plugins
Plugin=RenderSystem_Direct3D9
Plugin=RenderSystem_GL
# Plugin=RenderSystem_GLES
Plugin=Plugin_ParticleFX
A diretiva PluginFolder diz ao OGRE onde procurar pelos plug-ins listados
no arquivo. A forma como esse caminho é interpretado, fica a seu cargo: se você
utilizar um caminho absoluto, OGRE irá procurar apenas neste diretório. Se você
utilizar um caminho relativo (i.e., um caminho que não inicia com / ou \), então o
OGRE buscará no caminho relativo ao diretório atual do executável. A diretiva
PluginFolder especificada em nosso arquivo de exemplo diz ao OGRE para
procurar pelos plug-ins no diretório atual do executável (“.”). Perceba que linhas que
começam com # são tratadas como comentários em arquivos de configuração do
OGRE.
O restante do arquivo contém a lista de plug-ins que você deseja que o OGRE
carregue. Perceba que as extensões dos plug-ins não são inseridas; isto é proposital, e
lhe permite utilizar o mesmo arquivo de configuração em múltiplas plataformas, sem
ter que lidar com convenções de nomes de arquivos (embora o Linux seja bem flexível
nesse aspecto, não se importando com a extensão que você dá ao arquivo). Os
primeiros dois plug-ins listados anteriormente são implementações de render systems
(DirectX e OpenGL). Você não precisa incluir todos eles em seu programa; no fim, você
precisa de apenas um render system.
ogre.cfg
O OGRE fornece um meio simples de definir as opções básicas de renderização
através de uma janela com GUI (Graphical User Interface) nativa, como mostrado na
Figura 10. Essa janela de configuração é responsável por permitir ao usuário modificar
parâmetros da renderização, como por exemplo, Full Screen (Yes ou No), FSAA (Full
Screen Anti-Aliasing, i.e., nível de serrilhado das imagens), Video-Mode (resolução da
tela) etc. Para exibir essa janela de configuração:
bool resposta = mRoot->showConfigDialog();
25
O método showConfigDialog retorna true ou false dependendo se o
usuário clicou no botão OK ou no botão Cancelar. Você deve considerar terminar a
aplicação caso o usuário clique no botão Cancelar. Utilizar a janela de configuração do
OGRE significa tratar automaticamente das definições do render system escolhido,
podendo modificá-los na própria janela da configuração.
O que o tudo isso tem a ver com o arquivo ogre.cfg? É essa janela de
configuração que gera esse arquivo. Claro que você também pode criar esse arquivo
você mesmo abrindo o editor de textos, e se você estiver usando outros recursos mais
“manuais”, você sequer precisa ter esse arquivo de configuração, mas, por agora,
vamos apenas olhar o que esse arquivo contém.
Render System=Direct3D9 Rendering Subsystem
[Direct3D9 Rendering Subsystem]
Allow NVPerfHUD=No
FSAA=0
Floating-point mode=Fastest
Full Screen=No
Rendering Device=Monitor-1-NVIDIA GeForce GTS 250
Resource Creation Policy=Create on all devices
VSync=No
VSync Interval=1
Video Mode=800 x 600 @ 32-bit colour
sRGB Gamma Conversion=No
[OpenGL Rendering Subsystem]
Colour Depth=32
Display Frequency=100
FSAA=0
Full Screen=Yes
RTT Preferred Mode=FBO
VSync=No
VSync Interval=1
Video Mode=1024 x 768
sRGB Gamma Conversion=No
Perceba que estas opções acima correspondem às opções mostradas na janela
de configuração. Estes valores variam de computador para computador. Embora este
arquivo não seja perfeitamente compreensível e intuitivo para nós, humanos, ele foi
realmente planejado para ser lido pela máquina, e embora seja possível defini-los à
mão, provavelmente é melhor deixar a sua criação e edição a cargo da janela de
configuração do OGRE.
O OGRE também nos fornece um método para carregar o arquivo de
configuração existente (i.e., ogre.cfg).
26
if (!mRoot->restoreConfig())
mRoot->showConfigDialog();
Esta seqüência de operação é muito comum quando utilizamos o arquivo
ogre.cfg. Se o método restoreConfig() falhar, então não existe o arquivo
ogre.cfg, e a a janela de configuração é, então, exibida. Quando o usuário clicar em OK,
as definições serão salvas num recém-criado, de nome ogre.cfg.
Utilizando o método restoreConfig(), você evita ter de forçar os usuários
do aplicativo a verem a janela de configuração toda vez que executarem o programa.
Você também pode salvar as definições atuais do OGRE para o arquivo
ogre.cfg a qualquer momento, com o método saveConfig().
mRoot->saveConfig();
Ogre.log
O OGRE fornece ainda logs de diagnostico e exceções utilizando sua classe de
gerenciamento de logs. Registros de logs são úteis para obter detalhes a respeito de
uma falha ou erro na máquina do usuário, sem precisar perguntar a este por detalhes
sobre o seu ambiente de execução.
A saída de log gerada pelo OGRE contém todos os eventos, bem como dados
sobre a inicialização, estados e informações sobre a capacidade da máquina em
questão, sendo este arquivo gerado a partir de cada execução do programa. Essa saída
é enviada para um arquivo de texto simples; o ogre.log. O nome deste arquivo é
definido no momento da criação do Root.
Render Window
A qualquer ponto, após o render system ter sido selecionado (neste exemplo,
ocorre quando o usuário seleciona e configura o render system na janela de
configuração e clica em OK), você pode chamar o método initialise(), da classe
Root:
27
mRoot->initialise(true, "OgreFramework");
Ogre::RenderWindow *mRenderWindow =
mRoot->getAutoCreatedWindow();
Ou simplesmente:
Ogre::RenderWindow *mRenderWindow =
mRoot->initialise(true, "OgreFramework");
A primeira linha irá fazer com que o Root complete sua inicialização e crie uma
janela de renderização com as definições que o usuário selecionou na janela de
configuração. A string “OgreFramework” será o título desta janela. O segundo
parâmetro não é obrigatório e, caso você não informe título algum, o padrão “OGRE
Render Window” será utilizado. O primeiro parâmetro é obrigatório, ele diz ao OGRE
se ele deve criar automaticamente a janela de renderização; para facilitar a
compreensão nesta parte do curso, vamos apenas dizer ao OGRE para que crie nossa
janela de renderização. A segunda linha obtém o ponteiro para a instancia do
RenderWindow. O render window é somente uma parte da renderização da cena. Ele é
o canvas, a superfície na qual o OGRE renderiza seu conteúdo. O OGRE precisa de pelo
menos uma câmera para “capturar quadros” da sua cena 3D, e um ou mais viewports,
os quais são regiões sobre a superfície de renderização (como o render window) na
qual a câmera “revela” seu conteúdo.
Scene Manager
Não vamos nos aprofundar muito no Scene Manager por agora, uma vez que
vamos falar dele com mais detalhes adiante. Entretanto, com o propósito de manter
este capítulo coeso (já que mencionamos o Scene Manager tantas vezes), é necessário
que você saiba pelo menos o básico sobre a criação do Scene Manager para utilizá-lo
em seu código. Ok. Antes de utilizar a instancia de um Scene Manager, você deve criar
uma.
Ogre::SceneManager* mSceneMgr =
mRoot->createSceneManager(Ogre::ST_GENERIC, "MySceneManager");
28
Quando o OGRE carrega seus plug-ins, entre esses plug-ins pode haver várias
implementações de scene manager, como discutido anteriormente. Cada uma dessas
implementações irá se auto-registrar junto ao OGRE como um tipo particular de scene
manager:
ST_GENERIC: Implementação mínima de um scene manager, não otimizado
para qualquer tipo de cena ou estrutura. Muito útil para cenas minimamente
complexas (como as cenas onde existe apenas GUI).
ST_INTERIOR: Implementação otimizada para renderizar interiores e cenas
potencialmente densas, do tipo quarto fechado.
ST_EXTERIOR_CLOSE: Implementação otimizada para renderizar cenas
exteriores (outdoor scenes) com visibilidade até distancias próximas ou médias.
ST_EXTERIOR_FAR: Anacronismo para retro-compatibilidade entre versões do
OGRE, pouco ou não mais utilizado. Utilize ST_EXTERIOR_CLOSE ou
ST_EXTERIOR_REAL_FAR ao invés.
ST_EXTERIOR_REAL_FAR: Implementação típica para mundos do tipo “paged”.
Mundo “paged” geralmente são enormes, possivelmente planetas inteiros.
No exemplo dado, criamos um scene manager do tipo ST_GENERIC, uma vez
que não tínhamos nenhuma cena específica para renderizar.
Você aprenderá mais sobre as classes SceneManager do OGRE mais adiante;
por agora, é suficiente saber que elas funcionam como uma fábrica (pois implementam
o Design Pattern Factory) para os mais diversos tipos diferentes de objetos que
existem numa cena 3D, incluindo câmeras.
De modo a criar uma nova câmera para renderizar sua cena 3D, você deve
chamar o método createCamera() na interface SceneManager:
Ogre::Camera *mCamera = mSceneMgr->createCamera("MyCamera");
mCamera->setNearClipDistance(1);
mCamera->setFarClipDistance(1000);
mCamera ->setAspectRatio(Ogre::Real(1.333333));
Neste exemplo, mSceneMgr é um ponteiro para uma instância válida do um
SceneManager. A classe Camera tem muitas propriedades que podem ser ajustadas, e,
claro, métodos para ajustá-las.
29
O código anterior demonstra o básico que você irá precisar para uma aplicação
OGRE mínima. Ele define o aspect ratio equivalente a um display de 4:3 (como a
maioria dos monitores CRT e alguns LCDs non-widescreen). Esse valor pode ser
ajustado ou redefinido a qualque momento, e usualmente é definido como a razão
entre a altura e comprimento do viewport (tal como fizemos aqui, visto que 4/3 é
aproximadamente igual a 1.33333).
O código mostrado também define os valores das distancias do near clip plane
e do far clip plane. Aqui utilizamos adotamos nosso padrão de 1 e 1000, mas você
pode utilizar qualquer um que quiser, tão logo a razão entre far e near esteja próxima
de 1000, ou menos, para evitar problema de z-fighting.
Posteriormente, vamos aprender como manipular a câmera de modos mais
complexos, mas por agora, já é suficiente para o propósito de criar uma viewport em
nossa janela de renderização.
Ogre::Viewport *mViewport = mRenderWindow->addViewport(mCamera);
mViewport->setBackgroundColour(Ogre::ColourValue(0, 0, 0));
O código acima cria um novo viewport no render window que criamos quando
chamamos o método initialise() anteriormente no Root. Esse código também
define a cor do background do viewport para preto.
Render Loop
O modo mais simples de pedir ao OGRE a tarefa de renderizar sua cena é
invocando o método startRendering() no Root:
mRoot->startRendering();
Isso fará com que o OGRE renderize sua cena “eternamente” em loop, não
importando que conteúdo você tenha em sua cena. Esse loop continuará existindo
mesmo que você feche a janela de renderização criada utilizando (por exemplo,
clicando no botão x, no canto direito das janelas dos aplicativos Windows), ou quando
um frame listener devidamente registrado retorna false. Um método alternativo
para terminar o loop de renderização é chamando o método
30
queueEndRendering() do Root, em qualquer lugar no código, embora seja mais
comum simplesmente retornar false a partir de algum frame listener.
Frame Listener
Pra início de conversa, Frame listeners são o único meio pela qual você pode
invocar seu próprio código durante o Render Loop do OGRE quando estiver utilizando o
método startRendering(). Um frame listener é simplesmente uma classe que
implementa a interface FrameListener, atuando como um callback que permite ao
OGRE invocar o seu código no início, durante ou ao fim do processamento de cada
frame. O Exemplo abaixo mostra como criar um frame listener. No framework base, a
classe Application é um frame listener.
class myFrameListener : public Ogre::FrameListener
{
public:
bool frameStarted (const Ogre::FrameEvent &evt);
bool frameEnded (const Ogre::FrameEvent &evt);
};
bool myFrameListener::frameStarted(const Ogre::FrameEvent &evt)
{
// aqui você pode fazer algo antes do frame ser renderizado
return true;
}
bool myFrameListener::frameEnded(const Ogre::FrameEvent &evt)
{
// aqui você pode fazer algo após o frame ser renderizado
return true;
}
MyFrameListener myListener;
// Não esqueça que você precisa adicionar um frame listener
// ANTES de chamar o método startRendering()!!!
// Assumindo que você já criou o Ogre::Root
mRoot->addFrameListener(myListener);
mRoot->startRendering();
31
A implementação do método frameStarted() será chamada antes do
OGRE invocar o pipeline de renderização. Geralmente, o método frameEnded() é
menos utilizado, sendo útil quando você precisa destruir algum objeto a cada frame, e
é chamado após o OGRE completar a renderização do frame.
Geralmente, durante cada frame. Você deve processar eventos de entrada da
HID (Human Interface Device, como teclado, mouse, joystick, WiiMote, Kinect etc).
Dependendo do evento ocorrido, você pode programar um modelo 3D se mova e/ou
rotacione, pode fazer a câmera se mover ou girar, pode fazer um personagem andar
ou o que quiser. Não importando que evento seja, ele ocorre durante um ou ambos os
métodos de callback do FrameListener.
Main Rendering Loop
Uma típica aplicação OGRE irá renderizar os frames um após o outro, sem
cessar (a menos que você interrompa, é claro).
Vimos anteriormente o método para invocar o render loop do OGRE:
startRendering(). Entretanto, esse método apenas inicia um pequeno loop que
invoca outro método: renderOneFrame(). A existência deste último método é
importante por diversos motivos. Por exemplo, você pode querer incorporar o OGRE
em uma aplicação já existente ou em algum framework (o nosso caso, aliás), onde
seria complicado utilizar o método startRendering().
É importante resaltar que você ainda pode utilizar as classes FrameListener com
o método renderOneFrame(). O método renderOneFrame() é, na verdade,
o método que notifica qualquer frame listener que esteja registrado junto ao Root.
Em nosso framework base, utilizamos o método renderOneFrame()
juntamente com um frame listener, que é a classe Application, assim, sempre que o
método renderOneFrame() é chamado, ele notifica a classe Application que por
sua vez executa o método frameRenderingQueued(), o qual é, em palavras
simples, um intermediário entre os métodos frameStarted() e frameEnded()
discutidos anteriormente .
Abaixo temos um pequeno exemplo que objetiva lhe mostrar como você pode
implementar seu próprio render loop manual, e onde exatamente ele estaria situado
no fluxo do seu código.
32
// Faz tudo o que fizemos até agora a respeito da inicialização
// do OGRE: cria o Root, carrega plug-ins, cria o render window,
// scene manager, câmera e viewport, além de colocar alguma
// coisa na cena.
bool keepRendering = true;
while (keepRendering)
{
// processa eventos da rede em eventos do aplicativo
// processa eventos de input em eventos do aplicativo
// renderiza o próximo frame
mRoot->renderOneFrame();
// verifica se deve sair do loop
// Nota: NextMessageInQueue() é completamente fictício
// sendo utilizado aqui apenas com fins ilustrativos
// Isso não existe no OGRE
if (NextMessageInQueue() == QUIT)
keepRendering = false;
}
// Deleta objetos criados para liberar memória
// Então, finaliza o OGRE
delete mRoot;
33
Gerenciamento dos Recursos de Media
Temos razões muito boas para utilizar o sistema de gerenciamento de recursos
do OGRE ao invés de simplesmente carregar os recursos a partir de um arquivo no
disco rígido quando requisitado. O primeiro é velocidade: o acesso ao disco é muito
lento quando comparado ao acesso à memória, de modo que não queremos exacerbar
um já apertado tempo do frame carregando qualquer coisa do disco. Além disso, não
somente é mais rápido ter dados carregados (potencialmente comprimidos),
descompactados, e prontos para uso na memória, como também é mais eficiente
descarregá-los quando não forem mais necessários, e trazê-los de volte caso sejam
necessários novamente. Por fim, com o sistema de gerenciamento de recursos do
OGRE, não precisamos carregar na memória, um por um, cada recurso que a aplicação
possa precisar.
Gerenciamento de Recursos na Prática
Abaixo temos uma cópia do arquivo resources.cfg que acompanha o
OGRE SDK. Este arquivo é utilizado pelo SampleBrowser para indicar a localização dos
recursos.
# Resources required by the sample browser and most samples.
[Essential]
Zip=../../media/packs/SdkTrays.zip
FileSystem=../../media/thumbnails
# Common sample resources needed by many of the samples.
# Rarely used resources should be separately loaded by the
# samples which require them.
[Popular]
FileSystem=../../media/fonts
FileSystem=../../media/materials/programs
FileSystem=../../media/materials/scripts
FileSystem=../../media/materials/textures
FileSystem=../../media/materials/textures/nvidia
FileSystem=../../media/models
FileSystem=../../media/particle
FileSystem=../../media/DeferredShadingMedia
Zip=../../media/packs/cubemap.zip
Zip=../../media/packs/cubemapsJS.zip
Zip=../../media/packs/dragon.zip
Zip=../../media/packs/fresneldemo.zip
Zip=../../media/packs/ogretestmap.zip
Zip=../../media/packs/ogredance.zip
34
Zip=../../media/packs/Sinbad.zip
Zip=../../media/packs/skybox.zip
[General]
FileSystem=../../media
Este arquivo é praticamente auto-explicativo. Três grupos de recursos são
declarados e preenchidos: Essential, Popular e General. O grupo General sempre existe
independente de ter sido declarado ou não.
As definições de FileSystem e Zip descrevem o tipo de arquivo:
FileSystem indica um recurso do tipo que é baseado numa localização no sistema
de arquivos, enquanto que a definição Zip indica que o recurso é baseado num
arquivo compactado (do tipo .zip padrão).
Localização dos Recursos
Uma pergunta comum nos fóruns é “Como posso definir a localização de um
recurso sem utilizar o resources.cfg?”. Vejamos então a implementação do método
addResources() da classe Manager, que lê o arquivo resources.cfg
mostrado anteriormente.
Ogre::ConfigFile cf;
cf.load("resources.cfg");
Ogre::ConfigFile::SectionIterator seci =cf.getSectionIterator();
Ogre::String secName, typeName, archName;
Ogre::ResourceGroupManager *rgm =
Ogre::ResourceGroupManager::getSingletonPtr();
Ogre::ConfigFile::SettingsMultiMap *settings;
while (seci.hasMoreElements())
{
secName = seci.peekNextKey();
Settings = seci.getNext();
Ogre::ConfigFile::SettingsMultiMap::iterator i;
for (i = settings->begin(); i != settings->end(); ++i)
{
typeName = i->first;
archName = i->second;
rgm->addResourceLocation(archName, typeName, secName);
}
}
35
Este código simplesmente itera sobre cada seção no arquivo (neste caso, as
seções são também os nomes dos grupos: Essential, Popular e General), e para cada
seção, itera cada par de nome/valor. Para cada par de nome/valor, é chamado o
método addResourceLocation() do ResourceGroupManager.
O primeiro método a ser observado é o addResourceLocation(). Pode
ser mais fácil observar a analogia entre o código e o arquivo de configuração, no
exemplo hard-coded abaixo.
Ogre::ResourceGroupManager *rgm =
Ogre::ResourceGroupManager::getSingletonPtr();
rgm->addResourceLocation( "../../media/packs/SdkTrays.zip",
"Zip",
"Essential");
rgm->addResourceLocation( "../../media",
"FileSystem",
"General");
rgm->addResourceLocation( "../../media/fonts",
"FileSystem",
"General");
// e assim por diante, para o resto dos caminhos no arquivo
Perceba que todos os exemplos estão utilizando caminhos relativos. O OGRE
não tem qualquer problema com caminhos absolutos, porém, se você utilizá-los, seu
programa correrá o risco de não funcionar em outra máquina que não seja a sua, uma
vez que você não poderá garantir que todos os computadores estarão organizados da
mesma forma que o seu. Então, faça um favor a si mesmo e utilize caminhos relativos
para localizar seus recursos.
Inicialização dos Recursos
Uma vez que você tenha definido a localização dos seus recursos, você terá que
inicializa-los antes de utilizá-los na aplicação (é por isso que temos o método
loadResources() na classe Application do framework base). Você deve também
ter criado pelo menos um RenderWindow antes de tentar inicializar seus recursos, uma
vez que fazer o parser dos scripts, poderá criar recursos que utilizam a GPU, os quais
requerem um contexto de renderização para que venham a existir.
36
Ogre::ResourceGroupManager *rgm =
Ogre::ResourceGroupManager::getSingletonPtr();
// initialize all of the previously defined resource groups
rgm->initialiseAllResourceGroups();
// or, alternately, initialize the defined resource groups
// one at a time
rgm->initialiseResourceGroup("General");
rgm->initialiseResourceGroup("Essential");
rgm->initialiseResourceGroup("Popular");
No código acima, o primeiro exemplo inicializa todos os grupos que ainda não
foram inicializados. Já o segundo exemplo inicializa apenas os grupos especificados,
um de cada vez.
Descarregamento de Recursos
Você pode descarregar um recurso (individualmente ou por grupos) da
memória qualquer momento; se o recurso estiver referenciado em outro lugar no seu
código quando você descarregá-lo, ele será recarregado na próxima vez que for
utilizado. O OGRE, então, irá preveni-lo de desacrregar permanentemente um recurso
que ainda esteja em uso, de modo a salvá-lo de uma situação potencialmente ruim
(pelo menos em termos de recursos relacionados a aplicações 3D).
O código abaixo mostra como descarregar um grupo de recursos através da
interface ResourceGroupManager:
Ogre::ResourceGroupManager *rgm =
Ogre::ResourceGroupManager::getSingletonPtr();
rgm->unloadResourceGroup("Popular", true);
rgm->unloadUnreferencedResourcesInGroup("Popular", true);
Como já mencionado, a interface carrega e descarrega recursos de um único
grupo a cada vez. Este código apenas descarrega os recursos da memória; ele não
remove as instancias desses recursos.
O método unloadUnreferencedResourcesInGroup() irá descarregar
somente os recursos para os quais não existe qualquer referência.
37
Dispositivos de Entrada
Neste capítulo, iremos estudar como se dá a utilização da biblioteca OIS (Object
Oriented Input System) em conjunto com o Framework base. O Framework elaborado
neste curso tem uma arquitetura flexível, de modo a suportar futuras expansões ao
uso de dispositivos não-convencionais, como o Wiimote, Kinect, Dispositivos Hápticos,
Joysticks etc. Por agora, vamos nos limitar aos dois dispositivos mais comuns: Mouse e
Teclado.
Biblioteca de Input
A OIS é uma biblioteca open-source, multiplataforma, que suporta diversos
dispositivos de interface com o ser humano, como mouse e teclado (suporta outros
dispositivos também, não abordados neste curso).
Para integrar a OIS no Framework base, basta incluir no seu projeto (Additional
Include Directories, no VC++) o diretório $(OGRE_HOME)\include\. Nas bibliotecas a
serem linkadas (Additional Dependencies), inclua a lib OIS.lib. Adicione os arquivos
InputManager.cpp e InputManager.h ao seu projeto (arquivos enviados por e-
mail).
Como o propósito deste curso não é abordar a uma biblioteca de input, e sim
uma biblioteca de renderização, não entraremos nos detalhes da OIS. Por agora, basta
saber que o InputManager funcionará para o framework como uma caixa-preta, onde
iremos apenas utilizar seus métodos.
Input Manager e Input Listener
A OIS utiliza bastante o Design Pattern Observer (ou Listener) o qual permite
que uma classe seja notificada sempre que determinados eventos ocorrerem. No
nosso caso, desejamos que o Manager seja notificado pela OIS sempre que ocorrerem
os seguintes eventos:
Tecla pressionada;
Tecla liberada;
Mouse movido;
Botão do mouse pressionado;
Botão do mouse liberado.
38
Como o intuito do Framework é fazer com que o programa seja escrito na
camada Application, fizemos com que a tarefa de lidar diretamente com a OIS fique a
cargo do Manager, através de um subsistema chamado de Input Manager. Assim, a
classe Manager será o Listener de eventos gerados pelo mouse e teclado. O Manager
poderá, então, notificar a classe Application a respeito desses eventos.
Para isso devemos fazer com que o Manager herde as classes
OIS::MouseListener e OIS::KeyListener. Assim, no Manager.h, faça
#include “InputManager.h”
class Manager : public OIS::MouseListener,
public OIS::KeyListener
{
// código anterior do Manager;
};
Após fazer do Manager o nosso Input Listener, devemos herdar e implementar
alguns métodos pure virtuals das classes OIS::MouseListener e
OIS::KeyListener. A declaração da assinatura destes métodos deve ser feita na
Manager.h. Esses métodos serão chamados sempre que o evento correspondente
acontecer.
protected: // Private methods inherited from OIS.
virtual bool mouseMoved (const OIS::MouseEvent &arg);
virtual bool mousePressed (const OIS::MouseEvent &arg,
OIS::MouseButtonID id);
virtual bool mouseReleased (const OIS::MouseEvent &arg,
OIS::MouseButtonID id);
virtual bool keyPressed (const OIS::KeyEvent &arg);
virtual bool keyReleased (const OIS::KeyEvent &arg);
Adicionalmente, na classe Manager, você pode criar um atributo-ponteiro para
a classe Input Manager. Dessa forma fica mais fácil acessar sua instancia (quando
estiver declarada, obviamente). Ou, ao invés, você poderia acessar sua instancia
39
diretamente através de seu método Singleton (a classe Input Manager implementa o
Design Pattern Singleton). Para criar o atributo ponteiro, apenas faça:
InputManager *mInputMgr;
Agora precisamos criar obter uma instancia válida do Input Manager, registrar
o Manager como um Input Listener e por último, porém não menos importante,
escutar por eventos a cada frame. Para isso, no método setup(), em qualquer lugar
após a criação do Render Window, faça:
01 mInputMgr = new InputManager();
02 mInputMgr->initialise(mRenderWindow, true);
03
04 mInputMgr->setWindowExtents
05 (mRenderWindow->getHeight(),
06 mRenderWindow->getWidth());
07
08 mInputMgr->addKeyListener(this, "MyKeyListener");
09 mInputMgr->addMouseListener(this, "MyMouseListener");
Na linha 01, é criada a instância do Input Manager. A linha seguinte inicializa o
subsistema, passando como parâmetro o Render Window (pois este representa a
janela na qual os eventos serão recebidos); o segundo parâmetro é um valor boolean,
onde se for verdadeiro, o aplicativo mantém (ou seja, não oculta) o mouse nativo do
sistema operacional. Se for falso, o mouse nativo é ocultado, podendo ceder espaço a
um mouse com ícone personalizado, como veremos no capítulo GUI com SdkTrays. Na
linha 04 é definida a área útil na qual os eventos serão recebidos. As linhas 08 e 09
registram o Manager (ponteiro this) como um Key Listener e Mouse Listener,
respectivamente.
Agora é necessário implementar os métodos que foram herdados. Perceba que
o código abaixo mostra a implementação de cada método, e veja também que
automaticamente chamamos o evento correspondente na classe Application (embora
os métodos correspondentes na Application só serão implementados nos próximos
passos).
40
01 bool Manager::mouseMoved(const OIS::MouseEvent &arg)
02 {
03 return mApp->mouseMoved(arg);
04 }
05
06 bool Manager::mousePressed(const OIS::MouseEvent &arg,
07 OIS::MouseButtonID id)
08 {
09 return mApp->mousePressed(arg, id);
10 }
11
12 bool Manager::mouseReleased(const OIS::MouseEvent &arg,
13 OIS::MouseButtonID id)
14 {
15 return mApp->mouseReleased(arg, id);
16 }
17
18 bool Manager::keyPressed(const OIS::KeyEvent &arg)
19 {
20 return mApp->keyPressed(arg);
21 }
22
23 bool Manager::keyReleased(const OIS::KeyEvent &arg)
24 {
25 return mApp->keyReleased(arg);
26 }
Após implementar estes métodos, para finalizar a integração do Input Manager
com o Manager, precisamos:
Escutar os dispositivos a cada frame;
Redimensionar a área válida para o mouse, quando a janela for
redimensionada;
Deletar o Input Manager ao finalizar o Aplicativo.
É importante ressaltar que a OIS não utiliza threads ou qualquer outro tipo de
mágica para escutar os dispositivos. Sendo assim, é necessário verificar os estados do
mouse e do teclado a cada instante. O melhor modo de fazer isso é escutando-os a
cada frame (este é o modo de entrada buffered, caso você resolva fazer suas próprias
pesquisas no assunto). No método update(), coloque:
mInputMgr->capture();
41
Para redimensionar a área de atuação do mouse ao redimensionar a janela, no método
WindowResized(), adicione:
mInputMgr->setWindowExtents(rw->getWidth(), rw->getHeight());
No método shutdown(), após deletar o mApp, adicione:
if (mInputMgr)->capture();
delete mInputMgr;
Após isso, basta implementar o métodos correspondentes na Application. A
declaração da assinatura destes métodos deve ser feita na Application.h. Esses
métodos serão chamados através do Manager, sempre que o evento correspondente
acontecer.
public:
bool mouseMoved (const OIS::MouseEvent &arg);
bool mousePressed (const OIS::MouseEvent &arg,
OIS::MouseButtonID id);
bool mouseReleased (const OIS::MouseEvent &arg,
OIS::MouseButtonID id);
bool keyPressed (const OIS::KeyEvent &arg);
bool keyReleased (const OIS::KeyEvent &arg);
No Application.cpp, esses métodos serão utilizados para responder a ações
do mouse e do teclado. Abaixo temos um exemplo de implementação.
01 bool Application::mouseMoved(const OIS::MouseEvent &arg)
02 {
03 return true;
04 }
05
06 bool Application::mousePressed(const OIS::MouseEvent &arg,
07 OIS::MouseButtonID id)
08 {
09 return true;
10 }
42
11
12 bool Application::mouseReleased(const OIS::MouseEvent &arg,
13 OIS::MouseButtonID id)
14 {
15 return true;
16 }
17
18 bool Application::keyPressed(const OIS::KeyEvent &arg)
19 {
20 return true;
21 }
22
23 bool Application::keyReleased(const OIS::KeyEvent &arg)
24 {
25 return true;
26 }
43
Materials
TODO.
Scene Management
TODO.
Ferramentas de Produtividade
TODO.
Animação
TODO.
GUI com SdkTrays
TODO.
Estudo de Caso
TODO.
44
Hot tips
TODO.
Dúvidas comuns
TODO.
Exportação com o Blender
TODO.