Documente Academic
Documente Profesional
Documente Cultură
2
3
4
5
1. INTRODUÇÃO A VISUALIZAÇÃO DE INFORMAÇÃO. ............... 13
2.1 Introdução....................................................................................................................47
2.1.1 VRML97..............................................................................................................48
2.1.2 X3D .....................................................................................................................50
6
2.2 Grafo de Cena ..............................................................................................................53
2.2.1 Definições básicas ................................................................................................53
2.2.2 Atributos ..............................................................................................................54
2.2.3 Nós em VRML e X3D ..........................................................................................55
2
Programa de Pós-Graduação - Universidade Federal do Pará (UFPA)
Departamento de Engenharia Elétrica, C.P. 8619 - CEP 66075-900 - Belém - PA –
Brasil.
bianchi.serique@terra.com.br, aruanda@redeinformatica.com.br,
mbgarcia_pa@yahoo.com.br, rosico@amazon.com.br
Dados Dados
Brutos Brutos
ESPECTADOR
SELEÇÃO CODIFICAÇÃO APRESENTAÇÃO
SELEÇÃO CODIFICAÇÃO APRESENTAÇÃO
Figura 1-4 : Usuário não participa da Com o advento do computador o usuário pode
concepção da visualização da informação interagir em qualquer parte do processo de
visualização.
1.5.1 Tamanho
Um exemplo do uso de tamanho para codificar dados pode ser visualizado em
um projeto de um circuito elétrico. Um círculo é sobreposto em componentes de
interesse (Figura 1-5), o tamanho de cada círculo indica a extensão da influência
daquele componente em relação a uma propriedade do circuito. Quando o projetista
altera um componente, automaticamente os tamanhos se ajustam, afim de que o
projetista possa perceber a influencia de sua mudança nos pontos em estudo (Spence,
2001).
21
Figura 1-7 – Codificação de dados com conhecimento prévio do usuário (Spence, 2001).
1.5.5 Som
Infelizmente o termo 'visualização' contém o termo 'visual', mas uma
representação de dados por som – por si só ou combinada com apresentação visual - tem
muito para oferecer. Freqüentadores de concertos e fãs de bandas de rock são capazes
não só de identificar os instrumentos musicais diferentes, entre vinte ou mais, mas
também as notas diferentes, cordas, tempo, e ritmo em que estão sendo tocadas. Assim,
o potencial uso do som para codificar dados parece considerável. Por exemplo, ao usar
um banco 24 horas as pessoas estão acostumadas a ouvir um 'bip' indicando uma
mudança de estado da máquina, um modo muito simples, mas extremamente eficiente
de codificar dados em som e permitir visualizar assim o estado da máquina (Spence,
2001).
1.5.7 Cor
Como já demonstrado anteriormente, dados numéricos podem ser codificados
através de cor. Uso de cor deve ser utilizado com cautela. Por exemplo, não utilizar
cores semelhantes para dados muito próximos, pois poderá prejudicar a percepção do
usuário. Cores em escala representam magnitude, e uma escolha popular é o espectro de
freqüência, com elementos grandes denotando vermelho e azul para os elementos
pequenos (Spence, 2001).
Figura 1-11- Diagramas de coordenada paralelos aplicado a seis variáveis. (Wegman, 1990)
Árvore de cones (Figura 1-12) e perspective wall (Figura 1-13) usam uma
representação tridimensional para permitir ao usuário uma visão geral ou uma visão
com detalhes. Nenhuma das duas técnicas tem como objetivo filtrar informação nem de
permitir a escolha de novas representações. Contudo, no modelo perspective wall é
possível realizar pesquisa, isso não implica em filtrar dados, uma vez que a informação
é apresentada sempre na sua totalidade, havendo uma adaptação da representação de
forma a salientar o foco de interesse do usuário.
Figura 1-16- Métodos de codificar parâmetros que caracterizam uma ligação (Spence,
2001).
1.7 Aplicações
A seguir serão apresentadas algumas ferramentas de visualização de dados
(Chen, 1999) (Brath, 1999), (Spence, 2001) e (Furuhata, 2004). A maioria delas será
voltada para ambientes virtuais tridimensionais, contudo as bidimensionais mais
famosas na literatura também serão citadas.
1.7.1 SpotFire.
SpotFire (Figura 1-17), assim como outras ferramentas, faz uso das técnicas de
consultas dinâmicas, que permite que um usuário formule um problema
simultaneamente com sua resolução, relatado primeiramente por Williamson e
Shneiderman (Shneiderman, 1994). O SpotFire usa uma diagrama de dispersão, pode
utilizar outros gráficos simultâneos, que dada uma coleção de objetos, cada um descrito
pelos valores associados com um conjunto de atributos, é possível achar o mais
aceitável de tais objetos ou, talvez, um número pequeno de objetos candidatos
merecedor de uma consideração mais detalhada. E pode ser aplicado em qualquer área
do conhecimento. Mais detalhes em http://www.spotfire.com.
28
Figura 1-17- O uso de consultas dinâmicas aplicadas à seleção de um filme no Spot Fire
(Spence, 2001).
1.7.2 Paralax.
O software (Figura 1-18) está baseado em Coordenadas Paralelas que são uma
metodologia para visualização não ambígua de dados e relações multivariadas. A
descoberta de relações multidimensionais em um conjunto de dados é transformada em
um problema bidimensional de reconhecimento de padrão. A interface oferece
descobertas visuais, através de consultas com operadores booleanos, de relações
complexas em conjunto de dados de multivariados. Mais detalhes em:
http://www.kdnuggets.com/software/parallax/
29
1.7.3 Treemap
Treemap (Figura 1-19) é um método de visualização capaz de representar
grandes coleções de dados que possuem hierarquia entre si em um espaço limitado,
como o monitor de vídeo, e consiste em dividir a área de visualização em seqüências de
retângulos cujas dimensões são definidas por um atributo dos dados. A peça chave de
um treemap é o algoritmo usado para criar os retângulos que o compõem, o original é o
“slice and dice”. Outros algoritmos já foram propostos para solucionar algumas
desvantagens do algoritmo original. Mais detalhes em
http://www.cs.umd.edu/hcil/treemap-history.
30
1.7.6 NetViz
O software NetViz (Figura 1-22) auxilia organizações a entender e administrar
sua tecnologia de informação e sistema empresarial. Importa dados de vários tipos de
fonte, e é baseada na representação de rede de dados.
32
1.7.9 Cat-a-Cone
É uma ferramenta para categorização de documentos. Os usuários navegam pela
árvore de cones até o livro de desejado, e uma representação virtual do livro se torna
disponível (Figura 1-27).
APPLETJAVA
JAVA Ambiente3D
Ambiente 3D Ambiente3D
Ambiente 3D
APPLET
Compartilhado
Compartilhado Individual
Individual
Basede
Base de
EAI
Dados
Dados
Servidor JDBC//ODBC
JDBC ODBC
Servidor
PROTO Informacao [
exposedField SFVec3f posicao 0 0 0
exposedField SFColor cor 0 0 0
field SFFloat qtdade 0
]
Figura 1-39 – Protótipo para a exibição de uma informação do banco de dados
A exibição da quantidade no AV o deixaria extremamente poluído visualmente.
Para contornar esta situação, faz-se uso de sensores em cada objeto (Figura 1-40). Desta
forma ao passar o mouse sobre um determinado objeto, o usuário terá um painel
mostrando o valor real associado.
Transform {
scale 1 15 1
children [
Shape {
appearance Appearance
{
material Material {
diffuseColor .5 .36 .5
}
}
geometry Cylinder {
height 0.1
radius 0.1
}
}
DEF Toque TouchSensor {}
]
}
Figura 1-42– Utilização de sensor e script para controlar a interação do usuário sobre um
objeto
Na applet, podem-se encontrar cinco áreas principais (Figura 1-43). A primeira
trata dos pontos de visões disponibilizadas no ambiente, tais como, visão frontal, aérea,
etc. como também movimentos que não foram pré-definidos anteriormente utilizando as
barras de rolagem para interagir no ambiente. A segunda área trata da troca de
informações entre os usuários de modo textual, além de guardar o histórico das trocas
de informações. No campo histórico também ficam registradas as ações dos usuários,
que podem pode ser inserção, remoção, construção do plano e troca de mensagens entre
os usuários que compartilham o ambiente. A terceira área trata da configuração do plano
tais como escolher qual o tipo de gráfico 3D a ser gerado (Mensal ou Anual), o plano a
ser colocado o gráfico (Compartilhado ou Individual), ano, paciente e o mês quando
necessário. Todo novo plano inserido é colocado no lugar do anterior. A quarta parte
trata da visualização ou não dos dados contidos no gráfico gerado, o estado default é
inserir todos os dados da consulta baseado no ano, mês (opcionalmente) e paciente.
Caso o usuário não queira visualizar certos dados, basta desmarcar a opção
referente a uma determinada medição para realizar a ocultação no AV. Ao fazer isso,
uma mensagem é enviada para cada objeto com alteração do valor do campo
transparency correspondente às características de cor do objeto (Figura 1-44Figura
1-44).
44
Shape {
appearance Appearance {
material Material {
transparency 0.8
}
}
geometry Box {}
}
Brath, Richard Karl Effective Information Visualization Guidelines and Metrics for 3D
Interactive Representations of Business. Master Project of Toronto University. 1999
Data. Disponível em: http://www3.sympatico.ca/blevis/thesis49toc.html
Card, S., Mackinlay, J., and Shneiderman, B. eds. Readings in Information
Visualization Using Vision to Think. Morgan Kaufmann, 1999.
Carr, D. A. Guidelines for Designing Information Visualization Applications. 2004
(disponível em: http://www.sm.luth.se/~david/papers/VizGuidelines.pdf
Chen, Chomei. Information Visualization and Virtual Environments, Springer, 1999.
Freitas, Carla M. Dal Sasso et. al. Visualização de Informações. RITA - Volume VIII -
Número 2 - págs. 143-158, Porto Alegre - RS, 2001.
Furuhata, R.; Fujishiro, I.; Maekawa, K; Yamashita, Y. Information Visualization and
Visualization Techniques. 2004. Disponível em:
http://www.imv.is.ocha.ac.jp/MIKY/
Horstmann, Cay S., Cornell, Gary. Core Java 2 – Volume II – Recursos Avançados,
Makron Books, São Paulo, 2001.
Meiguins, Bianchi S., Guedes, Luis A., Araújo, Marcos V., Garcia, Marcelo B., Souza,
Rosevaldo D. A Proposal for Collaborative Virtual Environments Architecture Using
Internet Patterns. Proceedings of IASTED International Conference on Software
Engineering (SE 2004). Innsbruck, Austria. 2004.
46
Panas, T.; Berrigan, R.; Grundy, J. A 3D Metaphor for Software Production
Visualization. Proceedings of the Seventh International Conference on Information
Visualization (IV’03). IEEE. 2003
Roehl. B.; et al. Late Night VRML 2.0 with Java. ZD Press. Emeryville, California.
1997.
Shneiderman, B. The eyes have it: a task by data type taxonomy for information
visualizations, Procedings of 1996 IEEE Visual Language. 336-343
Shneiderman, B., Dynamic queries for visual information seeking, IEEE Software 11, 6
(1994), 70-77.
Spence, Robert. Information Visualization. Addison-Wesley. 2001.
Inselberg, A. Multidimensional Detective, IEEE, Proceedings of Information
Visualization’97, pág.100-107, 1998.
Wegman, E. J. Hyperdimensional Data Analysis Using Parallel Coordinates, Journal of
the American Statistical Associations, pág. 270 – 277, 1990
Sherman, William R., Craig, Alan B. Understanding Virtual Reality: Interface
Application and Design. Morgan Kaufmann Publishers. 2003
47
2
VR Centre - CAVERNA Digital LSI - POLI - USP
Av. Prof. Luciano Gualberto,158 trav.3 CEP 05508-900 São Paulo/SP/Brazil
2.1 Introdução
VRML tem uma história fundamentada na colaboração de diversos
pesquisadores e importantes empresas relacionadas com a Computação Gráfica e
Realidade Virtual.
O Scenario nasce a partir de um projeto, iniciado em 1989, na Silicon Graphics
Inc. por Rikk Carey e Paul Strass, fundamentada em duas características básicas:
capacidade de criação de uma gama variada de aplicações 3D e a possibilidade de usar
este ambiente para construir uma nova interface para 3D.
Em 1992, baseado nas proposições do Scenario, surge o Iris Inventor 3D, uma
ferramenta fundamentada em C++ que, posteriormente, fundamenta muito da semântica
de VRML. A revisão do Inventor realizada em 1994 origina o Open Inventor
caracterizada por sua portabilidade a uma grande variedade de plataformas e baseada no
Open GL da Silicon. O manual de referência da mesma descrevia os objetos e formatos
de arquivos que, adequados por Gavin Bell, originariam a especificação da primeira
versão da Virtual Reality Modeling Language, VRML 1.0.
Em 1994, Mark Pesce e Tony Parisi construíram um protótipo de um navegador
3D para a World Wide Web - WWW, chamado Labyrinth. Um ano depois, Mark e Brian
Behlendorf criaram a lista de discussão do VRML e publicaram uma chamada para
propostas de uma especificação formal para 3D na WWW.
De discussões nesta lista, iniciadas por Gavin BellI, usando como ponto de
partida o manual do Inventor nasce a especificação do VRML 1.0. Em 1995, o VRML
1.0 foi alvo de muitas correções e novas discussões, de forma que nasce a proposta de
uma segunda especificação, a do VRML 1.1 (ou VRML 2.0).
48
Aprimorada e capaz de definir comportamentos (com mais interação e
animação) para elementos 3D, a nova proposição foi submetida à lista em 1996. As
propostas apresentadas pela Silicon em colaboração com a Sony e com a Mitra
receberam a grande maioria dos votos e originaram o documento de definição de
VRML 2.0. Em agosto de 1996, esta versão foi publicada no SIGGRAPH´96 em New
Orleans.
A versão final deste texto, com correções e modificações técnicas foi publicada
em Abril de 1997, definida como VRML´97. Suas principais características estão
relacionadas com o desenvolvimento de cenários mais realísticos, prototipação
(capacidade de encapsular novos recursos de forma a criar novos nós), interação direta
com o usuário através de sensores, interpoladores e criação de animações usando
scripts.
Desde então, VRML (Virtual Reality Modeling Language) tem sido aplicada em
diversos projetos para concepção de mundos virtuais [ELLIS 1994, CHEN 1997,
MATSUBA 1999, CARDOSO et al. 1999] e é uma importante aliada no
desenvolvimento de mundos tridimensionais interativos na Web.
2.1.1 VRML97
• Header – obrigatório;
• Prototypes – usado para descrever classes de objetos que podem ser usados na
descrição do cenário;
• Comments;
• Nodes;
2.1.2 X3D
O X3D é um padrão aberto para distribuir conteúdos de realidade virtual em 3D,
em especial pela Internet. Ele combina tanto dados geométricos como descrições de
comportamentos instantâneos em um simples arquivo que tem inúmeros formatos de
transmissão, sendo que o padrão de codificação ideal é o XML (Extensible Markup
Language). O X3D é a próxima revisão da especificação ISO VRML97, incorporando
os avanços dos recursos disponíveis nos últimos dispositivos gráficos comerciais tanto
quanto melhoras na sua arquitetura baseado nos anos de retorno da comunidade de
desenvolvimento do VRML97. Este padrão esta sendo desenvolvido por um consórcio
internacional, conhecido como Web3D, que tem o objetivo de propor e manter o padrão,
e manter ele como um sistema aberto para a comunidade.
O X3D pode ser utilizado para Modelagem e animação, interação,
interoperabilidade com outras tecnologias da web, treinamento, visualização científica,
suporte a vendas, etc.
O XML foi adotado como sintaxe para o X3D para resolver um grande número
de problemas reais, A sintaxe do VRML 97 é estranha para todos com exceção da
comunidade do VRML. Ela é similar a sintaxe do grafo de cena do Open Inventor, na
qual foi baseada e algumas notações de objetos. Todavia, a sintaxe dominante na Web
51
atualmente é o XML. Linguagens de marcações tem provado ser a melhor solução para
o problema de um longo ciclo de vida de arquivamento de dados.
Integração baseada em páginas XML vai direto ao problema de manter o sistema
mais simples, assim mais pessoas podem desenvolver páginas web, tanto em conteúdo
como implementações. Extensível suporte ao XML é esperado na última versão do
Mozilla e do Internet Explorer. O X3D, como um formato que define informações
visuais, é tipicamente o último estágio em uma linha de produção. Usando um conjunto
de ferramentas disponíveis, como stylesheets, você pode trabalhar em qualquer formato
nativo XML que você queira, e ver que uma representação 3D é tão trivial quanto um
processo de transformação.
Existe uma Document Type Definition (DTD) para X3D, definida como parte do
padrão. A URL do DTD é: http://www.web3d.org/specifications/x3d-3.0.dtd. Também
existe um Schema para X3D aceito. Ele é definido como parte do padrão. A URL do
Schema é: http://www.web3d.org/specifications/x3d-3.0.xsd.
O X3D é um padrão aberto que não tem royalties associados com ele - você
pode usar livremente aonde você quiser. Não existe nenhum política de limite de
Propriedade Intelectual para a tecnologia, além de existir um acordo com a ISO para
publicar a especificação para o público sem nenhum custo.
Existe um esforço para um programa de conformidade para a especificação do
X3D que tem o objetivo de prover consistência e confiabilidade para as implementações
que suportem X3D pelos diversos vendedores das múltiplas plataformas, e para criar
uma definição objetiva de conformidade com o padrão X3D. Somente produtos que
passe pela conformidade poderão usar a marca registrada X3D.
Profiles e components são a nova forma do X3D de definir ambas,
extensibilidade e o conjunto de serviços que o conteúdo dos usuários necessita. Um
componente (component) define uma específica coleção de nós. Tipicamente esta
coleção tem em comum um conjunto de funcionalidades - por exemplo a estruturas
NURBS e as habilidades de texturização. Um componente (component) consiste da
definição dos nós e um conjunto de níveis que prove um cada vez maior conjunto de
implementações. Um nível simples requer apenas poucos nós e talvez uma seleção de
campos a serem suportados, enquanto que níveis maiores requerem todos os níveis mais
simples, mais nós mais complexos.
Por exemplo, o nível 1 de NURBS requer apenas linhas e curvas 2D básicas,
enquanto que o nível 4 requer, costura, junção e superfícies de revolução. Um perfil
52
(profile) é uma coleção de componentes para um específico nível de suporte. Um perfil
(profile) pode não conter outro perfil, porém ele necessita todos os mesmos
componentes (components) e níveis como outro perfil (profile), e ainda mais. Todos os
arquivos X3D requerem a definição do perfil (profile) que está em uso, na qual pode ser
suprida com a requisição de componentes adicionais pelo usuário - ou por níveis
maiores que aqueles providos pelo perfil (profile) ou que ainda não foram definidos no
perfile (profile). Empresas podem criar novos Componentes com suporte para seus
produtos e submetê-los para a diretoria do X3D para sua aprovação.
Quando um componente é submetido, este contém um prefixo para a empresa
que submete o componente similar como as extensões OpenGL que têm o prefixo da
empresa que criou a extensão. Componentes vão sofrer os testes e revisões pela diretoria
do X3D, o Consórcio Web3D e a comunidade como um todo. Uma vez que um
componente seja aceito e implementado por mais de uma empresa, o prefixo muda para
EXT_. Se o componente é classificado pela diretoria, ele então recebe o prefixo X3D_.
A diretoria pode julgar que certos componentes são tão largamente adotados e
importantes que deveriam ser incluídos em um conjunto de modificações para a
especificação ISO oficial. Uma vez que um grupo de componentes (components) e/ou
perfils (profiles) são julgados importantes para a inclusão através das várias aplicações,
uma nova versão do X3D pode ser criada incluindo, por padrão, um conjunto de perfis
(profiles).
Uma nova versão implica mais funcionalidade que as versões anteriores.
Empresas podem criar navegadores, ferramentas, importadores e exportadores X3D na
qual suportam diferentes versões, perfils (profiles) e componentes (components). Por
exemplo, um exportador para o 3DSMax que é usado nos ambientes de produção de
video-games pode suportar somente o perfil Interchange, enquanto que um plug-in para
navegador da Internet pode suportar o perfil Immersive ou Full.
As empresas não precisam suportar todos os Profiles, Components e Levels.
Perfis e componentes existem para que as empresas precisem somente suportar perfis e
componentes para suas necessidades. Por ter perfis, seus produtos podem ter certeza que
o conteúdo que eles lerem irá funcionar nas suas aplicações, e que aquele conteúdo que
eles criaram irá funcionar em outras aplicações que suportem seus componentes ou
perfis. Muitas empresas não vão querer suportar uma especificação grande e complexa
como o VRML97. Porém a estrutura modular do X3D significa que eles podem
começar suportando perfis (profiles) e componentes (components) simples, e
53
gradualmente adicionar perfis adicionais conforme eles se sentirem preparados. Por
haver empresas capazes de desenvolver componentes e submetê-los, o X3D força os
avanços da indústria a serem rápidos e eficientes. Isto também garante que o X3D
crescerá e florescerá, e não se tornará tecnicamente obsoleto.
2.2.2 Atributos
Os atributos declarados em cada nós podem conter um valor simples ou
múltiplos, isto é definido pelas duas primeiras letras. Caso o tipo do atributo comece
com SF (Single Field) somente suportará um valor, caso seja MF (Multiple Fields), este
suportara vários valores. Estes também podém se referenciar outros nós com o tipo
abstrato básico SFNode and MFNode.
55
Dentre os tipos básicos de atributos temos:
Bool - para valores booleanos
Color - para a descrição de RGB de uma dada cor
ColorRGBA- para a descrição de RGBA de uma dada cor
Double – para valores reais com altíssima precisão
Image – para imagem
Int32 - para valores inteiros
FLoat - para valores reais
Node - para a descrição de um nó
Rotation – para os valores de uma rotação
String – para um texto
Time – para um valor de tempo
Vec2d, Vec2f – para um vetor de 2 elementos de alta e menor precisão
Vec3d, Vec3f – para um vetor de 3 elementos de alta e menor precisão
• Geometrias
Box : X3DGeometryNode {
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [] size 2 2 2 (0,∞ )
SFBool [] solid TRUE
}
Group : X3DGroupingNode {
MFNode [in] addChildren [X3DChildNode]
MFNode [in] removeChildren [X3DChildNode]
MFNode [in,out] children [] [X3DChildNode]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [] bboxCenter 000 (-∞ ,∞ )
SFVec3f [] bboxSize -1 -1 -1 [0,∞ ) or − 1 − 1 − 1
}
Transform : X3DGroupingNode {
MFNode [in] addChildren [X3DChildNode]
MFNode [in] removeChildren [X3DChildNode]
SFVec3f [in,out] center 000 (-∞ ,∞ )
MFNode [in,out] children [] [X3DChildNode]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFRotation [in,out] rotation 0 0 1 0 [-1,1] or (-∞ ,∞ )
SFVec3f [in,out] scale 111 (0,∞ )
SFRotation [in,out] scaleOrientation 0 0 1 0 [-1,1] or (-∞ ,∞ )
59
SFVec3f [in,out] translation 000 (-∞ ,∞ )
SFVec3f [] bboxCenter 000 (-∞ ,∞ )
SFVec3f [] bboxSize -1 -1 -1 [0,∞ ) or − 1 − 1 − 1
}
Shape : X3DShapeNode {
SFNode [in,out] appearance NULL [X3DAppearanceNode]
SFNode [in,out] geometry NULL [X3DGeometryNode]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [] bboxCenter 0 0 0 (-∞ ,∞ )
SFVec3f [] bboxSize -1 -1 -1 [0,∞ ) or − 1 − 1 − 1
}
Appearance : X3DAppearanceNode {
SFNode [in,out] fillProperties NULL [FillProperties]
SFNode [in,out] lineProperties NULL [LineProperties]
SFNode [in,out] material NULL [X3DMaterialNode]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFNode [in,out] texture NULL [X3DTextureNode]
SFNode [in,out] textureTransform NULL [X3DTextureTransformNode]
}
Material : X3DMaterialNode {
SFFloat [in,out] ambientIntensity 0.2 [0,1]
SFColor [in,out] diffuseColor 0.8 0.8 0.8 [0,1]
SFColor [in,out] emissiveColor 000 [0,1]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFFloat [in,out] shininess 0.2 [0,1]
SFColor [in,out] specularColor 000 [0,1]
SFFloat [in,out] transparency 0 [0,1]
}
Background : X3DBackgroundNode {
SFBool [in] set_bind
MFFloat [in,out] groundAngle [] [0,π/2]
MFColor [in,out] groundColor [] [0,1]
MFString [in,out] backUrl [] [urn]
MFString [in,out] bottomUrl [] [urn]
MFString [in,out] frontUrl [] [urn]
MFString [in,out] leftUrl [] [urn]
SFNode [in,out] metadata NULL [X3DMetadataObject]
MFString [in,out] rightUrl [] [urn]
60
MFString [in,out] topUrl [] [urn]
MFFloat [in,out] skyAngle [] [0,π]
MFColor [in,out] skyColor 0 0 0 [0,1]
SFTime [out] bindTime
SFBool [out] isBound
}
DirectionalLight : X3DLightNode {
SFFloat [in,out] ambientIntensity 0 [0,1]
SFColor [in,out] color 1 1 1 [0,1]
SFVec3f [in,out] direction 0 0 -1 (-∞ ,∞ )
SFFloat [in,out] intensity 1 [0,1]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFBool [in,out] on TRUE
}
PointLight : X3DLightNode {
SFFloat [in,out] ambientIntensity 0 [0,1]
SFVec3f [in,out] attenuation 1 0 0 [0,∞ )
SFColor [in,out] color 1 1 1 [0,1]
SFFloat [in,out] intensity 1 [0,1]
SFVec3f [in,out] location 0 0 0 (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFBool [in,out] on TRUE
SFFloat [in,out] radius 100 [0,∞ )
}
SpotLight : X3DLightNode {
SFFloat [in,out] ambientIntensity 0 [0,1]
SFVec3f [in,out] attenuation 100 [0,∞ )
SFFloat [in,out] beamWidth π/2 (0,π/2]
SFColor [in,out] color 111 [0,1]
SFFloat [in,out] cutOffAngle π/4 (0,π/2]
SFVec3f [in,out] direction 0 0 -1 (-∞ ,∞ )
SFFloat [in,out] intensity 1 [0,1] Figura 2-14 - Elementos de SpotLight
SFVec3f [in,out] location 000 (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFBool [in,out] on TRUE
SFFloat [in,out] radius 100 [0,∞ )
}
LOD : X3DGroupingNode {
MFNode [in] addChildren [X3DChildNode]
MFNode [in] removeChildren [X3DChildNode]
MFNode [in,out] children [] [X3DChildNode]
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [] bboxCenter 000 (-∞ ,∞ )
SFVec3f [] bboxSize -1 -1 -1 [0,∞ ) or − 1 − 1 − 1
SFVec3f [] center 000 (-∞ ,∞ )
MFFloat [] range [] [0,∞ ) or -1
61
}
ImageTexture : X3DTexture2DNode {
SFNode [in,out] metadata NULL [X3DMetadataObject]
MFString [in,out] url [] [urn]
SFBool [] repeatS TRUE
SFBool [] repeatT TRUE
}
TimeSensor : X3DTimeDependentNode,X3DSensorNode{
SFTime [in,out] cycleInterval 1 (0,∞ )
SFBool [in,out] enabled TRUE
SFBool [in,out] loop FALSE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFTime [in,out] pauseTime 0 (-∞ ,∞ )
SFTime [in,out] resumeTime 0
SFTime [in,out] startTime 0 (-∞ ,∞ )
Figura 2-16 - Elementos do nó TimeSensor
SFTime [in,out] stopTime 0 (-∞ ,∞ )
SFTime [out] cycleTime
A figura apresenta os elementos do nó
SFTime [out] elapsedTime
SFFloat [out] fraction_changed TimeSensor. É importante destacar que o tempo é sempre
SFBool [out] isActive uma fração do valor máximo (que é sempre 1.0). Assim,
SFBool [out] isPaused quando define-se que o intervalo de tempo
SFTime [out] time (cycleInterval) será de 10.0 s, em 2 s teremos o tempo
} relativo à fração 0.2.
PositionInterpolator : X3DInterpolatorNode {
SFFloat [in] set_fraction (-∞ ,∞ )
MFFloat [in,out] key [] (-∞ ,∞ )
MFVec3f [in,out] keyValue [] (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [out] value_changed
}
OrientationInterpolator : X3DInterpolatorNode {
SFFloat [in] set_fraction (-∞ ,∞ )
MFFloat [in,out] key [] (-∞ ,∞ )
MFRotation [in,out] keyValue [] [-1,1] or (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFRotation [out] value_changed
}
ScalarInterpolator : X3DInterpolatorNode {
SFFloat [in] set_fraction (-∞ ,∞ )
MFFloat [in,out] key [] (-∞ ,∞ )
MFFloat [in,out] keyValue [] (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFFloat [out] value_changed
}
NavigationInfo : X3DBindableNode {
SFBool [in] set_bind
MFFloat [in,out] avatarSize [0.25 1.6 0.75] [0,∞ )
63
SFBool [in,out] headlight TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFFloat [in,out] speed 1.0 [0,∞ )
MFString [in,out] transitionType [LINEAR] ["TELEPORT" "LINEAR" "ANIMATE"]
MFString [in,out] type ["EXAMINE" "ANY"]
SFFloat [in,out] visibilityLimit 0.0 [0,∞ )
SFTime [out] bindTime
SFBool [out] isBound
}
Viewpoint : X3DBindableNode {
SFBool [in] set_bind
SFVec3f [in,out] centerOfRotation 0 0 0 (-∞ ,∞ )
SFString [in,out] description ""
SFFloat [in,out] fieldOfView π/4 (0,π)
SFBool [in,out] jump TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFRotation [in,out] orientation 0 0 1 0 [-1,1],(-∞ ,∞ )
SFVec3f [in,out] position 0 0 10 (-∞ ,∞ )
SFTime [out] bindTime
SFBool [out] isBound
}
PlaneSensor : X3DDragSensorNode {
SFBool [in,out] autoOffset TRUE
SFString [in,out] description ""
SFBool [in,out] enabled TRUE
SFVec2f [in,out] maxPosition -1 -1 (-∞ ,∞ )
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec2f [in,out] minPosition 0 0 (-∞ ,∞ )
SFVec3f [in,out] offset 0 0 0 (-∞ ,∞ )
SFBool [out] isActive
SFBool [out] isOver
SFVec3f [out] trackPoint_changed
SFVec3f [out] translation_changed
}
SphereSensor : X3DDragSensorNode {
SFBool [in,out] autoOffset TRUE
SFString [in,out] description ""
SFBool [in,out] enabled TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFRotation [in,out] offset 0 1 0 0 [-1,1],(-∞ ,∞ )
SFBool [out] isActive
SFBool [out] isOver
SFRotation [out] rotation_changed
SFVec3f [out] trackPoint_changed
}
TouchSensor : X3DTouchSensorNode {
64
SFString [in,out] description ""
SFBool [in,out] enabled TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [out] hitNormal_changed
SFVec3f [out] hitPoint_changed
SFVec2f [out] hitTexCoord_changed
SFBool [out] isActive
SFBool [out] isOver
SFTime [out] touchTime
}
VisibilitySensor : X3DEnvironmentalSensorNode {
SFVec3f [in,out] center 0 0 0 (-∞ ,∞ )
SFBool [in,out] enabled TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [in,out] size 0 0 0 [0,∞ )
SFTime [out] enterTime
SFTime [out] exitTime
SFBool [out] isActive
}
ProximitySensor : X3DEnvironmentalSensorNode {
SFVec3f [in,out] center 0 0 0 (-∞ ,∞ )
SFBool [in,out] enabled TRUE
SFNode [in,out] metadata NULL [X3DMetadataObject]
SFVec3f [in,out] size 0 0 0 [0,∞ )
SFTime [out] enterTime
SFTime [out] exitTime
SFVec3f [out] centerOfRotation_changed
SFBool [out] isActive
SFRotation [out] orientation_changed
SFVec3f [out] position_changed
}
Anchor : X3DGroupingNode {
MFNode [in] addChildren
MFNode [in] removeChildren
65
MFNode [in,out] children [] [X3DChildNode]
SFString [in,out] description ""
SFNode [in,out] metadata NULL [X3DMetadataObject]
MFString [in,out] parameter []
MFString [in,out] url [] [url or urn]
SFVec3f [] bboxCenter 000 (-∞ ,∞ )
SFVec3f [] bboxSize -1 -1 -1 [0,∞ ) or − 1 − 1 − 1
}
teríamos metade do cilindro acima e metade do cilindro abaixo do eixo 'x' (o mesmo
vale para o Cone).
2.3.2 Textos
É possível inserir textos nos ambientes 3D concebidos através do nó Text, cuja
sintaxe foi apresentada no grafo de cena.
A apresentação do texto pode ser formatada com uso do nó FontStyle, que
permite definir a fonte que será utilizada, seu tamanho, espaçamento de caracteres,
como o texto será justificado etc.
66
O trecho de código abaixo, relativo à geometria, gera um texto simples como
Comentário: NÃO ACHEI ESTA
exemplo da Figura 2-17 - Exemplo de texto em VRML FIGURA, POR FAVOR REINSERIR
!!!!.
geometry Text {
string ["SVR 04 - Curso de VRML e X3D"]
fontStyle FontStyle {
size 0.9
justify "MIDDLE"
spacing 0.3
style "BOLD"
family "SERIF"
}
}
nó Shape que é usado para definir uma outra forma, no caso, um cilindro.
68
A facilidade de implementar formas geométricas é facilmente observada através
deste exemplo, que permite verificar que um arquivo que tem menos de 1kb é capaz de
produzir uma forma geométrica 3D,que a partir dos recursos do navegador VRML pode
ser vista de diferentes ângulos, rotacionada para verificação, aproximada ou afastada,
girada, apontada etc, tornando a navegação uma agradável experiência interativa com a
forma.
Até meados do ano de 2000, a edição de textos que descreviam formas em
VRML não dispunha de um editor de textos exclusivo para este fim. De olho neste
nicho de mercado, a empresa Parallel Graphics lançou o VrmlPad® [VRMLPAD
2000], que se encontra na versão 2.0 e que facilita sobremaneira a edição de tais textos.
2.3.8 Iluminação
VRML provê diversos nós para uma iluminação adequada de cenário. Todos
estes nós apresentam os seguintes campos: color, ambientIntensity e intensity. As
funções dos nós podem ser:
- iluminação do tipo direcional, com os raios emanando de forma radial em
todas as direções: PointLight;
- iluminação do tipo direcional, com os raios pertencem a um pincel de luz
paralela: DirectionalLight;
- iluminação do tipo 'spot', com os raios em um pincel na forma de cone, com
a fonte de luz no ápice do cone: SpotLight;
Em todos os casos, a contribuição de uma fonte de luz é definida pelo campo
intensityColor, enquanto que a contribuição da luz ambiente é dade em função do valor
do campo ambientIntensity. Objetos com textura não são afetados pela fontes de luz.
Pode-se desligar a luz na cabeça do usuário (navegador) através da definição a headlight
FALSE no nó NavigationInfo.
2.3.8.1 DirectionalLight
O pincel de luz paralelo tem a orientação dada pelo campo direction, a cor
definida no campo color e a intensidade definida em intensity. A Figura 2-28 apresenta
um conjunto de esferas que foi iluminado com uma luz direcional, no sentido do eixo x.
77
2.3.8.2 PointLight
A sintaxe do nó PointLight foi apresentada no grafo de cena.
O pincel de luz puntiforme tem a localização no ambiente 3D dada pelo campo
locaion, o raio da esfera de iluminação dado pelo campos radius, a intensidade definida
em intensity. Os campos intensity e color combinam-se para definir o nível de cor
provida pela fonte de luz em definição. Assim, a equação que define a cor da luz é:
lightColor = color X intensity.
A intensidade da luz ambiente é dada por:
lightAmbientColor = color X intensity X ambientIntensity.
As Figura 2-29 e Figura 2-30 apresentam um conjunto de esferas que foi
iluminado com uma luz puntiforme, que está definida no centro do eixo de coordenadas
do sistema. Na figura temos uma fonte de luz com grande intensidade e baixa atenuação
(caso 1) e na figura temos o mesmo conjunto de esferas associado a uma fonte de luz
com baixa intensidade e grande atenuação (caso 2).
]
}
ROUTE cont_tempo.fraction_changed TO cont_pos.set_fraction
ROUTE cont_pos.value_changed TO elemento.set_translation
]
}
ROUTE cont_tempo.fraction_changed TO cont_or.set_fraction
ROUTE cont_or.value_changed TO elemento.set_rotation
A definição da rotação está nos valores de keyValue, onde define-se que será
feita sobre o eixo 'x', que é o único dos três eixos que está com valor diferente de '0.0'
(como pode ser visto na linha 1 do campo keyValue. A rotação será de 0 a 2π e deve ser
definida com ângulos em radianos.
A última forma de animação relativa às transformações geométricas é a mudança
de escala. O nó que permite mudança de escala é o nó PositionInterpolator (o mesmo
que permite a animação de posição). Neste caso, no entanto, devem ser colocados
valores de escala no campo keyValue e a rota de saída de valores deve ser entrada para
valores de escala ao invés de valores de posição. Supondo a esfera apresentada
anteriormente, a modificação do nó de controle e das rotas seria dada por:
DEF cont_esc PositionInterpolator {
key [ 0.0 0.2 0.4 0.6 0.8 1.0]
keyValue [
1.0 1.0 1.0
1.5 1.5 1.5
2.0 2.0 2.0
2.5 2.5 2.5
1.5 1.5 1.5
1.0 1.0 1.0
]
}
DEF esfera Shape{
appearance Appearance {
material Material {
diffuseColor .46 .37 .14
specularColor .38 .31 .12
emissiveColor .14 .11 .04
ambientIntensity 0
shininess .04
}
}
geometry Sphere {
radius 0.5}
83
}
]
}
ROUTE cont_tempo.fraction_changed TO cont_esc.set_fraction
ROUTE cont_esc.value_changed TO elemento.set_scale
Neste exemplo, quando o usuário toca na esfera, que está definida no mesmo
grupo do nó 'toque', um evento de disparo de tempo é enviado para o nó de controle de
tempo - 'cont_tempo'. Só então, frações de tempo são recebidas pelo nó 'cont_pos',
disparando a animação (que acontece uma única vez).
De maneira a permitir que um dado elemento gráfico seja manipulado pelos
movimentos do usuário, existem três nós distintos;
PlaneSensor: converte as ações do usuário em movimentos em um plano 2D;
SphereSensor: converte as ações do usuário em movimentos ao longo de
uma esfera que envolve a forma;
CylinderSensor: converte as ações do usuário em movimentos ao longo de
um cilindro definido sobre um dos eixos.
Os campos maxPosition e minPosition definem os limites da translação que será
aplicada à forma. O trecho de código abaixo permite que, com a movimentação do
mouse, uma dada esfera sofra mudança de posição ao longo do plano 'XY':
DEF elemento Transform {
children[
DEF sensor_pos PlaneSensor{
enabled TRUE
autoOffset TRUE
offset 0.0 0.0 0.0
maxPosition -1.0 -1.0
minPosition 0.0 0.0
}
DEF esfera Shape{
appearance Appearance {
material Material {
diffuseColor .62 0 .62
specularColor .5 0 .5
emissiveColor .15 0 .15
ambientIntensity 0
shininess .15
85
}
}
geometry Sphere {
radius 0.8}
}
]
}
ROUTE sensor_pos.translation_changed TO elemento.translation
]
}
ROUTE sensor_esf.rotation_changed TO elemento.rotation
86
O trecho de código abaixo apresenta a utilização de CylinderSensor para
movimentar uma dada caixa (box):
DEF elemento Transform {
children[
DEF sensor_esf CylinderSensor {
autoOffset TRUE
enabled TRUE
diskAngle 0.262
offset 0.0
maxAngle -1.0
minAngle 0.0
}
DEF esfera Shape{
appearance Appearance {
material Material {
diffuseColor .6 .23 0
specularColor .5 .2 0
emissiveColor .3 .12 0
ambientIntensity 0
shininess .15
}
}
geometry Box {
size 2.0 3.0 5.0}
}
]
}
ROUTE sensor_esf.rotation_changed TO elemento.rotation
Sound {
minFront 10
minBack 10
maxFront 50
maxBack 50
source DEF SOUND AudioClip {
loop TRUE
url "pop.wav"
startTime -1
}
}
Group {
children [
Shape {
appearance Appearance {
material Material {
emissiveColor .1 .1 0
diffuseColor .75 .75 0
specularColor .86 .86 .86
ambientIntensity .127
shininess .38
}
}
geometry Box { size 0.8 0.5 0.1}
}
Transform {
translation 0.0 0.0 0.12
children
Shape {
89
appearance Appearance {
material Material {
diffuseColor .9 .05 .5
specularColor .1 .1 .1
emissiveColor .1 0 .05
ambientIntensity .12
shininess .08
}
}
geometry Text {
string "Alerta"
fontStyle FontStyle{
size 0.27
justify "MIDDLE"
}
}
}
}
]}
Anchor {
# inserção do link para onde se deseja ir:
url [ "http://www.compgraf.ufu.br/alexandre"]
description "Homepage do Autor"
# nós que ativarão o link:
children [
Transform {
translation 2.0 0.0 0.0
children [ Shape {
appearance Appearance {
material Material {
diffuseColor .03 .03 .18
specularColor .18 .27 .69
emissiveColor .03 .03 .17
ambientIntensity .0367
shininess .03
}
}
91
geometry USE Door
}
Transform {
translation 0.0 0.0 0.2
children Shape {
appearance Appearance {
material Material {
diffuseColor .6 .55 .24
specularColor .5 .46 .2
emissiveColor .3 .27 .12
ambientIntensity 0
shininess .14
}
}
# inserção de um texto para identificar o link:
geometry Text {
string "Autor"
fontStyle FontStyle {
size 0.4
justify "MIDDLE"}
}
}
}
]
}
]
}
2.3.15.1 Introdução
Os nós já apresentados para animação, tais como TouchSensor, TimeSensor,
PlaneSensor etc são muito limitados quando se desejam animações mais complexas ou
controle de elementos de cena a partir de equações (matemáticas, físicas, químicas etc).
Em tais situações é imperativa a necessidade de uso dos nós Script, que associam
VRML com JavaScript ou Java.
Um nó Script pode ser entendido como uma forma particular de controle ou de
sensor. Como qualquer nó de controle ou de sensor, este nó requer uma lista de campos
(field) , eventos de entrada (eventIns) e eventos de saída (eventOuts). A descrição do nó
deve complementar a definição destes campos, dando a eles uma dada finalidade . Um
nó Script deve ser entendido como um nó que recebe informações de outros nós através
dos eventos de entrada, processa-as e envia informações na forma de eventos de saída.
92
Logicamente, não serão encontrados nós Script independentes da descrição de
rotas, que mapeiam a troca de informações entre nós externos e o nó Script. Uma
exigência importante é a necessidade de equivalência de tipos de elementos entre os nós
que trocam informações.
Característica básica de um Script:
Script {
# definição de campos, suas naturezas e valores iniciais:
field SFBool booleano1 TRUE
# definição de eventos de entrada e sua natureza:
eventIn SFBool entrada
# definição de eventos de saída e sua natureza:
eventOut SFBool saida
url "javascript:
function entrada(param){
// processamento e determinação da saída
saida = param;
"
}
2.3.15.2 Exemplos
Como exemplo, a função abaixo representa um Script capaz de inserir um novo
elemento, no caso, uma esfera em uma área de um mundo virtual:
function sphere_touchTime(value,time) {
newVRML = 'Group {';
newVRML += ' children [';
newVRML += ' DEF SENSOR PlaneSensor {';
newVRML += ' maxPosition 0.45 0.45';
newVRML += ' minPosition -0.45 -0.45'
newVRML += ' }';
newVRML += ' DEF OBJECT Transform {';
newVRML += 'translation '
93
newVRML += x;
newVRML += ' 0.0 ';
newVRML += ' 0.0';
newVRML += ' children [';
newVRML += ' Shape {';
newVRML += ' appearance Appearance {';
newVRML += ' material Material {';
newVRML += ' diffuseColor 0 1 1';
newVRML += ' }';
newVRML += ' }';
newVRML += ' geometry Sphere {';
newVRML += ' radius 0.05';
newVRML += ' }';
newVRML += ' }';
newVRML += ' ]';
newVRML += ' }';
newVRML += ' ]';
newVRML += '}';
newVRML+=' ROUTE SENSOR.translation_changed TO
OBJECT.set_translation';
node = Browser.createVrmlFromString(newVRML);
new_child = node;
nopai.addChildren = new_child;
}
"
}
ROUTE SPHERESENSOR.touchTime TO Criador.sphere_touchTime
NavigationInfo {
type [ "ANY" ]
}
Transform {
children [
Shape {
appearance Appearance {
material Material {
diffuseColor 1.0 1.0 1.0
}
}
geometry Sphere {}
}
]
}
• Externprotos agora são usados somente para definir conteúdo externo ao arquivo
X3D. Eles não podem ser usados para prover mecanismos de extensão para o
navegador. A forma de prover extensões específicas para o navegador é através
de componentes (components) adaptados.
Extensões
Codificação X3D Extensão de arquivo Tipo MIME
Compactadas
Maya
O Maya é uma ferramenta muito utilizada para a criação de filmes no ciname.
Contudo ela possui um sistema avançado de modelagem, e ativando o seu plug-in é
possível salvar o arquivo no formato VRML97. Alguns cuidados devem ser tomados,
pois poderão haver perdas de informação, pois infelizmente o conversor do Maya não é
completo o suficiente.
3D-Studio
O 3D-Studio assim como o Maya apresenta uma série de vantagens para a
modelagem. E da mesma forma apresenta uma ferramenta para exportar os dados para
arquivos VRML97.
Cosmo
O Cosmo foi um dos primeiros navegadores desenvolvidos para visualizar
arquivos VRML, contudo não sofreu grandes avanços desde então. Assim apresenta
alguns limites.
102
Xj3D
Existe uma implementação código aberto (Open Source) escrita em Java
chamada de Xj3D. Uma aplicação funcional está disponível hoje e tem sido testada
sobre Linux, Solaris e Win32. O Xj3D é baseado em Java3D, logo necessita o Java3D
para rodar, como o Java3D necessita o Java 2, uma grande quantidade de dados deve ser
instalado para a utilização do Xj3D. O navegador Xj3Dé uma boas fonte para
implementação.
JINX
O sistema JINX é um navegados estritamente X3D, que pode ser utilizado em
ambientes de aglomerados de computadores e sistemas de projeções mais variados,
desde simples monitores até avançados sistema de projeção cúbica como Cavernas e
Domos. Este projeto ainda esta em desenvolvimento.
CHEN, S.; MYERS, R.; PASSETO, R. The Out of Box Experience - Lessons Learned
Creating Compelling VRML 2.0 Content. In: Proceedings of the Second Symposium
on Virtual Reality Modeling Language, p. 83-92, 1997.
MATSUBA, N.; STEPHEN; ROEHL, B. Bottom, Thou Art Translated: The Making of
VRML Dream. IEEE Computer Graphics and Applications, v. 19, n. 2, p. 45-51,
Mar./Apr. 1999.
Harold, E. R., Means, W. S., XML in a Nutshell, 2nd Edition, O'Reilly; 2nd edition,
2002
104
{ricardo.nakamura, romero.tori}@poli.usp.br
3.1 Introdução
O desenvolvimento de ambientes virtuais é uma tarefa complexa pois envolve a
integração de diferentes tecnologias e áreas de conhecimento. Hoje em dia, existem
vários sistemas de autoria e bibliotecas de programação para Realidade Virtual que
procuram reduzir essa complexidade. Ferramentas como WorldToolkit, ARToolkit e
VRML apresentam diferentes soluções para atingir este objetivo e trazem consigo
vantagens e desvantagens. O objetivo deste minicurso é apresentar a linguagem Java e
suas bibliotecas de programação como mais uma alternativa para o desenvolvimento de
ambientes virtuais. Não se pretende com isso implicar que esta solução seja melhor ou
pior do que qualquer outra, inclusive pelo fato de que este tipo de julgamento depende
do contexto. Entretanto, espera-se que as informações apresentadas possam contribuir
para os conhecimentos dos participantes em futuros projetos.
Este texto tem como objetivo servir como material complementar e de referência
para o minicurso. Desta forma, foi dada prioridade para a apresentação de exemplos de
código-fonte, figuras e diagramas explicativos.
try {
Class classeDin = minhaClasse.forName(nomeClasse);
Object objeto = classeDin.newInstance();
System.out.println(objeto);
}
catch(ClassNotFoundException ex) {
System.out.println("A Classe não existe!");
}
catch(IllegalAccessException ex) {
System.out.println("Erro ao criar o objeto dinamicamente");
}
catch(InstantiationException ex) {
System.out.println("Erro ao criar o objeto dinamicamente");
}
}
}
Num sistema real, uma interface pública para plug-ins ou extensões poderia ser
definida, para permitir que usuários criassem seus próprios objetos. Os objetos criados
dinamicamente seriam convertidos para esta interface pública, para utilização dentro do
sistema. Existem também muitos outros detalhes sobre o uso de reflection que não serão
discutidos aqui devido ao escopo deste curso, mas que devem ser estudados no caso de
se usar este recurso da linguagem Java.
Listagem 3.2 - Carregamento Dinâmico com Reflection
106
import java.lang.reflect.*;
try {
Class classeDin = minhaClasse.forName(nomeClasse);
3.3 Java 3D
Universe
Locale
Group
Leaf
3.3.2 NodeComponents
Além dos objetos que compõem a estrutura do grafo de cena, o Java 3D define
um conjunto de objetos acessórios, representados pela classe NodeComponent e suas
subclasses. Estes objetos definem parâmetros para os objetos do grafo. A Figura 3-3
apresenta um grafo de cena contendo um NodeComponent.
110
Universe
Locale
NodeComponent
Leaf
3.3.4 Capabilities
Por questões de otimização, o Java 3D apresenta o conceito de capabilities. Em
resumo, quando um nó é conectado ao universo do grafo de cena, suas propriedades não
podem mais ser alteradas – a não ser que o programador tenha indicado anteriormente
que determinadas propriedades precisariam ser alteradas. A maneira de indicar isso é
através do método setCapability que é definido na classe SceneGraphObject e
portanto está presente na maioria das classes do Java 3D. Cada classe possui
capabilities diferentes. A Listagem 3.4 exemplifica o uso de uma capability da classe
BranchGroup, que permite que um ramo do grafo de cena seja desconectado do
universo posteriormente. Executando este programa, veremos uma saída como:
Tentativa 1 não funcionou
Tentativa 2 funcionou
Comparando as duas tentativas, veremos que a diferença está na chamad do
método setCapability. Recomenda-se acessar a documentação das classes do Java 3D,
para saber quais as capabilities existentes.
Listagem 3.4 - Exemplo do uso de capabilities
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
try {
BranchGroup bg = new BranchGroup();
bg.setCapability(BranchGroup.ALLOW_DETACH);
uni.addBranchGraph(bg);
bg.detach();
System.out.println("Tentativa 2 funcionou");
}
catch(CapabilityNotSetException ex) {
System.out.println("Tentativa 2 não funcionou");
}
}
}
3.3.5 Loaders
O Java 3D define uma interface comum para carregamento de conteúdo através
das interfaces Loader e Scene. Um loader é uma classe capaz de carregar modelos em
um determinado formato (como por exemplo 3DS, OBJ, WRL) e converter tais modelos
em um grafo do Java 3D. A interface Scene define uma maneira uniforme de ter acesso
aos modelos carregados. A Listagem 3.5 demonstra uma forma simples de utilizar um
loader. Neste exemplo foi utilizado um loader distribuído com o Java 3D, entretanto a
sintaxe seria exatamente a mesma para qualquer classe que implemente a interface
Loader.
Listagem 3.5 - Exemplo de uso de um Loader
import com.sun.j3d.loaders.objectfile.*;
import com.sun.j3d.loaders.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
try {
ObjectFile loader = new ObjectFile();
Scene cena = loader.load("conteudo.obj");
BranchGroup bg = cena.getSceneGroup();
uni.addBranchGraph(bg);
}
catch(java.io.FileNotFoundException ex) {
System.out.println("Arquivo não encontrado");
}
catch(IncorrectFormatException ex) {
System.out.println("Formato incorreto para os dados");
}
catch(ParsingErrorException ex) {
System.out.println("Erro na interpretação do arquivo");
}
}
}
Uma dificuldade existente com os loaders, ou mais especificamente com a
interface Loader, é que não existe uma maneira uniforme para obter informações de
animação do modelo carregado. Alguns loaders simplesmente ignoram informações de
animação dos modelos, enquanto outros incluem métodos adicionais para retornar este
tipo de informação. O resultado é que embora o carregamento de modelos estáticos seja
extremamente simples no Java 3D, a implementação de animação destes modelos pode
se tornar bastante complexa.
3.3.6 Behaviors
No Java 3D, Behaviors são os objetos responsáveis por toda a funcionalidade de
interação, navegação e animação. Cada Behavior é uma folha do grafo de cena que
define código que deve ser executado quando um ou mais critérios são satisfeitos.
Alguns dos critérios possíveis são:
• executar o código a cada N segundos;
• executar o código quando o usuário mover o mouse;
• executar o código quando uma região estiver visível.
Adicionalmente, cada Behavior possui um volume de ativação. Os critérios de
execução de um Behavior somente são verificados quando o view frustum intercepta o
seu volume de ativação (ou seja, quando o volume de ativação estaria “visível” para o
usuário). Por exemplo, na Figura 3-4, o Behavior 1 poderia ser executado (dependendo
das suas condições de ativação) enquanto o Behavior 2 não seria executado de forma
alguma.
114
Volume de Ativação
Behavior 1
View Frustum
Câmera
Volume de Ativação
Behavior 2
uni.addBranchGraph(bg);
}
}
tg2.addChild(new ColorCube());
tg1.addChild(tg2);
bg.addChild(b);
uni.addBranchGraph(bg);
}
}
A Listagem 3.7 apresenta um exemplo de uso do Behavior utilitário
MouseRotate. Este programa cria um grafo de cena simples, incluindo um cubo
colorido na frente da câmera. O Behavior é utilizado para permitir que o usuário
rotacione este cubo colorido na tela ao clicar e arrastar o mouse.
import java.awt.GraphicsConfiguration;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.geometry.ColorCube;
118
import javax.media.j3d.*;
import javax.vecmath.*;
viewTrans.addChild(camera);
viewGroup.addChild(viewTrans);
loc.addBranchGraph(viewGroup);
// mostra a janela
window.show();
}
119
}
A primeira coisa que se observa é que esta versão parece bem mais complexa do
que a Listagem 3.3, que tem o mesmo resultado (exceto por não desenhar o cubo
colorido, mas isso é resolvido com 4 linhas de código).
View Canvas3D
ViewPlatform
PhysicalBody PhysicalEnvironment
3.3.8 Views
Como visto acima, a classe View faz a ligação entre uma câmera no mundo
virtual e um componente visual, que mostra a imagem renderizada. Os parâmetros desta
classe, juntamente com objetos das classes PhysicalBody e PhysicalEnvironment,
120
permitem adaptar a visualização para diferentes configurações como: monitor
convencional, monitor com imagens estereoscópicas, caverna virtual etc.
Em primeiro lugar, a classe View contém uma série de métodos que permitem
ajustar parâmetros de visualização como abertura do campo de visão, tipo de projeção,
planos de clipping e outros. Recomenda-se consultar a documentação do Java 3D para
saber todos os detalhes.
A classe PhysicalBody permite estabelecer parâmetros tais como distância
interocular e altura dos olhos, para que o Java 3D ajuste a renderização em
configurações com head tracking. Um objeto da classe PhysicalBody construído sem
parâmetros é inicializado com uma configuração adequada para ambientes visualizados
em computadores desktop sem o recurso de head tracking.
Por fim, a classe PhysicalEnvironment faz a interface com dispositivos não
convencionais, tais como rastreadores de posição. O uso destes dispositivos será visto
na seção seguinte.
3.3.9 InputDevices
O Java 3D possui uma maneira uniforme de representar dispositivos de entrada
diversos, o que é conveniente para aplicações de Realidade Virtual. Através deste
mecanismo, é possível integrar rastreadores diversos, joysticks, head trackers e outros
dispositivos não convencionais.
Um dispositivo de entrada é representado por uma classe que implemente a
interface InputDevice. Tal classe por sua vez produz um ou mais objetos da classe
Sensor, que representam os dados gerados pelo dispositivo de entrada. Cada Sensor
pode conter uma matriz de transformação (correspondendo a até seis graus de liberdade)
e um número qualquer de botões ou controles (cada um dos quais podendo retornar um
valor inteiro). Por exemplo:
• um joystick pode ser implementado como um InputDevice com um
único Sensor;
• um dispositivo com múltiplos rastreadores (como um Polhemus Flock of
Birds por exemplo) pode ser implementado como um InputDevice
com vários Sensors, um para cada rastreador.
A Listagem 3.9 traz um exemplo de implementação de um dispositivo de
entrada. Os comentários nesta listagem indicam o que deve ser implementado em cada
método da interface InputDevice para uma correta integração com o Java 3D.
121
A parte complexa de implementar os dispositivos de entrada, obviamente, é a
interface com o hardware. No caso de dispositivos ligados à porta serial, pode-se
recorrer à API Java Comm. Geralmente, entretanto, será preciso escrever código nativo
integrado via Java Native Interface (JNI). O problema com esta abordagem,
infelizmente, é que esta parte do código torna-se dependente de plataforma.
Listagem 3.9 - Exemplo de Implementação de um InputDevice
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
public MeuDispositivo() {
// Deve-se fazer o mínimo necessário aqui. O método
// initialize deve ser usado para a inicialização
// real do dispositivo.
}
3.4.2 Xj3D
O projeto Xj3D tem como objetivo fornecer ferramentas para visualização de
arquivos no padrão X3D através da linguagem Java. Atualmente, o projeto possui tanto
um visualizador autônomo como um Loader para o Java 3D. Um roteiro para usar o
Loader pode ser encontrado no endereço http://www.xj3d.org/loader.html embora o
processo seja essencialmente o mesmo discutido para outros Loaders anteriormente.
Com a existência de um conjunto de ferramentas em Java para visualização de
arquivos X3D, pode-se imaginar a possibilidade de elaborar sistemas muito mais
integrados e robustos do que era possível utilizando-se VRML e EAI, por exemplo.
Entretanto, a aplicabilidade deste tipo de sistema ainda depende da formalização do
padrão X3D e da sua aceitação pela comunidade.
3.5.1 RMI
O recurso de Remote Method Invocation (RMI) da linguagem Java pode ser
utilizado para implementar aplicações distribuídas de forma transparente. A maior
vantagem deste método (assim como CORBA) é que o código-fonte escrito não tem que
tratar explicitamente da comunicação em rede.
A idéia básica do uso do RMI para ambientes distribuídos é criar objetos que
podem ser executados remotamente e usar as chamadas de métodos destes objetos para
fazer a comunicação.
Objetos remotos precisam implementar uma subinterface de java.rmi.Remote,
que deve definir os métodos que podem ser executados remotamente. Eles devem
preferencialmente ser subclasses de java.rmi.server.UnicastRemoteObject, caso
contrário a implementação se torna bem mais complexa.
125
Objetos que podem ser passados como parâmetros para um objeto remoto
precisam implementar a interface java.io.Serializable, que permite que o objeto seja
copiado através da rede. Obviamente, o fato de que o objeto será copiado integralmente
pela rede já indica que deve-se evitar passar objetos grandes como parâmetro.
A Listagem 3.11 demonstra o uso de RMI para criar um simples “chat” de texto
entre dois usuários. As primeiras linhas do método main instalam um gerenciador de
segurança similar ao usado para applets. Este gerenciador evita que código remoto não-
confiável execute na máquina local. Isso é necessário porque o RMI pode fazer
download automático de classes que não existem localmente. Por outro lado, se nenhum
gerenciador for instalado, este comportamento de download automático é desabilitado.
Cada usuário, em um computador diferente, pode usar o exemplo executando
primeiramente a aplicação rmiregistry em uma janela de console. Depois, em outra
janela, pode executar a aplicação com:
java RMIChat <nome> <endereço>
import java.io.*;
try {
Chat chatLocal = new RMIChat();
Naming.rebind(args[0], chatLocal);
System.out.print("nome do usuário remoto: ");
BufferedReader in =
new BufferedReader(new InputStreamReader(System.in));
String nome = in.readLine();
String line;
126
do {
line = in.readLine();
chatRemoto.enviarMensagem(line);
} while (line != "FIM");
} catch (Exception e) {
e.printStackTrace();
}
}
3.5.2 JSDT
A API Java Shared Data Toolkit (JSDT) pode ser vista como um meio-termo
entre as soluções de alto nível que tornam a comunicação de rede transparente (RMI,
CORBA) e as soluções que expõem todos os detalhes (Sockets). Uma característica
interessante desta API é que ela pode utilizar o protocolo Multicast, que tem o potencial
para um bom desempenho no caso de um grande número de participantes.
O JSDT trabalha com a metáfora de Sessão colaborativa. Um servidor centraliza
informações sobre as sessões existentes, e usuários podem então se conectar a uma ou
mais delas. Cada sessão armazena três tipos de objetos compartilhados: canais, vetores
de bytes e tokens. Canais são usados para enviar mensagens de dados para os outros
usuários. Vetores podem ser usados para representar vários tipos de dados
compartilhados e tokens são usados primariamente como mecanismos de sincronização.
A Listagem 3.12 mostra como criar uma Sessão e cada um dos objetos compartilhados.
Listagem 3.12 - Exemplo de uso do JSDT
import com.sun.media.jsdt.*;
3.5.3 Sockets
Trabalhar diretamente com Sockets em Java é relativamente simples. No
entanto, criar uma implementação robusta e eficiente é tão complexo como seria em
qualquer outra linguagem.
Listagem 3.13 - Exemplo de uso de Sockets
import java.net.*;
import java.io.*;
128
public class SocketSimples {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1", 4444);
InputStreamReader isr =
new InputStreamReader(s.getInputStream());
BufferedReader br =
new BufferedReader(isr);
PrintStream ps =
new PrintStream(s.getOutputStream());
ps.println("Teste: cliente");
String l = br.readLine();
System.out.println(l);
ps.close();
br.close();
s.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
A Listagem 3.13 mostra como abrir uma conexão TCP/IP no Java. Deve-se notar
que a conexão irá falhar se não houver um servidor no endereço e porta de destino. O
código da Listagem 3.14 contém um servidor que interage com o cliente da listagem
anterior.
Listagem 3.14 - Servidor usando Sockets
import java.net.*;
import java.io.*;
while(true) {
Socket s = serv.accept();
Thread t = new Thread(new Conexao(s));
t.start();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
public Conexao(Socket s) {
this.s = s;
}
129
public void run() {
try {
InputStreamReader isr =
new InputStreamReader(s.getInputStream());
BufferedReader br =
new BufferedReader(isr);
PrintStream ps =
new PrintStream(s.getOutputStream());
String l = br.readLine();
System.out.println(l);
ps.println("Teste: servidor");
ps.close();
br.close();
s.close();
}
catch(Exception e) {
e.printStackTrace();
}
}
}
Para o servidor, utiliza-se a classe ServerSocket em vez de Socket, e a maneira
mais simples de tratar os clientes que se conectam é criar um novo thread para cada
cliente. Assim, o servidor não fica ocupado enquanto um cliente está se conectando.
A utilização do protocolo UDP é bastante similar ao caso da conexão TCP/IP
mostrada na Listagem 3.13, mas utiliza-se a classe DatagramSocket em vez de Socket.
Em vez de usar streams, os dados são transferidos através dos métodos send e receive,
que recebem um objeto da classe DatagramPacket. Esta classe é essencialmente um
invólucro de dados; no envio, o objeto deve ser configurado com o endereço e porta do
computador destinatário.
3.6 Conclusão
Foram apresentados exemplos de utilização de diferentes APIs da linguagem
Java para uso no desenvolvimento de ambientes virtuais. Este material pode ser útil
como referência para o início de um estudo mais aprofundado destas tecnologias.
4.1 Introdução
Este documento aborda alguns aspectos envolvidos no desenvolvimento de
aplicações de realidade virtual imersiva.
O texto baseia-se na utilização da biblioteca gráfica OpenGL e na experiência do
Grupo de Realidade Virtual da PUCRS no desenvolvimento de aplicações imersivas de
Realidade Virtual.
São apresentadas técnicas para os seguintes problemas:
• Modelagem de cenários;
• Transformações geométricas;
• Navegação em ambientes virtuais;
• Geração de imagens estereoscópicas;
• Interação em ambientes virtuais;
• Transformações geométricas hierárquicas;
• Ambientes Virtuais Colaborativos;
• Exibição de Cenas em Múltiplas Telas;
• Geração de tato.
Diversos dos exemplos aqui apresentados são fruto da experiência acumulada no
desenvolvimento da biblioteca gráfica SmallVR [PIN2002] (que pode ser encontrada
em http://www.smallvr.org) e nas aulas da disciplina de Tópicos Especiais em
Computação Gráfica (http://www.inf.pucrs.br/~pinho/TCG) do curso de Bacharelado
em Ciência da Computação da PUCRS, nos últimos dois anos.
4.4.1 Translação
Para efetuar uma translação há o comando glTranslatef(tx, ty, tz) que move
todas as coordenadas dos objetos ao longo dos eixos coordenados. Na Figura 4-4 pode-
se observar do uso do comando de translação.
glTranslatef(10,10,10);
DesenhaObjeto(); // Desenha o objeto descolado de 10
// unidades em cada eixo
glTranslatef(10,10,10);
DesenhaObjeto(); // Desenha o objeto descolado de 20
// unidades em cada eixo
// LEMBRE-SE, AS TRANSFORMAÇÕES SÃO
// CUMULATIVAS
Figura 4-4 - Exemplos de Translação
4.4.2 Rotação
glRotatef(20,1,0,0);
DesenhaObjeto(); // Desenha outro objeto rotacionado 20
// graus ao redor do eixo X
glRotatef(30,1,0,0);
DesenhaObjeto(); // Desenha mais um objeto, rotacionado
// 30 graus ao redor do eixo X
// LEMBRE-SE, AS TRANSFORMAÇÕES SÃO
// CUMULATIVAS. Neste caso o giro total será de 50
136
// graus
Figura 4-5 - Exemplos de Rotação
4.4.3 Escala
Para efetuar uma escala há o comando glScalef(ex, ey, ez) que altera a escala
do objeto ao logo dos eixos coordenados (Figura 4-6).
glScalef(0,0.5,0);
DesenhaObjeto(); // Desenha outro objeto com a altura
// diminuída pela metade
glScalef(0,2.0,0);
DesenhaObjeto(); // Desenha mais um objeto no tamanho original
// LEMBRE-SE, AS TRANSFORMAÇÕES SÃO
// CUMULATIVAS.
Figura 4-6 - Exemplos de Escala
glScalef(0,0.5,0);
DesenhaObjeto(); // Desenha outro objeto com a altura
// diminuída pela metade
glLoadIdentity(); // reinicializa as transformações
glScalef(0,2.0,0);
DesenhaObjeto(); // Desenha o outro objeto com o dobro do tamanho
original
// LEMBRE-SE, AS TRANSFORMAÇÕES SÃO
// CUMULATIVAS.
Figura 4-7 - Exemplos de Re-inicialização de Transformações
Note, entretanto que esta fórmula rotaciona o ponto ao redor do ponto (0,0,0).
Como fazer para rotacioná-lo corretamente ? Uma alternativa é executar os passos da
Figura 4-11.
// *************************************************************
// void PosicUser()
// esta função define a posicão de cada um dos olhos do
// observador
//
// Variáveis usadas:
// DistOlhos: distância entre os olhos do usuário
//
// *************************************************************
void PosicUser(int Olho)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(80,ratio,0.01,200);
switch (Olho)
{
case ESQUERDO: // seta posição para o olho esquerdo
gluLookAt(-DistOlhos/2, 0, 5, 0, 0, 0, 0.0f,1.0f,0.0f);
break;
case DIREITO: // seta posição para o olho direito
gluLookAt(DistOlhos/2, 0, 5, 0, 0, 0, 0.0f,1.0f,0.0f);
break;
}
glMatrixMode(GL_MODELVIEW);
}
O bloqueio (ou desbloqueio) das linhas pares e ímpares neste caso é feito
através da montagem de uma “máscara” no stencil, conforme a Figura 4-13. Esta
máscara é, na verdade, um conjunto de linhas horizontais desenhadas no stencil,
somente nas linhas pares da tela.
// ****************************************************************
// void DesenhaFundo()
// Inicializa o stencil com 1 nas linhas pares
//
// ****************************************************************
void DesenhaFundo(int Largura, int Altura )
{
// *****************************************************************
// void HabilitaOlhoEsquerdo()
//
//
// *****************************************************************
void HabilitaOlhoEsquerdo()
{
glStencilFunc(GL_NOTEQUAL, 1, 1);
glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP);
}
// *****************************************************************
// void HabilitaOlhoDireito()
//
//
// *****************************************************************
void HabilitaOlhoDireito()
{
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP,GL_KEEP, GL_KEEP);
}
// *****************************************************************
//
//
// *****************************************************************
void display( void )
{
// Limpa a tela
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
DefineLuz();
142
PosicUser(ESQUERDO); // posiciona o observador no olho esquerdo
HabilitaOlhoEsquerdo();
DesenhaCena();
PosicUser(DIREITO); // posiciona o observador no olho direito
HabilitaOlhoDireito();
DesenhaCena();
glutSwapBuffers();
}
Figura 4-14 – Exibição de Cenas Estereoscópicas com Stencil Buffer
Existem algumas variantes desta técnica. Liang [LIA94], por exemplo, propôs a
técnica de spotlight, na qual o raio apontador é substituído por um cone de
apontamento (Figura 4-19) facilitando o uso em objetos pequenos e/ou distantes.
Forsberg [FOR96], por sua vez, aprimora este último método possibilitando a alteração
interativa do raio da base do cone, garantindo um maior controle em regiões com muitos
objetos próximos. Este controle é feito baseado na distância entre as mãos do usuário
(Figura 4-20).
#include <windows.h>
#include <gl\gl.h>
typedef struct
{
GLfloat x,y,z;
} Ponto3D;
// ***********************************************
// void calcula_ponto(Ponto3D *p, Ponto3D *out)
//
// Esta função calcula as coordenadas de um ponto no sistema de
// referência do universo (SRU), ou seja, aplica as rotações,
// escalas e translações a um ponto no sistema de referência
// do objeto (SRO).
// ***********************************************
void calcula_ponto(Ponto3D *p, Ponto3D *out)
{
GLfloat ponto_novo[4];
GLfloat matriz_gl[4][4];
int i;
glGetFloatv(GL_MODELVIEW_MATRIX,&matriz_gl[0][0]);
for(i=0;i<4;i++)
{
ponto_novo[i]= matriz_gl[0][i] * p->x+
matriz_gl[1][i] * p->y+
matriz_gl[2][i] * p->z+
matriz_gl[3][i];
}
out->x=ponto_novo[0];
out->y=ponto_novo[1];
out->z=ponto_novo[2];
}
1 0 0
0
0 1 0
0
[10 15 20 1] ∗ = [7 17 12 1]
0 0 1 0
− 3 2 − 8 1
Figura 4-25 – Aplicação de uma Translação a um ponto
152
Caso seja desejável ou necessário, é possível setar "à mão" esta matriz de
transformação. Esta operação manual pode ser feita de três formas:
• usando a função glLoadIdentity(): com esta função a matriz de
transformação converte-se na matriz identidade;
• usando a função glLoadMatrixf(matrix): com esta função é possível
definir uma nova matriz de transformação destruindo-se a matrix anterior;
• usando a função glMultMatrixf(matrix): com esta função é possível
multiplicar a matriz de transformação atual por uma segunda matriz.
// ***************************************************************
// void CriaVinculoPai_Filho()
// ***************************************************************
void CriaVinculoPai_Filho()
{
GLfloat MatInv[4][4];
TemFilho = TRUE;
// calcula a inversa da matriz do Pai
CopyMatrix(MatInv_Pai, Mat_Pai);
M_invert(MatInv_Pai);
// Multiplica a Matriz do filho pela inversa da matriz do pai
M_mult(MatObj, MatInv_Pai); // MatObj = MatObj * MatInv_Pai
}
Figura 4-30 – Cálculo da Transformação do Objeto-Filho
*
Avatar é uma palavra em sânscrito que tem origem na Índia, com o significado de encarnação.
Parece ter sido trazida para o campo da tecnologia pela série de TV Snowcrash, escrita por Neal
Stephenson.
156
O uso de ambientes virtuais colaborativos tem crescido nos últimos anos,
principalmente em face da melhoria das condições providas pelos computadores
pessoais e do aumento dos recursos de rede, cada vez mais baratos, rápidos e confiáveis.
// ****************************************************************
// void SetViewFrustum()
//
//
// ****************************************************************
void SetViewFrustum()
{
float Near, Left, Right, Bottom, Top;
float ViewAngleRad;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Seta o Frustum
glFrustum(Left, Right, Bottom, Top, Near, Far);
glMatrixMode(GL_MODELVIEW);
SetObs(); // posiciona o observador
}
Figura 4-38 – Setando o Volume de Visualização
// **************************************************************
// void SetViewFrustum()
// **************************************************************
void SetViewFrustum()
{
float Near, Left, Bottom, Top, Right, TileWidth, TileHeight;
float ViewAngleRad;
glMatrixMode(GL_PROJECTION); glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
SetObs();
}
Figura 4-40 – Código de Divisão do View Frustum
Para utilizar a placa deve-se conectá-la na porta serial e pressionar seu botão de
reset, para reiniciar o driver. O driver ficará parado até receber os dois primeiros bytes,
que indicarão o período base que a placa utilizará, sendo FFFF o maior período e 0000 o
menor. Depois disso o driver passa a monitorar o funcionamento dos motores. Então,
para cada alteração no comportamento de algum motor deve ser enviado um byte para a
serial. Nesse byte os dois bits mais significativos indicam o motor 00, 01, 10 ou 11, e os
outros indicam a proporção de tempo que o motor deve ficar ligado, sendo que 000000
deixa desligado e 111111 deixa sempre ligado.
Uma vez alterada a freqüência de algum motor, a mesma ficará inalterada até
que o valor seja atualizado novamente.
4.13 Referências
1
Universidade Metodista de Piracicaba (UNIMEP)
2
Escola de Engenharia de São Carlos – Universidade de São Paulo (USP)
ckirner@unimep.com.br, cprov@gwyddion.com
5.1 Introdução
Quando se trabalha com aplicações gráficas relacionadas com cenas imaginárias
ou representativas do mundo real, surgem vários conceitos que podem, à primeira vista,
gerar alguma confusão, envolvendo: multimídia, realidade virtual, realidade aumentada,
realidade misturada, virtualidade aumentada e hiper-realidade.
Além desses conceitos, o ambiente de hardware apropriado para cada
caso pode sofrer variações, impondo requisitos diferentes.
Nas seções seguintes, esses conceitos serão apresentados e os ambientes
de hardware serão discutidos, dando-se uma ênfase especial ao ambiente de hardware
para realidade aumentada, em função de sua importância e do relacionamento desse
assunto com outros capítulos deste livro, particularmente aqueles que abordam o uso do
software de realidade aumentada ARToolKit [ARToolkit, 2004].
169
5.2 Conceitos
5.2.1 Mutimídia
Existem várias definições de multimídia, sendo algumas citadas a seguir:
a) Multimídia é a combinação de várias tecnologias e formas de arte, incluindo texto,
áudio, música, fotografia e vídeo, gerando aplicações novas e maravilhosas [Olsen,
1997].
b) Multimídia é o uso simultâneo de dados em diferentes formas, envolvendo voz,
vídeo, texto, animações, etc [Buford, 1994].
c) Multimídia é a integração, controlada por computador, de textos, gráficos, imagens,
vídeo, animações, áudio e outras mídias que possam representar, armazenar,
transmitir e processar informações de forma digital [Mashall, 2001].
A multimídia pode ainda ser interativa, na medida em que a aplicação
possa responder às ações do usuário.
Normalmente, a multimídia trabalha com imagens pré-gravadas ou
capturadas, atuando no espaço bidimensional e usando grande volume de dados, que,
em geral, costumam ser comprimidos. A grande preocupação da multimídia situa-se na
qualidade da imagem.
Os ambientes computacionais multimídia precisam de processamentos
específicos executados em placas de vídeo e de som, além de canais internos e externos
com alta capacidade de transmissão.
5.2.6 Hiper-realidade
Depois da combinação do real com o virtual, o próximo passo é incrementar esse
ambiente, adicionando novos elementos para facilitar e potencializar a interação do
usuário com os recursos necessários na sua vida diária.
Nessa linha de pensamento, surge o conceito de hiper-realidade [Tiffin,
2001], cuja definição é a seguinte: hiper-realidade é a capacidade tecnológica de
combinar realidade virtual, realidade física, inteligência artificial e inteligência humana,
integrando-as de forma natural para acesso do usuário.
Ambientes de hiper-realidade permitirão que habitantes reais interajam
com habitantes remotamente localizados, bem como com formas de vida imaginárias ou
artificiais, geradas por computador, em um mundo misturado. Esse mundo será
formado por pessoas, animais, insetos, plantas, terrenos, construções e objetos virtuais
inteligentes, todos integrados. Com a visão do mundo misturado, cada usuário poderá
enxergar o que lhe interessa, de acordo com seu perfil ou sua necessidade, e interagir
com os objetos, de forma a ter suas necessidades satisfeitas. Como exemplo, o usuário,
ao caminhar ou dirigir seu automóvel por uma cidade (usando um capacete de visão
direta), poderá fazer solicitações por comandos de voz e ver legendas virtuais nos
prédios e ruas orientando-o ou mostrando opções como: o melhor caminho para chegar
a um destino; restaurantes de determinados tipos ou padrões; entretenimentos
específicos; lojas; supermercados; hospitais; e assim por diante.
174
5.3 Ambiente de Hardware para Realidade Aumentada
Um dos recursos de software, muito usado no desenvolvimento de aplicações de
realidade aumentada, é o ARToolKit. Além de ter seu código aberto e ser gratuito, esse
software está disponível para uso em diversas plataformas de sistemas operacionais,
incluindo o Linux, também aberto e gratuito.
No entanto, para ser utilizado, o ARToolKit precisa ser configurado,
calibrado e ajustado para o ambiente computacional, incluindo as câmeras de vídeo
utilizadas.
Uma alternativa para eliminar a configuração e os ajustes está no
desenvolvimento de uma plataforma de hardware dedicada ao ARToolKit. Essa
plataforma compõe-se de: processador, webcam e monitor ou televisão. Ao ligar-se a
plataforma, ela passa automaticamente a executar a aplicação residente. O uso de uma
memória externa permitirá a troca de aplicações.
Assim, é apresentado em seguida o projeto de uma plataforma de
hardware dedicado, denominada DRAI (Dispositivo de Realidade Aumentada
Interativo) [Providelo, 2004].
5.3.3 Arquitetura
A arquitetura proposta para o DRAI (Figura 5-6) foi projetada para suportar alta
interatividade para usuários leigos, da mesma forma como é feito com os consoles de
videogames, suportando a inserção de novos aplicativos e a interação com novos
periféricos, que expandem não só a interface com o próprio usuário, mas também a
forma de aplicação para a qual ele foi concebido, atingindo o grau de portabilidade
encontrado hoje nos computadores pessoais.
5.4 Conclusões
O conceito de realidade aumentada foi discutido num contexto mais amplo,
incluindo multimídia, realidade virtual e realidade misturada, analisando-se rapidamente
alguns requisitos de hardware para suportar essas aplicações. O Projeto DRAI foi usado
como ambiente para a análise do hardware de aplicações de realidade aumentada.
Para melhorar o desempenho e flexibilidade do Sistema DRAI, algumas
otimizações e ajustes foram sugeridos, além de terem sido mostrados testes de várias
possibilidades de renderização, incluindo técnicas de "raster", textura e fundos virtuais
para representar o ambiente real (espaço de trabalho).
A técnica de fundos virtuais, apesar de eliminar o sinal de vídeo,
continuou propiciando a mesma sensação de presença, com a vantagem de eliminar
situações indesejáveis em alguns casos, como flutuação de iluminação e poluição visual,
ressaltando somente o foco de interesse do trabalho.
A avaliação de desempenho mostrou novas alternativas para otimizar o
processo de visualização, bem como novos caminhos no sentido de viabilizar o uso
deste tipo de recurso em aplicações presentes no cotidiano, com o uso de equipamentos
comumente encontrados no mercado.
A partir dos dados provenientes deste trabalho, será desenvolvida uma
pesquisa mais detalhada, seguida por experimentos mais profundos, com o objetivo de
implementar estas soluções em situações reais. Além disso, está-se produzindo material
consistente, somado ao de outros grupos de pesquisa no contexto mundial, como o
OpenTrack [OpenTrack, 2001], usufruindo das possibilidades oferecidas pela adoção de
Software Livre como base do desenvolvimento.
1
Luís Augusto Consularo, 1Nivaldi Calonego Júnior Carlos A. Dainese1, Tania R.
Garbin1, Claudio Kirner1, Jorge Trindade2 , Carlos Fiolhais2
1
Programa de Pós Graduação em Ciência da Computação
Faculdade de Ciências Matemáticas da Natureza e Tecnologia da Informação
Universidade Metodista de Piracicaba (UNIMEP)
Rodovia do Açucar, Km 156 – 13.400-911 - Piracicaba – SP
2
Centro de Física Computacional - CFC, Universidade de Coimbra - UC, Portugal
{cdainese, ckirner, trgarbin}@unimep.br,
{alberto, tcarlos}@teor.fis.uc.pt
6.1 Introdução
Este documento apresenta o pacote ARToolKit, enfatizando a instalação e o uso.
O ARToolKit é uma biblioteca em linguagem C que permite aos programadores
desenvolver aplicações de Realidade Aumentada. Realidade Aumentada (RA) é a
sobreposição de imagens virtuais de computação gráfica sobre cenas do mundo real.
Esse modelo de interface tem mostrado potencial para muitas aplicações em pesquisa
industrial e acadêmica.
Nos tutoriais do ARToolKit [KATO 2002], os autores encorajam os leitores a
enviar comentários e questões sobre o ARToolKit e relatos de erros e falhas para
Hirokazu Kato (kato@sys.im.hiroshima-cu.ac.jp) ou para Mark Billinghurst
(grof@hitl.washington.edu). Há também uma lista de discussões que é usada para
difundir notícias sobre novas versões do ARToolKit, correções e aplicações que a
comunidade que trabalha com ARToolKit está desenvolvendo. Para assinar esta lista,
envie uma mensagem para majordomo@hitl.washington.edu com as palavras "subscribe
artoolkit" no corpo da mensagem. Depois disso, qualquer mensagem que você enviar
para artoolkit@hitl.washington.edu será enviada a todos os membros desta lista de
discussões. As listas são muito úteis para encontrar dicas sobre o uso das funções, sobre
189
equipamentos que estão sendo utilizados pelos desenvolvedores †,‡ e ainda sobre novas
versões e revisões do pacote.
Atualmente, o ARToolKit executa nas plataformas SGI Irix§, PC Linux**, PC
Windows 95/98/NT/2000/XP†† e Mac OS X‡‡. Há versões separadas para cada uma
destas plataformas. A funcionalidade de cada versão do kit é a mesma, mas o
desempenho pode variar conforme as diferentes configurações de hardware. Na
plataforma SGI, por exemplo, o ARToolkit foi testado apenas para computadores SGI
O2, contudo deve também executar nos computadores SGI atuais que contém com
entradas de vídeo.
A versão atual do ARToolKit oferece suporte para realidade aumentada com
visão direta por vídeo ou visão direta óptica. A RA por visão direta por vídeo é aquela
cujas imagens virtuais são sobrepostas às imagens de vídeo ao vivo adquiridas do
mundo real. A outra opção é a RA por visão direta óptica, na qual modelos de
computação gráfica (os objetos virtuais) são sobrepostos diretamente às imagens do
mundo real percebidas pelo sujeito. A RA por visão direta requer um dispositivo HMD
(Head Mounted Display) e exige também um procedimento de calibração da câmera que
adquire imagens do mundo real [KATO 2002; KATO & BILLINGHURST 1999].
Estes procedimentos podem variar entre algo mais simples (que será mostrado na seção
6.3), quando a visão direta é por vídeo, ou mais complexo quando por visão direta
óptica.
Uma das partes mais trabalhosas no desenvolvimento de uma aplicação em RA é
calcular precisamente o ponto de vista do usuário em tempo-real para que imagens
virtuais sejam alinhadas com precisão às imagens dos objetos do mundo real
[HARTLEY & ZISSERMAN 2003]. O ARToolKit usa técnicas de visão computacional
para calcular a posição no espaço real da câmera e sua orientação em relação aos cartões
marcadores, permitindo ao programador sobrepor objetos virtuais aos cartões. O pacote
inclui bibliotecas de rastreamento e disponibiliza o código fonte completo, tornando
possível o transporte do código para diversas plataformas ou adaptá-los para resolver as
†
http://onyx.sys.im.hiroshima-cu.ac.jp/people/kato/
‡
http://www.hitl.washington.edu/people/grof/
§
http://www.sgi.com/products/software/irix/
**
http://www.linux.org/
††
http://www.microsoft.com/windows
‡‡
http://www.apple.com/macosx/
190
especificidades de suas aplicações. Várias aplicações simples são fornecidas com o
ARToolKit para que programadores comecem rapidamente a desenvolver suas
aplicações. Além disso, o ARToolKit é livre para uso em aplicações não-comerciais e é
distribuído com código aberto sob licença GPL. Os interessados no uso do ARToolKit
para o desenvolvimento de aplicações comerciais devem entrar em contato com
Hirokazu Kato† ou com Mark Billinghurst‡.
O ARToolKit é uma novidade em termos de modelo e programação de
interfaces, em que alguns tutoriais apresentados pelos autores do ARToolKit e outros
interessados [BERRE et al. 2002; KATO, BILLINGHURST & POUPYREV 2000; KE
2000] são as principais fontes de informação. Assim, a elaboração de um texto que trata
de mostrar os elementos necessários ao desenvolvimento desse tipo de aplicação exige
uma organização de texto que é o resultado da compilação desses tutoriais e de
experimentações dos próprios autores deste texto, e está distribuído em cinco sessões.
A primeira apresenta a instalação do ARToolKit. A segunda trata da
programação de aplicações com o ARToolKit, explorando os exemplos mais simples de
execução, que são distribuídos com o Kit, e detalhando os passos do desenvolvimento
de uma aplicação típica. A terceira sessão apresenta o procedimento necessário à
calibração de câmeras, usando os utilitários disponíveis no ARToolKit. Os utilitários
podem ser usados isoladamente, pois seus resultados são armazenados em arquivos que
podem ser lidos por outras aplicações. A quarta sessão descreve as bibliotecas,
enfocando as funções mais importantes utilizadas para implementar aplicações com o
ARToolKit em computadores PC-compatíveis com Windows. A quinta e última sessão
discute algumas limitações deste tipo de implementação de RA e mostra também
algumas perspectivas para esta biblioteca.
§§
http://www.ptgrey.com/
***
http://www.ims.tuwien.ac.at/~thomas/artoolkit.php
192
a aquisição das imagens seja mais rápida, possibilitando o aumento da taxa de
processamento dos quadros. O autor alega que o suporte ao DirectShow tem um
desempenho em torno de 3 vezes superior ao desempenho das versões com OpenGL.
A versão 2.68 é a mais recente e tem versões disponíveis para Windows e para
Linux/SGI/MacOSX. Ainda não oferece suporte ao VRML e está disponível em
http://www.eden.net.nz/phil/develop/artoolkit/. Esta versão corrige alguns problemas da
versão 2.65, que invertia as coordenadas de altura nas imagens adquiridas das câmeras.
Ainda há implementações independentes do ARToolKit para Matlab
(http://mixedreality.nus.edu.sg/ software.htm), uma outra que conecta as bibliotecas do
ARToolKit com Java, o JARToolKit††† [GEIGER et al. 2002], e também uma iniciativa
de software para aplicações de RA para PDAs da linha iPaq‡‡‡ [WAGNER &
SCHMALSTIEG 2003].
A Erro! A origem da referência não foi encontrada. ilustra um diagrama
resumindo as versões convencionais disponíveis do ARToolKit. As versões PC, SGI e
Linux do ARToolKit estão disponíveis gratuitamente em
http://www.hitl.washington.edu/research/shared_space/download/.
Este tutorial descreve a instalação da versão 2.65 com VRML, que está
disponível em http://www.hitl.washington.edu/artoolkit/download.htm.
†††
http://www.c-lab.de/jartoolkit
‡‡‡
http://studierstube.org/handheld_ar
193
Esta versão do ARToolKit foi compilada e testada em PCs executando Windows
XP com instalação das câmeras QuickCam Express da Logitech§§§ e Webcam 3 modelo
da Creative Labs**** conectadas a portas USB†††† versão 1.1 (40 Mbps). O ARToolKit
usa ou o Vision SDK (existe uma distribuição do ARToolKit específica para o Vision
SDK) ou o DirectX 9‡‡‡‡ da Microsoft (segundo a página do ARToolKit, da versão 8 em
diante) para que não haja motivo de incompatibilidade entre câmeras e placas de
aquisição de vídeo que sejam suportados pelo Vision SDK, Video for Windows ou pelo
WDM (Windows Driver Model) da Microsoft. Os códigos-fonte foram compilados com
o MS Visual C++ 6.0 e o MS Visual C++ 7.0 (ambos com instalação do Visual
Studio§§§§).
§§§
http://www.logitech.com/index.cfm/support/products/details/US/EN,CRID=1795,CONTENTID=6041
****
http://www.creative.com/products/product.asp?prodid=15
††††
http://www.usb.org/home
‡‡‡‡
http://www.microsoft.com/directx
§§§§
http://msdn.microsoft.com/vstudio
194
Figura 6-1 - Versões do ARToolKit.
Os programas de exemplo incluídos com o ARToolKit, todos, utilizam a
biblioteca GLUT de interface com o OpenGL. Portanto, para compilar estes programas,
deve estar instalada a versão 3.6 ou alguma versão mais atualizada. As bibliotecas
GLUT estão disponíveis em http://opengl.org/resources/libraries/glut.html. Para
economizar tempo, copie os diretórios do OpenGL nos diretórios do ARToolKit. O
diretório GL com os protótipos (arquivos com extensão .h) do OpenGL no diretório
include do ARToolKit, o arquivo de biblioteca glut32.lib no diretório lib e o
glut32.dll no diretório bin. Se existe uma instalação das bibliotecas em outro
diretório, com os caminhos todos definidos na configuração de projetos do Visual C,
então isto não é necessário. Para definir estes caminhos do Visual C, é necessário abrir o
arquivo do workspace de sua aplicação, selecionar no projeto de sua aplicação o item
Project e, então, a opção Settings. Surgirá uma caixa de diálogo com várias
configurações. Você precisará das opções C/C++ e Link. Na opção C/C++ você poderá
adicionar novos diretórios de protótipos selecionando a opção Preprocessor em
Category. Na caixa de texto Additional include directories, inclua o diretório de sua
preferência. Na opção Link, selecione Input em Category. Na caixa de texto Additional
library path, inclua os diretórios de bibliotecas de sua preferência, isto é, aqueles nos
quais você incluiu os arquivos com extensão .lib.
195
#pattern 1
VRML Wrl/bud_B.dat
Data/patt.hiro
80.0
0.0 0.0
#pattern 2
VRML Wrl/snoman.dat
Data/patt.kanji
80.0
0.0 0.0
(c)
arInitCparam( &cparam );
printf("*** Camera Parameter ***\n");
arParamDisp( &cparam );
/* abre a janela grafica */
argInit( &cparam, 1.0, 0, 0, 0, 0 );
/* cparam, zoom, fullflag, xwin, ywin, hmd */
Código 7 – Inicialização dos parâmetros e sua exibição na tela.
Cabem alguns comentários relativos aos parâmetros de argInit. O primeiro
parâmetro é na verdade a estrutura que contém os parâmetros da câmera. O segundo
parâmetro é o zoom, isto é, o quanto se quer aumentar a imagem de aquisição para ser
exibida na tela. Lembre-se que o zoom aumenta o tamanho do pixel. O terceiro
parâmetro é um sinal indicando se a janela gráfica deve cobrir toda a tela (1, neste caso)
ou se deve abrir uma janela sobre a área de trabalho (zero, neste caso). Os outros dois
parâmetros são os tamanhos de eventuais extensões da tela contendo a imagem da
câmera e, finalmente, o último parâmetro indica se a inicialização deve considerar que o
display é um HMD, isto é, um capacete.
A atribuição ao parâmetro arImageProcMode =
AR_IMAGE_PROC_IN_FULL indica ao ARToolKit para processar as imagens com o
tamanho completo e original adquirido da câmera (veja o Código 8). Isto pode tornar o
processamento muito lento, dependendo do resultado desejado. Por isso, é possível
reduzir a resolução da imagem a ser processada fazendo arImageProcMode =
AR_IMAGE_PROC_IN_HALF. Esta configuração deixa o processamento mais rápido,
porém menos preciso.
206
arImageProcMode = AR_IMAGE_PROC_IN_FULL;
// arImageProcMode = AR_IMAGE_PROC_IN_HALF;
argDrawMode = AR_DRAW_BY_TEXTURE_MAPPING;
// argDrawMode = AR_DRAW_BY_GL_DRAW_PIXELS;
Código 8 – Configurações dos parâmetros arImageProcMode e argDrawMode.
O parâmetro argDrawMode = AR_DRAW_BY_TEXTURE_MAPPING
permite desenhar os pixels do vídeo como um mapeamento de texturas (veja o Código
8). Se a placa gráfica do computador tiver esta capacidade implementada, o
processamento do vídeo ficará bem mais rápido. Com argDrawMode =
AR_DRAW_BY_GL_DRAW_PIXELS os pixels da imagem são desenhados
individualmente, e portanto, para equipamentos mais novos é menos recomendado.
Agora é o momento de carregar os dados VRML, isto é, os objetos 3D
representados em arquivos cujo nome é passado em model_name (veja o Código 9).
Nesta chamada de função retorna ainda uma estrutura descrevendo este objeto e o
número de objetos que devem ser lidos.
6.2.7.2 mainLoop
Esta é a rotina na qual a maior parte das chamadas de função do ARToolKit. Ela
contém o código correspondente aos passos 2, 3, 4 e 5 da aplicação.
Primeiro o quadro do vídeo é capturado usando a função arVideoGetImage
(veja o Código 12).
argDrawMode2D();
/* mostra a imagem na tela como um mapa de bits
argDispImage( dataPtr, 0, 0 );
/* captura o próximo quadro de vídeo */
arVideoCapNext();
Código 13 – Exibição da imagem e captura.
Então os quadrados que contenham os marcadores corretos na imagem
capturada devem ser detectados. Para isso são passados os parâmetros: dataPtr, que é
o ponteiro indicando o início da memória de vídeo; thresh que é o limiar para separar
o que é fundo de um eventual objeto; marker_info, que é a estrutura que contém
informações sobre o marcador e; marker_num que é um valor contendo o número de
marcadores detectados. Um retorno negativo indica uma falha que deve ocasionar a
saída da aplicação (veja o Código 14).
208
if ( object[i].visible == 0 ) {
arGetTransMat( &marker_info[k],
object[i].marker_center,
object[i].marker_width,
object[i].trans);
}
else {
arGetTransMatCont(&marker_info[k], object[i].trans,
object[i].marker_center, object[i].marker_width,
object[i].trans);
}
209
object[i].visible = 1;
Código 16 – Chamadas das funções para obter o posicionamento e a pose da
câmera.
Finalmente, os objetos virtuais podem ser desenhados na placa usando a função
draw (veja o Código 17).
6.2.7.3 cleanup
A função cleanup é chamada para finalizar o processamento de vídeo e
desconectar o dispositivo de vídeo, liberando-o para outras aplicações. Isto acontece
quando se chama as rotinas arVideoCapStop(), arVideoClose() e
argCleanup().
#padrao 1
cube
Data/patt.hiro
80.0
Código 19 – Exemplo de estrutura que define o padrão do marcador e seu
objeto virtual.
Observe que as linhas que começam com um caracter # são linhas de comentário
e são ignoradas pelo analisador do arquivo.
Para mudar os padrões que são reconhecidos, o nome de arquivo do padrão (no
exemplo, patt.hiro) deve ser substituído pelo nome do arquivo com o padrão
211
desejado. Estes arquivos de padrões pré-definidos são simplesmente um conjunto de
exemplos de imagens do padrão desejado. O programa que cria estes arquivos de
padrões pré-definidos é chamado mk_patt e fica no diretório bin. O código fonte do
mk_patt é o arquivo mk_patt.c, que fica no diretório util.
Para criar um novo padrão pré-definido, primeiro edite em um editor de imagens
o arquivo blankPatt.gif, localizado no diretório patterns. É apenas um
quadrado preto com um quadrado branco no meio. Então crie uma imagem em preto e
branco do padrão desejado que caiba no meio deste quadrado e imprima-o. Os melhores
padrões são assimétricos e sem muitos detalhes. A Figura 6-9 mostra alguns padrões
possíveis. Insira o novo padrão no centro do quadrado vazio.
Figura 6-9 – Exemplos de padrões que podem ser usados como marcadores.
Uma vez confeccionado o novo padrão, vá para o diretório bin e execute o
programa mk_patt. Será pedido para que você entre com um nome de arquivo de
parâmetros de câmera (veja Figura 6-10). Entre com o nome do arquivo
camera_para.dat. Este é o nome default para o arquivo de parâmetros de câmera.
O programa abrirá então uma janela de vídeo conforme mostra a Figura 11.
Coloque o padrão a ser treinado em uma superfície plana em condições de
iluminação similares àquelas que existirão quando a aplicação de reconhecimento estará
executando. Então, coloque a câmera de vídeo apontando diretamente para o padrão e
vire-o até que um quadrado com dois lados vermelhos e dois lados verdes apareça em
212
torno do padrão (veja a Figura 6-11). Isto indica que o software mk_patt encontrou o
quadrado em torno do padrão de teste. A câmera deve ser rotacionada até que os lados
vermelhos do quadrado estejam no topo e à esquerda do quadrado na imagem de vídeo,
conforme mostra a Figura 11. Uma vez que o quadrado encontrado esteja orientado
corretamente clique o botão esquerdo do mouse. Será então pedido um nome de arquivo
para o padrão. Fornecido o nome do arquivo, é gerada uma imagem em mapa de bits do
padrão que é criado e copiado para este arquivo. Este padrão é então usado na
comparação de padrões do ARToolKit. Outros podem ser treinados simplesmente
apontando a câmera para novos padrões e repetindo o processo, ou clicando o botão
direito do mouse para sair da aplicação. É preciso copiar os novos arquivos de padrões
no diretório bin/Data antes de usá-los. É preciso também que se edite o arquivo
vrml_data para associar os padrões com os objetos virtuais.
6.2.9.1 ExView
A aplicação ExView (veja a Figura 6-12) permite que você tenha uma visão
externa da câmera, como se a câmera estivesse sendo rastreada. Isto é útil para verificar
213
a acurácia do rastreamento. Esta aplicação permite também mostrar como as bibliotecas
do ARToolKit podem ser usadas para encontrar uma representação quaternion da
orientação do ponto de vista. No exemplo simpleVRML, o ponto de vista da câmera
foi definido usando transformações matriciais. Isto é difícil de se fazer corretamente
para aplicações 3D que usem representações por quaternion, que é o caso do VRML. O
ARToolKit também suporta a saída de quaternions, permitindo que rotinas de
rastreamento de outros pacotes de renderização sejam também utilizadas.
6.2.9.2 Simple
O simple.exe é o programa mais simples do ARToolKit. Na verdade ele não
interage com o VRML. Isto é útil quando há algum problema do qual se suspeita
alguma relação com o grafo de cena VRML. Se o simple executar e o simpleVRML
214
não, isto é uma indicação de que há algum problema na configuração dos objetos ou no
próprio renderizador do grafo de cena VRML. A Figura 6-13 mostra um instantâneo do
simple.
(a) (b)
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
Figura 6-17 – Saída de texto enquanto cada ponto estiver sendo desenhado.
Uma vez encontrados todos os 24 pontos da imagem, pressione botão esquerdo
do mouse novamente. Isto armazenará a posição dos pontos e descongelará a imagem de
vídeo. A saída ilustrada na Figura 6-18 mostra a saída da tela depois disso, isto é, a
posição capturada de cada um dos pontos, bem como suas respectivas posições na
grade.
218
(a) (b)
Figura 6-24 – A linha se torna azul e surge uma outra linha branca.
Uma vez que a última linha horizontal tenha sido ajustada, uma linha branca
vertical aparecerá e o processo deverá ser repetido para as linhas verticais. A primeira
linha branca vertical deverá ser ajustada sobre a linha da grade mais à esquerda e as
outras linhas se ajustarão da esquerda para a direita (ver Figura 6-25).
inter_coord[k][j][i+7][0] = 40.0*i;
inter_coord[k][j][i+7][1] = 40.0*j;
inter_coord[k][j][i+7][2] = 100.0*k;
Código 20 – Trecho do programa calib_cparam.c para alterar o distanciamento
dos padrões de calibração.
Neste código, 40 é a distância entre as grades e entre os pontos, e 100.0 é a
distância padrão em que devem ser afastados os padrões a partir da câmera, a cada vez.
O número de medidas que devem ser tomadas pode ser alterado na variável loop_num
(veja Código 21).
225
*loop_num = 5;
Código 21 – Variável que deve ser alterada para mudar o número de distâncias
do padrão de calibração até a câmera.
typedef struct {
int area;
int id;
int dir;
double cf;
double pos[2];
double line[4][3];
double vertex[4][2];
} ARMarkerInfo;
Código 22 – Estrutura de descrição de marcadores.
6.4.2.2 arLoadPatt
6.4.2.2.1 Função: Carregar o mapa de bits do padrão especificado no arquivo
em filename, no vetor de padrões para uso posterior pelas rotinas de
detecção de marcadores.
6.4.2.2.2 Variável: *filename – nome do arquivo que contém o mapa de bits
a ser carregado
6.4.2.2.3 Retorno: o número do padrão carregado ou –1 em caso de falha.
6.4.2.4 arGetTransMat
6.4.2.4.1 Função: calcular a transformação entre um marcador detectado e a
câmera real, isto é, a posição e orientação da câmera relativas à
marcação de rastreamento.
6.4.2.4.2 Variáveis: ARMarkerInfo *marker_info – a estrutura que
contém os parâmetros para o marcador para o qual a posição e
orientação da câmera será relativa. Essa estrutura é encontrada usando
arDetectMarker.
double pos3d[4][2] – posições físicas dos vértices do marcador.
arGetTransMat assume que o marcador está no plano xy, e que o eixo z
está apontando para baixo do plano do marcador. Deste modo, as posições
dos vértices podem ser representadas em coordenadas 2D, ignorando a
informação do eixo z. A ordem das posições dos vértices são especificadas
no sentido horário. Por exemplo, para um marcador com lado medindo 50
mm e com a origem das coordenadas do marcador no seu centro:
6.4.2.5 arSavePatt
6.4.3.1 arVideoOpen
6.4.3.1.1 Função: abre o driver de vídeo para tentar encontrar todos os
dispositivos de vídeo registrados no Windows
6.4.3.1.2 Variáveis: nenhuma
6.4.3.1.3 Retorno: zero – sucesso, -1 se o driver de vídeo não puder ser aberto.
231
6.4.3.2 arVideoClose
6.4.3.2.1 Função: é uma função que precisa ser chamada para finalizar a
captura de vídeo.
6.4.3.2.2 Variáveis: nenhuma
6.4.3.2.3 Retorno: zero – se finalizou com sucesso, -1 caso contrário.
6.4.3.3 arVideoInqSize
6.4.3.3.1 Função: retorna tamanho do quadro de vídeo capturado.
6.4.3.3.2 Variáveis: int *x, *y – ponteiros para largura (*x) e altura
(*y) da imagem capturada.
6.4.3.4 arVideoGetImage
6.4.3.4.1 Função: capturar um único quadro de vídeo
6.4.3.4.2 Variáveis: nenhuma
6.4.3.4.3 Retorno: retorna um ponteiro para o quadro de vídeo capturado ou
NULL se um quadro não puder ser capturado.
6.6.1 Introdução
Os sistemas que permitem maior interatividade entre o homem e a máquina,
tornam-se cada vez mais utilizados em todos os setores, pois enriquece a relação
homem-máquina e possibilita um controle maior do usuário frente às tarefas.
Nesse sentido, os sistemas virtuais possibilitam experiências com a sensação de
presença, através da integração dinâmica de diferentes modalidades perceptivas, que
envolvem imagens, sons, tato, etc. Assim, torna-se possível a capacidade de manipular,
relacionada às reações sensório-motora em tempo real [Lévy, 1999].
Por outro lado, os ambientes educativos devem oferecer condições favoráveis à
criação, comportando-se como um espaço agradável e permitindo aplicações práticas e a
relação do conhecimento com experiências, necessidades e realidade do aluno (usuário).
De maneira geral, a construção do conhecimento dá-se através da reflexão, da
crítica, da identificação e da busca de resoluções dos problemas, propiciando situações
que determinem o desafio - papel importante na formação de atitudes [Valente. 1991,
2001]. Os ambientes podem contribuir, estimulando a curiosidade e auxiliando no
desenvolvimento da autonomia.
234
A aprendizagem ocorre, quando o indivíduo está engajado e utiliza de forma
consciente estratégias de resolução de problemas para a construção significativa. Não se
deve questionar o valor da instrução, mas é importante a descoberta de novos
conhecimentos, através da relação do novo com a experiência anterior.
Assim, a possibilidade de interação entre objetos reais e virtuais, que ocorre
através da Realidade Aumentada (RA), pode oferecer ao usuário maiores informações
sensitivas, facilitando a associação e a reflexão sobre a situação. Os sistemas de
Realidade Aumentada permitem que o usuário decida sobre os ambientes, compondo
cenas com imagens de objetos tridimensionais geradas por computador misturadas com
imagens reais, aumentando as informações do cenário e oferecendo condições para a
imersão no ambiente criado. A principal característica destes ambientes é que as
informações do mundo real são utilizadas para criar um cenário incrementado com
elementos gerados por computador [Dainese, 2003].
.
Figura 6-29 – Parte superior do quebra-cabeças
Figura 6-33 - Sobreposição do modelo virtual ao objecto real tomando como exemplo a
orbital 2p x.
A webcam capta o padrão pré-definido e converte-o para um formato binário
para reconhecimento. O modelo da orbital associado ao padrão é identificado e é
calculada a posição e a orientação do marcador relativamente à webcam. Finalmente
efetua-se o rendering do modelo virtual no vídeo que aparecerá sobreposto ao
respectivo marcador.
245
6.6.8 Conclusões
Em atividades educativas com uso de recursos computacionais, é necessário o
planejamento adequado do uso de tecnologias em software e hardware, que possibilitam
explorar: a carga cognitiva do usuário, o senso de observação, a atenção, a exploração e
a retenção de informações, utilizando elementos de percepção visual, tátil e auditiva.
Para isso, é necessário desenvolver sistemas computacionais que apresentem: 1)
facilidade na identificação dos componentes; 2) adaptabilidade ao nível do usuário; 3)
adequação dos programas às necessidades curriculares; 4) existência de recursos
motivacionais; 5) posssibilidade constante de alterações do sistema (inclusão de novos
elementos); 6) fornecimento de retorno; 7) integração do sistema com outros recursos;
8) capacidade de armazenamento de respostas; 9) registro de tempo de resposta e
latência e 10) liberdade de manipulação e navegação - controle sobre os elementos.
Uma das vantagens do uso da Realidade Aumentada é a possibilidade de
criar interfaces multisensorias, sem a necessidade de periféricos de alto custo, como
óculos e capacete de visualização, luva, caverna (CAVE), utilizados em experimentos
de realidade virtual. Com isto, é possível o desenvolvimento de ambientes relevantes e
interessantes para o usuário, utilizando materiais acessíveis e disponíveis nos
laboratórios de informática das escolas.
Considerando a importância do processo de construção do conhecimento
para a formação do indivíduo, os ambientes de realidade aumentada podem contribuir
de forma a oferecer condições de experimentar, criar, descobrir, sem instruções
previamente elaboradas ou definidas pelo sistema, pois o ambiente funciona como
mediador, auxiliando o educando na descoberta e construção do novo.
A construção do ambiente gráfico ficou muito mais simplificada e rápida,
reduzindo-se exclusivamente ao que é essencial: os modelos que se pretendem explorar
no ensino e aprendizagem.
A tecnologia envolvida desempenha um papel muito menos dominante e
distrativa para o aluno. Tal como referido por Cornu [Cornu, 1995], “as novas
tecnologias apenas estarão integradas no ensino quando elas não forem ferramentas
247
suplementares mas sim quando elas se tornarem ‘naturais’ e ‘invísiveis’ como o
telefone, o televisor e as calculadoras de bolso. As novas tecnologias só estarão
realmente integradas na pedagogia quando, dessa união, surgirem novos métodos
pedagógicos bem sucedidos”.
CAREY, R. & BELL, G. The Annotated VRML 2.0 Reference Manual. Addison-
Wesley, 504pp, 1997.
249
DAVIS, L., CLARKSON, E. & ROLLAND, J.P. Predicting Accuracy in Pose
Estimation for Marker-based Tracking. In: Proceedings of the Second IEEE and
ACM International Symposium on Mixed and Augmented Reality (ISMAR '03),
Tokyo, Japan, p28-35, 2003.
KE, X. Tutorial: Installation of the ARToolkits and the relevant hardware (Version
2.11), 2000. (http://www.ece.nus.edu.sg/stfpage/eleadc/ARToolkit-tutorial-
v2.pdf).
OWEN, C.B., XIAO, F. & MIDDLIN, P. What is the best fiducial? In: Proceedings
of The First IEEE Augmented Reality Toolkit International Workshop, p124,
2002.
(1) Para cima e para baixo (2) Girar para direita e para esquerda
(3) Girar para frente e para trás (4) Girar ao redor do próprio eixo
7.4.2.1 Criação
Você já está pronto para aprender a criar seu próprio mundo do zero. Para isso
você precisa de um mundo novo e limpo para começar. Selecione New World (Novo
Mundo) a partir do menu File (Figura 7-27).
269
7.4.2.4 Mudanças
As mudanças realizadas na cena de abertura podem ser desfeitas ou refeitas
utilizando o botão undo ou o botão redo, ambos mostrados na Figura 7-38.
Com essa palavra-chave você pode mover ou girar qualquer objeto do ponto de
vista de outro objeto. Por exemplo, podemos fazer um objeto se mover na direção de
outro apenas acrescentando essa palavra-chave ao comando.
Por exemplo, temos, horse.move(forward, 1, asseenby = windmill).
Assim, o cavalo irá se mover na direção do moinho.
276
7.5.1.4 A dica EachFrame
Como palavras-chave, você pode usar dicas para dar aos comandos mais
detalhes. A dica EachFrame serve para que os objetos continuem fazendo um
determinado comando tão freqüentemente quanto possível.
Por exemplo, bunny.head.pointat(helicopter, eachframe).
Assim, a cabeça do coelhinho continuará olhando para o helicóptero até o final
do roteiro.
7.5.2 Interação
Os eventos dizem ao Alice o que fazer e quando fazer. Esses eventos podem ser
um clique do mouse ou o pressionar de uma tecla do teclado. Dessa, forma o mundo
Alice estará interagindo com o usuário.
Vejamos o seguinte exemplo de evento: queremos que quando o mundo se inicie
alguns pingüins comecem a cantar uma pequena música. O evento fica da seguinte
maneira (Figura 7-39):
7.6 Ajuda
Para aprender mais sobre Alice e o que é possível fazer, sugerimos os seguintes
locais, todos em inglês:
Tutorial Interativo
O próprio programa Alice possui um tutorial interativo. Basta clicar em “Start
the Tutorial” na caixa “Welcome to Alice”. Você também pode escolher qual
tutorial deseja fazer escolhendo diretamente um dos quatro nos botões abaixo do
botão “Start the Tutorial”.
280
Seção de Documentação Online
Esta seção contém conselhos para usuários avançados de Alice que completaram
o tutorial interativo e estão procurando por novas idéias e desafios.
Menu Alice de Help
Este contém o manual de referência Alice, uma fonte exaustiva de informação
sobre funções e opções da Alice. Aqui você também encontrará exemplos e
demonstrações que poderá usar para começar seus trabalhos.
Lista de correspondência: alice-users@cs.cmu.edu
A lista de correspondência é a melhor maneira de usuários Alice ajudarem
outros usuários. Os criadores de Alice também lêem esta lista, inserindo algumas
respostas e comentários quando necessário.
objeto.RespondTo( AoQuêResponder,
RespondTo (ResponderA)
ComoAgir)
AsSeenBy (ComoVistoPor) Qualquer objeto no mundo. Você pode mover e girar qualquer
objeto como ele é visto por outro.
Speed (Velocidade) Qualquer número. Para movimeno, este número é metros por
281
segundo, para girar, rotações por segundo.
8.1 Histórico
Uma das principais dificuldades quando se trata da programação de jogos de
computador é a simulação da física aos objetos do ambiente virtual. Colisões, frenagem,
efeitos de gravidade são assuntos até certo ponto complexos de serem tratados pelos
desenvolvedores.
Para suprir tal necessidade, em 2001, surgiu a O.D.E. (Open Dynamics Engine).
A O.D.E. é uma biblioteca open-source, multiplataforma, desenvolvida por Russel
Smith, voltada à simulação de objetos rígidos articulados e dinâmicos. Ela tem um
enfoque ao nível de mercado, demonstrado pela sua qualidade e facilidade em trabalhar
junto com APIs C/ C++ e Delphi.
Ela disponibiliza como principais características à manipulação de fenômenos
físicos como articulação de corpos, gravidade, detecção de colisão e fricção de objetos
em mundos virtuais. Além disto, é possível simular comportamentos tais como uma
prensa hidráulica em operação, motores elétricos, suspensão de veículos, enfim, tudo o
que envolva a física. Outro exemplo prático de sua manipulação são os jogos de corrida,
que apresentam elementos como frenagem, aceleração, atrito e movimentações laterais
presentes em qualquer ação do usuário. Também permite também considera forças,
torques, massa e energia nos corpos, dando mais realismo ao produto em questão.
Assim, este tutorial visa apresentar a comunidade científica um breve apanhado
dos recursos desta biblioteca, associando seu trabalho juntamente com a biblioteca
GLScene, que incorporou seus recursos na versão 2.0, com contribuição de Mattias
Fagerlund.
A estrutura deste material está disposta em uma breve explicação de sua
instalação, seguido da descrição de suas características, acompanhada de exemplos
demonstrativos (com e sem GLScene), finalizando com dicas e procedimentos para a
construção de um ambiente ideal utilizando a física em seus objetos 3D.
283
8.2 Instalação
A seguir, são apresentados os modos de instalação da biblioteca O.D.E. para
desenvolvedores C/ C++ e Delphi, em suas devidas plataformas:
Download:
• http://www.ode.org/
Passos de Instalação:
1º Passo: Descompacte o arquivo da O.D.E. em um diretório específico;
2º a 4º passo (opcional – para Windows): se você está no Windows e usa o MS Visual
C, você pode usar o workspace e os arquivos de projeto do subdiretório da distribuição
do VC6;
2º Passo: Utilize o GNU Make;
3º Passo: Edite as configurações no arquivo config/user-settings. A lista de plataformas
suportada aparece ali;
4º Passo: Dê um make para configurar e compilar O.D.E. e programas de testes
gráficos. Tenha certeza de que você está usando a versão correta do GNU Make. A
ordem de make segue abaixo:
make configure: cria o arquivo de configuração include/ode/config.h
5º Passo: Para instalar a biblioteca O.D.E. nas suas IDE’s, você deve copiar os
diretórios /lib e /include para o lugar da sua suíte de desenvolvimento (por exemplo):
include/ode/ --> /usr/local/include/ode/
lib/libode.a --> /usr/local/lib/libode.a
Download:
• http://www.glscene.org/
Passos de Instalação:
1º Passo: Descompacte a biblioteca num diretório à parte, dentro do path do Delphi,
preferencialmente, (\arquivos de programas\ borland\ delphi\ glscene);
2º Passo: Em seguida, copie o arquivo “glscene.inc” para dentro do diretório \LIB do
Delphi;
3º Passo: Também copie os arquivos com extensão “dll” para dentro do diretório \BIN
do Delphi;
4º Passo: Acesse o diretório do Delphi e, dentro da pasta criada para a GLScene,
execute os arquivos com extensão “dpk”. Compile e instale-os, na ordem (como
exemplo, Delphi 7):
• GLScene7.dpk (biblioteca padrão);
• GLS_sld7.dpk (plug-in para áudio);
• GLS_fmod7.dpk (plug-in para áudio);
• GLS_bass7.dpk (plug-in para áudio).
• GLS_ode7.dpk (plug-in para a O.D.E.).
5º Passo: Por fim, copie todos os arquivos com extensão “dcu” gerados na compilação
para um diretório chamado “DCU”, dentro do diretório da GLScene. Após isto,
configure o path destes arquivos no menu Tools, opção: \Enviroment Options\Library
Path, adicionando um novo caminho.
285
Figura 8-1- À esquerda o robô no mundo real e a direita a simulação com utilização da
O.D.E.
No material, abordaremos exemplos em alto nível de abstração. Caso prefira
acompanhar este tutorial associando suas construções a exemplos utilizando linha de
código, utilize como material auxiliar o Tutorial O.D.E., escrito pelo seu criador,
disponível em http://www.ode.org/.
Figura 8-2 - Estrutura física de um corpo rígido. Fonte: O.D.E. Site Oficial.
A origem desta estrutura física de coordenadas é o ponto de referência do corpo.
Alguns valores na O.D.E. (vetores, matrizes, etc) são relacionados a ele, enquanto
outros são relacionados à estrutura de coordenadas globais.
Observe que o shape de um corpo rígido não é uma propriedade dinâmica (a não
ser que várias propriedades maciças influenciem-no). É somente na detecção de colisão
que o detalhamento do shape é cuidado.
Os corpos são conectados um ao outro através de articulações. Uma “ilha” de
corpos é um grupo que não pode ser separado – em outras palavras, cada corpo é
conectado de alguma maneira ao outro formando ilhas de corpos.
Por exemplo, uma chave é conectada a um chaveiro através de uma argola de
metal. Estes três objetos formam uma ilha de corpos. Cada ilha no mundo é tratada
separadamente quando os passos de simulação são realizados.
289
Corpos também podem ser habilitados ou desabilitados, quando se sabe que o
corpo é imóvel ou irrelevante em específico passo da simulação. A desabilitação de
corpos é uma maneira efetiva de economizar tempo de computação.
Figura 8-3 - Três diferentes tipos de constraints. Fonte: O.D.E. Site Oficial.
A primeira é uma articulação ball-and-socket, que pressiona a esfera de um
corpo contra um soquete de outro corpo. A segunda é um hinge que pressiona dois
corpos para uma mesma posição, procurando alinhar ambas ao longo do eixo de uma
dobradiça. O terceiro é um slider que força um pistão a um soquete, alinhados,
adicionando pressão nos dois corpos para manterem-se na mesma orientação.
Cada vez que um passo de simulação é realizado (também chamado de
integração), todas as articulações tornam-se habilitadas a aplicar pressão nos corpos que
afetam. Estas forças são calculadas para que os corpos movam-se coordenadamente,
preservando todos os relacionamentos comuns.
Cada articulação tem um número de parâmetros de controle para suas
geometrias. Um exemplo é a posição de um ball-and-socket para uma articulação ball-
and-socket. As funções de configuração articulam os parâmetros de todas as
coordenadas globais, não relacionadas às coordenadas do objeto. Conseqüência disto é
que os corpos rígidos que têm uma conexão articulada devem ser posicionados
corretamente antes da articulação ser confirmada (união).
Existem também grupos de articulações. Cada grupo de articulações é um
container especial que prende articulações em um mundo. As articulações podem ser
290
adicionadas a um grupo, e quando estas não são necessárias para um grupo inteiro, elas
podem ser rapidamente destruídas com uma única chamada de função.
Entretanto, articulações individuais em um grupo não podem ser destruídas antes
que o grupo inteiro esteja vazio. Isto se torna útil para contato de articulações, os quais
são adicionados e removidos de um mundo a cada simulação.
A articulação inicialmente não tem nenhum efeito de simulação porque ainda
não está conectada a nenhum corpo. O ID do grupo de articulações é zero para alocar
uma articulação normal. Se não for zero, a articulação fará parte de um grupo de
articulações. O contato será inicializado através da estrutura dContact;
Quando se pretende finalizar um mundo, é importante destruir primeiramente
todos os objetos, desconectando suas ligações de corpos e removendo-os do mundo.
Entretanto, se a articulação é membro de um grupo, é necessário eliminar ou esvaziar
(empty) o grupo.
Figura 8-4 - Articulação Ball and Socket. Fonte: O.D.E. Site Oficial.
8.6.2 Hinge
Uma articulação do tipo hinge (dobradiça) é mostrada na Figura 8-5. A seguir,
são apresentados os passos para a construção desta estrutura:
• Ajustar o ponto de ancoragem do hinge e os parâmetros do eixo;
• Iniciar o ponto de ancoragem, em coordenadas do mundo. Executa o mesmo
processo que o tipo ball and socket, anteriormente destacado;
• Iniciar os parâmetros do eixo;
• Iniciar o ângulo do hinge. O ângulo é medido entre 2 corpos, ou entre um corpo
e um ambiente estático, e está entre –π ... +π. Quando a âncora ou o eixo são
ajustados, a posição corrente dos corpos ligados é examinada, e sua posição
recebe ângulo zero.
1.1.2. Slider
292
Uma articulação do tipo slider é mostrada na Figura 8-6. A seguir, são
apresentados os passos para a construção desta estrutura:
• Criar um mundo dinâmico onde a física dos corpos irá atuar;
• Configurar o parâmetro do eixo slider;
• Iniciar os parâmetros do eixo;
• Ajustar a posição linear do slider. Quando o eixo é ajustado, a posição corrente
dos corpos ligados é examinada, e sua posição recebe ângulo zero.
1.1.3. Universal
8.6.3 Hinge-2
Uma articulação do tipo hinge-2 é mostrada na Figura 8-8.
294
Figura 8-8 - Uma articulação hinge-2. Fonte: O.D.E. Site Oficial.
A articulação hinge-2 equivale a dois hinges conectados em série, com a
diferença em seus eixos. Um exemplo, mostrado na figura acima, é o sistema de direção
das rodas de um carro, onde um dos eixos permite que a roda seja guiada e o outro
permite que a roda gire.
A articulação hinge-2 tem um ponto de ancoragem e dois eixos. O eixo1 está
relacionado ao corpo1 (onde o corpo1 é o chassi do veículo), enquanto o eixo2 está
relacionado ao corpo2 (onde o corpo2 é a roda).
O hinge-2 tem seu eixo1 perpendicular ao eixo2, equivalente a uma articulação
universal com suspensão adicionada.
Passos para a construção desta estrutura:
• Ajustar a âncora e os parâmetros do eixo. Eixo1 e Eixo2 devem ser
perpendiculares um ao outro;
• Iniciar o ponto de ancoragem. Será retornado o ponto de um dos corpos, e, se a
articulação estiver perfeitamente correta, o mesmo será executado para o outro
corpo;
• Iniciar os parâmetros dos eixos;
• Iniciar os ângulos hinge-2 (ao redor dos eixos 1 e 2) e suas taxas de variação.
Quando a âncora ou o eixo estão ajustados, a posição corrente dos corpos
ligados é examinada, e sua posição recebe ângulo zero.
8.6.5 Contato
Uma articulação de contato é mostrada na Figura 8-9.
295
Tabela 8.1 – Flags de Contato para surfaces. Fonte: O.D.E. Site Oficial.
Flag Definição
dContactMu2 Se não estiver configurado, use mu para as duas direções do
atrito. Se estiver configurado, usa-se mu para a direção do atrito
1 e mu2 para a direção do atrito 2.
dContactFDir1 Se ajustado, use fdir1 para a direção 1 da fricção. Caso
contrário, o ajuste será automático para 1, sendo perpendicular
ao contato normal (no qual sua orientação resultante é
297
imprevisível).
dContactBounce Se estiver configurada, a superfície de contato é flexível, e
assim os corpos irão chocar-se, proporcionando um ricocheteio.
A quantidade exata de ricocheteio é controlada pelo parâmetro
de impacto.
dContactSoftERP Se configurada, o parâmetro da redução de erro do contato da
normal pode ser ajustada com o parâmetro do soft_erp. Isto é
útil para fazer superfícies suaves.
dContactSoftCFM Se configurada, o parâmetro de limitação de força de contato
normal pode ser setado com o parâmetro soft_cfm. É útil para se
fazer superfícies suaves.
dContactMotion1 Se ajustada, a superfície de contato assumida move-se
independentemente do movimento dos corpos. Este é um tipo
de esteira. Quando este flag é setado, motion1 define a
velocidade de superfície na direção 1 da fricção.
dContactMotion2 Idem ao dContactMotion1, mas para a direção de atrito 2.
dContactSlip1 Force-dependent-slip (FDS) na direção 1 do atrito (inclinação).
dContactSlip2 Force-dependent-slip (FDS) na direção 2 do atrito (inclinação).
dContactApprox1_1 Usa a pirâmide de aproximação de atrito para a direção 1. Se
isto não for especificado, então a aproximação do constante-
força-limite será usada (onde mu é um limite da força).
dContactApprox1_2 Usa a pirâmide de aproximação de atrito para a direção 2. Se
isto não for especificado, então a aproximação do constante-
força-limite será usada (onde mu é um limite da força).
dContactApprox1 Equivalente a dContactApprox1_1 e dContactApprox1_2.
O FDS é um efeito que faz com que superfícies de contato entre si tenham uma
velocidade que seja proporcional à força aplicada tangencialmente a cada superfície. A
força não causa uma aceleração constante nas superfícies – ela causa uma aceleração
breve para chegar a uma velocidade constante.
Isto é útil para modelar, por exemplo, pneus. Considere um carro parado em uma
estrada. Empurrando o carro para frente, este começa a se mover (isto é os pneus
começarão a girar). Empurrando o carro na direção perpendicular não ocasionará
nenhum efeito, porque os pneus não giram nesse sentido. Contudo se o carro estiver se
298
movendo a uma velocidade v, aplicando uma força f na direção perpendicular fará com
que os pneus deslizem na estrada com uma velocidade proporcional ao f*v, o que
realmente é suscetível a acontecer.
Importante ressaltar que o FDS não tem relação com os efeitos de
aderência/deslize de atrito de Coulomb – ambos os modos podem ser usados juntos em
um único ponto de contato.
Figura 8-10 – Uma articulação AMotor com ângulos de Euler. Fonte: O.D.E. Site Oficial.
Neste diagrama, a0, a1 e a2 são os três eixos ao longo do qual o movimento
angular é controlado. Os eixos verdes (incluindo a0) são ancorados ao corpo 1. Os eixos
azuis (incluindo a2 são ancorados ao corpo 2. Para pegar o eixo do corpo 2 dos eixos
do corpo 1 a seguinte seqüência de rotações é executada:
299
• Rotação por θ0 sobre a0;
• Rotação por θ1 sobre a1(a1 foi rotacionado de sua posição original);
• Rotate by θ2 sobre a2 (a2 foi rotacionado duas vezes a partir de sua posição
original).
Há uma limitação importante ao usar os ângulos de Euler: o ângulo do θ1 não
pode começar fora da escala -π/2...π/2. Se isto acontecer, então a articulação AMotor
tornar-se-á instável (há uma particularidade entre +/- π/2). Para tanto, você deve ajustar
as paradas apropriadas no eixo número 1.
Passos para a construção desta estrutura:
• Atribuir e receber o mode do motor angular. O parâmetro mode deve ser uma
das seguintes constantes:
Tabela 8.2 – Constantes para Motor Angular. Fonte: O.D.E. Site Oficial.
Flag Definição
dAMotorUser O eixo AMotor e as configurações do ângulo de articulação são
inteiramente controladas pelo usuário. Este é o modo padrão.
dAMotorEuler Os ângulos de Euler são computados automaticamente. O eixo a1
é computado também automaticamente. Os eixos do AMotor
devem ser ajustados corretamente quando neste modo, como
descritos abaixo. Quando este modo é ajustado inicialmente
atribua as orientações relativas atuais dos corpos corresponderão
a todos os ângulos do Euler em zero.
• Atribuir e receber o número dos eixos angulares que serão controlados pelo
AMotor (de 0 a 3);
• Atribuir e receber os eixos de AMotor, onde:
o 0: O eixo é ancorado para o quadro global.
o 1: O eixo é ancorado para o primeiro corpo.
o 2: O eixo é ancorado para o segundo corpo.
O vetor dos eixos (x, y, z) é sempre especificado em coordenadas globais.
Para o modo dAMotorEuler:
o Somente os eixos 0 e 2 necessitam ser configurados. O eixo 1 será
determinado automaticamente a cada passo de tempo;
o Os eixos 0 e 2 devem ser perpendiculares entre si;
300
o O eixo 0 deve ser ancorado para o primeiro corpo, o eixo 2 deve ser
ancorado para o segundo corpo.
• Informar ao AMotor que o ângulo atual está junto com o eixo especificado. Esta
função deve ser chamada somente no modo dAMotorUser, porque neste modo o
AMotor não tem nenhuma outra maneira de saber os ângulos de articulação. A
informação do ângulo é necessária se as paradas forem ajustadas ao longo do
eixo central, mas não é necessário para os eixos dos motores;
• Retornar o ângulo atual para o eixo especificado;
• Retornar a taxa do ângulo atual para o eixo especificado. No modo
dAMotorUser isto é sempre zero, porque não há informação disponível. No
modo dAMotorEuler esta é a taxa correspondente ao ângulo Euler.
o Pontos de Contato
Se dois corpos se tocam, ou se um corpo toca um objeto estático dentro do
ambiente, este é representado por um ou mais pontos de contato. Cada ponto de contato
tem um ponto de contato correspondente de nome dContactGeom:
struct dContactGeom {
305
dVector3 pos; // posição de contato
dVector3 normal; // vetor normal
dReal depth; // profundidade de penetração
dGeomID g1,g2; // geometrias de colisão
};
o Objetos Geométricos
Objetos geométricos fundamentais no sistema de colisão. Um geom pode
representar um formato de corpo rígido (tal como uma esfera ou caixa) ou pode
representar um grupo de outras geometrias – este é um tipo especial de geometria
chamada “space”.
306
Qualquer geometria pode ser colidida contra qualquer outra geometria para
produzir zero ou mais pontos de contato. Os objetos space têm uma capacidade extra de
serem capazes de colicir suas geometrias para produzir pontos de contato internos.
Geoms podem ser estabelecidas ou não. Uma geometria estabelecida tem um vetor de
posição e uma matriz de rotação de 3x3, tal como um corpo rígido que pode ser trocado
durante a simulação. Uma geometria não estabelecida não tem esta capacidade – por
exemplo, pode ser trocada durante a simulação. Por exemplo, pode representar algumas
características estáticas do ambiente que não pode ser movido. Spaces não são
geometrias estabelecidas, porque cada um pode ter sua própria posição e orientação,
mas isto não faz sentido para o space por si só para ter uma posição e orientação.
Para usar um engine de colisão em uma simulação de corpo rígido, geometrias
que podem ser alocadas são associadas com objetos de corpos rígidos. Isto permite ao
engine de colisão pegar a posição e orientação das geometrias dos corpos.
Observe que as geometrias são distintas dos corpos rígidos porque estas tem
propriedades (tamanho, formato, posição e orientação) mas sem propriedades dinâmicas
(tais como velocidade ou massa). Um corpo e uma geometria juntos representam todas
as propriedades do objeto simulado.
Cada geometria é uma instância de uma classe, tais como esferas, planos ou
caixas. Há um número de classes nativas, que são descritas abaixo e que podem ser
definidas como classes proprietárias.
O ponto de referência para uma geometria alocável é o ponto que é controlado
pela posição vetorial. O ponto de referência para as classes padrão usualmente
corresponde ao centro de massa destas. Esta característica permite as classes padrão
conectarem-se facilmente a corpos dinâmicos. Se outros pontos de referência forem
solicitados, um objeto de transformação pode ser usado para encapsulá-la.
Os conceitos e funções que são aplicadas a todas as geometrias serão descritos
abaixo, seguidas pelas várias classes de geometrias e as funções que as manipulam.
o Espaços (Spaces)
Um space é uma geometria sem lugar determinado que pode conter outras
geometrias. É similar ao conceito de corpo rígido, exceto que é aplicado para colisão ao
invés de dinâmica.
Objetos Space existem para fazer a detecção de colisão de forma rápida e
transparente. Sem spaces, você poderia gerar contatos em sua simulação pela chamada
307
do dCollide() para encontrar pontos de contato para cada par simples de geometrias.
Para N geometrias este é O(N2) testes, aos quais são mais custosos computacionalmente
se seu ambiente tem muitos objetos.
Uma aproximação melhor seria inserir as geometrias dentro de um space e
chamar dSpaceCollide(). O space então escolherá um tipo de colisão, o que significa
que irá rapidamente identificar quais pares de geometrias que estão potencialmente
colidindo. Estes pares serão passados para uma função callback, na qual poderá
novamente chamar a função dCollide() para eles.
Isto economiza muito tempo que poderia ser gasto em testes de colisão
dCollide() inúteis, porque o número de pares passados para a função callback será uma
fração menor de cada par possível objeto-objeto. Os spaces podem conter outros spaces.
Isto é útil para dividir um ambiente de colisão entre diversas hierarquias para mais
adiante otimizar a velocidade de detecção de colisão.
o Detecção de Colisão
Uma detecção de colisão no mundo é criada para um espaço de atuação, onde
são adicionados os tipos geométricos. Três funções básicas são usadas para isto:
• dCollide() intersecta dois geoms e gera os pontos de contato;
• dSpaceCollide() determina quais pares de geoms no espaço potencialmente
poderão colidir, e chama uma função callback para cada par candidato. Isto não
gera pontos de contato diretamente, porque o usuário pode querer manipular
alguns pares em especial – por exemplo, ignorando eles ou usando diferentes
estratégias de contato. Cada decisão tem que fazer chamada a uma função
callback podendo escolher se colide ou não com o par;
• dSpaceCollide2() determina qual geom de um espaço pode potencialmente
intersectar com geoms de outro espaço, e chama a função callback para cada par
candidato. Pode também testar com um espaço sem geoms. Esta função é usada
quando existe uma hierarquia de colisão, isto é, quando existem espaços que
contém outros espaços.
O sistema de colisão tem sido projetado para dar ao usuário máxima
flexibilidade na decisão de quais objetos serão testados em comparação a outros. Isto
porque existem três funções de colisões ao invés de uma função que apenas gera os
pontos de contato.
308
Espaços podem conter outros espaços. Estes sub-espaços representarão
tipicamente uma coleção de geoms (ou outros lugares) que são alocados próximos uns
dos outros. Isto é usado para aumentar o desempenho de colisão de hierarquias dentro
de um mundo.
Exemplo: suponha que você tem dois carros guiados sobre um terreno. Cada
carro tem seus próprios geoms. Se todos estes geoms estavam inseridos em um mesmo
espaço, a computação do tempo de colisão entre dois carros seria sempre proporcional
ao número total de geoms (ou para cada área deste número, dependendo de qual tipo
espaço é usado).
Para acelerar a colisão um espaço separado é criado para representar cada
veículo. As geometrias do carro são inseridas neste espaço para auxílio. A cada passo de
simulação, dSpaceCollide() é chamada para este nível de espaço. Assim, ocorrerá um
único teste da interseção entre estes espaços (limitados por envoltórios que são caixas
que definem o espaço que este irá ocupar), retornando a ocorrência de toque. A função
callback pode então testar as geometrias destes espaços comparando com
dSpaceCollide2(). Se os carros não estiverem próximos, então a função callback não
será executada.
Se hierarquias de espaço são utilizadas então a chamada de retorno será
recursiva. Neste caso, o usuário deve ter certeza de que a função callback é
corretamente aplicada. Aqui está a mesma função callback que varre todos os espaços e
sub-espaços, gerando os possíveis pontos de contato nas interseções de geoms:
void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
if (dGeomIsSpace (o1) || dGeomIsSpace (o2))
{
// colliding a space with something
dSpaceCollide2 (o1,o2,data,&nearCallback);
// collide all geoms internal to the space(s)
if (dGeomIsSpace (o1)) dSpaceCollide (o1,data,&nearCallback);
if (dGeomIsSpace (o2)) dSpaceCollide (o2,data,&nearCallback);
}
else
{
// colliding two non-space geoms, so generate contact
// points between o1 and o2
int num_contact = dCollide (o1,o2,max_contacts,contact_array,skip);
// add these contact points to the simulation
...
309
}
}
...
// collide all objects together
dSpaceCollide (top_level_space,0,&nearCallback);
o Objetos compostos
Considere os exemplos abaixo:
• Uma mesa que foi feita com um box para a superfície e um box para cada perna
da mesa;
• Um galho de árvore que é modelado com vários cilindros para cada ramificação
presa a ele;
311
• Uma molécula que tem várias esferas representando cada átomo.
o Notas de implementação
Grandes Ambientes
Freqüentemente o mundo de colisões conterá muitos objetos que são partes de
um ambiente estático, que não estão associados a corpos rígidos. A detecção de colisão
O.D.E. é otimizada para detectar geoms que não se movem e não precomputam tanta
informação como possível sobre estes objetos para economizar tempo. Por exemplo,
estruturas de dados de colisão interna e envoltórios são precomputados.
8.10 Exemplos
Esta seção demonstra como criar uma simulação em tempo real de uma
máquina, onde são efetuadas conexões entre objetos O.D.E. utilizando articulações a
fim de criar movimentações realísticas. A ferramenta de demonstração escolhida foi o
Delphi.
Cilindro 1 X 0
BottomRadius 2 Y 1
Direction Z 0
X 0
Y 0 Cilindro 2
Z 1 BottomRadius 0,5
Height 0,5 Direction
Name Wheel X 0
Position Y 0
X -2,5 Z 1
Y 0 Height 5
Z 0 Name Axle
Slices 32 Position
TopRadius 2 X 0
Up
315
Y -2 X 3,5
Z 0 Y 0,5
Slices 16 Z -1,5
TopRadius 0,5 Slices 16
Up TopRadius 0,25
X 0 Up
Y 1 X 0
Z 0 Y 1
Z 0
Cilindro 3 Cubo 1
BottomRadius 0,25 CubeDepth 0,75
Direction CubeHeight 0,25
X 0 CubeWidth 7,5
Y 0 Direction
Z 1 X 0
Height 1 Y 0
Name Pin1 Z 1
Position Name Arm
X 0 Position
Y 0,5 X 0,5
Z -1,5 Y 0,75
Slices 16 Z -1,5
TopRadius 0,25 Up
Up X 0
X 0 Y 1
Y 1 Z 0
Z 0
Cilindro 4 Cubo 2
BottomRadius 0,25 CubeDepth 1
Direction CubeHeight 0,5
X 0 CubeWidth 4
Y 0 Direction
Z 1 X 0
Height 1 Y 0
Name Pin2 Z 1
Position
316
Name Slider Up
Position X 0
X 3,25 Y 1
Y 0 Z 0
Z -1,5
Figura 8-15– Visualização da câmera após definição dos objetos componentes da máquina.
Agora, ajusta-se o comportamento para os objetos do mundo que irão exercer
movimentos dentro da simulação. Passo isso, selecione cada um dos objetos e mude a
propriedade Behaviours clicando em [...]. Uma nova janela será aberta, como mostra a
Figura 8-16, onde cada objeto será definido como O.D.E. Dynamic.
317
Neste caso, os objetos que receberão esta propriedade são o Arm, Pin2 e Wheel.
Apesar de Axl e Pin1 não estarem definidos como um objeto dinâmico, eles também se
movimentarão. Isto ocorre porque todos os objetos filhos herdam suas propriedades do
objeto pai, neste caso o objeto Wheel.
Assim, um item será inserido nesta janela. Em suas propriedades, é requerido
indicar qual é o gerenciador O.D.E. a ser utilizado através da opção Manager. Há
também outra propriedade chamada Elements onde será definido como o objeto atuará
no sistema de colisão. Mesmo que o objeto mostrado na tela seja uma esfera, e este
tenha sido definido como um elemento box, então esta esfera atuará na simulação como
se fosse um cubo. Por isso, utiliza-se sempre o elemento que tem maior semelhança com
o objeto que se pretende simular.
O processo para os três objetos citados acima é o mesmo, o que muda são os
tipos de elementos a serem usados e suas propriedades, respectivamente. Nas tabelas
abaixo estão disponíveis as propriedades de cada objeto suscetíveis de alterações.
Arm – Element Box
BoxDepth 0,75
BoxHeight 0,25
BoxWidth 7,5
Pin2 – Element Cylinder
Density 1
Density 1
Name Box Length 1
Radius 0,25
Name Cylinder
318
Wheel – Element Cylinder Radius 2
Density 1 Name Cylinder
Length 0,5
Uma vez alterado estas propriedades, são criadas as articulações entre objetos.
As articulações limitam a movimentação e dão sincronismo ao mecanismo
desenvolvido. Para criá-las, selecione o componente GLODEJointList já inserido no
Form principal. Em suas propriedades, acesse a opção Joints. Abrirá uma janela
semelhante ao do processo anterior, onde definimos o comportamento do objeto no
mundo. São criadas quatro articulações, sendo que três são do tipo hinge e outra do tipo
slider. Suas definições seguem abaixo:
Hinge 1 Object1 Wheel
Anchor Object2 Arm
X -2,5 Hinge 3
Y 0 Anchor
Z 0 X 3,5
Axis Y 0,5
X 0 Z -1,5
Y 1 Axis
Z 0 X 0
Manager GLODEManager1 Y 1
Name Wheel Fixed Z 0
Object1 Wheel Manager GLODEManager1
Object2 Name Arm - Pin2
Object1 Arm
Object2 Pin2
Hinge 2
Anchor
Slider
X -2,5
Axis
Y 0,5
X 1
Z -1,5
Y 0
Axis
Z 0
X 0
Manager GLODEManager1
Y 1
Name Pin2 Fixed
Z 0
Object1 Pin2
Manager GLODEManager1
Object2
Name Wheel - Arm
319
Para finalizar, atribuímos uma força para atuar no mundo, dando movimentação
ao objeto. Aplica-se em Arm no sentido x. Para isso, no eventoOnCreate do Form
adicionamos o seguinte código:
TGLODEDynamicBehaviour(Arm.Behaviours[0]).AddForce(AffineVectorMake(-50,0,0));
Compile e veja o resultado! Observe que a força aplicada no objeto Arm fará
com que o objeto Wheel gire e o objeto Pin2 deslize sobre o objeto Slider. A simulação
está concluída.
Figura 8-19
– Propriedades do objeto “bola”.
Figura 8-21–Propriedades da
Câmera.
Figura 8-22–Propriedades do
DummyCube.
Figura 8-27–GLSceneViewer.
325
• Após o ajuste das propriedades, a visão da câmera será apresentada conforme as
próximas figuras:
8.11 Referências
Grange, Eric. GLScene – Open Solution for Delphi. http://www.glscene.org
(25/08/04).
Mojon, Stéphane. Realization of a Physic Simulation for a Biped Robot. Swiss
Federal Institute of Technology Lausanne (EPFL), 2003.
Smith, Russel. Open Dynamics Engine – O.D.E. User Guide. http://www.ode.org
(25/08/04).