Saltar para o conteúdo

Panda3D/Manual/A Scene Graph

Origem: Wikilivros, livros abertos por um mundo aberto.

A Scene Graph: Uma árvore de nós

[editar | editar código-fonte]

Muitas engines 3D mantém uma lista de modelos 3D para renderizar a cada frame. Nessas engines simples, primeiro o modelo 3D deve ser alocado (ou carregado), e então inserido numa lista de modelos a renderizar. O modelo não é 'visível' até ele ser inserido na lista.

O Panda3D é um pouco mais sofisticado. Em vez de manter uma lista de objetos a renderizar, ele mantém uma árvore de objetos a renderizar. Um objeto não é visível até ele ser inserido na árvore.

A árvore consiste de objetos da classe PandaNode. Esta é na verdade uma superclasse para um número de outras classes: ModelNode, GeomNode, LightNode, e por ai vai. Através deste manual, vai ser comum nos referirmos aos objetos dessas classes simplesmente como nós. A raiz da árvore é um nó chamado render .

'A árvore de coisas para renderizar' do Panda3D é chamada de scene graph

O que você precisa saber sobre hierarquia na scene graph

[editar | editar código-fonte]

Aqui estão as coisas mais importantes sobre a disposição hierárquica da scene graph:

  • Você controla aonde os objetos vão na árvore. Quando você insere um objeto na árvore, você especifica aonde inseri-lo. Você pode mover ramos da árvore para onde desejar. Você pode fazer a árvore ser tão profunda ou nem tanto ao seu gosto.
  • A posição dos objetos são especificas relativo aos seus parentes na árvore. Por exemplo, se você tem um modelo 3D de um chapéu, você pode querer especificar que ele sempre permaneça a cinco unidades acima de um modelo 3D da cabeça de um personagem. Insira o chapéu como filho da cabeça, e marque a posição do chapéu com (0,0,5)
  • Quando os modelos são posicionados na árvore, qualquer atributo de renderização que você adicionar a um nó será propagado nos seus filhos. Por exemplo, se você especificar que um certo nó deve ser renderizado com depth fog, então seus filhos também serão renderizados com depth fog, a não ser que você anule explicitamente no nível do filho

Os iniciantes como de costume escolhem fazer a sua árvore completamente plana, ou seja, tudo é inserido imediatamente abaixo da raiz. Este é de verdade um bom design para começar. Eventualmente, você vai encontrar razões para querer adicionar mais profundidade a sua hierarquia. Mas é sabido que você não deve se complicar até você ter uma razão clara e específica para fazê-lo.

Existe uma classe de ajuda chamada NodePath a qual é um objeto muito pequeno que contém um ponteiro para um nó, mais alguma informação administrativa. No momento, você pode ignorar a informação administrativa; ela será explicada numa seção mais adiante do manual. É da intenção dos designer do panda que você pense em um NodePath como uma ponte para um nó. Qualquer função que cria um nó retorna um NodePath que se refere ao nó recém-criado.

Um NodePath não é exatamente um ponteiro para um nó, é uma asa para o nó. Conceitualmente, isso é quase uma distinção sem diferença. No entanto, existem certas funções API que esperam que você passe um NodePath, e existem outras funções API que esperam que você passe o ponteiro do nó. Por causa disso, embora exista uma pequena diferença conceitual entre eles, você ainda precisa saber que ambos existem.

Você pode converter um NodePath num ponteiro "regular" a qualquer instante chamando nodePath.node(). Contudo, não existe maneira sem ambiguidade para converter de volta. Isso é importante: algumas vezes você precisa do NodePath, e algumas vezes você precisa do ponteiro do nó. Por causa disso, é recomendável que você armazene NodePaths, e não ponteiros. Quando você passa parâmetros, você provavelmente deve passar NodePaths, e não ponteiros.

Os métodos do NodePath e os métodos do nó

[editar | editar código-fonte]

Existem muitos métodos que você pode invocar em nodepaths, que são apropriados para nós de qualquer tipo. Certos tipos de nós, como os LODNodes e câmeras (por exemplo), fornecem métodos adicionais que estão disponíveis só para nós daquele tipo, que você deve invocar no próprio nó. Aqui estão alguns exemplos:

#métodos do NodePath

   myNodePath.setPos(x,y,z)
   myNodePath.setColor(banana)

#métodos do LODNodes

   myNodePath.node().addSwitch(1000, 100)
   myNodePath.node().setCenter(Point3(0, 5, 0))

métodos do nó câmera

   myNodePath.node().setLens(PerspectiveLens())
   myNodePath.node().getCameraMask()

Lembre-se sempre: quando você chama um método do NodePath, você está realmente executando uma operação no nó para o qual ele aponta.

No exemplo acima, nós chamamos os métodos do nó primeiro convertendo o nodepath num nó (node), e então imediatamente chamamos o método do nó. Esse é o estilo recomendado.