Ações e Transformações com Luzes no V-ART

Ações no V-ART

Recentemente o Bruno Schneider, um dos contribuidores do projeto, submeteu no repositório de código uma série de classes para realizar ações em cima de transformações. Transformações no V-ART são nodos da árvore de cena que aplicam uma matriz de transformação para todos os nodos filhos. As transformações tem métodos de atalho para gerar matrizes de rotação, translação, escala e outras. Já as ações, são uma série de novas classes criadas para controlar transformações ao longo do tempo. Elas vêm em vários 'sabores' conforme o tipo de transformação que se deseja executar e ao se instanciar uma delas uma transformação algo é associada. Um exemplo de código explica melhor:

// Criamos uma transformação alvo
VART::Transform target;

// Agora criamos nossa ação
VART::TranslationAction translationAction;
translationAction.SetTarget(&target);
translationAction.SetTranslation(-20,0,0);
translationAction.SetDuration(3);

// Quando quisermos que a ação passe a ter efeito, nós a ativamos
translationAction.Activate();


Esse trecho exemplifica a criação de uma transformação e uma ação de translação associada. Porém, apenas isso não basta para que a ação efetivamente aconteça. Também é necessário que a cada frame seja chamado o método estático VART::BaseAction::MoveAllActive(). Para isso podemos usar a classe IdleHandler do V-ART como o descrito abaixo:

class MyIHClass : public VART::ViewerGlutOGL::IdleHandler
{
    public:
        MyIHClass(){}
        virtual ~MyIHClass() {}
        virtual void OnIdle() {
            VART::BaseAction::MoveAllActive();
            viewerPtr->PostRedisplay();
        }
};


Depois criamos e registramos um idle handler como mostrado abaixo e o método OnIdle será chamado a cada frame.

MyIHClass idleHandler;
viewer.SetIdleHandler(&idleHandler);

Transformações em Luzes

Após concluir os reparos no sistema de iluminação do V-ART comecei a criar uma aplicação para testar as luzes movimentando-as durante a cena. O Bruno me sugeriu então que eu usasse as novas Actions para fazer a movimentação das luzes. Eu achei uma ótima idéia, porém ela não pôde ser executada de imediato.

A razão das ações não funcionarem para esse teste é porque as luzes dentro do V-ART não são nodos da árvore da cena. Elas são, na verdade, objetos a parte adicionados na nossa cena. As luzes são sempre avaliadas antes de toda a árvore da nossa cena, fazendo com que todos os objetos recebam a mesma iluminação. Por conta disso, não era possível que luzes tivessem como pai uma transformação e assim não poderiam ser animadas através de ações.

Para resolver esse problema foi adotada a solução mais simples possível: adicionar uma propriedade transform na classe Light. Depois também foi implementada a aplicação dessa transformação sobre a lâmpada. Essa propriedade é inicializada de forma a ser uma matriz identidade na criação da lâmpada, dessa forma não é necessário se preocupar com ela caso não se deseje usá-la. Quando for desejado usá-la a propriedade pode ser acessada pelo método getTransform(). O tipo de retorno do método é VART::Transform* o que torna ele apropriado para ser usado diretamente com as ações.

Para terminar, segue um exemplo da utilização de uma action de translação com uma point light do V-ART:

#include <vart/scene.h>
#include <vart/baseaction.h>
#include <vart/translationaction.h>
#include <vart/transform.h>
#include <vart/light.h>
#include <vart/pointlight.h>
#include <vart/sphere.h>
#include <vart/time.h>
#include <vart/contrib/viewerglutogl.h>

#include <iostream>

using namespace std;
using namespace VART;

class MyIHClass : public VART::ViewerGlutOGL::IdleHandler
{
    public:
        MyIHClass(){}
        virtual ~MyIHClass() {}
        virtual void OnIdle() {
            VART::BaseAction::MoveAllActive();
            viewerPtr->PostRedisplay();
        }
        VART::Transform* rotationPtr;
        VART::Transform* translationPtr;
    protected:
    private:
};


// The application itself:
int main(int argc, char* argv[])
{
    Transform sphereTrans;
    Material redPlastic(Color(255,0,0));

    ViewerGlutOGL::Init(&argc, argv); // Initialize GLUT
    static Scene scene; // create a scene
    static ViewerGlutOGL viewer; // create a viewer (application window)

    // create a camera (scene observer)
    Camera camera(Point4D(0,0,10),Point4D(0,0,0),Point4D(0,1,0));
	scene.AddCamera(&camera);	

	// Create a sphere
    Sphere sphere;
    
    sphereTrans.MakeTranslation(0,0,0);
    sphereTrans.SetDescription("sphereTrans");

    sphere.SetRadius(1.5);
    sphere.SetMaterial(redPlastic);
    sphere.SetDescription("sphere");
    sphereTrans.AddChild(sphere);

    scene.AddObject(&sphereTrans);
	
	// Create a new light and a translation action to apply to it
	Light* light = new PointLight(Point4D(10, 10, 0), 2.0);

	VART::TranslationAction translationAction;
	translationAction.SetTarget(light->GetTransform());
    translationAction.SetTranslation(-20,0,0);
    translationAction.SetDuration(3);

	scene.AddLight(light);
	
	// Create and attach an idle hanlder
	MyIHClass idleHandler;
	viewer.SetIdleHandler(&idleHandler);

    // Set up the viewer
    viewer.SetScene(scene); // attach the scene

    // Run application
	translationAction.Activate();
    ViewerGlutOGL::MainLoop(); // Enter main loop (event loop)

    return 0;
}

Last edited Sep 5, 2008 at 9:37 PM by kcfelix, version 1

Comments

No comments yet.