Introdução
Essse documento tem por objetivo mostrar, através de exemplos práticos alguns conceitos básicos de VRML 2.0, tais como criação de objetos simples, aplicação de cor e textura aos objetos, como fazer links e includes e animações simples.
Histórico
VRML (Virtual Reality Modeling Language) é uma linguagem que serve para descrever objetos e mundos 3D interativos através do world wide web. A primeira especificação de VRML1.0 foi criada pela Silicon Graphics Inc. baseada na linguagem OpenInventor. Na segunda versão, foram adicionadas mudanças significativas na capacidade interativa. Esta versão foi desenvolvida pela Silicon Graphics (http://www.sgi.com)com contribuições da SONY Research (http://www.sony.com) e da Mitra (http://www.mitra.com).
Esta primeira parte deste tutorial objetiva mostrar as características básicas da linguagem VRML 2.0 e suas diferenças em relação à primeira versão.
Se desejar, o leitor pode obter um tutorial de VRML 1.0 no endereço: http://tinos.pucrs.br/~grv/
3. Definições básicas
3.1 Node
É o componente fundamental de uma cena em VRML. Pode ser definido como abstrações dos objetos e conceitos do mundo real, por exemplo, esfera, cubos, luzes e descrição de materiais. Os nodes contém campos e eventos.
3.2 Geometry node
O nodo geometry é representado pelos tipos Box,Cone, Cylinder, ElevationGrid,
IndexedFaceSet, IndexedLineSet, PointSet, Sphere, Text. este nodo contém uma descrição de pontos tridimensionais, linhas, superfícies, string de textos e objetos sólidos.
3.3 Children node
São nodos nos quais vários nodos filhos são agrupados e estes são afetados pelas transformações feitas no nodo pai. Serve para criar uma hierarquia de transformações que são herdadas de pai para filho.
3.4 Event
São utilizados para a troca de mensagens de um nodo para outro, através de uma rota ( ver item 3.7 Route ). Os eventos sinalizam mudanças nos valores dos campos, estímulos externos, interações entre nodos, etc.
3.5 Field
Os parâmetros distinguem um nodo de outro do mesmo tipo. Fields podem conter vários tipos de dados e um ou mais valores.
3.6. Appearance node
O nodo appearance é representado pelos tipos Appearance, FontStyle, ImageTexture, Material, MovieTexture, PixelTexture e TextureTransform, e seu objetivo é controlar a aparência "renderizada" dos nodos geométricos (objetos) as quais estão relacionados.
3.7 Route ( Rota )
É a conexão entre o nodo gerador do evento e o nodo receptor do evento.
4. Características do VRML2.0
VRML 1.0 permitia a criação e a visualização de mundos 3D, VRML 2.0 permite estes recursos e ainda a capacidade de interação, melhoria nos mundos estáticos, animação, prototipação e script, conforme será apresentado a seguir.
4.1 Interação
Para permitir interação VRML 2.0 criou o conceito de sensores. Nodos sensores habilitam eventos quando o objeto se move para certas áreas do mundo virtual e quando certos objetos são clicados. Estes sensores permitem que o usuário arraste objetos ou controle o objeto de um lugar para outro. Outro tipo de sensor permite que se faça animações repetitivas, baseadas em um certo período de tempo pré-definido.
Detecção de colisões permitem que objetos sólidos (virtuais) reajam como se fossem objetos reais, isto é, bloqueando movimentos de outros objetos quando estes se chocarem, não existindo mais a possibilidade de andar através das paredes. O terrenos em que o usuário está navegando acompanha os movimentos feitos por ele, como descer ou subir degraus ou rampas.
4.2 Animação
VRML 2.0 possui uma variedade de objetos ( orientação a objetos ) animados que são chamados interpoladores. Isto permite que sejam criadas animações pré-definidas que vão ocorrer em um determinado evento ou tempo oportuno. Alguns exemplos de animações pré-definidas que o usuário pode criar com o uso de interpoladores são pássaros voando, portas com abertura e fechamento automático, robôs andando, objetos que trocam de cor quando se movem (sol , por exemplo), objetos que realizam metamorfose da sua geometria original para outra forma.
4.3 Prototipação
Em VRML 2.0 permite-se o encapsulamento de grupos de vários nodos formando um novo tipo de nodo, isto é, um protótipo. Este protótipo fica disponível para qualquer nova aplicação e criação de novas instâncias.
4.4 Scripting
Em VRML 2.0 pode-se definir scripts para cada objeto ou nodo. Isto significa que não somente se pode animar criaturas e objetos em um mundo, mas também dar-lhes características próprias, como por exemplo animação de um cachorro pegando um jornal, relógio de pulso que se move, pássaros que voam, etc.
Estes efeitos são acessados de acordo com a ocorrência de eventos no mundo virtual, um script capta dados do sensor e gera eventos baseados nesta entrada. Eventos são transmitidos para os nodos por caminhos os quais são denominados rotas (ver item 3.7) .
4.5 Extensão do Mundo Estático
Nodos permitem a criação de cenários de fundo (solo e céu) para as cenas, adicionar montanhas distantes, nuvens, fumaças. Esta característica permite também a criação de terrenos irregulares ao invés de usar simples retas para superfícies.
5. Primeiro programa em VRML 2.0
Um programa em VRML inicia sempre com a linha #VRML V2.0 utf8. Toda a especificação de objetos, links, atributos ou transformações, é colocada dentro de blocos que são definidos pela expressão Transform.
Os comentários em VRML iniciam sempre pelo símbolo # e valem na linha em que este aparece. É bom lembrar que assim com C e C++, VRML também é case-sensitive, ou seja, diferencia letras maiúsculas e minúsculas. Quando se cria um objeto em VRML ele é colocado no centro da tela (0,0,0), isto se o usuário não aplicar uma movimentação no objeto.
Em VRML 2.0 é possível o agrupamento de nodos, que possibilita a criação de transformações baseadas numa hierarquia, isto é realizado através da utilização do campo children, que está presente nos seguintes comandos VRML: Anchor, Background, Collision, CylinderSensor, DirectionalLight, Inline, OrientationInterpolator, PointLight, Shape, SpotLight, SphereSensor, Switch, TimeSensor, TouchSensor, Transform. Isto significa que utilizando-se de qualquer um dos comandos acima, este deverá estar dentro de um nodo filho (children), porém o comando Transform serve também para demarcar blocos, então poderá aparecer vários comandos Transform um dentro do outro. O exemplo que segue abaixo serve para demonstrar o conteúdo deste parágrafo.
Em VRML o sistema de coordenadas utilizado segue o esquema da figura 1.
#VRML V2.0 utf8
Transform
{
rotation 1 0 0 1.57
children [
Shape {
geometry Sphere {radius 5} #esfera que aparece entre os dois paralelepípedos
}
#utilizando o comando DEF define-se um bloco que poderá ser reutilizado em
#outro local apropriado, evitando-se que se escreva todo o código novamente
#porém ao se definir um bloco este também é exibido na cena
#define um bloco com o nome "Quadra"
DEF Quadra Transform
{
translation 7 0 0
children [
Shape { # paralelepípedo que aparece à direita na figura
geometry Box {size 2 3 5}
}
]
}
Transform
{
#herda as transformações geométricas que foram feitas na definição do objeto (DEF #Quadra Transform), isto é, soma as transformações feitas na definição do bloco com #as transformações feitas na chamada do bloco, através do comando USE.
translation -14 0 0
children [ USE Quadra ] #paralelepípedo que aparece à esquerda na figura
}
]
}
5.1 Definindo objetos
Para criar um objeto em VRML 2.0 usa-se o comando Shape. Neste comando define-se a geometria e a aparência do objeto.
A geometria de um objeto é definida pelo comando Geometry. As possibilidades de objetos são paralelepípedo, cilindro, cone e esfera.
A aparência, por sua vez, diz respeito à cor e à textura do objeto.Para definir a aparência, existe o comando Appereance.
5.1.1 Definindo um Paralelepípedo
Na definição de um paralelepípedo utiliza-se a diretiva:
Box { size comprimento altura profundidade }.
#VRML V2.0 utf8
#Exemplo de um paralelepípedo em VRML 2.0
Transform
{
children
[
Shape {
geometry Box { size 1 5 10 }
}
]
}
5.1.2 Definindo um Cone
Na definição de um cone utiliza-se a diretiva:
Cone { bottomRadius raio da base do cone height altura do cone }
#VRML V2.0 utf8
Transform
{
children
[
Shape{
geometry Cone { bottomRadius 2 height 5 }
}
]
}
5.1.3 Definindo uma Esfera
Na definição de uma esfera utiliza-se a diretiva:
Sphere { radius tamanho do raio da esfera }.
#VRML V2.0 utf8
#Exemplo de uma esfera em VRML 2.0
Transform
{
children
[
Shape {
geometry Sphere {radius 5}
}
]
}
5.1.4 Definindo um Cilindro
Na definição de um cilindro utiliza-se a diretiva:
Cylinder { height altura do cilindro radius raio do cilindro }.
#VRML V2.0 utf8
Transform
{
children
[
Shape {
geometry Cylinder {height 10 radius 3}
}
]
}
5.2 Definindo transformações geométricas
Os objetos definidos nos programa apresentados até aqui aparecem sempre com seu centro em (0,0,0).
Na figura a seguir, por exemplo, dois paralelepípedos de tamanhos diferentes aparecem com o centro na mesma posição (0,0,0).
#VRML V2.0 utf8
Transform
{
children
[
Shape {
geometry Box {size 2 9 2}
}
Shape {
geometry Box {size 6 6 6}
}
]
}
Para permitir o reposicionamento de objetos em posições e orientações diferentes, a linguagem VRML 2.0, possui três tipos de transformações básicas: translação, rotação e escala.
5.2.1 Definindo uma translação
Uma translação consiste na mudança da posição de um objeto no espaço. O comando para a realização da translação é:
translation valor em x valor em y valor em z
Para definir uma translação é preciso especificar além da posição dos objetos, quais são os nodos filhos desta translação. Para tanto existe o comando:
children [objeto1, objeto2, objeto3, ... objeto n]
Neste contexto os objetos são comandos do tipo Shape. Todos os objetos dentro dos colchetes sofrem a mesma transformação.
No exemplo a seguir, um cubo de aresta 6 é movido para a posição 3, 6, 9 e outro para a posição 4, 5, 6.
#VRML V2.0 utf8
Transform
{
translation 3 6 9
children
[
Shape {
geometry Box {size 6 6 6}
}
]
}
Transform
{
translation 4 5 6
children
[
Shape {
geometry Box {size 6 6 6}
}
]
}
5.2.2 Definindo uma rotação
Uma rotação consiste em alterar a posição de um objeto em torno de um eixo no espaço. Sendo assim, deve-se estabelecer um eixo ( X, Y, Z) para a rotação e um quarto parâmetro para o ângulo de rotação, que deve estar em radianos:
rotation x y z angulo
No exemplo a seguir, um cone irá ser rotacionado em 90° no eixo Y, enquanto o outro cone manterá sua posição normal, transladado de 5 unidades no eixo X.
#VRML V2.0 utf8
Transform
{
rotation 0 1 0 1.57 #eixo 0,1,0 ângulo 1.57 radianos
children [
Shape {
geometry Cone{ bottomRadius 2 height 5 }
}
]
}
Transform
{
translation 5 0 0
children [
Shape {
geometry Cone{ bottomRadius 2 height 5}
}
]
}
5.2.3 Definindo escala
Escala consiste em alterar a proporção de tamanho dos objetos em um ou mais eixos, para tanto, utiliza-se a diretiva:
scale tamanho x tamanho y tamanho z
#VRML V2.0 utf8
Transform
{
scale 10 1 1
children [
Shape
{
geometry Box { size 2 2 2 }
}
]
}
5.3 Definindo a aparência dos objetos
As possíveis manipulações com relação a aparência dos objetos são feitas com as diretivas: Appearance, ImageTexture, Material .
5.3.1 Utilizando texturas
O formato do arquivo contendo uma textura pode ser um GIF, JPG ou PNG.
#VRML V2.0 utf8
Transform
{
children
[
Shape
{
appearance Appearance
{
texture ImageTexture
{url "outros\puclogo.gif"} #caminho e nome da imagem
}
geometry Box{size 2 2 2}
}
]
}
5.3.2 Utilizando cores
O formato das cores é RGB, sendo que cada componente pode assumir valores entre 0.0 e 1.0.
#VRML V2.0 utf8
Transform
{
children
[
Shape
{
appearance Appearance
{
material Material{diffuseColor 0 0 1} #cor azul
}
geometry Sphere {radius 2}
}
]
}
Todas as possibilidades de cores e elementos relacionados a aparência do objeto estão sendo utilizadas no exemplo abaixo:
#VRML V2.0 utf8
Transform
{
children
[
Shape
{ #a palavra appearance se refere ao campo do comando Shape, já
#a palavra Appearance se refere ao nodo, que por sua vez
#possui um campo chamado material, que deve conter um nodo do tipo
#Material
appearance Appearance #aparencia do cone
{
material Material {diffuseColor 0 0 1, #cor difusa
ambientIntensity 0.6, #intensidade do ambiente
emissiveColor 0 0 1, #cor emissiva
shininess 0.3 #brilho
specularColor 0 0 0.7 #cor especular
transparency 0 #transparencia do objeto
}
}
geometry Cone {bottomRadius 2 height 5} # cone de altura 5 e
# raio da base 2
}
]
}
5.4 Utilizando iluminação e luzes
Existem três tipos básicos de luzes em VRML 2.0. Luz pontual, direcional e spot.
5.4.1 Utilizando luz pontual
Posiciona nos eixos cartesianos um ponto de luz, os parâmetros que auxiliam na iluminação e que podem ser utilizados estão na forma de comentários no exemplo abaixo.
#VRML V2.0 utf8
Transform
{
children
[
PointLight
{
ambientIntensity 0.3
attenuation 0.1 0.1 0.1 #atenuacao em RGB
color 0 0 1 #cor da luz RGB
intensity 0.6 #intensidade da luz
location 15 3 5 #localizacao do ponto de luz
on TRUE #ligada ou nao
radius 100
}
translation 5 0 0
Shape
{
appearance Appearance
{
texture ImageTexture
{url "outros\cal.gif"} #textura a ser aplicada na esfera
}
geometry Sphere {radius 2} #esfera de raio 2
}
]
}
5.4.2 Utilizando luz direcional
Define uma fonte de luz direcional que ilumina através de raios paralelos do vetor tridimensional fornecido, porém esse tipo de luz só ilumina os objetos que estão no mesmo nodo que a luz, os parâmetros que auxiliam na iluminação e que podem ser utilizados estão na forma de comentários no exemplo abaixo.
#VRML V2.0 utf8
Transform
{
children
[
DirectionalLight {
ambientIntensity 0.4 #intensidade da luz
color 0 0 1 #cor da luz
direction 15 13 15 #direção da luz
intensity 0.9 #intensidade
on TRUE #luz ligada ou desligada
}
Shape {
appearance Appearance
{
texture ImageTexture
{url "outros\cal.gif"} # textura a ser aplicada a esfera
}
geometry Sphere {radius 2} #esfera de raio 2
}
]
}
5.4.2 Utilizando um spot de luz
Define uma fonte luminosa que emite luz de um ponto específico para a sentido do vetor direção. Os parâmetros do comando devem ser usados conforme a figura abaixo, e conforme os comentários no exemplo abaixo.
#VRML V2.0 utf8
Transform
{
children
[
SpotLight
{
ambientIntensity 0.4 #intensidade da luz ambiente
attenuation 0.1 0.1 0.1 #índice de intensidade luminosa em #relação a localização do spot de #luz
beamWidth 1.785398 #
color 0 0 1 #cor da luz
cutOffAngle 1.570796 #
direction 0 0 0 #direção de saída da luz
intensity 0.8 #intensidade da luz
location 15 3 5 #localização da luz no espaço
on TRUE #luz ligada ou desligada
radius 100 #raio do foco de luz
}
Shape
{
appearance Appearance
{
texture ImageTexture
{url "outros\cal.gif"} #textura a ser exibida na esfera
}
geometry Sphere {radius 2} #esfera de raio 2
}
]
}
5.5 Fazendo links e includes
Para se fazer links e includes torna-se necessário conhecer os comandos Inline e Anchor, que serão definidos a seguir.
5.5.1 Inline
O comando Inline serve para que se inclua um arquivo VRML dentro de outro. O arquivo a incluir pode estar em qualquer URL válido.
#VRML V2.0 utf8
Transform
{
translation 5 0 0 #define as transformações geométricas a serem aplicadas ao arquivo "box.wrl"
scale 2 2 2
children
[
Inline { url "box.wrl" } #aparece o paralelepípedo que foi definido no arquivo box.wrl
]
}
Transform
{
rotation 0 1 0 0.8
children
[
Shape {
geometry Sphere { radius 2 }
}
]
}
5.5.2 Anchor
Serve para criar uma referência (link) de um objeto com outro URL. Ao clicarmos no objerto o Browser carrega o documento especificado no URL.
#VRML V2.0 utf8
Anchor
{
url "box.wrl" #localização(caminho) do arquivo, qualquer arquivo válido
description "descricao que aparece no rodape do browser da Sony "
children #objeto que serve como link
[
Shape
{
geometry Sphere {radius 2} #esfera de raio 2
}
]
}
No exemplo acima se o usuário clicar na esfera utilizando-se de um browser, aparecerá o paralelepípedo que foi definido no arquivo box.wrl.
5.6 Fazendo uma animação
Para criar uma animação em VRML 2.0 se faz necessário definir alguns sensores.
- TimeSensor: gera eventos no domínio do tempo e pode ser usado para animações e eventos periódicos.
- TouchSensor: determina um objeto que será sensível ao toque ( clique ) e colisões.
Para que a animação possa ser feita é necessário a definição de rotas, isto é, de caminhos(passos) para especificar o que fazer quando da ocorrência de determinados eventos.
A rota especificada no rodapé do programa(a declaração de uma rota deve ser fora do nodo mais externo) funciona da seguinte maneira: quando o usuário clica em cima do objeto é disparado ( zerado ) o sensor de tempo, quando fração de tempo é alterada a fração da animação é também alterada ,então é feita a animação correspondente, no caso a rotação.
#VRML V2.0 utf8
DEF XForm Transform
{
children
[
Shape
{ geometry Box {} }
DEF Clicker TouchSensor {} # Define que o objeto declarado a
# cima é sensível a cliques
# (toque) que iniciam a animação
DEF TimeSource TimeSensor # Gera uma especie de clock que serve # para gerenciar o tempo da animação
{
cycleInterval 3.0 #tempo de execucao do movimento
#loop TRUE # Opção para loop infinito do evento executado
} # Tempos de execução da animação
DEF Animation OrientationInterpolator
{
key [0, .33, .66, 1.0] #intervalo de tempo p/proximo quadro
keyValue [1 0 0 0, 1 0 0 2.1, 1 0 0 4.2, 1 0 0 0]
#keyValue=> coordenada de movimento
#nesse exemplo nota-se que em key e keyValue existem 4 valores,
#quando a animação for exibida, o objeto começa da sua posição inicial
#sem nenhuma transformação, o próximo quadro o objeto rotaciona no eixo
# X 2.1 unidades, o próximo quadro ele rotaciona no eixo X 4.2 unidades e
#no último quadro ele volta para a posição inicial
}
]
}
#rotas para animação,
ROUTE Clicker.touchTime TO TimeSource.startTime
ROUTE TimeSource.fraction_changed TO Animation.set_fraction
ROUTE Animation.value_changed TO Xform.rotation #exibe a rotação
6. Referências