UNIJUÍUniversidade Regional do Noroeste do Estado do Rio Grande do Sul DeTec Departamento de Tecnologia
Bacharelado em Informática
Tutorial
V R M L 2.0
Marcos Carrard
Apresentação
Este texto apresenta um apostila ou tutorial para o uso da linguagem VRML –
Virtual Reality Modeling Language. Conforme será visto, está é uma linguagem de uso
muito frequente e amplo quando da descrição de mundos e ambientes para realidade virtual através de uma rede de computadores de velocidade relativamente baixa, como a internet.
Não é o objetivo deste material se caracterizar como tendo um conteúdo novo e inédito. Pelo contrário, como o próprio nome diz, ele é uma apostila ou tutorial e, portanto, o seu conteúdo foi retirado de algumas publicações e páginas na internet, especialmente o livro do autor Andrea Ames, David Nadeau e John Moreland ([ANM96]). Esta é uma publicação bastante completa e recomendada a todos que desejam conhecer profundamente o VRML. Esta apostila traz o seu conteúdo e uma boa parte dos seus exemplos na sequência, forma e conteúdo apresentados por este livro.
Qualquer dúvida, correção, sugestão ou acréscimo de conteúdo para este material é muito bem vinda e pode ser enviada através do endereç[email protected] através da páginahttp://labinf.detec.unijui.tche.br/~carrard.
Sumário
Apresentação Sumário 1 Aspectos Iniciais 1.1 Introdução 1.2 Sistema de Coordenadas 1.3 Arquivo VRML 1.4 Descrevendo Figuras 1.5 Eventos e Rotas 2 Construção das Figuras2.1 Nodo Shape 2.2 Nodo Appearance 2.3 Nodo Material 2.4 Primitivos Geométricos 2.5 Agrupando Figuras 3 Inserindo Texto 3.1 Introdução 3.2 Nodo Text 3.3 Nodo FontStyle 4 Transformando Figuras 4.1 Introdução 4.2 Nodo Transform 4.3 Translação 4.3.1 Vetores em 3D 4.3.2 Transformação de translação 4.4 Rotação 4.5 Escala
5 Animando o Posicionamento, Orientação e Escala das Figuras 5.1 Introdução
5.2 Processo de Animação 5.3 Nodo TimeSensor
5.4 Nodo PositionInterpolator 5.5 Nodo OrientationInterpolator
5.6 Exemplos
6 Interagindo com os Objetos 6.1 Introdução 6.2 Nodo TouchSensor 6.3 Nodo PlaneSensor 6.4 Nodo SphereSensor 6.5 Nodo CylinderSensor 6.6 Exemplos
7 Controlando a Aparência das Figuras 7.1 Introdução 7.2 8 Agrupando Nodos 8.1 Introdução 8.2 9 Incluindo Arquivos 9.1 Introdução 9.2
10 Construindo com Pontos, Linhas e Faces 10.1 Introdução 10.2 11 Grids de Elevação 11.1 Introdução 11.2 12 Figuras de Extrusão 12.1 Introdução 12.2 13 Construção de Cores 13.1 Introdução 13.2 14 Mapeamento de Textura 14.1 Introdução 14.2 15 Luz e Sombra 15.1 Introdução 15.2
16 Adicionando Fundo e Fumaça 16.1 Introdução 16.2 17 Adicionando Som 17.1 Introdução 17.2 18 Controle de Detalhes 18.1 Introdução 18.2
19 Definindo Pontos de Vista 19.1 Introdução
20 Adicionando Âncoras e Informações ao Mundo Virtual 20.1 Introdução 20.2 21 Criando Scripts 21.1 Introdução 21.2
22 Criando Novos Tipos de Dados 22.1 Introdução
22.2
Anexo I – Tabela de Cores do Modelo RGB Bibliografia
1
Aspectos Iniciais
1.1 Introdução
VRML é a abreviação para Virtual Reality Modeling Language ou Linguagem para Modelagem em Realidade Virtual. Seu objetivo é a descrição de objetos e mundos tridimensionais interativos através da World Wide Web na internet. Esta linguagem é indente de plataforma e permite a criação de ambiente virtuais por onde se pode passear, visualizar objetos e interagir com eles.
VRML foi apresentada pela primeira vez em 1994 durante a conferência sobre WWW com o propósito de atingir os objetivos acima sem necessitar de uma rede de alta velocidades para dar suporte as atividades. Nesta ocasião ela foi apresentada como um subconjunto de um formato de arquivos ASCII do software Open Inventor da Silicon Graphics.
Esta versão, conhecida como VRML 1.0, trabalha principalmente com a geometria 3D dos objetos que são elaborados em polígonos e primitivos como cones, esferas, cilindros e esferas. Ela suporta ainda algumas transformações com estes objetos e permite o ajuste da complexidade dos objetos dependendo da distância do observador do ambiente.
A versão atual da linguagem, denominada de Moving Worlds VRML 2.0 agrega todas as definições existentes na versão anterior e amplia as possibilidades de representação e interação neste mundo e com outros mundos virtuais. Nelas os objetos podem mover-se e reagir a eventos originários do usuário ou de alguma outra forma de controle. Além disto, esta versão permite o uso de objetos multimídia nos ambientes, assim é possível integrar sons e filmes nas cenas.
Conforme [Kir97] as características do VRML 2.0 podem ser agrupadas em quatro áreas principais: melhoria dos mundos estáticos, interação, animação e comportamento baseado em scripts, além da prototipação de novos objetos.
A linguagem VRML não é reconhecido de forma padronizada pelos navegadores da HTML como o Netscape e o Internet Explorer. Desta forma, é necessário configurar o navegador para que ele compreenda o conteúdo do arquivo que está recebendo. Para isto é
necessário um navegador VRML que deverá, tipicamente, ser adicionado ao navegador HTML na forma de plug-in. Plug-in nada mais são do que programas que trabalham de forma associada ao navegador HTML para que este entenda arquivos de tipos diferenciados. Sugere-se que antes de continuar na leitura deste tutorial, o leitor adquira um navegador VRML (estão disponíveis na internet de forma gratuita) para poder avaliar os exemplos propostos. Todos eles forma escritos e testados utilizando o software Cosmo Player 2.1 e o navegador HTML Nestcape 4.7.
1.2 Sistema de Coordenadas
A linguagem VRML utiliza o sistema de coordenadas cartesiano para a representação espacial, ou seja, um sistema baseado em 3 eixos de deslocamento vetorial. Veja a figura 1.1 para a descrição desta representação.
Figura 1.1 – Sistema de coordenadas cartesiano
Ainda sobre esta questão, existem duas convenções que são relevantes na definição do mundo virtual e na sua possibilidade de conexão com outros mundos. A primeira delas é que é adotado a regra da mão direita para definição dos eixos do sistema e seu sentido de crescimento. Nesta regra, toma-se a mão direita e aponta-se os dedos polegar, indicador e médio de forma que fiquem com 90 graus entre si, aproximadamente (veja a figura 1.2). Nesta disposição, o dedo polegar representa o eixo X, o indicador o eixo Y e o dedo médio, o eixo Z, crescendo no sentido que os dedos apontam. Além disso, a definição original do mundo virtual, utilizada em casos default, coloca o observador da cena no sentido do eixo +Z.
A segunda convenção adotada, não pela linguagem mas pelos seus usuários, é o uso da unidade de medidas metros para o sistema de coordenadas. A razão desta convenção é permitir facilmente a integração de mundos virtuais escritos por usuários diferentes sem que ocorram problemas de proporção nas figuras.
1.3 Arquivo VRML
Os mundos virtuais são descritos através de um arquivo texto com extensão .wrl que pode ser criado com qualquer editor de programas fontes. É importante notar que não pode ser utilizado um editor de textos comum, como o Word, e sim um editor de programas fontes, como o Notepad do Windows.
Nesta seção vamos discutir alguns aspectos básicos e introdutórios a respeito do conteúdo destes arquivos. Para tanto será utilizado o arquivo do exemplo 1.1.
#VRML V2.0 utf8 # Primeiro exemplo Group{
children[
# Desenha o cilindro da base Shape{
appearance DEF Azul Appearance{ material Material{ diffuseColor 0.0 0.0 1.0 } } geometry Cylinder{ height 2.0 radius 2.0 } },
# Desenha o cone da cobertura Transform{
translation 0.0 2.0 0.0 children Shape{
appearance USE Azul geometry Cone{ height 2.0 bottomRadius 2.5 } } } ] }
a) Cabeçalho VRML
O cabeçalho está presente em todos os arquivos VRML e é obrigatório. Seu formato é:
#VRML V2.0 utf8
onde: VRMLÿ indica que o arquivo que segue é a descrição de um ambiente virtual; V2.0ÿ identifica a versão ou especificação 2.0 da linguagem VRML;
utf8ÿ identifica um arquivo que utiliza o conjunto de caracteres UTF-8;
Para a descrição de um arquivo fonte utilizando a versão 1.0 da linguagem VRML, também há um cabeçalho, com o mesmo sentido na composição das suas partes, mas descrito diferentemente:
#VRML V1.0 ascii
b) Comentários
Após o cabeçalho do arquivo VRML, toda e qualquer sequência de caracteres que iniciar ou contiver o caracter #, é tratada como comentário e é ignorada pelo navegador. Por exemplo:
# Desenha o cilindro da base
c) Nodos
O arquivo VRML é formado por nodos (nodes) que descrevem as figuras contidas nele e as suas propriedade no mundo virtual. O nodo é a estrutura sintática básica de composição deste tipo de arquivo e, tipicamente, contém:
- o tipo de nodo (obrigatório); - um par de chaves (obrigatório);
- um conjunto de campos e seus atributos (opcional); Exemplo:
Cylinder { height 2.0 radius 2.0 }
Neste exemplo, Cylinder é o tipo do nodo e height e radius dois campos com seus valores que especificam a altura e diâmetro do cilindro a ser desenhado.
d) Tipo de valores
Existe um conjunto pré-definido de tipos de dados ou valores que são aceitos como atributo dos campos de um nodo. É importante ressaltar que a não presença de um destes campos no nodo implica no uso de um valor default, mas sempre dentro das especificações da linguagem.
A tabela a seguir apresenta os tipos de dados possíveis na linguagem VRML. Nesta tabela os tipos obedecem a um padronização de nomenclatura, iniciando-se sempre com SF ou MF:
- SF: Single value types – indica um único valor para o tipo a ser utilizado no dado;
- MF: Multiple value types – indica o uso de múltiplos valores para o dado deste tipo;
Tipo de Valor Descrição
SFBool Descreve um valor booleano: verdadeiro (TRUE) ou falso (FALSE)
SFColor MFColor
Grupo de três valores reais descrevendo as componente vermelho (red), verde (green) e azul (blue) do modelo de cores RGB
SFFloat MFFloat
Descreve valores reais ou de ponto flutuante.
SFImage Uma lista de valores descrevendo as cores de uma imagem digital
SFInt32 MFInt32
Valores inteiros de 32 bits SFNode
MFNode
Identifica um dado do tipo node VRML (nodo) SFRotation
MFRotation
Descreve um grupo de quatro valores reais onde os três primeiros identificam um eixo o sistema de representação e o último um ângulo medido em radianos. Estes valores definem uma transformação geométrica de rotação.
SFString MFString
Descreve uma lista de caracteres, que devem estar obrigatoriamente entre aspas, caracterizando uma string.
SFTime Descreve um valor real para a medida absoluta de tempo, em segundos, contados a partir da 00:00hs do dia 01/01/1970.
SFVec2f MFVec2f
Dois valores reais descrevendo um ponto ou vetor bidimensional no plano cartesiano.
SFVec3f MFVec3f
Três valores reais descrevendo um ponto ou vetor tridimensional no espaço cartesiano.
Os tipos de dados descritos acima irão aparecer na descrição formal dos campos dos nodos que a linguagem VRML comporta a serem vistos mais tarde. Por exemplo, a descrição formal do campo height do nodo Cylinder é:
height 2.0 # SFFloat
Esta descrição indica que o campo height tem um calor default de 2.0 e este dado é do tipo SFFloat, portanto, admitindo somente valores reais na sua descrição.
e) Nomes de nodos
Todos os nodos no ambiente virtual podem ser nominados. Os nomes podem ser compostas de qualquer sequência de letras, números e underscore. Os nomes compostos diferenciam letras maiúsculas e minúsculas (case sensitives) e não podem iniciar com um número.
A definição de um nome para um nodo VRML tem a função de identificá-lo para novo uso posterior. Para fazer este uso, o nodo deve ser definido previamente com a seguinte definição:
DEF nome_do_nodo tipo_do_nodo {...} Exemplo:
DEF Meu_Cilindro Cylinder{ height 2.0
radius 2.0 }
Após a definição do nodo ele pode ser utilizado sempre que se fizer necessário. Para esta utilização, o nome definido ao nodo deve aparecer precedido pela palavra chave USE:
USE nome_do_nodo Exemplo:
geometry USE Meu_Cilindro
1.4 Descrevendo Figuras
A construção do ambiente virtual é realizada com figuras (shapes) descritas pelos nodos e por seus atributos. Desta maneira, a figura VRML tem uma forma ou geometria (geometry) que define a sua estrutura tridimensional. Além disto, esta figura tem sua aparência baseada no material com o qual é feita (material) e na textura da sua superfície (texture). Assim, geometry e appearance são os campos do nodo Shape:
Exemplo:
Shape {
Appearance DEF Azul Appearance { # Campo da aparência material Material { # da figura
diffuseColor 0.0 0.0 1.0 }
}
geometry Cylinder { # Definição da sua
height 2.0 # forma 3D
radius 2.0 }
}
A linguagem VRML suporta vários tipos de primitivos geométricos para as figuras de forma pré-definida, como caixas, cilindros, cones e esferas. Além disto existem várias figuras geométricas avançadas como figuras de extrusão e grids de elevação.
Com base nestes tipos, a linguagem VRML permite que as figuras sejam agrupadas e reagrupadas sempre que necessário para formar figuras mais complexas. O agrupamento das figuras se dá através do nodo Group. O nodo que agrupa outras figuras e nodos é chamado de pai (parent) e as figuras que fazem parte de um grupo são chamadas de filhos (children). Neste contexto, nãohá limite para o número de filhos existentes em um grupo.
1.5 Eventos e Rotas
A linguagem VRML permite a criação de mundos dinâmicos. Para fazer isto, os arquivos VRML devem prever “instruções” para a construção do mundo. Estas instruções descrevem como conectar nodos para atuação conjunta ou condicionada. Por exemplo, abrir uma porta quando o mouse clica em um certo objeto ou acender uma lâmpada nas mesmas condições.
Estes eventos são mecanismos de troca de mensagens entre os objetos e envolvem: - um par de nodos para atuar conjuntamente;
- uma rota de comunicação entre os dois nodos envolvidos;
Uma vez a rota tendo sido definida entre os dois nodos, o primeiro deles pode enviar mensagens ao segundo. Esta mensagens, chamada de event (evento) contém valores que forçarão o nodo receptor a reagir. Existe inclusive a possibilidade de agrupar vários nodos criando um circuito de comunicação.
Cada tipo de nodo apresenta acionadores (jacks) de entrada e saída com os quais as mensagens atuam. Por exemplo, o nodo que cria uma luz (lâmpada) tem um acionador de entrada que pode ligá-la ou desligá-la (on/off). Acionando-o, através do envio de uma mensagem, é possível ligar e desligar esta luz a distância.
É importante salientar que nodos podem ter vários acionadores para interação entre nodos do circuito. Por outro lado, estes acionadores são de entrada (input) e saída (output). Os acionadores de entrada são chamados de eventIn e ou acionadores de saída são chamados de eventOut. Também é importante notar que estes acionadores tem um tipo de dado definido para receber ou enviar através dele.
Neste contexto, o circuito necessita descrever uma rota (route) de um acionador
eventOut de um dado nodo para um acionador eventIn de outro nodo. O circuito
permanecerá inativo até que um evento seja enviado entre os nodos. A reação do segundo nodo depende:
- do tipo de nodo que está recebendo o evento; - do acionador de entrada que foi ativado; - do valor contido no evento;
2
Construção das Figuras
2.1 Nodo Shape
O nodo Shape é utilizado na linguagem VRML para descrever as figuras presentes no ambiente virtual através da sua estrutura tridimensional, definido sua forma geométrica e sua aparência neste mundo. Sua sintaxe é:
Shape {
appearance NULL # SFNode
geometry NULL # SFNode
}
O valor do campo geometry define a forma tridimensional do objeto. Normalmente ele define uma das primitivas geométrica: Box, Cone, Cylinder ou Sphere. O valor default do campo, indicado como nulo, caracteriza a ausência de forma para um objeto.
O valor do campo geometry pode ser alterado através de um evento enviado ao campo eventIn set_geometry. A respostas, após a alteração da forma do objeto, se dará através do campo eventOut geometry_changed.
O campo appearance define a aparência do objeto descrito naquele nodo. Este campo tipicamente inclui o nodo Appearance que, quando nulo, define um objeto com aparência “esbranquiçada”.
O valor do campo appearance pode ser mudado com um evento para o campo evenIn set_appearance e a resposta da mudança da aparência do objeto será enviada através do campo eventOut appearance_changed.
2.2 Nodo Appearance
Conforme mencionado, este nodo tem a função de descrever a aparência do objeto a ele associado. Sua sintaxe é:
Appearance {
material NULL # SFNode
texture NULL # SFNode
textureTransform NULL # SFNode }
O campo material define os atributos de aparência do material que compõem a figura. O valor NULL define um material “sem aparência”. A este campo sempre está associado um outro nodo VRML que traz as propriedades do material.
O campo texture define uma textura a ser aplicada sobre o objeto e
textureTransform indica as transformações que esta textura sofrerá durante o processo de
mapeamento. Veja o capítulo 14 para maiores informações.
2.3 Nodo Material
Este nodo indica as propriedades da simulação física do material que comporá o objeto em questão. Sua sintaxe é:
Material { ambienteIntensity 0.2 # SFFloat diffuseColor 0.8 0.8 0.8 # SFColor emissiveColor 0.0 0.0 0.0 # SFColor shininess 0.2 # SFFloat specularColor 0.0 0.0 0.0 # SFColor transparency 0.0 # SFFLoat }
A função de cada um destes campos será descrita detalhadamente no capítulo 7 deste material. Em linhas gerais são:
- ambienteIntensity: intensidade de luz ambiente;
- diffuseColor: cor difusa do objeto (cor aparente do mesmo); - emissiveColor: cor emitida pelo objeto;
- shininess: coeficiente de brilho daquele objeto;
- specularColor: coeficiente de reflexão especular da luz para o objeto; - transparency: índice de transparência do objeto.
2.4 Primitivos Geométricos
A linguagem VRML traz alguns primitivos geométricos pré-definidos que são utilizados para a composição das figuras presentes nos mundos virtuais. Estes primitivos são: caixa, cone, cilindro e esfera. É importante notar que estes primitivos são, por definição da linguagem, sempre ocos, ou seja, a parte interna dos mesmos é vazia.
a) Nodo Box
Este primitivo define uma caixa (prisma regular de quatro lados) e sua sintaxe é: Box {
size 2.0 2.0 2.0 # SFVec3f
}
O campo size define o tamanho da caixa a ser criada no sentido de cada um dos eixos do sistema. O primeiro valor define o tamanho no sentido do eixo X, o segundo do eixo Y e o terceiro, do eixo Z. Esta caixa será sempre criada de forma centralizada na origem do sistema de coordenadas, ou seja, no ponto (0,0,0).
O exemplo 2.1 apresenta o código necessário para a criação de uma caixa com os valores default, ou seja, quadrada com 2m de lado. O exemplo 2.2, por sua vez, apresenta uma caixa com 1m no sentido do eixo X, 3m no sentido do eixo Y e 5m no sentido do eixo Z. #VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Box{} }
Exemplo 2.1: Criação de uma caixa default.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Box{ size 1.0 3.0 5.0 } }
Exemplo 2.2: Definição de uma caixa de 1x3x5 metros.
b) Nodo Cone
Cone {
bottomRadius 1.0 # SFFloat
height 2.0 # SFFloat
side TRUE # SFBool
bottom TRUE # SFBool
}
O cone a ser criado no mundo virtual estará com a sua base centrada na origem do sistema, no ponto (0,0,0), e seu ápice será projetado no sentido positivo do eixo Y. Os campos presentes no nodo tem a seguinte função:
- bottomRadius: define o raio da base do cone. Seu valor deve ser sempre
maior do zero;
- height: define a altura do cone no sentido positivo do eixo Y. Também
deve ter valor maior do que zero;
- side: campo booleano, verdadeiro ou falso, que define se o lado do cone
(paredes alterais) serão ou não desenhadas no mundo virtual;
- bottom: tem natureza idêntica ao campo side, mas define se a base do
cone será apresentada ou não no mundo virtual.
O exemplo 2.3 apresenta a criação de um cone com os valores default e o exemplo 2.4 um cone com 3.5m de raio na base e 1.5m de altura.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Cone {} }
Exemplo 2.3: Um cone com os valores default.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Cone { bottomRadius 3.5 height 1.5 } }
c) Nodo Cylinder
Este primitivo define um cilindro no mundo virtual e sua sintaxe é: Cylinder {
radius 1.0 # SFFloat
height 2.0 # SFFloat
side TRUE # SFBool
top TRUE # SFBool
bottom TRUE # SFBool
}
O cilindro a ser criado estará localizado ao longo do eixo Y do sistema. Seu raio é a distância entre este eixo e a borda do cilindro e sua altura é centralizada na origem, ou seja, um cilindro de 2m de altura terá 1m acima do eixo X e 1m abaixo deste mesmo eixo. Os campos presentes e sua função são:
- radius: define o raio do cilindro. Deve ter um valor maior do que zero;
- height: define a altura do cilindro no sentido do eixo Y e seu valor
também deve ser maior do que zero;
- side, top e bottom: são campos booleanos que definem se os lados, topo e
base do cilindro, respectivamente, serão ou não apresentados no mundo virtual durante o desenho do primitivo.
Os exemplos 2.5 e 2.6 apresentam dois cilindros. O primeiro deles é criado com os valores default para os campos e o segundo com 4m de raio e 1m de altura. Já o exemplo 2.7 mostra um cilindro onde somente será desenhado o lado do mesmo, ficando a base e o topo sem serem vistos.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Cylinder {} }
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Cylinder { radius 4.0 height 1.0 } }
Exemplo 2.6: Define um cilindro de 1m de altura e 4m de raio.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Cylinder { radius 4.0 height 1.0 top FALSE bottom FALSE side TRUE } }
Exemplo 2.7: Apresenta um cilindro sem a base e o topo (cano).
d) Nodo Sphere
Este primitivo define uma figura geométrica com a forma de uma esfera. Sua sintaxe é:
Sphere {
radius 1.0 # SFFloat
}
Esta esfera tem um raio definido pelo campo radius e seu valor devem sempre ser maior do que zero. A esfera será, assim como as demais figuras, criada centrada no ponto (0,0,0), ou seja, na origem do sistema.
Os exemplo 2.8 e 2.9 apresentam duas esferas. A primeira criada com o valor default do raio (1m) e a segunda com 3.5m de raio.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Sphere {} }
Exemplo 2.8: Uma esfera de 1m de raio.
#VRML V2.0 utf8 Shape{ appearance Appearance{ material Material {} } geometry Sphere { radius 3.5 } }
Exemplo 2.9: Apresenta uma esfera de 3.5m de raio.
2.5 Agrupando Figuras
As figuras criadas no mundo virtual podem ser agrupadas para formar novos e mais complexos nodos que, por sua vez, podem vir a ser agrupados para criar novas figuras. Para esta função a linguagem VRML define um nodo denominado de Group. Sua sintaxe é:
Group {
children [ ] # MFNode
bboxCenter 0.0 0.0 0.0 # SFVec3f
bboxSize -1.0 –1.0 –1.0 # SFVec3f
addChildren # eventIn MFNode
removeChildren # eventOut MFNode
}
O valor do campo children especifica a lista de nodos filhos que serão incluídos neste grupo. Seus componentes são nodos Shape ou outros nodos Group.
Os campos bboxCenter e bboxSize especificam o centro e o tamanho (no sentido de cada eixo) de uma caixa suficientemente grande para envolver todo o grupo. Os valores default listados acima indicam que o navegados VRML deve calcular automaticamente esta caixa, se necessário. Veja o capítulo XX para mais informações.
Os campos addChildren e removeChildren são para tratar os eventos de adição e remoção de um filho ou nodo do grupo em questão.
O exemplo 2.10 apresenta um agrupamento de três figuras geométricas do tipo box, apresentando o sentido de deslocamento dos eixos do sistema de coordenadas. O exemplo 2.11 mostra o agrupamento de vários tipos de figuras com o intuito de espelhar como podem ser compostos objetos mais complexos a partir de figuras mais simples.
#VRML V2.0 utf8 Group{
children[ Shape{
appearance DEF Branco Appearance{ material Material {} } geometry Box{ size 25.0 2.0 2.0 } }, Shape{
appearance USE Branco geometry Box{
size 2.0 25.0 2.0 }
}, Shape{
appearance USE Branco geometry Box{ size 2.0 2.0 25.0 } } ] }
#VRML V2.0 utf8 Group{
children[ Shape{
appearance DEF Branco Appearance{ material Material {} } geometry Box{ size 10.0 10.0 10.0 } }, Shape{
appearance USE Branco geometry Sphere{
radius 7.0 }
}, Shape{
appearance USE Branco geometry Cylinder{ radius 12.5 height 0.5 } }, Shape{
appearance USE Branco geometry Cylinder{ radius 4.0 height 20.0 } }, Shape{
appearance USE Branco geometry Cylinder{ radius 3.0 height 30.0 } }, Shape{
appearance USE Branco geometry Cylinder{ radius 1.0 height 60.0 } } ] }
3
Inserindo Texto
3.1 Introdução
A apresentação de textos em VRML é especificada em dois nodos. O primeiro deles é destinado à apresentação geométrica do texto (nodo Text) e o segundo destinado às propriedades deste texto (nodo FontStyle).
O nodo Text permite o controle do texto a ser impresso, seu tamanho em linhas ou colunas e o tamanho de cada uma delas, além do tipo de fonte a ser utilizado. O nodo
FontStyle faz o controle da aparência do texto a ser apresentado, definindo a família de
fontes, o estilo, tamanho, espaçamento e justificação, entre outras características.
A linguagem VRML faz uso do conjunto de caracteres utf8 e, portanto, somente aqueles caracteres presentes neste padrão serão possíveis de serem utilizados no nodo Text. Este padrão é definido na especificação ISSO 10646-1:1993.
3.2 Nodo Text
O nodo Text, conforme mencionado, define a geometria do texto e pode ser utilizado como valor para o campo geometry do nodo Shape. Sua sintaxe é:
Text {
string [ ] # MFString
length [ ] # MFFloat
maxExtent 0.0 # SFFloat
fontStyle NULL # SFNode
}
O valor do campo string especifica uma ou mais linhas de texto a serem apresentadas no mundo virtual. Cada uma das linhas deve ser expressa com o uso de aspas duplas. Os vários textos presentes neste campo devem ser separados por vírgulas. O valor deste campo pode ser modificado através do campo eventIn set_string. Quando este evento é recebido o campo string é modificado para o novo valor e uma mensagem é enviada pelo
campo eventOut string_changed. O texto criado será localizado sobre o plano XY do sistema de coordenadas (Z=0) e será descrito no sentido crescente do eixo X, ou seja, se olharmos de algum ponto positivo sob o eixo Z, o texto iniciar-se-á na origem e será escrito para a sua direito, como em qualquer outro local.
O campo length especifica o comprimento desejado para cada linha do texto, segundo a medida padrão do sistema VRML. Uma vez especificada uma medida, as linhas são comprimidas ou expandidas, através da mudança do tamanho do caracter ou do espaçamento, para atingirem o tamanho desejado. O valor default de 0.0 especifica que o texto deve ser apresentado de maneira natural, sem preocupação com compressão ou expansão. Este campo admite vários valores, sendo que cada um deles tem validade para uma das linhas do texto, na ordem que aparecerem, ou seja, o primeiro valor para a primeira linha, o segundo valor para a segunda linhas, e assim por diante. Se o número de valores presentes for inferior ao número de linhas, aquelas que excederem este número (as últimas) serão apresentadas como se o seu comprimento default. Finalmente, o valor deste campo pode ser alterado através de um campo eventIn set_length e, o resultado, retorna através do campo evnetOut length_changed.
O campo maxExtent define o comprimento máximo possível admissível ao texto, para qualquer linha ou coluna. As linhas que atingirem um comprimento maior do que o especificado neste campo são comprimidas até que atinjam o limite. Este tamanho é medido horizontalmente para textos horizontais e verticalmente para textos verticais. A este campo está associado outro campo eventIn chamado de set_maxExtent que redefine o comprimento máximo. A resposta a este evento é dada no campo eventOut
maxExtent_changed.
O campo fontStyle define as características que serão utilizadas para apresentar o texto presente no nodo, ou seja, para definir a sua aparência. Normalmente este campo tem como valor um nodo FontStyle a ser visto a seguir. Na ausência deste campo, o valor default de NULL, instrui o navegador a apresentar um texto no sentido esquerda para a direita no caso de texto horizontal e de cima para baixo no caso de texto vertical, justificado pela esquerda e utilizando o tipo de fonte serif. Este campo pode ser alterado através do campo eventIn set_fontSytle e a resposta se dará pelo campo eventOut fontStyle_changed.
Observe o exemplo 3.1 para a criação de um texto simples, utilizando os valores default dos campos, exceto a string.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text { string "Programando em VRML" } }
É possível também a criação de múltiplos campos textos que serão distribuídos em linhas no ambiente virtual. Veja isto no exemplo 3.2.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text {
string [ "Programando", "em VRML" ] }
}
Exemplo 3.2: Distribuindo o texto em linhas.
No exemplo 3.3 o texto mostrado no primeiro exemplo é comprimido para que tenha comprimento igual a 5 unidades. Caso tenhamos um texto disposto em linhas, isto pode ser feito com a determinação de vários valores para o campo length. Veja isto no exemplo 3.4. #VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text { string "Programando em VRML" length 5.0 } }
Exemplo 3.3: Definindo o comprimento do texto.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text {
string [ "Programando", "em VRML" ] length [ 4.0, 3.0 ]
} }
Exemplo 3.4: Definindo o comprimento de cada linha do texto.
Finalmente, no exemplo 3.5, é caracterizada a opção de determinar o comprimento máximo admissível ao texto. Neste exemplo, qualquer valor para o campo length que for maior do que aquele explicitado para o comprimento máximo será ignorado.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text { string "Programando em VRML" maxExtent 5.0 } }
Exemplo 3.5: Definindo o comprimento máximo de um texto.
3.3 Nodo FontStyle
O nodo FontStyle controla a aparência de um texto criado pelo nodo Text. O nodo
FontStyle pode ser utilizado como valor para o campo fontStyle deste último citado. Sua
sintaxe é:
FontStyle {
family “SERIF” # SFString
style “PLAIN” # SFString
size 1.0 # SFFloat
spacing 1.0 # SFFloat
justify “BEGIN” # SFString
horizontal TRUE # SFBool
leftToRight TRUE # SFBool
topToBottom TRUE # SFBool
language “ ” # SFString
}
O campo family especifica a família de fontes que a linguagem VRML irá adotar para apresentar aquele texto. O valor default para o campo é a família serif e todas estão listadas na seguinte tabela:
Nome da Família Descrição
SERIF Fonte de tamanho variável, semelhante ao tipo Times Roman
SANS Fonte de tamanho variável, semelhante ao tipo Helvetica
TYPEWRITER Fonte de tamanho fixo, semelhante ao tipo Courier
O campo style define qual será o estilo de apresentação do texto proposto. O seu valor é um dos presentes na seguinte tabela, sendo o estilo plain o default:
Nome do Estilo Descrição PLAIN Texto normal, sem estilo especial
BOLD Texto apresentado em negrito
ITALIC Texto apresentado em itálico
BOLDITALIC Texto apresentado em negrito e itálico ao mesmo tempo
O campo size especifica a altura dos caracteres com valor medido em unidades do sistema de coordenadas utilizado no ambiente VRML. A altura default dos caracteres é de 1 unidade (metro).
O valor do campo spacing determina o espaçamento vertical entre as linhas que compõem o texto em um texto horizontal. No case de um texto vertical, ele determina o espaçamento entre as colunas do texto.
O campo horizontal especifica se o texto será apresentado no sentido horizontal (TRUE) ou vertical (FALSE). Todo o texto tem uma direção principal e uma direção secundária. A direção principal, para um texto horizontal, é ao longo do eixo X, e a secundária, ao longo do eixo Y. Para um texto vertical, a direção principal é ao longo do eixo Y e a secundária, ao longo do eixo X.
Os campos leftToRight e topToBottom são utilizados em conjunto com o campo
horizontal para controlar a disposição horizontal ou vertical do texto. Para um texto
horizontal, o campo leftToRight especifica como os caracteres consecutivos serão dispostos ao longo da direção principal, da esquerda para a direita (TRUE), no sentido positivo do eixo X, ou da direita para a esquerda (FALSE), no sentido negativo do eixo X. Ainda no caso de textos horizontais, o campo topToBottom especifica como as linhas de texto serão dispostas, se de cima para baixo (TRUE),no sentido negativo do eixo Y, ou de baixo para cima, no sentido positivo do eixo Y.
Quando o texto for vertical, o uso dos campos leftToRight e topToBottom é análogo, mas opera invertendo as direções principal e secundária do texto. O campo topToBottom determina se os caracteres serão dispostos de cima para baixo (TRUE) ou de baixo para cima (FALSE). Já o campo leftToRight determina a disposição das colunas do texto, se elas serão colocadas da esquerda para a direita (TRUE) ou da direita para a esquerda (FALSE).
O campo justify especifica como o bloco de texto será disposto em relação aos eixos X e Y do sistema de coordenadas. Este campo pode receber dois valores de justificação, sendo o primeiro deles considerado como principal e o segundo como secundário. O valor principal controla a disposição do texto ao longo da direção principal do texto e o secundário faz o mesmo em relação a direção secundária do texto. Os valores possíveis para este campo vem da seguinte tabela e o seu efeito depende dos campos leftToRight e
Nome da Justificação
Valor do campo
leftToRight
Descrição
TRUE Coloca o lado esquerdo do bloco de texto no eixo Y
FIRST
FALSE Coloca o lado direito do bloco de texto no eixo Y
TRUE Coloca o lado esquerdo do bloco de texto no eixo Y
BEGIN
FALSE Coloca o lado direito do bloco de texto no eixo Y
TRUE Coloca o meio do bloco de texto no eixo Y MIDDLE
FALSE Coloca o meio do bloco de texto no eixo Y TRUE Coloca o lado direito do bloco de texto no eixo
Y END
FALSE Coloca o lado esquerdo do bloco de texto no eixo Y Nome da Justificação Valor do campo topToBottom Descrição TRUE Coloca o topo do texto no eixo X FIRST
FALSE Coloca a base do texto no eixo X TRUE Coloca o topo do texto no eixo X BEGIN
FALSE Coloca a base do texto no eixo X TRUE Coloca o meio do texto no eixo X MIDDLE
FALSE Coloca o meio do texto no eixo X
TRUE Coloca o lado direito do bloco de texto no eixo X
END
FALSE Coloca o lado esquerdo do bloco de texto no eixo X
O campo language especifica o contexto de linguagem a ser utilizado para apresentação do bloco de texto. Os valores válidos para este campo são baseados no local de apresentação do texto e respeitam padrões internacionais. Os valores válidos vem da seguinte tabela:
Descrição Valor do campo
Linguagem Território
ar Arábico
de Alemão Alemanha
de_DE Alemão Suíça
de_CH Alemão
en Inglês
en_US Inglês Estados Unidos
en_GB Inglês Inglaterra
hi Hindú jp Japonês ru Russo sa Sanscrito sw Swahili zh Chinês zh_TW Chinês Taiwan zh_CN Chinês China
O exemplo 3.6 apresenta a disposição de um texto controlando a família dos caracteres e o estilo de apresentação. Já o exemplo 3.7 controla o tamanho dos caracteres a serem apresentados segundo aquele estilo de fonte.
O exemplo 3.8 mostra como pode ser realizado o controle do espaçamento entre as linhas de um texto e o exemplo 3.9, apresenta um texto composto de duas partes a serem apresentadas com estilos de fonte diferentes.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text { string "Programando em VRML" fontStyle FontStyle { family "SERIF" style "BOLD" } } }
Exemplo 3.6: Controlando a família e estilo do texto.
O exemplo 3.10 dispõem um texto utilizando o campo de justificativa e o exemplo 3.11 apresenta como é possível definir e utilizar posteriormente um estilo de fonte.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text { string "Programando em VRML" fontStyle FontStyle { size 0.5 } } }
Exemplo 3.7: Controlando a altura dos caracteres do texto.
#VRML V2.0 utf8 Shape { appearance Appearance { material Material { } } geometry Text {
string [ "Programando", "em VRML" ] fontStyle FontStyle {
spacing 0.5 }
} }
#VRML V2.0 utf8 Group {
children [ Shape {
appearance DEF Branco Appearance { material Material { } } geometry Text { string "Programando" fontStyle FontStyle { family "SERIF" style "ITALIC" justify "END" size 1.0 } } }, Shape {
appearance USE Branco geometry Text { string "em VRML" fontStyle FontStyle { family "SANS" style "BOLD" justify "BEGIN" size 1.0 } } } ] }
#VRML V2.0 utf8 Group {
children [ Shape {
appearance DEF Branco Appearance { material Material { }
}
geometry Text {
string [ "Acima", "Abaixo" ] fontStyle FontStyle { justify "MIDDLE" } } }, Shape {
appearance USE Branco geometry Box { size 5.0 0.01 2.0 } } ] }
#VRML V2.0 utf8 Group {
children [ Shape {
appearance DEF Branco Appearance { material Material { }
}
geometry Text {
string [ "Programando", "em VRML" ] fontStyle DEF Meu_Estilo FontStyle {
size 3.0 family "TYPEWRITER" justify "MIDDLE" } } }, Shape {
appearance USE Branco geometry Text {
string [ "---", "---" ] fontStyle USE Meu_Estilo
} }
] }
4
Transformando Figuras
4.1 Introdução
Como pode ser observado nas seções anteriores esta, os figuras primitivas básicas e os textos são criados em locais pré-definidos do sistema de coordenadas. Por exemplo, uma esfera é criada, originalmente, centrada na origem do sistema, no ponto (0,0,0).
Por outro lado, na quase totalidade dos casos, a necessidade de localização destas figuras geométricas não está situada nestes pontos pré-definidos. Neste caso, apresenta-se a necessidade de levar a figura para a posição desejada, ou seja, de fazermos uma translação.
O mesmo raciocínio pode ser feito para o tamanho e para a orientação da figura. Quando acontece a mesma situação, na qual a geometria não nos satisfaz, pode ser aplicada uma transformação de escala ou uma rotação para resolver o problema.
4.2 Nodo Transform
Em qualquer um dos casos citados acima, quando se faz necessário alterar geometricamente a figura a ser colocada no ambiente tridimensional, deve ser aplicado a ela um nodo Transform:
Transform { children [ ] # MFNode translation 0.0 0.0 0.0 # SFVec3f rotation 0.0 0.0 1.0 0.0 # SFRotation scale 1.0 1.0 1.0 # SFVec3f scaleOrientation 0.0 0.0 1.0 0.0 # SFRotation bboxCenter 0.0 0.0 0.0 # SFVec3f bboxSize -1.0 –1.0 –1.0 # SFVec3f center 0.0 0.0 0.0 # SFVec3f
addChildren # EventIn MFNode
removeChildren # EventIn MFNode
Neste nodo, o campo children defini as figuras que sofrerão as transformações a serem definidas. Os valores admissíveis para este campo são componentes dos nodos Shape e Group. Os campos translation, rotation e scale definem as transformações de translação, rotação e escala, respectivamente. O campo scaleOrientation também está envolvido com o processo de escala, assim como o campo center participa do processo de rotação.
Os campos bbocCenter e bboxSize definem a localização e o tamanho de um caixa suficientemente grande para envolver toda a figura transformada. Os valores default listados no nodo indicam que esta caixa deverá ser calculada automaticamente pelo navegador se for necessário. A necessidade e aplicação desta caixa será discutida mais adiante.
Finalmente, os campos eventIn addChildren e removeChildren acrescentam um novo nodo para a lista de figuras a serem transformadas e removem um nodo previamente existente nesta lista. Estes campos também serão trabalhados oportunamente.
4.3 Translação
4.3.1 Vetores em 3DA realização de uma operação de translação é baseada na definição de um vetor tridimensional. Considerando dois pontos no espaço, um vetor é um segmento de reta orientado que tem origem em um destes pontos e destino no outro. Em especial, vamos considerar aqueles vetores que tem origem no ponto (0,0,0), ou seja, na origem do sistema de coordenadas.
Todo o vetor é definido por três componentes: direção, sentido e comprimento. A noção de direção é idêntica aquela dada para uma reta, ou seja, é o ângulo pelo qual esta reta corta os eixos do sistema. Como o vetor é um segmento de reta, ele possuí uma dada direção. A componente sentido informa, dados os dois pontos que definem este segmento, qual será a origem e qual será o destino do vetor. Finalmente, a componente direção estabelece a distância existente entre estes dois ponto.
Note que a definição de um vetor é independente da localização deste vetor. Na verdade existe um número infinito de vetores que possuem a mesma direção, sentido e comprimento e, portanto, são iguais. Em especial perceba que o vetor que tem origem no ponto (0,0,0) é idêntico aos demais.
4.3.2 Operação de Translação
Transladar um objeto, em qualquer circunstância significa modificar a sua posição no espaço, trocando-o de local. Se fizermos uma analogia com o mundo real, sempre que trocamos algum objeto de local, ou seja, fizemos uma translação, implicitamente definimos
esta operação como tendo uma direção, um sentido de deslocamento e uma distância. Como estes elementos são exatamente aqueles que definem geometricamente um vetor, este elemento tem papel fundamental na definição desta operação.
Retornando ao nodo Transform, o campo translation é o que caracteriza a existência de uma translação a ser aplicada ao conjunto de objetos listados no campo children e também como são os parâmetros desta operação. Note que ele é sucedido por três valores reais (um campo do tipo SFVec3f) onde deve ser colocado o vetor de translação.
A definição deste vetor pode ser realizada tomando-se como origem do mesmo o ponto (0,0,0) e o destino como um ponto qualquer (Px, Py, Pz). São justamente os valores deste ponto que devem ser listados como valores do campo translation. Por exemplo, se os valores listados forem (-3.0,2.0,2.5), a figura será translada na direção, sentido e comprimento deste vetor, ou seja, 3.0 unidades no sentido negativo do eixo X, 2.0 unidades no sentido positivo do eixo Y e 2.5 unidades no sentido positivo do eixo Z.
#VRML V2.0 utf8 Transform { translation 2.0 0.0 0.0 children [ Shape { appearance Appearance { material Material {} } geometry Cylinder {} } ] }
Exemplo 4.1: Deslocando um cilindro no sentido positivo de X.
Quando deseja-se fazer um deslocamento preservando um ou mais eixos do sistema, basta colocar o valor zero (0.0) no seu respectivo campo. Por exemplo, o vetor (2.0, 0.0, 0.0) faz com que a figura a ser translada não altere as suas coordenadas em Y e Z, apenas deslocando o valor da coordenada X e duas unidades.
#VRML V2.0 utf8 Transform { translation -2.0 0.0 0.0 children [ Shape { appearance Appearance { material Material {} } geometry Cylinder {} } ] }
Os exemplos 4.1 e 4.2 fazem com que a figura de um cilindro seja transladada duas unidades na direção do eixo X. O primeiro exemplo o faz no sentido de X positivo e o segundo, em X negativo. O exemplo 4.3 desloca a mesma figura duas unidades em Y positivo e o exemplo 4.4 faz isto em Z positivo.
#VRML V2.0 utf8 Transform { translation 0.0 2.0 0.0 children [ Shape { appearance Appearance { material Material {} } geometry Cylinder {} } ] }
Exemplo 4.3: Transladando no sentido de Y positivo.
#VRML V2.0 utf8 Transform { translation 0.0 0.0 2.0 children [ Shape { appearance Appearance { material Material {} } geometry Cylinder {} } ] } Exemplo 4.4: Transladando em +Z.
Existe ainda a possibilidade de estabelecermos deslocamentos em múltiplos eixos. É o que acontece no exemplo 4.5 onde a figura é deslocada 2 unidades em X positivo, 1 em Y positivo e 2 em Z negativo. #VRML V2.0 utf8 Transform { translation 2.0 1.0 -2.0 children [ Shape { appearance Appearance { material Material {} } geometry Cylinder {} } ] }
#VRML V2.0 utf8 Group {
children [ # Chao Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 25.0 0.1 25.0 } }, # Coluna da esquerda Transform { translation -2.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Coluna da direita Transform { translation 2.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Cobertura Transform { translation 0.0 6.05 0.0 children Shape {
appearance USE Branco geometry Box { size 4.6 0.4 0.6 } } } ] }
Uma vez compreendido o processo de múltiplas translações, é possível compor figuras mais complexas através de vários deslocamentos realizados em figuras diferentes. O exemplo 4.6 define duas colunas (cilindros), desloca-as para os lados esquerdo e direito do observador e para “cima” (+Y), criando a base para uma espécie de pórtico. Feito isto, o exemplo cria uma caixa que será utilizada na cobertura do pórtico e a coloca na parte de cima das colunas.
No exemplo 4.7 é criada a mesma figura do exemplo 4.6 e feita uma segunda cópia da mesma que, por sua vez, é deslocada duas unidades no sentido negativo do eixo Z.
#VRML V2.0 utf8 Group {
children [ # Chao Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 25.0 0.1 25.0 } }, # Coluna da esquerda DEF ColunaE Transform {
translation -2.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Coluna da direita DEF ColunaD Transform {
translation 2.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Cobertura
DEF Cobertura Transform { translation 0.0 6.05 0.0
children Shape {
appearance USE Branco geometry Box { size 4.6 0.4 0.6 } } }, # Segundo objeto Transform { translation 0.0 0.0 -2.0 children [ USE ColunaE USE ColunaD USE Cobertura ] } ] }
Exemplo 4.7: Faz uma cópia da figura do exemplo anterior e coloca-a em outra posição.
4.4 Rotação
A operação de rotação é definida no campo rotation do nodo Transform. Este campo estabelece quatro valores reais. Os três primeiros deles representam um eixo imaginário no sistema de coordenadas em torno do qual a figura irá girar. O quarto e último parâmetro representa o ângulo de rotação.
A definição de um eixo dentro do sistema de coordenadas no qual acontecerá a rotação é necessária em razão desta operação acontecer sempre em volta de algum segmento. A definição deste eixo segue os mesmos princípios dos vetores utilizados na translação. Aqui, entretanto, o comprimento do vetor não é considerado e sim a sua direção e sentido de crescimento.
A rotação irá acontecer em torno deste eixo por um ângulo medido sempre em radianos1
e é orientada também pela regra da mão direita. Considere que, com a mão direita envolvemos o eixo de rotação, com o polegar apontando no sentido positivo de crescimento do mesmo. Se este ângulo for positivo, a figura irá girar no sentido em que apontam os demais dedos da mão. Se o ângulo for negativo, acontece o contrário.
Existe ainda a possibilidade de especificarmos um centro de rotação para a figura através do campo center do nodo Transform. Por definição, o centro de rotação das figuras é a origem do sistema de coordenadas, ou seja, o ponto (0,0,0). Com o uso deste campo você especifica um outro sistema de coordenadas (outro ponto de referência) que servirá de base para a rotação. Isto é necessário quando possuímos figuras articuladas como a junção de braços e pernas, onde o movimento força o giro em torno de um outro ponto que não a origem do sistema.
1
Os exemplos 4.8, 4.9, 4.10 e 4.11 fazem com que uma caixa seja rotacionada em 0,785 radianos (45º graus) em torno dos eixos +X, +X, +Y e +Z, respectivamente. No segundo exemplo o ângulo de rotação é negativo e a figura girará no sentido contrário ao do exemplo 4.8. #VRML V2.0 utf8 Transform { rotation 1.0 0.0 0.0 0.785 children [ Shape { appearance Appearance { material Material {} } geometry Box {} } ] }
Exemplo 4.8: Girar um caixa por 45 graus em torno do eixo X.
#VRML V2.0 utf8 Transform { rotation 1.0 0.0 0.0 -0.785 children [ Shape { appearance Appearance { material Material {} } geometry Box {} } ] }
Exemplo 4.9: Girar um caixa por –45 graus em torno do eixo X.
#VRML V2.0 utf8 Transform { rotation 0.0 1.0 0.0 0.785 children [ Shape { appearance Appearance { material Material {} } geometry Box {} } ] }
#VRML V2.0 utf8 Transform { rotation 0.0 0.0 1.0 -0.785 children [ Shape { appearance Appearance { material Material {} } geometry Box {} } ] }
Exemplo 4.11: A caixa irá girar em torno do eixo Z.
#VRML V2.0 utf8 Group {
children [
DEF Coluna Shape {
appearance Appearance { material Material {} } geometry Cylinder { height 1.0 radius 0.1 } }, Transform { rotation 1.0 0.0 0.0 1.047 children USE Coluna
},
Transform {
rotation 1.0 0.0 0.0 2.094 children USE Coluna
} ]
}
Exemplo 4.12: Girando vários objetos.
Os exemplo 4.12 e 4.13 criam uma figura mais complexa que é formada por primitivos simples (cilindros) rotacionados convenientemente. O exemplo 4.14 toma o pórtico construído no exemplo 4.6 e coloca uma cobertura no mesmo girando duas caixas que formarão o telhado.
#VRML V2.0 utf8 Group {
children [
DEF Coluna1 Shape {
appearance Appearance { material Material {} } geometry Cylinder { height 1.0 radius 0.1 } },
DEF Coluna2 Transform {
rotation 1.0 0.0 0.0 1.047 children USE Coluna1
},
DEF Coluna3 Transform {
rotation 1.0 0.0 0.0 2.094 children USE Coluna1
}, Transform { rotation 0.0 1.0 0.0 1.785 children [ USE Coluna2, USE Coluna3 ] } ] }
Exemplo 4.13: Agregando mais objetos ao exemplo 4.12.
#VRML V2.0 utf8 Group {
children [ # Chao Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 25.0 0.1 25.0 } }, # Coluna da Esquerda
translation -2.0 3.0 0.0 children DEF Coluna Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Coluna da Direita
DEF ColunaD Transform { translation 2.0 3.0 0.0 children USE Coluna },
# Cobertura
DEF Cobertura Transform { translation 0.0 6.05 0.0 children Shape {
appearance USE Branco geometry Box { size 4.6 0.4 0.6 } } }, # Telhado
DEF TelhadoE Transform {
translation -1.15 7.12 0.0 rotation 0.0 0.0 1.0 0.524 children DEF Telha Shape { appearance USE Branco geometry Box {
size 2.86 0.4 0.6 }
} },
DEF TelhadoD Transform { translation 1.15 7.12 0.0 rotation 0.0 0.0 1.0 -0.524 children USE Telha
} ]
}
Exemplo 4.14: Colocando telhado no pórtico do exemplo 4.6.
O exemplo 4.15 constrói um abajur estilizado. Note que para formar a articulação de junção das duas partes do braço do abajur é necessário estabelecer um centro de rotação diferente da origem. Neste caso o ponto escolhido é (0.0, –0.15, 0.0).
#VRML V2.0 utf8 Group {
children [
# Base da lampada Shape {
appearance DEF Branco Appearance { material Material {} } geometry Cylinder { radius 0.1 height 0.01 } }, # Braco da lampada Transform { translation 0.0 0.15 0.0 rotation 1.0 0.0 0.0 -0.7 center 0.0 -0.15 0.0 children [
DEF Braco Shape {
appearance USE Branco geometry Cylinder { radius 0.01 height 0.3 } }, Transform { translation 0.0 0.3 0.0 rotation 1.0 0.0 0.0 1.9 center 0.0 -0.15 0.0 children USE Braco }
] }
] }
Exemplo 4.15: Desenho de um abajur.
4.5 Escala
A operação de escala faz com que as dimensões de uma figura sejam ampliadas ou reduzidas conforme a necessidade. Ela é realizada através do campo scale do nodo
Transform.
Este campo é representado por três valores reais que especificam os fatores de escala para cada um dos eixos do sistema de coordenadas. O primeiro deles nos diz o
quanto desejamos aumentar ou diminuir a figura no sentido do eixo X; o segundo, em Y; e, o terceiro em Z.
Os fatores de escala são valores maiores do que zero (0) necessariamente. Se eles estão no intervalo ] 0 ; 1 [, acontece uma redução proporcional ao valor. Por exemplo, o valor de 0.5 reduz a figura a metade do seu tamanho original naquele eixo. Se os valores forem maiores do que 1, ocorre uma ampliação desta figura. O valor de 1 para a escala não acarreta em modificações da figura.
Se os fatores de escala forem iguais, esta operação acontece de forma uniforme, ou seja, preservando as proporções originais da figura. O mesmo não acontece se estes valores forem diferentes.
Em algumas situações não é suficiente ou desejável aplicar a escala tendo como referência os eixos X, Y e Z do sistema de coordenadas. Para estes casos é previsto um outro campo do nodo Transform chamado de scalaOrientation, que descreve um novo sistema de coordenadas para aplicação da escala através da rotação do sistema original. Os seus parâmetros são os mesmos e tem a mesma função daqueles utilizados na operação de rotação.
Ainda é possível especificar um novo centro de referência para a operação de escala através do campo center. Assim como na rotação, este campo especifica um ponto que é a origem deste novo centro.
Observando a aplicação da transformação de escala, nos exemplos 4.16, 4.17, 4.18, 4.19 e 4.20, é apresentada a transformação de uma esfera em um processo de escala não uniforme, ou seja, o resultado final é topologicamente equivalente a uma esfera, mas a sua forma não é idêntica.
#VRML V2.0 utf8 Transform { scale 2.0 1.0 1.0 children [ Shape { appearance Appearance { material Material {} } geometry Sphere {} } ] }
#VRML V2.0 utf8 Transform { scale 0.5 1.0 1.0 children [ Shape { appearance Appearance { material Material {} } geometry Sphere {} } ] }
Exemplo 4.17: Outra transformação da esfera.
#VRML V2.0 utf8 Transform { scale 1.0 2.0 1.0 children [ Shape { appearance Appearance { material Material {} } geometry Sphere {} } ] }
Exemplo 4.18: A esfera ampliada diferenciadamente nos eixos do sistema.
#VRML V2.0 utf8 Transform { scale 1.0 1.0 0.5 children [ Shape { appearance Appearance { material Material {} } geometry Sphere {} } ] }
#VRML V2.0 utf8 Transform { scale 2.0 0.5 4.0 children [ Shape { appearance Appearance { material Material {} } geometry Sphere {} } ] }
Exemplo 4.20: A esfera reduzida no eixo Y e ampliada nos demais.
#VRML V2.0 utf8 Group {
children [
DEF Corpo Transform { scale 0.5 1.0 1.5 children Shape {
appearance DEF Branco Appearance { material Material {} } geometry Cylinder { radius 1.0 height 0.025 } } },
DEF Fuselagem Transform { scale 2.0 0.2 0.5 children Shape {
appearance USE Branco geometry Sphere {} } }, Transform { scale 0.3 2.0 0.75 children [ USE Corpo USE Fuselagem ] } ] }
O exemplo 4.21 desenha um avião estilizado utilizando-se apenas da deformação de figuras básicas como esferas e cilindros. O exemplo 4.22 faz cópias do pórtico utilizado no exemplo 4.14 e reduz estas cópias a metade do tamanho original. Note que os fatores de escala deste exemplo são iguais, portanto a escala é uniforme e o resultado é uma figura com as mesmas proporções da original
#VRML V2.0 utf8 Group {
children [ # Chao Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 25.0 0.1 25.0 } },
DEF Casa Group { children [
# Coluna da Esquerda
DEF ColunaE Transform { translation -2.0 3.0 0.0 children DEF Coluna Shape {
appearance USE Branco geometry Cylinder { radius 0.3 height 6.0 } } }, # Coluna da Direita
DEF ColunaD Transform { translation 2.0 3.0 0.0 children USE Coluna },
# Cobertura
DEF Cobertura Transform { translation 0.0 6.05 0.0 children Shape {
appearance USE Branco geometry Box {
size 4.6 0.4 0.6 }
} },
# Telhado
DEF TelhadoE Transform {
translation -1.15 7.12 0.0 rotation 0.0 0.0 1.0 0.524 children DEF Telha Shape { appearance USE Branco geometry Box {
size 2.86 0.4 0.6 }
} },
DEF TelhadoD Transform { translation 1.15 7.12 0.0 rotation 0.0 0.0 1.0 –0.524 children USE Telha
} ]
},
# Faz copias de tamanho diferente Transform {
translation -4.0 0.0 0.0 scale 0.5 0.5 0.5
children USE Casa },
Transform {
translation 4.0 0.0 0.0 scale 0.5 0.5 0.5
children USE Casa }
] }
Exemplo 4.22: Criando duas cópias do pórtico do exemplo 4.14.
A figura do exemplo 4.23 é transformada tendo como base um novo centro de referência no ponto (0,-1,0), o que faz com que a árvore da figura aumente seu tamanho tendo como base o ponto dado e não a origem do sistema.
Por último, o exemplo 4.24 apresenta uma transformação de escala definida como uma orientação diferente do usual, o que faz com que a árvore incline para o lado indicado pelo novo eixo de orientação.
#VRML V2.0 utf8 Group {
children [ Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 12.0 0.1 12.0 } }, Transform { translation 0.0 1.0 0.0 scale 1.0 2.0 1.0 center 0.0 -1.0 0.0 children [ Shape {
appearance USE Branco geometry Cylinder { radius 0.5 height 2.0 } }, Transform { translation 0.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cone { bottomRadius 2.0 height 4.0 } } } ] } ] }
#VRML V2.0 utf8 Group {
children [ Shape {
appearance DEF Branco Appearance { material Material {} } geometry Box { size 12.0 0.1 12.0 } }, Transform { translation 0.0 1.0 0.0 scale 1.0 2.0 1.0 scaleOrientation 0.0 0.0 1.0 -0.785 center 0.0 -1.0 0.0 children [ Shape {
appearance USE Branco geometry Cylinder { radius 0.5 height 2.0 } }, Transform { translation 0.0 3.0 0.0 children Shape {
appearance USE Branco geometry Cone { bottomRadius 2.0 height 4.0 } } } ] } ] }
5
Animando o Posicionamento,
Orientação e Escala das Figuras
5.1 Introdução
Para adicionar movimento ao mundo virtual, uma das alternativas é animar o posicionamento, orientação e escala de uma cena. Se o sistema de coordenadas desta cena se move, todas as figuras construídas nela também se moverão.
Neste contexto, entende-se como animação qualquer modificação da figura que ocorre em um determinado intervalo de tempo. Os dois elementos básicos deste processo são um relógio que controla a animação no tempo e a descrição do que irá e como irá mudar neste intervalo de tempo. A linguagem VRML fornece o nodo TimeSensor para criar o relógio e os nodos PositionInterpolator e OrientationInterpolator para controlar as modificações. Estes últimos tem a função de definir a orientação ou posição correta da figura a partir das informações de tempo obtidas do relógio.
O nodo TimeSensor age como um relógio real, contabilizando o tempo a partir do momento da sua inicialização. Sempre que estiver ativo, o tempo corrente é disponibilizado pelo seu campo eventOut time. Para fazermos o controle da animação, estes eventos de saída (tempo) devem ser roteados para os nodos que controlam as modificações.
Quando trabalha nestas condições, o resultado do nodo TimeSensor é uma unidade de tempo absoluto, medido em segundos, desde a 00:00 hora do dia 1ºde janeiro de 1970. Nesta situação, o segundo 0 (zero) aconteceu nesta data, o segundo 1 logo a seguir e assim por diante. Através disto, é possível programar o nodo TimeSensor para agir em datas e horas específicas. Isto acontece quando o tempo específico de início e fim da atuação do nodo é informado aos campos startTime e stopTime.
Apesar de fornecer um bom mecanismo de controle, a medida do tempo de forma absoluta nem sempre é conveniente ao trabalho. Muitas vezes, senão a maioria delas, necessita-se apenas animar uma figura num certo intervalo de tempo que independe da data e da hora exata. Este tempo é conhecido como tempo fracional. Nele a animação começa no
tempo 0 (zero) e termina o tempo 1 (um), podendo ser fracionada neste intervalo como for necessário. Como isto, na maioria das vezes, não o suficiente, é possível ainda colocar este tempo em um loop e repetí-lo tanto quanto seja necessário.
5.2 Processo de Animação
Conforme mencionado, o resultado do cômputo do tempo é utilizado nos nodos de interpolação para calcular o valor exato da translação ou rotação a ser informado ao nodo
Transform. Este tem a responsabilidade de apresentar a figura, como visto anteriormente.
Neste processo, uma descrição da animação deve fornecer a posição ou orientação para cada nova unidade de tempo fracional pertencente ao intervalo listado. De forma mais simples podemos dizer que esta descrição funciona como uma tabela, havendo uma entrada de descrição para cada entrada de tempo existente. Os valores de posicionamento ou orientação calculados para estes tempos são chamados de valores de chave (key values). O interpolador VRML utiliza estes valores de chave e os de tempo para construir um modelo ou rascunho da animação e preenche os valores entre aqueles especificados por conta própria, se necessário.
Por exemplo, caso se deseje fazer com que um carro vá da esquerda para a direita, pode-se mencionar apenas os valores 0.0 e 1.0 como tempos fracionais, pois se tratando de uma reta, o interpolador não terá dificuldades em encontrar os valores intermediários necessários. Nesta situação, o tempo fracionário 0.5 terá seus valores calculados pelo interpolador e corresponderá ao meio do caminho. Por outro lado, se desejamos fazer com que o carro faça um curva, será necessário fornecer mais valores no intervalo para que o mesmo descreva esta curva de forma “suave”.
Assim sendo, os nodos PositionInterpolator e OrientationInterpolator utilizam os valores listados de tempo fracional e valores de chave para descrever a animação. Os tempos fracionais são descritos no campo key e os valores chave no campo keyValue. Ambos os campos podem ter qualquer quantidade de valores, mas sempre na correspondência de um para um.
Para finalizar, o interpolador VRML utiliza-se sempre de uma interpolação linear entre dois valores de chave listados, ou seja, o caminho encontrado entre os dois será sempre uma reta. Todos os pontos calculados neste intervalo farão parte deste segmento. Desta forma, para descrever um caminho curvo, vários pontos de interpolação deverão ser descritos, em quantidade tanta quanto for a precisão desejada.
Durante a aplicação, quando é necessário fazer uma interpolação de posicionamento, o interpolador calcula os respectivos valores para as coordenadas X, Y e Z dos pontos necessário ao processo. Já para realizar uma animação de rotação, além do eixos de rotação X, Y e Z, é necessário interpolar também o ângulo de rotação.
O valor computado pelo nodo PositionInterpolator é do tipo SFVec3f e é projetado para ser utilizado como entrada de valores de translações ou coordenadas tridimensionais. O nodo Transform, por exemplo, utiliza um valor deste como definição do campo
translation e, por tanto, o interpolador de posições pode controlá-lo. De forma analógica,
podemos fazer a mesma relação para o interpolador de orientação, pois o seu resultado é no mesmo formato necessário ao campo rotation.
Seguindo esta linha de raciocínio, todo o campo que necessite de um valor SFVec3f como entrada é candidato a ser animado através do interpolador de posicionamento. O mesmo para a orientação. Em especial, este procedimento pode ser adotado para o campo
scale do nodo Transform que controla a escala aplicada a um objeto e tem um campo no
formato SFVec3f. Através do PositionInterpolator podemos então animar fatores de escala para um dado objeto.
5.3 Nodo TimeSensor
O nodo TimeSensor, mencionado nas seções anteriores é o responsável pelo controle do relógio que gera os eventos para a animação. Sua sintaxe é:
TimeSensor {
enable TRUE # SFBool
startTime 0.0 # SFTime
stopTime 0.0 # SFTime
cycleInterval 1.0 # SFTime
loop FALSE # SFBool
isActive # eventOut SFBool
time # eventOut SFTime
cycleTime # eventOut SFTime
fraction_changed # eventOut SFFloat
}
O valor do campo enable especifica se o relógio está ativado ou não. Se o seu valor é TRUE, o relógio está ligado e o restante dos campos do nodo são utilizados para controlar este funcionamento. Se o seu valor é FALSE, o relógio está desligado e nenhuma saída é produzida em intervalos de tempo.
Os campos startTime e stopTime especificam os tempos nos quais o relógio deve ser ligado ou desligado, respectivamente. O campo cycleInterval especifica a quantidade de tempo no qual o interpolador deverá levar para ir do tempo fracionário 0.0 para o tempo 1.0. Por exemplo, podemos especificar apenas os dois extremos do intervalo para animar uma figura, mas desejamos ir do primeiro para o último em 30 segundos ou em 10 segundos. Este último será o valor do campo cycleInterval.