Rapaz, não é que estou gostando dessa história de mexer no código do Blender 🙂

Isso me lembra os tempos do Civilization I, quando eu ficava alterando a história que aparecia no início do jogo junto com meu irmão. Na época os arquivos com a história eram arquivos comuns de texto, e bastava um pouco de curiosidade pra fuçar os arquivos e um tanto de criatividade para se divertir.

Hoje em dia o mais próximo que eu vejo deste tipo de personalização são definitivamente os programas de código aberto. O Blender é um deles, e por conta disso todo o seu código fonte se encontra disponível na internet para se estudar, modificar e redistribuir.

Eu já ouvi que na prática isto não é tão vantajoso, pois afinal não são tantas as pessoas que tem conhecimento suficiente pra lidar com programação. Eu particulamente não acredito nisso. Algumas vezes mesmo se você não tiver condições de resolver o problema, dar uma espiada no código ajuda ao menos a elucidá-lo.

Quer um exemplo?

Hoje na UBC, estávamos tentando mais uma vez solucionar um problema no projeto. Parte da dinâmica da visualização do fundo do mar está no nado dos cardumes. É muito rico visualmente ver os peixes se aglomerando e nadando em harmonia.

Para fazer isso em Blender, precisávamos de um peixe líder, e para fazer o cardume seguir o líder, o Mike escreveu um script bem bacana para controlar o que chamamos de AI (inteligência artificial). Para simplificar o processo, resolvemos que seria melhor se usássemos um recurso do Blender chamado TrackTo (Actuator->Edit Object->TrackTo).Pois bem, tudo parecia estar funcionando perfeitamente, mas reparamos que quando os peixes alcançavam o líder, eles começavam a nadar rumo ao infinito azul formando uma linda parede de peixes.

wall of fish

Puxa vida e agora ? ? ?

É nessas horas que respiramos fundo e mergulhamos no código do Blender.

Procura daqui, procura de lá descobrimos um arquivo chamado KX_TrackToActuator.cpp com a seguinte peça de código:

/* old function from Blender */
void compatible_eulFast(float *eul, float *oldrot)
{
float dx, dy, dz;/* verschillen van ong 360 graden corrigeren */dx= eul[0] – oldrot[0];

dy= eul[1] – oldrot[1];
dz= eul[2] – oldrot[2];

if( fabs(dx) > 5.1) {
if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI;
}
if( fabs(dy) > 5.1) {
if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI;
}
if( fabs(dz) > 5.1 ) {
if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI;
}
}

Uau, quando eles dizem old function é porque a função é velha mesmo, tem até comentário em holandês. Na verdade descobri que esta parte do código é anterior a 2002. E mais importante do que isso, é esta parte que é responsável por fazer os objetos seguirem o objeto líder.

/* passagem técnica, clique aqui para pular 🙂 */

Para entender melhor esta função é melhor dar uma olhada no resto do arquivo. Mas de modo geral o que ela faz é comparar a rotação do objeto com o objeto líder em cada um dos três eixos (x, y e z) e com este valor em radianos ela ajusta o valor do objeto sempre que a diferença for maior do que 5.1.

O quê? 5.1 não faz o menor sentido. Provavelmente isso foi um erro de digitação, a muito, muito tempo atrás. Porque eu acho isso? Bom, primeiro que estava analisando isso com o Mike, e ele com uma formação parcial de engenheiro entende mais de matemática vetorial do que eu. Eu não lembrava direito nem qual era a relação de radiano e graus.
Pois bem, um círculo completo tem 2 PI(2 x 3,1416…) radianos. Uma semi-circunferência tem PI radianos (3,1416). Tal qual os ângulos em grau, sempre que o valor em radianos ultrapassa 2 PI, podemos subtrair dele o valor da circunferência total (2 PI) e obteremos um ângulo equivalente.

Pois bem, passada a revisão, o que este código está tentando fazer é justamente ajustar o ângulo proveniente da diferença para estar sempre dentro de uma faixa pequena de números. E aqui está o X do problema, o código deveria estar checando se o ângulo é maior do que 3,1416, e não 5,1. Provavelmente o criador deste código tentou escrever 3.1, mas acabou escrevendo 5.1 (lembrando que em inglês as vírgulas trocam de lugar com os pontos nos números).

Agora ficou fácil resolver o problema . . .

/* pronto, pode continuar a leitura em paz 🙂 */

Depois do passe de mágica de descobrir qual é o problema, eis que chegamos à singela solução:
É só substituir 5.1 por MT_PI.

Mais uma vez criamos uma nova versão do Blender, e depois do teste, tcharannnn !!!!

circle of fish

Muito bacana né.  Agora me diz quando que você vai poder resolver um bug do 3DStudio você mesmo 😀

E o legal disso tudo é que depois é só submeter o arquivo e esperar para ser incorporado oficialmente ao Blender.

Um grande abraço, e até mais

Dalai Felinto

Um pouco artista, um pouco programador, um pouco músico, um pouco escritor, um pouco de arquiteto.
Acho que no fundo sou mesmo um pouco de tudo que vale a pena 😀

Alguns Links:

E alguns tutoriais em inglês:

4 Thoughts on “Um é bom, dois é demais

  1. MT_PI seria uma variável ou constante(por estar em maiúscula) do valor de PI?!
    Sei lá o que é isso, mas muito bom cara! Tomara que aceitem. Eu já tive problemas com o actuator “trackTo” também.

    Vocês estão de parabéns!

  2. MT_PI é uma constante (afinal PI nunca muda né 🙂 ).

    E assim como MT_2_PI, que está presente em várias partes do código do Blender, assim não precisa ser configurado cada vez que aparece.

    E obrigado pelo comentário e pelos parabéns!

    Abraços,
    Dalai

  3. Atualizando, o patch com a correção acabou de ser aceito.

    http://lists.blender.org/pipermail/bf-blender-cvs/2008-July/014963.html

    Demorou um pouco mais de duas semanas, mas o importante é que o problema foi corrigido !!!

  4. Uhm. virei fã de seu blog, além de boa informação temos bons comentários de código muito úteis.

    (Não que eu tenha algum animo em mexer no fonte do Blender)

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation