SmallVR - Virtual Reality Toolkit
Prof. Márcio Sarroglia Pinho
Uma Ferramenta Orientada a Objetos para o
Desenvolvimento de Aplicações de Realidade Virtual


1.Introdução

Este projeto iniciou-se da necessidade de se ter uma ferramenta de desenvolvimento para aplicações de realidade virtual que pudesse ser usada nas disciplinas de realidade virtual ministradas na PUCRS. Em face do curto espaço de tempo representado por uma disciplina, era necessário que se tivesse uma ferramenta que permitisse, entre outras coisas, um rápido aprendizado, o aproveitamento de conhecimentos prévios em OpenGL e a concentração do tempo de programação e projeto na solução do problema proposto e não em questões acessórias como controle de dispositivos gráficos e rotinas de leitura de objetos.
O desenvolvimento de aplicações de realidade virtual requer um grande esforço de programação. Por experiências em projetos de pesquisa, laboratórios e em disciplinas de realidade virtual e pela observação de vários grupos de pesquisa em realidade virtual, nota-se que boa parte deste esforço é devido à falta de ferramentas de desenvolvimento adequadas a aplicações deste tipo. Com isto, boa parte do tempo de trabalho que poderia ser dedicado ao processo de modelagem da aplicação, à melhoria de seus aspectos interativos e ao estudo e avaliação de sua efetividade com respeito à solução do problema ao qual se propõe, acaba sendo despendido em aspectos de implementação e solução de problemas alheios à aplicação, como controle de dispositivos, leitura de objetos gráficos, entre outros.

No mercado de realidade virtual existem algumas ferramentas comercias de desenvolvimento. O uso destas ferramentas, entretanto, em face de seu custo elevado, ainda não é uma realidade no meio acadêmico brasileiro. Na maioria dos grupos de pesquisa em realidade virtual do Brasil, a falta de ferramentas de desenvolvimento tem limitado os trabalhos principalmente pelos seguintes aspectos:

·Falta de leitores de modelos tridimensionais de objetos;

·Falta de drivers de leitura de dispositivos de realidade virtual;

·Dificuldade de modificação de uma aplicação para a troca de um dispositivo de realidade virtual por outro diferente;

·Dificuldade de gerenciamento de ambientes gráficos tridimensionais com elevado número de faces;

·Dificuldade no desenvolvimento de técnicas de interação em ambientes de realidade virtual;

·Pouca portabilidade do código gerado para aplicações de realidade virtual;

·Dificuldade em adequar aplicações pré-existentes de computação gráfica para ambientes com dispositivos de realidade virtual;

·Dificuldade na exibição de imagens em múltiplas telas.

Em face deste cenário foi desenvolvida uma arquitetura de suporte à criação de aplicações de realidade virtual, a SmallVR. Este desenvolvimento baseia-se em experiências prévias de desenvolvimento de bibliotecas de suporte a dispositivos de realidade virtual, no desenvolvimento de bibliotecas gráficas tridimensionais e no desenvolvimento de aplicações de realidade virtual com outras bibliotecas gráficas existentes.

Além do desenvolvimento de projetos em disciplinas, esta ferramenta tem sido utilizada no desenvolvimento projetos de pesquisa, bem como em escolas técnicas do SENAI-RS, sem custo e sem a necessidade de um longo tempo de aprendizagem.

Este artigo está organizado da seguinte forma. Primeiramente, faz-se um resumo das características de algumas ferramentas de desenvolvimento para aplicações de realidade virtual, apresentando os pontos em que se julga, estas poderiam ser melhoradas a fim de torná-las adequadas ao ambiente acadêmico brasileiro. A seguir inicia-se a apresentação da arquitetura da SmallVR, propriamente dita. Em primeiro lugar apresenta-se a modelagem do grafo de cenas que permite montar estruturas hierárquicas que descrevem objetos geométricos. Na seção 5 apresentam-se as formas de representar objetos geométricos. Na seção 6 são apresentados os controladores de dispositivo. A seguir são descritas as formas de exibição de cenas em múltiplas telas e alguns comentários à cerca de funções utilitárias disponíveis na biblioteca. Por fim, são apresentadas algumas considerações finais.

2. Ferramentas existentes

Antes de iniciar este projeto foram testadas algumas ferramentas existentes para o desenvolvimento de aplicações de realidade virtual a fim de avaliar se estas supriam as necessidades de desenvolvimento apresentadas acima. Nesta análise buscou-se ferramentas que atendessem às seguintes demandas:
·Ser gratuita e de código aberto e assim poder ser distribuída e usada livremente por alunos e pesquisadores;

·Manter a estrutura de programação usada com as bibliotecas OpenGL e GLUT e com isto aproveitar os conhecimentos já adquiridos em projetos de pesquisa e disciplinas anteriores;

·Permitir a utilização de diferentes dispositivos de realidade virtual com poucas (ou sem) modificações no código e permitir a inclusão de novos dispositivos de forma simples;

·Manter o controle do processo de rendering dos objetos gráficos com o programador;

·Não possuir um número muito grande de funções e ser de fácil assimilação;

·Ser de rápido aprendizado, possibilitando sua utilização em um curto espaço de tempo, em especial em disciplinas de graduação e pós-graduação;

·Ser portável e poder ser compilada e executada em ambiente Windows e Ser simples a ponto de permitir um rápido aprendizado do uso da ferramenta.

Ferramentas como WorldToolKit, Vega, dVise, Multigen e Performer foram descartadas pois são comerciais por isto não podem ser livremente utilizadas em nossos ambientes acadêmicos. A ferramenta Performer possui uma versão gratuita, entretanto esta só roda em ambiente Linux. As ferramentas MRObjects e MrToolkitnão tem seus fontes disponíveis e não possuem mais suporte de seus autores.Além disto, estas bibliotecas tiram o “controle” da aplicação das mãos dos usuários, impedindo-o de ter um controle mais detalhado da mesma.

A biblioteca VRJuggler[2] mostrou-se bastante interessante, suprindo a maioria das necessidades apresentadas acima. Porém, em face de seu tamanho, tempo necessário à sua aprendizagem, falta de uma documentação mais simples e também pelo fato de que o usuário fica sem o controle do processo de rendering dos objetos, esta biblioteca não foi utilizada. Neste aspecto específico, esta ferramenta usa uma filosofia que, em sua documentação, está descrita como “No main() - Don't call me, I'll call you” ou “você não me chama, eu chamarei você”.

A biblioteca Simple Virtual Enviroment Toolkit [6] testada em projetos de interação em ambientes virtuais, supre praticamente todas as nossas necessidades de programação. Porém o fato de não ser livre para distribuição, inviabilizou seu uso em nossos ambientes acadêmicos.

Foi avaliada também a biblioteca DIVERSE[5]. Esta biblioteca, entretanto, por não possuir ainda suporte à plataforma Windows e OpenGL, esta biblioteca não atendia um dos importantes requisitos previamente definidos.

As ferramentas VRUT[10] e ALICE[1]são bastante simples de ser usadas, e permitem a criação rápida de ambientes virtuais simples. Entretanto, em face de sua simplicidade e por usarem uma linguagem interpretada como Python, dificultam o desenvolvimento de aplicações mais complexas, que demandem velocidade de execução e que precisem usar a biblioteca gráfica OpenGL.

De todas as ferramentas utilizadas, a que mais se aproximou dos requisitos necessários foi a MAVERIK [4]. Usada durante todo um semestre letivo por um grupo de mais de vinte alunos, demonstrou, entretanto, que o tempo de aprendizagem necessário à sua utilização, a falta de suporte a um formato de objetos mais largamente utilizado em modeladores gráficos e a dificuldade no uso de dispositivos de realidade virtual em ambientes que não o UNIX, acabaram dificultando seu uso em nosso ambiente.

3. Visão Geral da Arquitetura

A ferramenta SmallVR é baseada nas bibliotecas OpenGL e GLUT. Uma das idéias centrais do projeto foi permitir que o usuário continuasse usando a estrutura básica de um programa com a GLUT e apenas adicionasse os objetos e comandos necessários à aplicação sem perder o controle da execução da aplicação. Este problema é muito comum em bibliotecas de desenvolvimento para realidade virtual que se valem com freqüência demasiada de funções de callback, tirando do usuário o controle do fluxo de execução. 
Para a inicialização da biblioteca, utiliza-se a funçãoSmVR_InitA função SmVR_Init devolve um apontador para um objeto que representa toda a cena tridimensional (chamado aqui de RootObject). Para garantir a exibição da cena, o programador deve colocar dentro da função informada na glutDisplayFuncuma chamada do método Render do objeto referido RootObject.

SmVR_GeometricObject *RootObject;

void display( void )

{

glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

RootObject->Render()

glutSwapBuffers();

}

void InitGLUTCallbacks(void)

{

// definição das funções de callback da GLUT

glutDisplayFunc ( display );

glutReshapeFunc ( reshape );

glutKeyboardFunc ( keyboard );

glutSpecialFunc ( arrow_keys );

}

void main()

{

// inicialização da GLUT

glutInit( &argc, argv ); 

glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );

glutInitWindowPosition (0,0);

glutInitWindowSize( 700, 500 ); 

glutCreateWindow( "SmallVR Test" ); 

RootObject = SmVR_Init();

InitGLUTCallbacks ();

glutMainLoop ( );

}

Figura 1 - Rotina de Inicialização da Biblioteca

4. Grafo de Cena

Um grafo de cena (GS) em uma aplicação gráfica tridimensional é a estrutura de dados que permite montar relações de hierarquia entre objetos e aplicar transformações geométricas a estas hierarquias.
As relações de hierarquia em um GS definem, resumidamente, quais as partes formadoras de um objeto tridimensional composto de outros objetos. Na modelagem de um carro, por exemplo, pode-se especificar o carro inteiro com sendo um único objeto “monolítico”, sem partes, sem hierarquia. Esta opção, entretanto, irá criar dificuldades caso seja necessário fazer, por exemplo, as rodas girarem independentes do carro e independentes umas das outras. Por outro lado, se for adotada uma estratégia diferenciada, em que cada parte do carro seja um objeto isolado, a aplicação de transformações geométricas globais (que afetem todas as partes do carro) acarretará um trabalho adicional ao programador. 

Com o uso de hierarquia, por sua vez, pode-se estabelecer quais objetos fazem parte (são filhos) de quais objetos. Com isto, as transformações geométricas aplicadas a um nível mais alto de uma hierarquia, afetam a todos os objetos existentes em níveis inferiores da hierarquia. 

Na arquitetura da SmallVR os nodos do GS são objetos geométricos representados por objetos da classe SmVR_CGeometricObject. Cada um destes objetos tem um (e somente um) pai e uma lista de zero ou mais filhos.A descrição de alguns dos métodos e atributos desta classe é apresentada a seguir. 

Para a montagem de um grafo de cenas são necessários basicamente dois métodos. Um que insira um objeto como filho de outro e um que o retire desta condição. Na Figura 2 pode-se observar a descrição de uma parte da classe SmVR_CGeometricObjectonde aparece a definição dos métodos AddChildRemoveChild.

Em adição a estes dois métodos há outros que servem para fornecer informações sobre um dado objeto dentro do grafo de cena. A Tabela 1 apresenta estes métodos e sua função.

class SmVR_CGeometricObject 
{

public:

// Métodos

int AddChild(SmVR_CGeometricObject*o);

int RemoveChild(SmVR_CGeometricObject*o);

};


Figura 2 – Classe SmVR_SmVR_CGeometricObjecte os Métodos de Gerência dos Objetos no Grafo

Tabela 1 - Métodos de consulta ao Grafo de Cena

Método

Descrição

SmVR_CGeometricObject *GetParent();

Informa o pai de um objeto

SmVR_CGeometricObject *GetFirstChild()

Informa o primeiro filho de um objeto

SmVR_CGeometricObject *GetBrother();

Informa o irmão objeto

SmVR_CGeometricObject *FindChildObject(char *name);

Busca um filho de um objeto

5. Objetos gráficos

O detalhamento dos modelos geométricos utilizados em uma aplicação de realidade virtual é um fator determinante da qualidade visual das imagens que podem ser geradas no ambiente virtual. Por este motivo, torna-se relevante permitir a carga e a exibição de objetos gráficos criados em modeladores externos à aplicação. 
No que tange à descrição geométrica dos objetos, a SmallVR é capaz de suportar dois tipos de objetos. Um deles, comentado acima, é representado pelos objetos lidos de arquivos. O outro é definido por uma rotina do próprio programa. 

Para permitir esta dualidade a classe SmVR_CGeometricObject mantém duas referências à descrição da geometria dos objetos: uma é um apontador para um objeto da classe SmVR_CobjFromFile, e outra é um apontador para uma função (a ser fornecida pela aplicação) que exibe um objeto. A especificação de qual das duas formas de representação de objetos será usada é feita através dos métodos construtores da classe SmVR_CGeometricObject (Tabela 2). 

Tabela 2 – Construtores da Classe CGeometryObject
 
Método
Descrição
SmVR_CGeometricObject (char *name, FunctionPointer *f)
Construtor com função de exibição
SmVR_CGeometricObject (char *name, SmVR_CobjFromFile *obj)
Construtor com nome de arquivo

5.1 Objetos pré-modelados

A classe SmVR_CobjFromFile permite que se carreguem objetos armazenados em qualquer formato do qual o programador possua uma rotina de leitura. Esta classe é defina como uma classe de dois de métodos virtuais (load,render) cujas implementações não sãofornecidas na SmallVR. A partir desta classe o programador deve criar uma classe derivada que implemente estes métodos que devem, respectivamente, armazenar o objeto em memória e exibi-lo usando comandos OpenGL.
Para permitir de imediato o aproveitamento de objetos criados em modeladores tridimensionais, a SmallVR fornece em sua distibuição padrão, duas classes derivadas da SmVR_CobjFromFile com as quais é possível carregar e exibir objetos no formato Wavefront OBJ.

Ferramentas de desenvolvimento como SVE, MRObjects, ALICE, MAVERIK e VRUT também permitem que se carreguem objetos em vários formatos. Entretanto, estas ferramentas tiram do usuário o acesso às faces do objeto e reduzem o controle que o programador pode exercer sobre a geometria do objeto. Em geral, o programador informa o nome de um arquivo onde está o objeto e este é armazenado e um formato interno da ferramenta. A partir disto, as faces não podem mais ser facilmente acessadas. Do ponto de vista da técnica de programação este “encapsulamento” é de fato interessante. Entretanto, esta filosofia causa dificuldades quando a tarefa a ser realizada necessita acessar os vértices ou as faces que compõem o objeto. No caso da SmallVR, como a classe que trata dos objetos é fornecida pelo próprio usuário, o acesso à sua estrutura de dados do objeto também fica à seu alcance. 

Para a carga de objetos no formato 3DS, pode-se usar um exemplo como o da Figura 3.

SmVR_COBJLoader *obj1 = new SmVR_COBJLoader();


obj1->Load("objetos3d/bola.obj");
RootObject->AddChild(new SmVR_CGeometricObject("bola1", obj1));


Figura 3 – Exemplo de objeto OBJ

5.2 Objetos descritos no código

A maioria das ferramentas de desenvolvimento de aplicações de realidade virtual não possibilita que o programador crie sua própria rotina de exibição de objetos. Nas poucas ocasiões em que isto ocorre este objeto fica totalmente desvinculado do grafo de cena, não sendo possível usá-lo em operações do grafo de cena, como na montagem de um objeto hierárquico.
A SmallVR, através do método construtor SmVR_CGeometricObject (FunctionPointer *f) permite informar o nome de uma rotina que possua comandos OpenGL que exibam o objeto. A fim de impedir que esta rotina modifique as matrizes de transformação de OpenGL e com isto altere a estrutura do grafo de cena, estas matrizes são salvas antes da chamada da função do usuário e recuperadas ao seu final.

Dentro desta função devem ser inseridos somente funções de desenho de primitivas OpenGL, ficando vetado o uso de funções de transformações geométricas. Estas transformações geométricas devem ser definidas fora desta rotina através de funções específicas da biblioteca. Esta restrição deve-se ao fato de que é necessário manter consistentes as matrizes de transformações de todos os objetos, o que não é possível caso a matriz seja alterada diretamente por comandos OpenGL.

No exemplo da Figura 4 observa-se a criação de um objeto geométrico a partir de uma rotian criada pelo programador.

int DesenhaTeste(void *p) {


glBegin(GL_TRIANGLES);
     glVertex3f(0,0,0);
     glVertex3f(10,0,0);
     glVertex3f(5,10,0);
glEnd();
}
int main(int argc, char **argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  glutInitWindowSize(800, 600);
  glutCreateWindow("Teste");
  RootObject = SmVR_Init(NULL); // Initialize the Small VR library
  SmVR_CGeometricObject *obj1 = new SmVR_CGeometricObject("Teste", DesenhaTeste);
  obj1->TranslateBy(-600, 0, 0);
  obj1->RotateBy(90, 0, 1, 0);
  obj1->ScaleBy(100, 1, 5000);
  RootObject->AddChild(obj1);
  glutDisplayFunc(RenderScene); // Especifica a funcao de desenho
  glutMainLoop();
  return 0;

Figura 4 – Exemplo de objeto criado no código

5.3 Transformações Geométricas

As transformações geométricas a serem aplicadas aos objetos são definidas através de métodos da classe SmVR_CGeometricObject. Na Tabela 3 pode-se observar estes métodos.
Internamente, cada objeto possui uma matriz 4x4 capaz de armazenar a seqüência de transformações geométricas aplicada ao objeto até um dado momento. Estas transformações são sempre acumulativas e, portanto aplicadas ao estado corrente da matriz. 

Tabela 3 - Métodos de Transformações geométricas
 
Método
Descrição
void SetTranslation(tx, ty, tz)
Define um deslocamento para o objeto a partir de sua posição atual
void SetRotation(ang, x,y,z)
Define uma rotação sobre o objeto a partir de um ângulo e do eixo ao redor de rotação
void SetScale(ex, ey, ez)
Define um fator de escala a ser aplicado ao objeto

Existem ainda métodos capazes de acessar diretamente a matriz de transformações lendo-a ou modificando-a de maneira absoluta. A Tabela 4 mostra estes métodos.

Tabela 4 - Métodos de acesso absoluto à matriz de transformações
 
Método
Descrição
void SetTransformationMatrix (M)
Define uma nova matriz de transformações para o objeto
void GetTransformationMatrix (M) 
Lê matriz de transformações atual do objeto

5.4 Propagação das transformações geométricas

O controle da propagação (dos pais para os filhos) das transformações geométricas dentro do grafo de cena é feito através da matriz de transformação geométrica existente em cada objeto. 
Ao adicionar um objeto como filho de outro é obtida a nova matriz de transformação do filho de forma que este permaneça na posição onde está, mas possa sofrer todas as transformações geométricas que forem aplicadas ao objeto-pai. Em outras palavras, obtém-se a matriz de transformação do objeto-filho, relativa ao sistema de coordenadas do objeto-pai. Esta nova matriz é obtida conforme é descrito a seguir. 

SejamMPaiMFilho as matrizes de transformação dos objeto pai e do objeto filho, respectivamente. Assim a equação,

NovaMFilho = MFilho * MPai-1

obtém NovaMFilho que representa a nova matriz do filho em relação ao pai. 

Ao remover um objeto da lista de filhos de um outro objeto, a nova matriz do objeto-filho é obtida por:

NovaMFilho = MFilho * MPai

6. Controladores de Dispositivos

A utilização de dispositivos de realidade virtual na SmallVR é feita a partir da premissa de que é possível, na maioria deles, obter-se a matriz de transformação geométrica que define sua posição e/ou orientação no espaço. Esta matriz é então, usada como matriz de transformação de um objeto que irá representar o sensor do dispositivo no programa. Nos casos em que o dispositivo tem mais de um sensor, para cada um destes é criado um objeto diferente.
A fim de tornar a aplicação independente do tipo do dispositivo que está sendo usado, adotou-se a estratégia de que o programador implementa uma classe derivada da classe SmVR_CDevice. Esta classe deve possuitmétodos para inicialização, leitura e finalização do dispositivo, que estão declarados como virtuais na classe SmVR_CDevice.

Após a criação do objeto controlador (da classe derivada de SmVR_CDevice), é necessário informar um objeto-sensor que será afetado por cada um dos sensores do dispositivo. Isto é feito através do método Bind. Na Figura 5 pode-se observar um trecho de código onde se cria um objeto controlador de um dispositivo e se associa um objeto da classe SmVR_CGeometricObject ao sensor físico deste dispositivo. A classe SmVR_CCyberTrackII que aparece no exemplo é derivada da classe SmVR_CDevice e implemeta seus métodos virtuais.

Após a criação desta associação entre sensor físico e objeto-sensor, pode-se definir qualquer objeto geométrico como sendo filho destes objetos-sensores. Isto fará com que este objeto geométrico acompanhe todos os movimentos do sensor.

A atualização dos dados a partir dos sensores é feita através da chamada do método UpdateAllSensors da classe SmVR_CDevice. Esta chamada não é feita de forma automática pela biblioteca a cada frame, pois, dependendo da aplicação e do tempo de resposta do dispositivo, isto pode não ser interessante. A finalização do uso do sensor é feita na destrutora da classe SmVR_CDevice.

// cria um objeto controlador do dispositivo
SmVR_CDevice *CT = new SmVR_CCyberTrackII();

// Inicializa o dispositivo

CT->Init("COM1");

// Cria um objeto geométrico para representar o dispositivo

TrackerObject = new SmVR_CGeometricObject("TrackerObject");

RootObject->AddChild(TrackerObject);

// Vincula o objeto a um dos sensores do dispositivo

CT->Bind(0, TrackerObject);

// cria um objeto geométrico

SmVR_CGeometricObject*o1;

o1 = new SmVR_CGeometricObject ("Teste", Draw);

// adiciona ‘o1’ ao objeto que representa o tracker 

TrackerObject->AddChild(o1);

Figura 5 – Exemplo do Controle de um Dispositivo
Para alguns dispositivos, a biblioteca já possui rotinas de inicialização e leitura pré?definidas. Estes dispositivos são: Iglasses!, CyberTracker II, Polhemus Isotrack II e a Luva 5DT.

6.1 Informações dependentes de dispositivos

Alguns dispositivos com luvas e joysticks, entre outros, fornecem dados que não podem ser representados em matrizes de transformação geométrica. Para estes casos, a classe SmVR_CDevice possui um método SetExtraData(void *), no qual é possível fornecer um apontador para uma região de memória onde estes dados estão armazenados após cada chamada do método UpdateAllSensors. A responsabilidade de atualização desta área é da rotina de leitura do dispositivo, fornecida pelo programador na criação do objeto da classe SmVR_CDevice.

7. Considerações Finais

Esta biblioteca, disponível nos sites http://grv.inf.pucrs.br e http://www.smallvr.org, foi fruto da necessidade identificada em nosso meio acadêmico e foi construída tendo em mente a necessidade de uma ferramenta simples e de fácil utilização.
A SmallVR tem sido usada com sucesso por alunos e pesquisadores em nosso ambiente acadêmico e está ainda em evolução. A forma como a biblioteca está organizada tem se mostrado bastante interessante em especial pela facilidade para de incluir-se novas funcionalidades e pelo reduzido tempo necessário para sua aprendizagem.

Para o futuro estamos avaliando a viabilidade e a adequação de usar-se, no lugar de nosso grafo de cena proprietário, uma ferramenta como OpenSG. Isto entretanto, só será feito se a modificação não trouxer maiores dificuldades na utilização da biblioteca.

Referências

[1]ALICE - Disponível em http://www.alice.org
[2]Bergen, G. “Fast and Robust GJK Implementation for Collision Detection of Convex Objects”. Journal of Graphics Tools, 4(2):7-25 (1999)Também disponível em http://www.win.tue.nl/~gino/solid/

[3]Bierbaum, A.; Just, C.; Hartling, P.; Meinert, K.; Baker, A. Cruz-Neira, C. "VR Juggler: A Virtual Platform for Virtual Reality Application Development". IEEE VR 2001, Proceedings, Yokohama, Japan, March 2001.

[4]Hubbold R.; Cook, J.; Keates, M., Gibson, S.; Howard, T.; Murta, A. West, A.; Pettifer, S. GNU/MAVERIK : A micro-kernel for large-scale virtual environments. Presence: Teloperators and Virtual Environments, 10:22-34, February 2001

[5]Kelso,J. Arsenault, L.; Satterfield, S.; Kriz, R. “DIVERSE: A Framework for Building Extensible and Reconfigurable Device Independent Virtual Environments”. IEEE VR 2002, Proceedings, Orlando, EUA, March 2002.

[6]Kessler, G. Drew, Doug A. Bowman, and Larry F. Hodges. "The Simple Virtual Environment Library, an Extensible Framework for Building VE Applications." PRESENCE, 9 (2), Apr. 2000. pp 187-208.

[7]Möller, T. “A fast triangle-triangle intersection test”. Journal of Graphics Tools, 2(2):25-30, 1997. Disponível em http://www.acm.org/jgt/papers/Moller97 .

[8]Morley, M. “Frustum Culling in OpenGL”. Disponível em http://www.markmorley.com/opengl/frustumculling.html

[9]Reiners D. OpenSG – Basic Concepts. OpenSG 2002 Fórum. Disponível em http://www.opensg.org/OpenSGPLUS/symposium/Papers2002

[10]VRUT - Virtual Reality Utilities. Disponível em http://www.recveb.ucsb.edu/vrut/