AM 533A - Computação Gráfica e Multimídia I
Utilização do VRML
Texto: Elisa Calhau de Castro e Léo Pini Magalhães
1o semestre de 1999
Aula 1


O que será visto nesta aula:
 


I - Introdução ao VRML:

    I.1 - O que é VRML?

             VRML, "Virtual Reality Modeling Language", é uma linguagem que nos possibilita descrever objetos 3D e agrupá-los, de modo a construir e animar cenas ou "verdadeiros mundos virtuais". As cenas criadas são, em geral, disponibilizadas na WWW e suas áreas de aplicação são bastante diversificadas, indo desde aplicações na área científica e tecnológica até entretenimento e educação, passando por representações artísticas e em multimídia.
Maiores informações veja  Tutorial  disponível na rede.


     Notação:

            Os links presentes ao longo das aulas referem-se a um Tutorial de VRML disponível e desenvolvido no DCA - FEEC (Departamento de Engenharia de Computação e Automação Industrial).
            Por vezes, julgou-se necessária a inclusão da nomenclatura inglesa de certos atributos da linguagem VRML por serem de uso frequente na literatura e, consequentemente, auxiliando o aluno na identificação dos mesmos em consultas a outras fontes de pesquisa.
            Exceto como primeiro caracter obrigatório no cabeçalho de todo arquivo VRML, o símbolo "#" precede comentários ao longo do código dos programas.
            Observa-se, ainda, que o nome dos nodos se inicia com letra maiúscula e que o nome dos campos ("fields") é escrito em minúsculas. Os campos são limitados por chaves.


I.2 - Estrutura de Arquivo e Como Programar:

               Os arquivos VRML têm extensão ".wrl" .
               A primeira linha de um arquivo VRML, o seu header, tem o seguinte formato:

                          #VRML V2.0 utf8 [comentários opcionais] <fim-de-linha

Nota-se que há, só e somente só, um espaço em branco separando os termos "#VRML" de "V2.0" e "V2.0" dos comentários.
              As cenas são basicamente compostas por nodos , os quais descrevem os objetos da cena e suas propriedades. Eles podem ser hierarquicamente agrupados de modo a viabilizar a representação audio-visual dos objetos, além de participarem do processo de geração e transmissão de eventos.
             Os arquivos com extensão ".wrl" podem ser editados usando-se um editor de texto comum, tal qual o "Edit" do DOS, "Bloco de Notas" do Windows, Emacs, etc. A seguir, para que a cena possa ser visualizada é utilizado um browser VRML, como por exemplo, o Cosmo Player da Silicon Graphics ou o Cyber da Sony, entre outros. É através desses browsers que o usuário enxerga e pode, até mesmo, interagir com a cena, participando da animação.

I.3 - Nodos

        I.3.1 - Conceito
                        Conjuntos de objetos, ou melhor, abstração de objetos e de certas entidades do mundo real, tais como: esferas, cubos, luz, som, etc. São definidos como sendo os "componentes fundamentais " de uma cena em VRML, pois esta é construída a partir da disposição, combinação e interação entre os nodos.
                        Cada tipo de nodo (ou node type) contém campos (fields) e eventos (events) e pode se comunicar com outros nodos através de routes que correspondem a conexões entre o nodo que está gerando o evento e o nodo que deverá receber o evento.
                        Os principais nodos estão descritos numa "tabela de nodos" à parte.

        I.3.2 - Semântica

                        Cada nodo apresenta, em geral, as seguintes características:

a) Tipo: citam-se como exemplos: Box, Color, Group, Sphere, Sound, etc;
b) zero ou mais atributos para fields que definem como um nodo difere de outro nodo do mesmo tipo;
c) conjunto de eventos que um nodo pode receber e enviar:  cada nodo pode receber zero ou mais tipos diferentes de eventos, os quais geram alterações no estado do nodo. Analogamente, podem gerar tipos distintos de eventos para comunicar alterações em seu estado;
d) implementação: a implementação de cada nodo define como ele reage a eventos que pode receber, à geração de eventos e às suas características visuais no mundo virtual;
e) nome: pode-se atribuir um nome a um nodo. Isso permite que possamos fazer referências a uma instância específica de um nodo. Isso é feito através das palavras DEF/USE.
Exemplo I.3.2: Definição de um Cone Vermelho
#VRML V2.0 utf8
  # Um cone vermelho é definido
 Shape {
   geometry ConebottomRadius 2
              height 4
              side TRUE
              bottom FALSE
            }
   appearance Appearance {
               material Material {
                     diffuseColor 1 0 0 #Vermelho
                        }
              }
 }
Observe, no exemplo acima, que o nome do nodo Cone está em negrito, bem como seus campos: bottomRadius, height, side e bottom. Note ainda, que outros nodos foram definidos (Appearance e Material), com seus respectivos campos: material e diffuseColor.
I.3.3 - Utilização dos DEF/USE

                        Uma vez tendo atribuído um nome a um nodo, através da palavra DEF, pode-se, futuramente, referenciá-lo através da palavra USE. A declaração de USE não cria uma nova cópia do nodo, em vez disso, o mesmo nodo é inserido na cena uma segunda vez. À utilização de múltiplos exemplos (ou instâncias) de um mesmo nodo dá-se o nome de "instanciação". Sendo assim, caso seja necessária a reutilização de um mesmo nodo, várias vezes numa cena, é mais eficiente atribuir a ele um nome, quando da primeira vez que o descrevemos e, a partir daí, referenciá-lo pelo nome cada vez que for necessário usá-lo novamente. Essa técnica, além de tornar o arquivo VRML menor e mais fácil de ler, diminui o tempo que se leva para carregar a cena, o que indica uma significativa melhoria na performance geral.
 

  Exemplo I.3.3: Utilização do DEF/USE

#VRML V2.0 utf8

Viewpoint {
      position 0 0 10  # Poderia ser omitido já que é o valor default
 }

Transform {

# Um cone é definido e posicionado na origem (valor default = 0 0 0)

   children [
      DEF Cone_Azul Shape {
                 geometry Cone {}    # Cone
                 appearance  Appearance {
                          material Material {
                              diffuseColor 0 0 1 # Azul
                                   }
                             }
                    }
# O cone é reutilizado e posicionado em (3 0 4)

            Transform{
              translation 3 0 4
              children USE Cone_Azul
            }
   ]
}

                    Observe nesse exemplo, que o segundo cone gerado (o da direita) tem as mesmas dimensões do primeiro, porém, foi posicionado (3 0 4) ao lado deste e mais próximo do observador (viewpoint = 0 0 10).
 

I.4 - Hierarquia de Nodos

        I.4.1 - Conceito

                        Um arquivo VRML é, essencialmente, hierárquico. Cada nodo pode conter outros nodos na sua especificação. De maneira simplificada, pode-se dizer que é usual haver "nodos incluídos em outros nodos", formando uma cadeia que culmina na formação de uma cena.
            Os nodos que estão mais no topo da hierarquia são chamados de ancestrais ( ou ancestors ) e os demais são seus descendentes, de modo análogo ao usado em árvores genealógicas. Dá-se o nome de "nodo raiz" ou root node ao nodo que não está contido em nenhum outro nodo, sendo que este deve ser um children node como será visto no próximo item.
                           Exemplificando, suponha o pequeno arquivo VRML, a seguir, onde se define um cilindro verde:
 

    Exemplo I.4.1-1: Cilindro Verde

        #VRML V2.0 utf8

        Shape {
          appearance Appearance {
            material Material {
                 diffuseColor 0 1 0
                 shininess    .5
            }
          }
          geometry Cylinder {
            radius 4
            height 8
            side   TRUE
            top    TRUE
            bottom TRUE
          }
         }

 Associado a esse exemplo, pode-se construir um diagrama como abaixo, onde fica mais evidente o "parentesco" entre os nodos:
 
 




Diagrama da cena referente ao Cilindro Verde


 


















                                                Fig. I.4.1-1: Diagrama da cena referente ao Cilindro Verde
 
 

Na figura, os nodos ancestrais (também ditos parent nodes) estão à esquerda dos seus descendentes ou "filhos" (ou children nodes como será visto mais adiante) e os filhos de um mesmo "pai", alinhados verticalmente.

I.4.2 - Grouping Nodes e Children Nodes

                            É comum, na construção de cenas, agruparem-se objetos, de modo a se criar uma nova figura. Os chamados Grouping Nodes estão listados abaixo. Os nodos que podem ser agrupados e, portanto, incluídos no campo children de um grouping node também, estão relacionados.
 

    São grouping nodes:

    São children nodes:
 
 
  • Anchor 
  • Background 
  • Billboard 
  • Collision 
  • ColorInterpolator 
  • CoordinateInterpolator 
  • CylinderSensor 
  • DirectionalLight 
  • Fog 
  • Group 
  • Inline 
  • LOD 
  • NavigationInfo 
  • NormalInterpolator 
  • OrientationInterpolator 
  • PlaneSensor 
  • PointLight 
  • PositionInterpolator 
  • ProximitySensor 
  • ScalarInterpolator 
  • Script 
  • Shape 
  • Sound 
  • SpotLight 
  • SphereSensor 
  • Switch 
  • TimeSensor 
  • TouchSensor 
  • Transform 
  • Viewpoint 
  • VisibilitySensor 
  • WorldInfo 
  •         A seguir são destacados os nodos que não são válidos como children nodes:
     
     
    • Appearance 
    • AudioClip 
    • Box 
    • Color 
    • Cone 
    • Coordinate 
    • Cylinder 
  • ElevationGrid 
  • Extrusion 
  • ImageTexture 
  • IndexedFaceSet 
  • IndexedLineSet 
  • Material 
  • MovieTexture 
  • Normal 
  • PointSet 
  • Sphere 
  • Text 
  • TextureCoordinate 
  • TextureTransform 
  •                         Destaca-se, no entanto, a diferença básica entre um grouping node e um Transform Node ( ou Nodo Transformação): quando se deseja apenas criar um novo objeto que seja constituído da combinação de outros objetos, usa-se um grouping node. Porém, caso se deseje somente agrupar espacialmente os objetos, ou seja, posicioná-los em certa região da cena, usa-se o nodo Transformação.
     
     
     

    II - Shape Nodes e Geometria

            II.1 - Shape Nodes e Geometry Nodes

                            Os nodos do tipo "Shape"são básicos para a construção de objetos geométricos. Eles associam um nodo geométrico ( geometry node) a nodos que definem as características visuais do objeto. Os nodos do tipo "Shape" devem fazer parte da hierarquia de transformação (discutido mais adiante na Aula 2), a fim de que os resultados gerados possam ser visualizados. Um nodo Shape contém, exatamente, um único nodo geométrico em seu campo geometry.
                            VRML provê um conjunto de nodos geométricos como a seguir:

                          Além desses, VRML permite que se criem outros nodos geométricos através do método de "prototyping" que será discutido posteriormente (Aula 3).
                            A seguir, exemplifica-se como criar um "box" default em VRML, deixando mais clara a relação entre os nodos Shape e Geometry:

            # VRML V2.0 utf8
          Shape {
                 appearance Appearance {
                   material Material {}
                }
                geometry Box {}
         }

                            Note que nenhum atributo foi atribuído ao box. Neste caso, diz-se que o objeto está usando atributos default, ou seja, previamente definidos na linguagem. Assim, o exemplo a seguir é equivalente ao anterior:

           # VRML V2.0 utf8
          Shape {
                 appearance Appearance {
                   material Material {}
                }
                geometry Box {
                  size 2 2 2   # eixos xyz respectivamente
                }
          }
                            Os nodos geométricos são, a seguir, discutidos mais detalhadamente.

    II.1.1 - Box

                            Um dos mais simples nodos geométricos é o box, que corresponde a um paralelepípedo centrado na origem (0,0,0) do sistema de coordenadas local e alinhado com os eixos cartesianos, tal qual indica a Fig.II.1-1.
     
     





    Fig. II.1-1 - Box


     


















                                                                 Fig. II.1-1: Box
     
     

                          Os valores default do nodo Box correspondem a um cubo de dimensões 2 x 2 x 2.

           Box {
             field SFVec3f size 2 2 2
          }

                            O campo size contém três números, indicando o comprimento do box ao longo dos eixos x, y, z  respectivamente. Para informações adicionais vide Box Node no Tutorial.
     

    II.1.2 - Cilindro

                     Cylinder {
                   field    SFBool    bottom  TRUE
                   field    SFFloat   height  2
                   field    SFFloat   radius  1
                   field    SFBool    side    TRUE
                   field    SFBool    top     TRUE
          }
     

                        Este nodo define um cilindro centrado na origem (0,0,0) do sistema de coordenadas cartesianas e com o eixo central ao longo do eixo y, como pode ser visto na Fig. II.1-2. Seus valores default correspondem a um cilindro de tamanho 2 nas três dimensões. O atributo radius refere-se ao raio do cilindro e height à sua altura ao longo do eixo central. Tanto radius quanto height devem ter valores maiores que 0.0  .
     
     




    Fig. II.1-2 - Cilindro


     





















                                                                      Fig. II.1-2: Cilindro
     
     

                       O cilindro é composto por três partes: lateral (side), a tampa (top) e o fundo (bottom). A cada uma dessas partes está associada uma variável do tipo SFBool (tipo prédefinido pela linguagem) que pode ser TRUE, indicando existência, ou FALSE, caso não exista.
                        Quando uma textura é associada ao cilindro, ela é feita diferentemente para cada uma das partes: lateral, tampa e fundo, sendo que este tópico ("Texturas") será visto mais detalhadamente na aula 2.
                        Destaca-se, ainda, que o nodo Cilindro só apresenta faces externas, ou seja, quando visto de dentro para fora, os resultados são imprevisíveis (dependentes da implementação do browser e não especificadas na norma).
                        Maiores informações estão em Cylinder Node no Tutorial.
     

    II.1.3 - Cone

                      Cone {
                     field     SFFloat   bottomRadius 1
                     field     SFFloat   height       2
                     field     SFBool    side         TRUE
                     field     SFBool    bottom       TRUE
          }
     

                   Este nodo especifica um cone centrado na origem do sistema local de coordenadas e cujo eixo central está alinhado com o eixo y, tal qual mostra a Fig. II.1-3.
     
     




    Fig. II.1-3 - Cone


     





















                                                                          Fig. II.1-3: Cone
     
     
     

                    O campo bottomRadius especifica o raio da base do cone, height a altura do cone, desde o centro da base até o ápice e bottom se a base do cone é visível ( TRUE ) ou não ( FALSE ), enquanto side especifica se a lateral do cone é visível ( TRUE ) ou invisível ( FALSE ).
                    Por default, o cone tem raio da base igual a 1.0 e altura igual a 2.0 . Os valores de bottomRadius e height debem ser maiores que 0.0  .
                    Dependendo do browser utilizado, o Cone pode ser invisível quando visto do interior, mas, de modo geral, os resultados são imprevisíveis (dependentes da implementação do browser e não especificadas na norma).
                    Maiores informações podem ser obtidas em Cone Node no Tutorial.

    II.1.4 - Esfera

                          Sphere {
                   field SFFloat radius  1
          }
     

                         Este nodo especifica uma esfera centrada na origem (0,0,0) do sistema local de coordenadas. O campo radius define o raio da esfera e, por default, seu valor é 1.0, sendo que sempre deve ser superior a 0.0  .
                         Quando uma textura ( Texture Node será visto na Aula 2) é conferida à esfera, toda a sua superfície é coberta, sendo envolvida no sentido anti-horário, desde a parte de trás da esfera, onde tem-se uma "costura" ou junta, como visto na Fig. II.1-4 ("texture seam" na figura).
     
     




    Fig. II.1-4 - Esfera


     


















                                                                 Fig. II.1-4: Esfera
     
     
     

                          Assim como os nodos apresentados anteriormente, quando a esfera é vista de dentro para fora, têm-se resultados imprevisíveis (dependentes da implementação do browser e não especificadas na norma).

                        Maiores informações, vide Sphere Node no Tutorial.
     

    II.1.5 - Texto

                 Text {
                  exposedField  MFString string    []
                  exposedField  SFNode   fontStyle NULL
                  exposedField  MFFloat  length    []
                  exposedField  SFFloat  maxExtent 0.0
                 }
     

                O nodo Texto é interessante quando se quer incluir, numa cena, informações, rótulos para objetos, etc. Este nodo contém outro nodo fundamental para se incluir textos em cenas: FontStyle Node que só é usado no nodo Texto.
                Cabe lembrar que, embora seja escrito no espaço tridimensional da cena, os textos são primitivas 2D.
                      Os caracteres do texto são determinados no campo string, enquanto length refere-se ao "tamanho"de cada caracter do texto dentro do sistema local de coordenadas. Porém, se a string é muito curta, ela é expandida ( o texto é escalonado ou acrescentam-se espaços em branco entre as letras) e, se muito longa, é comprimida. O campo maxExtent limita e comprime o texto: se o seu tamanho for maior que maxExtent, o texto é comprimido, caso contrário, não há compressão.
      O campo maxExtent é medido na horizontal para textos na horizontal (em FontStyle Node: horizontal = TRUE ) e na vertical para textos na vertical (horizontal = FALSE).
                       O campo fontStyle, por sua vez, contém o nodo FontStyle. Este define o estilo do texto a ser escrito, podendo-se especificar um dos três tipos de letra (serif, sans-serif ou typewriter/fixed-width), bem como se o texto ficará normal (plain roman), em negrito (bold) ou em itálico (italic) e se na horizontal ou vertical.
                       O exemplo a seguir, esclarece melhor a sintaxe deste nodo:

             Exemplo II.1.5: Nodo Texto

               #VRML V2.0 utf8

            Viewpoint { position 9 3 17 }
            Transform {
              translation 0 3 0
              children [
                Shape {
                  geometry Text {
                     string "Curso de VRML"
                     fontStyle FontStyle {
                        size 2.5
                        family "TYPEWRITER"   # Sempre maiúscula e entre aspas
                        style "ITALIC"        # Sempre maiúscula e entre aspas
                     }
                  }
                }
              ]
            }

                   Cuidado, porém, pois os textos não aparecem sempre da mesma forma em todos os browsers. De modo geral, os browsers escolhem a formatação que é mais adequada para os parâmetros fornecidos e de acordo com o sistema computacional no qual se está trabalhando.

                        Maiores informações podem ser vistas em Text Node no Tutorial.
     

    II.1.6 - ElevationGrid Node

                         Este nodo é o ideal quando se deseja representar a topografia de uma região, desde montanhas até pequenas irregularidades do solo, provendo uma maneira simplificada de representar superfícies que possuem altos e baixos diversificados ao longo de uma área.
                       A sintaxe do nodo é apresentada a seguir (os valores dos campos são default):
     
     
     

    ElevationGrid {
      eventIn      MFFloat  set_height
      exposedField SFNode  color             NULL
      exposedField SFNode  normal            NULL
      exposedField SFNode  texCoord          NULL
      field        MFFloat  height            []
      field        SFBool   ccw               TRUE
      field        SFBool   colorPerVertex    TRUE
      field        SFFloat  creaseAngle       0
      field        SFBool   normalPerVertex   TRUE
      field        SFBool   solid             TRUE
      field        SFInt32  xDimension        0
      field        SFFloat  xSpacing          1.0
      field        SFInt32  zDimension        0
      field        SFFloat  zSpacing          1.0
    }
     

          Abaixo, uma breve descrição da funcionalidade de cada campo:
     
     
     
       Campo                                      Descrição
    xDimension número de vértices ao longo da direção x. Seu valor deve ser superior a 1.
    xSpacing distância entre dois vértices na direção x. Não pode ser um valor negativo.
    zDimension número de vértices ao longo da direção z. Seu valor deve ser superior a 1.
    zSpacing distância entre dois vértices na direção z. Não pode ser um valor negativo.
    height "lista dos valores das alturas", uma para cada vértice, e enumerada por linha (direção x) em ordem crescente.
    color pode conter um nodo Color, caso se queira prover cores para cada quadrilátero da rede ou para cada vértice, em vez de para toda a rede, o que se faria usando o nodo Material. 
    colorPerVertex Quando TRUE, indica que se está provendo uma cor por vértice e quando FALSE, provê-se uma cor por quadrilátero. É ignorado se o campo color está NULL. Caso se especifique um nodo Color, deve-se prover, pelo menos, (xDimension - 1) x (zDimension - 1) cores para o caso de colorPerVertex estar FALSE e pelo menos, (xDimension) x (zDimension) cores para quando está TRUE.
    normal caso não especificado, o browser gera normais automaticamente, mas abre-se aqui a possibilidade de se definir um nodo Normal para se especificar, explicitamente, as normais a serem geradas.
    normalPerVertex ignorado se normal for NULL. É TRUE quando se provê uma normal por vértice e FALSE, quando por quadrilátero.
    texCoord pode conter um nodo TextureCoordinate (vide Aula 2) para se definir, explicitamente, uma textura para "a rede"
    ccw por default, as normais (e consequentemente as elevações) são definidas no sentido positivo de y (i.e. para cima). Porém, se ccw for FALSE, elas ficarão definidas para baixo, ou seja, sentido negativo de y.
    solid estabelece a possibilidade de se ver o lado de dentro da elevação (caso em que se atribui à variável o valor FALSE) ou se apenas o exterior (o mais usual) é interessante (TRUE).
    creaseAngle ângulo entre as arestas de duas faces (quadriláteros) consecutivos, o que proporciona o controle sobre a suavidade das curvas (minimizar o "facetamento" da figura).
                    Nota:
                         Eventos serão melhor abordados nas Aulas 3 (item "Nodos Sensores") e 4 (item "Route").

                   O exemplo seguinte ilustra este nodo.

    Exemplo II.1.6: ElevationGrid Node

    #VRML V2.0 utf8

    Viewpoint { position 2 1 13 }
    Shape {
            appearance Appearance { material Material{}}
            geometry ElevationGrid {

           xDimension        4   # 4 colunas
           xSpacing          2.1
           zDimension        5   # 5 linhas de 0 a 4
           zSpacing          2.0
           height            [0, 0, 0.2, 0,    # linha (row) 0
                              0, 0.8, 0.4, 0.2 # linha (row) 1
                              0, 1, 0.6, 0.4   # linha (row) 2
                              0, 0.8, 0, -0.4  # linha (row) 3
                              0, 0, 0, 0 ]     # linha (row) 4
                     }
    }
     

                Maiores detalhes em ElevationGrid Node no Tutorial.
     

    II.1.7 - Extrusão

                           Este nodo permite a criação de uma variedade de formas 3D, construídas a partir da extrusão de uma porção do plano 2D.
                        A sintaxe do nodo é apresentada a seguir:

    Extrusion {
      eventIn MFVec2f  set_crossSection
      eventIn MFRotation set_orientation
      eventIn MFVec2f  set_scale
      eventIn MFVec3f  set_spine
      field   SFBool   beginCap         TRUE
      field   SFBool   ccw              TRUE
      field   SFBool   convex           TRUE
      field   SFFloat  creaseAngle      0
      field   MFVec2f  crossSection     [ 1 1, 1 -1, -1 -1,
                                         -1 1, 1  1 ]
      field   SFBool   endCap           TRUE
      field   MFRotation orientation      0 0 1 0
      field   MFVec2f  scale            1 1
      field   SFBool   solid            TRUE
      field   MFVec3f  spine            [ 0 0 0, 0 1 0 ]
    }
     
     
     
       Campos                                                    Descrição 
    crossSection caminho ou figura no plano 2D descrito como uma série de vértices no plano xz e que sofrerá a extrusão 
    spine caminho no espaço 3D, ao longo do qual, a figura definida em crossSection sofrerá a extrusão. Também é descrito como uma série de vértices no sistema local de coordenadas
    scale série de fatores de escala, indicando a dimensão ao longo dos eixos x e z  da figura definida em crossSection e correspondendo aos pontos em spine, de tal modo que o primeiro valor em scale corresponde ao tamanho que a figura deverá ter entre os primeiro e segundo pontos especificados em spine. Caso somente um valor seja especificado, todos os pontos da figura terão o mesmo tamanho
    orientation série de rotações (pares: direção e ângulo), indicando a orientação da figura definida em crossSection e correspondendo aos pontos em spine, de tal modo que o primeiro valor em orientation corresponde à orientação que a figura deverá ter entre os primeiro e segundo pontos especificados em spine. Caso somente um valor seja especificado, ele será associado a todos os pontos de spine
    beginCap indica se a extremidade da figura que sofre a extrusão aparece tampada ou não
    endCap indica se a outra extremidade da figura que sofre a extrusão aparece tampada ou não
    ccw indica se os vértices em crossSection foram listados no sentido horário quando a figura é vista de cima (valores positivos do eixo y)
    solid indica se as faces de dentro da figura são visíveis (FALSE) ou não (TRUE)
    convex indica se todas as faces são convexas.Caso a figura em crossSection não seja convexa e tanto beginCap como endCap sejam TRUE, então, atribua FALSE a convex
    creaseAngle o ângulo entre as arestas das faces, de modo a suavisar as bordas, ou seja, tornar a figura menos "facetada"

     

                              O exemplo seguinte ilustra como este nodo é utilizado.

     Exemplo II.1.7: Extrusion Node

    #VRML V2.0 utf8

    Viewpoint {
       position    -8 1 1
       orientation  0 1 0 -1.75
       fieldOfView 0.785398
    }

    # Extrusao de um triângulo

    Shape {
        geometry Extrusion {
                ccw  TRUE
                convex TRUE
                solid  TRUE
                beginCap TRUE   #parte da frente da figura é fechada
                endCap FALSE    #parte de trás da figura é aberta

           # definem-se os vértices (os quais são interpolados pelo browser) que formam a figura 2D que sofrerá a extrusão:

               crossSection [0 0, 1 1, 1 0, 0 0]

       # a direção ao longo da qual ocorre a extrusao:

               spine [ 0 0 0, 2 1 0]
                  }
       appearance Appearance {
                     material Material {
                             diffuseColor 0 0 1
                              }
                  }
     }
     

                  Inicialmente, são fornecidos os vértices no campo crossSection, que, uma vez interpolados pelo browser, resultam num triângulo. Após definir-se a direção de extrusão (em spine), obtem-se um "alongamento" do triângulo, o que resulta na figura tridimensional.

    OBS.: O fato de o "triângulo original" aparecer mais claro na cena, deve-se, exclusivamente, à própria iluminação (default) definida para a cena.
     
     
     

                    Maiores informações podem ser obtidas em  Extrusion Node no Tutorial.
     

    II.1.8 - IndexedFaceSet Node

                            Este nodo representa uma figura 3D construída a partir de polígonos gerados de um conjunto de vértices localizados em coordenadas fornecidas (especificadas pelo nodo Coordinate).
     Neste nodo, suas faces poligonais são especificadas como listas de índices no campo coordIndex. O "índice - 1" indica o término de uma face e que a próxima face será iniciada a seguir.
     

    IndexedFaceSet {
      eventIn       MFInt32 set_colorIndex
      eventIn       MFInt32 set_coordIndex
      eventIn       MFInt32 set_normalIndex
      eventIn       MFInt32 set_texCoordIndex
      exposedField  SFNode color             NULL
      exposedField  SFNode coord             NULL
      exposedField  SFNode normal            NULL
      exposedField  SFNode texCoord          NULL
      field         SFBool  ccw               TRUE
      field         MFInt32 colorIndex        []
      field         SFBool  colorPerVertex    TRUE
      field         SFBool  convex            TRUE
      field         MFInt32 coordIndex        []
      field         SFFloat creaseAngle       0
      field         MFInt32 normalIndex       []
      field         SFBool  normalPerVertex   TRUE
      field         SFBool  solid             TRUE
      field         MFInt32 texCoordIndex     []
    }
     

                            A seguir, uma breve descrição dos campos presentes na especificação do nodo:
     
     
     

         Campo
    Descrição 
    coord contém um nodo Coordinate onde estão listados os vértices do  IndexFaceSet
    coordIndex lista de polígonos cada qual especificado como uma lista de índices no nodo Coordinate 
    texCoord pode conter um nodo TextureCoordinate, a fim de se especificar, explicitamente, uma textura para o nodo IndexedFaceSet
    texCoordIndex estabelece uma lista de índices para o nodo TextureCoordinate
    color pode conter um nodo Color com as cores a serem usadas ou "por face" ou "por vértice"
    colorIndex estabelece uma lista de índices para o nodo Color
    colorPerVertex Vide OBS. a seguir.
    normal pode conter um nodo Normal a fim de que as normais sejam especificadas explicitamente
    normalIndex estabelece uma lista de índices para o nodo Normal
    normalPerVertex indica se as normais são providas "por vértice" (TRUE) ou "por face" (FALSE). O valor deste campo é ignorado se o campo normal for NULL
    ccw indica se os vértices de cada face, quando vista de frente, são listados no sentido anti-horário (TRUE) ou horário (FALSE)
    solid indica se as faces são sólidas, em outras palavras, se o usuário pode enxergar o lado interno de cada uma delas ou não
    convex indica se todas as faces são convexas ou não
    creaseAngle ângulo segundo o qual permite-se suavizar as bordas das figuras (ângulo de uma pequena curvatura entre arestas adjacentes), diminuindo o seu "facetamento"
    Evento          Descrição
    eventIn                             MFInt32
    set_colorIndex atribui valores ao campo colorIndex
    set_coordIndex atribui valores ao campo coordIndex
    set_normalIndex atribui valores ao campo normalIndex
    set_texCoordIndex atribui valores ao campo texCoordIndex
                OBS: Caso o campo color seja NULL, o objeto geométrico deverá ser renderizado normalmente, usando-se um nodo Material e uma textura definidos no nodo Appearance. Porém, para o caso de color não ser NULL, procede-se da seguinte maneira:
    a) Se colorPerVertex é FALSE, as cores são aplicadas a cada uma das faces como a seguir:
    1- Se o campo colorIndex não está vazio, então, uma cor é usada para cada face do IndexedFaceSet. Deve haver tantos índices no colorIndex, quantas forem as faces do IndexedFaceSet. Além disso, se o maior índice em colorIndex é N, então, deve haver N + 1 cores no nodo Color. O campo colorIndex não pode conter valores negativos.
    2- Se o campo colorIndex está vazio, as cores no nodo Color são aplicadas a cada uma das faces do IndexedFaceSet em ordem. Deve haver tantas cores quantas forem as faces.
    b) Se colorPerVertex é TRUE, as cores são aplicadas a cada um dos vértices, como a seguir:
    1- Se colorIndex não está vazio, as cores são aplicadas aos vértices do IndexedFaceSet da mesma maneira que o campo coordIndex é usado para fornecer as coordenadas de cada vértice no nodo Coordinate. O campo colorIndex deve conter o mesmo número de índices do campo coordIndex e também "marcadores de fim de face (-1)" nos mesmos lugares em que aparecem no campo coordIndex. Se o maior índice em colorIndex for N, deverá haver N+1 cores no nodo Color.
    2- Se colorIndex está vazio, então, o campo coordIndex é usado para escolher as cores do nodo Color. Se o maior índice em coordIndex for N, deverá haver N+1 cores no nodo Color.
    A série de exemplos, a seguir, ilustra melhor cada um dos casos citados e a utilização do nodo IndexedFaceSet.
    NOTA: Os exemplos foram extraídos da referência [2] com algumas alterações. Destacaram-se, em negrito, as partes do código diretamente relacionadas ao assunto aqui discutido, porém, a título de curiosidade e ilustrando as potencialidades da linguagem, foram introduzidos também outros nodos que, por enquanto, não fazem parte do escopo das aulas ministradas, mas que são facilmente encontrados nas referências e em  livros e tutoriais sobre VRML.
    Maiores informações, ver IndexedFaceSet no Tutorial.
               Exemplo II.1.8 A - Especificação de um IndexedFaceSet colorido "por face"

             #VRML V2.0 utf8
    Background {
          skyColor  0 0 0.2
        }

        NavigationInfo {
          type      "EXAMINE"    # Permite-lhe girar a figura
        }

        Viewpoint {              # Sua localizacao na cena
          position 0 -6 17
          orientation 0.338246 -0.218865 0.915253  0.88
        }
    Group {
      children [

          Transform {
          children Shape {
     appearance NULL

            geometry        IndexedFaceSet {

       coord Coordinate {
                point       [ -5 -5 0,   # Vertice 0
                               5 -5 0,   # Vertice 1
                               5 5 0,    # Vertice 2
                              -5 5 0,    # Vertice 3
                               0 0 5 ]   # Vertice 4
       }

       color Color {
                color       [ 1 0 0,   # Cor (vermelho) para a face 0
                              0 1 0,   # Cor (verde) para a face 1
                              0 0 1,   # Cor (azul) para a face 2
                              1 1 0,   # Cor (amarelo) para a face 3
                              0 1 1 ]  # Cor (cyan) para a face 4 (base)
              }

       # Note que o maior indice = 4, logo, deve haver 5 pontos em point
       # O indice "-1" indica que o conj. de vertices precendes forma uma face, ou seja, o indice "-1" serve como um separador de faces

              coordIndex    [ 0, 1, 4, -1,    # Face 0: lado
                              1, 2, 4, -1,    # Face 1: lado
                              2, 3, 4, -1,    # Face 2: lado
                              3, 0, 4, -1,    # Face 3: lado
                           3, 2, 1, 0, -1 ]   # Face 4: base

       normal NULL

       texCoord NULL

             colorPerVertex        FALSE      # Colorir "por face"
     }

          }

        }
      ]
    }
     

    Exemplo II.1.8 B - Especificação de um IndexedFaceSet colorido "por face" com cores indexadas

    #VRML V2.0 utf8

    Group {
      children [
        Background {
          skyColor 1 1 1
        }
        NavigationInfo {
          type "EXAMINE"
        }
        Viewpoint {
          position -3 0 17
          orientation -0.069951 -0.669532 0.739483  0.26
        }
        Transform {
          children Shape {
     appearance NULL

     geometry IndexedFaceSet {
       coord Coordinate {
         point [ -5 -5 0,
                  5 -5 0,
                   5 5 0,
                  -5 5 0,
                  0 0 5 ]
       }

       color Color {
                color       [ 1 0 0,          # Cor com indice 0
                              0 0 1,          # Cor com indice 1
                              1 1 0 ]         # Cor com indice 2
       }

       coordIndex [   0, 1, 4, -1,                # Face 0: lado
                      1, 2, 4, -1,                # Face 1: lado
                      2, 3, 4, -1,                # Face 2: lado
                      3, 0, 4, -1,                # Face 3: lado
                      3, 2, 1, 0, -1 ]            # Face 4: base

       colorIndex      [ 2,      # Aplicada a face 0
                         1,      # Aplicada a face 1
                         2,      # Aplicada a face 2
                         1,      # Aplicada a face 3
                         0 ]     # Aplicada a face 4

       normal NULL

       texCoord NULL

       colorPerVertex FALSE
     }

          }

        }
      ]
    }

            Nos próximos dois exemplos, as cores são associadas aos vértices, o que possibilita um efeito visual bem mais bonito, apresentando gradações de cor por toda a superfície das faces. Isso é possível graças às interpolações que são feitas pelos browsers.

    Exemplo II.1.8 C - Especificação de um IndexedFaceSet colorido "por vértice"

    #VRML V2.0 utf8

    Group {
      children [
        Background {
          skyColor 1 1 1
        }
        NavigationInfo {
          type "EXAMINE"
        }
        Viewpoint {
          position -2 -5 17
          orientation 0.510051 -0.340034 0.790079  0.51
        }
        Transform {
          children Shape {
     appearance Appearance {
       material Material {
       }

       texture NULL

       textureTransform NULL

     }

     geometry IndexedFaceSet {
       coord Coordinate {
         point [ -5 -5 0, # Vertice 0
                 5 -5 0,  # Vertice 1
                  5 5 0,  # Vertice 2
                 -5 5 0,  # Vertice 3
                  0 0 5]  # Vertice 4
       }

       color Color {
         color [ 1 0 0,         # Vermelho aplicado ao vertice 0
                0 1 0,          # Verde aplicado ao vertice 1
                0 0 1,          # Azul aplicado ao vertice 2
                1 1 0,          # Amarelo aplicado ao vertice 3
               0 1 1 ]          # Cyan aplicado ao vertice 4
       }

       coordIndex [     0, 1, 4, -1,      # Face 0: lado
                        1, 2, 4, -1,      # Face 1: lado
                        2, 3, 4, -1,      # Face 2: lado
                        3, 0, 4, -1,      # Face 3: lado
                        3, 2, 1, 0, -1 ]  # Face 4: base

     # Observa-se que as core em colorIndex sao mapeadas sobre os vertices
     #  em coordIndex de maneira que: o vertice 0 - cor 3, vertice 1 - cor 4,
     #  vertice 2 - cor 0, vertice 3 - cor 2 e vertice 4 - cor 1

       colorIndex [    3, 4, 1, -1,
                       4, 0, 1, -1,
                       0, 2, 1, -1,
                       2, 3, 1, -1,
                    2, 0, 4, 3, -1 ]

       normal NULL

       texCoord NULL

       colorPerVertex TRUE # Como o valor default é mesmo TRUE, esse campo poderia ser omitido
     }

          }

        }
      ]
    }

            No exemplo seguinte, o campo colorIndex é omitido. Esse é um método prático e rápido de indexar as cores e associá-las aos vértices, pois assim procedendo, é como se o campo colorIndex fosse idêntico ao coordIndex.
     

    Exemplo II.1.8 D - Especificação de um IndexedFaceSet colorido "por vértice" com indexação de cores

    #VRML V2.0 utf8

    Group {
      children [
        Background {
          skyColor 1 1 1
        }
        NavigationInfo {
          type "EXAMINE"
        }
        Viewpoint {
          position -2 -5 17
          orientation 0.510051 -0.340034 0.790079  0.51
        }
        Transform {
          children Shape {
     appearance Appearance {
       material Material {
       }

       texture NULL

       textureTransform NULL

     }

     geometry IndexedFaceSet {
       coord Coordinate {
         point [ -5 -5 0,
                  5 -5 0,
                   5 5 0,
                  -5 5 0,
                  0 0 5 ]
       }

       color Color {
         color [ 1 0 0,
            0 1 0,
            0 0 1,
            1 1 0,
            0 1 1 ]
       }

       coordIndex [ 0, 1, 4, -1,
                    1, 2, 4, -1,
                    2, 3, 4, -1,
                    3, 0, 4, -1,
                    3, 2, 1, 0, -1 ]

       normal NULL

       texCoord NULL

       colorPerVertex TRUE
     }

          }

        }
      ]
    }
     
     

    II.1.9 - IndexedLineSet Node

                            Este nodo possibilita a representação de contornos de objetos, através da definição de seus vértices.

    IndexedLineSet {
      eventIn       MFInt32 set_colorIndex
      eventIn       MFInt32 set_coordIndex
      exposedField  SFNode color             NULL
      exposedField  SFNode coord             NULL
      field         MFInt32 colorIndex        []
      field         SFBool  colorPerVertex    TRUE
      field         MFInt32 coordIndex        []
    }
     
     
     

            Campo                                        Descrição
    coord contém um nodo Coordinate, listando os vértices a serem usados
    coordIndex corresponde a uma lista de índices dentro do nodo Coordinate, indicando quais vértices são conectados e em que ordem
    color pode conter um nodo Color com as cores a serem usadas ou "por segmento" ou "por vértice"
    colorIndex estabelece uma lista de índices para o nodo Color
    colorPerVertex Vide OBS. a seguir
            Evento                     Descrição
    eventIn                          MFInt32
    set_colorIndex atribui valores ao campo colorIndex 
    set_coordIndex atribui valores ao campo coordIndex
    OBS: Caso o campo color seja NULL e haja um nodo Material definido no nodo Appearance, afetando o IndexedLineSet, o campo emissiveColor de Material deverá ser usado para desenhar as linhas. Porém, para o caso de color não ser NULL, procede-se da seguinte maneira:
    a) Se colorPerVertex é FALSE:
    1- Se o campo colorIndex não está vazio, então, uma cor é usada para cada linha  do IndexedLineSet. Deve haver tantos índices no colorIndex, quantas forem as linhas do IndexedLineSet. Além disso, se o maior índice em colorIndex é N, então, deve haver N + 1 cores no nodo Color. O campo colorIndex não pode conter valores negativos.
    2- Se o campo colorIndex está vazio, as cores no nodo Color são aplicadas a cada uma das linhas do IndexedLineSet em ordem. Deve haver tantas cores quantas forem as linhas.
    b) Se colorPerVertex é TRUE:
    1- Se colorIndex não está vazio, as cores são aplicadas aos vértices do IndexedLineSet da mesma maneira que o campo coordIndex é usado para fornecer as coordenadas de cada vértice no nodo Coordinate. O campo colorIndex deve conter o mesmo número de índices do campo coordIndex e também "marcadores de fim de linha (-1)" nos mesmos lugares em que aparecem no campo coordIndex. Se o maior índice em colorIndex for N, deverá haver N+1 cores no nodo Color.
    2- Se colorIndex está vazio, então, o campo coordIndex é usado para escolher as cores do nodo Color. Se o maior índice em coordIndex for N, deverá haver N+1 cores no nodo Color.
                            Descreve-se, neste nodo, um objeto construído a partir de uma série de segmentos de linhas formadas a partir de vértices posicionados em coordenadas fornecidas. Esse nodo é essencialmente parecido com o IndexedFaceSet, porém, aqui, em vez de polígonos, é visualizado um conjunto de linhas. Os segmentos são definidos a partir de índices do campo coordIndex. Um "indice - 1" indica o término de uma série de segmentos conectados e que uma nova série será iniciada.
                            Os conjuntos de linhas não são afetados por luzes e a eles não são associadas texturas. Também não são válidos em colisões (assunto a ser explorado na Aula 3).

                    Nota: O exemplo seguinte foi extraído, com alterações, da referência [2].

             Exemplo II.1.9: Definição de um nodo IndexedLineSet

    #VRML V2.0 utf8

    Transform {
      children Shape {
        appearance Appearance {
          material Material {
     diffuseColor 1 0.8 0
     emissiveColor 1 0.8 0
     shininess 1
          }

          texture NULL

          textureTransform NULL

        }

        geometry IndexedLineSet {
          coord Coordinate {

     point [0 -1 -1,     # Vertice 0
              0 1 0,     # Vertice 1
        0.4 -1 -0.9,     # Vertice 2
        0.7 -1 -0.7,     # Vertice 3
        0.9 -1 -0.4,     # Vertice 4
             1 -1 0,     # Vertice 5
         0.9 -1 0.4,     # Vertice 6
         0.7 -1 0.7,     # Vertice 7
         0.4 -1 0.9,     # Vertice 8
             0 -1 1,     # Vertice 9
        -0.4 -1 0.9,     # Vertice 10
        -0.7 -1 0.7,     # Vertice 11
        -0.9 -1 0.4,     # Vertice 12
            -1 -1 0,     # Vertice 13
        -0.9 -1 -0.4,    # Vertice 14
        -0.7 -1 -0.7,    # Vertice 15
        -0.4 -1 -0.9 ]   # Vertice 16
          }

          color NULL

          coordIndex [ 0, 1, -1,   # Linha 0: une vertices 0 a 1
                       2, 1, -1,   # Linha 1: une vertices 2 a 1
                       3, 1,-1,
                       4, 1, -1,
                       5, 1, -1,
                       6,1, -1,
                       7, 1, -1,
                       8, 1, -1,
                       9, 1, -1,
                       10, 1, -1,
                       11, 1,-1,    # Linha 10: une vertices 11 a 1
                       12, 1, -1,
                       13, 1, -1,
                       14,1, -1,
                       15, 1, -1,
                       16, 1, -1 ]
        }

      }

      rotation -1 0 0  1.37
      scale 8 80 8
    }
     
     

                Maiores informações, ver IndexedLineSet no Tutorial.
     
     

    II.1.10 - PointSet
     

                            Define-se aqui, um conjunto de pontos desconexos no espaço 3D. Este nodo só aparece no campo geometry de um nodo Shape.

                PointSet {
                          exposedField  SFNode  color      NULL
                          exposedField  SFNode  coord      NULL
          }
     
     
     

    Campo                                           Descrição
    coord contém um nodo Coordinate onde estão listados os vértices a serem usados pelo PointSet
    color contém um nodo Color onde estão listadas as cores a serem usadas pelo PointSet, uma cor para cada ponto
                            São freqüentemente utilizados quando se deseja representar as luzes das pistas de pouso em aeroportos, estrelas, etc. Assim como o nodo anterior, não são afetados por luzes e a eles nenhuma textura é associada. Também não são válidos em colisões (tópico a ser discutido na Aula 3).

                            Caso um nodo Color seja especificado no campo color, ele deve conter tantas cores quantos forem os pontos no nodo Coordinate do campo coord . Cada cor é associada ao ponto correspondente: primeira cor associada ao primeiro ponto e assim por diante.

             Exemplo II.1.10: Definição de um nodo PointSet.

    #VRML V2.0 utf8

    Group {
      children [

        Background {
          skyColor  0 0 0            # Fundo preto
        }
     

        Transform {
          children Shape {
     appearance NULL

          geometry        PointSet {

       coord Coordinate {
            # Cada um destes "pontos" corresponde a um pixel na cena !!!

                point       [ -0.1 0 9.7,   # Ponto 0
                                 0 0 9.7,   # Ponto 1
                               0.1 0 9.7,   # Ponto 2
                               0.2 0 9.7 ]  # Ponto 3
       }

       color Color {
                color       [ 1 0 0,    # Cor (vermelho) para o ponto 0
                              1 1 0,    # Cor (amarelo) para o ponto 1
                              1 0 0,    # Cor (vermelho) para o ponto 2
                              1 1 0]    # Cor (amarelo) para o ponto 3

              }

        }

          }

        }
      ]
    }

                            Maiores informações, consultar PointSet no Tutorial.
     
     

    II.2 - Appearance Node

                            Este nodo só aparece no campo appearance de um nodo Shape e é responsável pela definição das propriedades visuais das figuras geométricas.

                   Appearance{

                   exposedField SFNode material         NULL
                   exposedField SFNode texture          NULL
                   exposedField SFNode textureTransform NULL
          }
     
     
     
     
           Campos                        Descrição
    material contém um nodo Material
    texture contém um nodo ImageTexture, MovieTexture ou PixelTexture.
    textureTransform contém um nodo TextureTransform. Caso o campo texture seja NULL, o campo textureTransform é ignorado.
                            Caso o campo material seja NULL, a geometria associada ao nodo Appearance não é iluminada, ou seja, as luzes são ignoradas durante a sua renderização. Esse seria o caso para a especificação abaixo:

                appearance Appearance {}

                             Contudo, se o campo material contém, por default, um nodo Material (vazio, no caso), a geometria é iluminada usando os atributos do nodo Material, como na especificação a seguir:

                   appearance Appearance {material Material{}}
     
     

    III - Exercícios

                        1) Definir uma única cena onde apareçam os seguintes nodos:

                                Procure alterar os parâmetros de tamanho, cor e posição dos objetos e analisar as mudanças na cena, a fim de se familiarizar com a linguagem.
       2) Faça algumas alterações nos exemplos dados para cada uma das primitivas (Box, Cilindro, Cone, Esfera e Texto).
     

    3) Obtenha uma imagem como a apresentada aqui. Descreva-a (programa VRML comentado).
    OBS.: A figura é vista animada para que se possa vê-la sob vários ângulos. NÃO há a necessidade de animar a cena, basta reproduzi-la, utilizando-se o nodo Extrusion.