terça-feira, 25 de outubro de 2011

Entities

Uma entidade (em inglês, Entity) é uma instância de um objeto móvel na cena - que pode ser um carro, uma pessoa, um cachorro, uma shuriken, etc. A única assertiva sobre ela é que não possui uma posição fixa no mundo.

Entidades se baseiam em malhas discretas (Mesh) , isto é, coleções de geometria que são independentes, normalmente muito pequenas em relação à escala do mundo virtual em que estão inseridas e representadas por objetos Mesh. Várias entidades podem ser criadas a partir de um mesmo mesh, desde que se deseje realmente criar cópias de um mesmo objeto na cena. As entidades exibidas na figura abaixo, por exemplo, foram criadas a partir do mesmo mesh:


O Objeto Mesh

Um objeto Mesh representa um modelo discreto: um conjunto de geometria que é independente e normalmente bastante pequeno em relação ao mundo virtual em que se insere. Objetos Mesh têm o intuito de representar objetos móveis e não são utilizados para representação da geometria plana extensa, geralmente usada para criar backgrounds.

Objetos Mesh são um tipo de recurso gerenciado pelo MeshManager. São normalmente carregados a partir do formato de objetos OGRE, .mesh. Arquivos .mesh são geralmente criados pela exportação de alguma ferramenta de modelagem 3D.

É possível criar meshes manualmente através da chamada ao método MeshManager::createManual. Assim, o programador pode ele mesmo definir a geometria do objeto mas isso está fora do escopo desta postagem.

Objetos Mesh são a base para os objetos móveis individuais no mundo, que são chamados Entities (assunto da próxima postagem).

Objetos Mesh também podem ser animados através do uso de Skeletal Animation (que, provavelmente, também será um assunto abordado em postagens futuras).

O Objeto ResourceGroupManager

O objeto ResourceGroupManager é, na realidade, uma espécie de hub para o carregamento de recursos reutilizáveis como texturas e meshes. Através dele o programador pode definir grupos de recursos que podem ser descarregados ou recarregados em conjunto sempre que se precisar. Ao seu favor, estão vários ResourceManagers, que gerenciam os tipos de recursos individualmente - a exemplo dos TextureManager e MeshManager. Nesse contexto, recursos são conjuntos de dados que devem ser carregados para fornecer ao OGRE os dados que ele precisa.

ResourceManagers asseguram que recursos sejam carregados uma única vez e compartilhados através da engine OGRE. Eles também são responsáveis pelos requisitos de memória dos recursos que gerenciam e podem procurar em vários lugares pelos recursos que precisam - inclusive caminhos de busca múltiplos e arquivos compactados (ZIP).

A maior parte do tempo, o programador não lida com ResourceManagers diretamente. Eles são chamados, quando necessário, por outras partes do sistema OGRE. Por exemplo, quando se solicita que uma textura seja aplicada a um material, o TextureManager é chamado automaticamente.

Se preferir, o programador pode manipular diretamente o gerente de recurso apropriado para pré-carregamento de recursos (se, por exemplo, ele quiser evitar o acesso a disco mais tarde) mas não há problema algum em deixar que OGRE decida quando fazer essa manipulação.

Uma coisa que se deve fazer é informar aos gerentes de recursos onde procurar pelos recursos. Isso é feito através da instrução Root::getSingleton().addResourceLocation - que, na verdade, passa a informação para o ResourceGroupManager.

Como só existe sempre uma única instância para cada ResourceManager da engine, se você quiser obter referência a um gerente de recursos, pode fazer como no exemplo a seguir:

TextureManager::getSingleton().algumMetodo() MeshManager::getSingleton().algumMetodo()

O Objeto SceneManager

Sem contar com o objeto Root, o SceneManager é, provavelmente, o objeto mais importante de todos com que você vai lidar quando estiver desenvolvendo sua aplicação OGRE. Certamente, será o objeto mais utilizado também.

O SceneManager é responsável pelo conteúdo da cena que está sendo renderizada pela engine. Ele é responsável por organizar o conteúdo usando a técnica que achar mais adequada para realizar as tarefas de criação e gerenciamento de câmeras, objetos móveis (entidades), luzes e materiais (propriedades superficiais dos objetos), bem como por gerenciar a "geometria global" - que é a geometria estática mais ampla, geralmente utilizada para representar partes da cena que não se movem.

É ao SceneManager que você recorre quando quer criar uma câmera para a cena! Também é através dele que se pode adicionar ou remover uma fonte de luz. Ou seja, sua aplicação não precisa manter listas dos objetos que estão sendo dispostos: o SceneManager mantém um conjunto de todos os objetos na cena para que o programador possa referenciá-los quando precisar. Consulte na API os métodos getLight(), getCamera(), getEntity() e outros.

O SceneManager também envia a cena para RenderSystem quando é hora de renderizar a cena. No entanto, o programador nunca precisa chamar o método _renderScene diretamente. Ele é chamado automaticamente sempre que um objeto que está sendo renderizado é atualizado.

Portanto, a maior parte da interação do programador com o objeto SceneManager é durante a configuração da cena em que, possivelmente, é invocada uma grande quantidade de métodos (o que às vezes é guiado por algum arquivo de entrada que contém os dados da cena). Também é possível modificar o conteúdo da cena dinamicamente durante o ciclo de renderização, caso se crie um objeto FrameListener.

Diferentes tipos de cena exigem abordagens algorítmicas muito diferentes para decidir quais objetos são mandados pro RenderSystem da maneira mais eficiente possível. Por conta disso, a classe SceneManager foi projetada para ser estendida para diferentes tipos de cena.

O objeto SceneManager padrão irá renderizar uma cena mas ele faz muito pouca ou quase nenhuma organização de cena e não se pode esperar que trabalhe de maneira ótima (o mais eficientemente possível) para cenas muito amplas.

O intuito de criar especializações para a classe SceneManager é justamente que cada uma delas irá otimizar a organização da cena para ganhar desempenho, visto que assumem o que pode ser feito para cada tipo de cena. Um exemplo de especialização é a BspSceneManager, que otimiza a renderização para cenas grandes in-door com base em uma árvore BSP.

A aplicação que usa OGRE não precisa saber quais são as especializações disponíveis. Ela deve simplesmente chamar Root::createSceneManager(..) passando como parâmetro um dos vários tipos de cena (ST_GENERIC, ST_INTERIOR, etc.). A engine irá automaticamente usar a melhor especialização de SceneManager para o tipo de cena escolhido ou o padrão caso uma especialização não esteja disponível. Isso permite que os desenvolvedores de OGRE possam criar novas especializações para tipos de cena para os quais ainda não havia especialização alguma e as aplicações usufruam das novas especializações sem mudar nada do seu código.

segunda-feira, 24 de outubro de 2011

O Objeto RenderSystem

O objeto RenderSystem é, na realidade, uma classe abstrata que serve de interface para a API 3D subjacente. Ele é responsável pela chamada a operações de renderização da API e pela configuração das várias opções de renderização. A classe é abstrata por que toda a implementação é específica à renderização implementada por uma API: existem subclasses específicas para cada API de renderização (D3DRenderSystem para a Direct3D, por exemplo). Depois que o sistema é inicializado através da chamada a Root::initialise(), o objeto RenderSystem da API de renderização selecionada pode ser obtido pela chamada ao método Root::getRenderSystem().

Apesar disso, uma aplicação normalmente não precisa manipular o objeto RenderSystem diretamente - tudo que o programador precisa para renderizar objetos e customizar configurações está disponível em classes orientadas a cena como SceneManager, Material, etc. O objeto deve ser manipulado diretamente apenas quando se desejar criar múltiplas janelas de renderização (neste caso, janelas completamente separadas, isto é, não apenas diferentes janelas de exibição de uma cena - como num efeito split screen -, o que pode ser feito via funcionalidades da classe RenderWindow) ou acessar propriedades avançadas do objeto RenderSystem.

Pelas razões explicitadas no parágrafo anterior, o manual oficial do OGRE não aborda mais profundamente este objeto. Durante o estudo do manual, pode-se assumir que o SceneManager lida com todas as chamadas às funcionalidades de RenderSystem nos momentos apropriados.