31 July 2010

Coca Cola - Copa do Mundo 2010


[EN]
The Fifa World Cup 2010 is over and the Brazil was not the winner, but we will see if the next will get a success.
This job was done at Vetor Zero - Lobo - Animatorio, for Coca Cola.

I have helped Paulo Nogueira from R&D to write a MEL script for automatic creation of sprite parcitles for crowd simulation of the soccer stadium. In this script named vzSpriteCrowdSystem.mel we used the processes:
1. for each selected polygon we created a surface emitter with high rate value = 1000000.
2. we created a particle and connected it to the emitter.
3. we added the following attributes to the particle shape:
"goalU", "goalU0", "goalV", "goalV0", "parentU", "parentU0", "parentV", "parentV0", "spriteNumPP", "spriteNumPP0", "spriteScaleXPP", "spriteScaleXPP0" ,"spriteScaleYPP", "spriteScaleYPP0", "scale", "sizeX", "sizeY", "fast", "directionPP0", "directionPP".
4. set emitter speed value as 0, particle type as sprite and check on the depthSort option for the particle
5. we did this dynamic expression to Creation of the particleShape:
// connect this creation expression to particleShape:
string $partShape = "particleShape1";
$partShape.goalU = $partShape.parentU;
$partShape.goalV = $partShape.parentV;
$partShape.directionPP = 1;
int $divisor = 305; // this is the lenght of each animated sequence
int $totalImages = 38125; // this is the maximum frame number
int $cicleLen = $totalImages/$divisor;
int $particleCicle = rand(1,$cicleLen);
int $particleCicleOffset = rand(0,50);
spriteNumPP = ($particleCicle * $divisor) + $particleCicleOffset;
float $scale = .scale;
float $size = rand((($scale/100.0)*80),$scale);
float $sizeX = .sizeX;
float $sizeY = .sizeY;
spriteScaleXPP = $size * $sizeX * $scale;
spriteScaleYPP = $size * $sizeY * $scale;
6. we also did this runBefore expression to the particleShape:
// connect this runBefore expression to the particleShape:
string $partShape = "particleShape1";
float $divisor = 305;
int $cicleId = $partShape.spriteNumPP / $divisor;
int $currentSpriteId = $partShape.spriteNumPP;
int $currentFrame = ($currentSpriteId-($cicleId * $divisor));
float $fast = $partShape.fast;
if ($currentFrame >= $divisor-1){
$partShape.directionPP = 0;
}
else if ($currentFrame <= 0) {
$partShape.directionPP = 1;
}
if ($partShape.directionPP == 1){
$partShape.spriteNumPP += 1 * $fast;
}
else{
$partShape.spriteNumPP -= 1 * $fast;
}
7. we needed to force this connection in order to make attributes able to access from command line, using this code:
connectAttr -f ($objShape[0]+".worldMesh[0]") ($part[0]+"Shape.goalGeometry[0]");
8. set the goalWeight as 1 and the maxCount to 100 for the particleShape in order to fix particles on the polygon vertices.
9. we created a shader to load the animated file textures.
10. finally, we hided the polygon geometry and set it as not renderable.

I also helped to do the clothes simulation with Richard Kazuo, Rogério Masao e Henrique Freitas, from the Rigging department.
A little explanation about our method used:

1. After the end of animation, we started the simulation processes exporting the geometry cache of the hided proxies in the rig, they were deformed by wrap deform from the final skinned model (but while the animation, we kept this off in order to our rig runs more quick).
2. in another scene, we imported the proxies models and applied the geometry cache from animated scene.
3. we used colored shaders in different models to make more easy to visualization of geometry inter penetration.
4. we used the Maya nCloth to do the proxies simulations with the body as a passive object and the clothes as active objects.
5. initially, we set some values like:
nucleus:
    Start Frame (como o frame que inicia a cena)
    Space Scale = 0.1
nClothShape:
    replace (load 100%) do Preset tshirt
    Thickness = 0.02
    Self Collide Width Scale = 0.25
    Friction = 0.3
    Stretch Resistance = 80.0
    Compression Resistance = 10.0
    Bend Resistance = 0.02
    Mass = 1.0
    Lift = 0.05
    Drag = 0.02
    Damp = 1.3
    Stretch Damp = 0.1
theses values really change a lot by shot depending of the animation.
6. sometimes we needed to use dynamic Point to Surface nConstraints in situations when the clothes got away a lot from our desired position, so we animated the Glue Strength attribute in necessary frames.
7. we exported the nCloth simulation cache.
8. we created a wrap deformer fom proxy to final model.
9. we exported the final model geometry cache to be imported in render scene.

However we have re-do theses finalized simulations a lot of time because final animations..., I liked to work in this project because I learned a good nCloth workflow and helped to develop an useful script for the company pipeline.

[PT]
A Copa do Mundo de 2010 já passou e o Brasil não ganhou, vamos ver se na próxima será um sucesso.
Esse trabalho foi feito na Vetor Zero - Lobo - Animatorio, para a Coca Cola.

Ajudei ao Paulo Nogueira do R&D a escrever um MEL script para criação automatica de particulas sprites para a multidão do estadio de futebol. Nesse script que chamamos de vzSpriteCrowdSystem.mel, usamos o seguinte raciocinio:

1. para cada poligono selecionado criamos um emissor por superficie com grande valor de rate = 1000000.
2. criamos uma particula e a conectamos a esse emissor.
3. adicionamos atributos ao shape da particula que são:
"goalU", "goalU0", "goalV", "goalV0", "parentU", "parentU0", "parentV", "parentV0", "spriteNumPP", "spriteNumPP0", "spriteScaleXPP", "spriteScaleXPP0" ,"spriteScaleYPP", "spriteScaleYPP0", "scale", "sizeX", "sizeY", "fast", "directionPP0", "directionPP".
4. configuramos valores de speed do emissor como 0, tipo da particula como sprite e ligamos a opção de depthSort da particula.
5. criamos uma expressão dinamica de criação:
// connect this creation expression to particleShape:
string $partShape = "particleShape1";
$partShape.goalU = $partShape.parentU;
$partShape.goalV = $partShape.parentV;
$partShape.directionPP = 1;
int $divisor = 305; // this is the lenght of each animated sequence
int $totalImages = 38125; // this is the maximum frame number
int $cicleLen = $totalImages/$divisor;
int $particleCicle = rand(1,$cicleLen);
int $particleCicleOffset = rand(0,50);
spriteNumPP = ($particleCicle * $divisor) + $particleCicleOffset;
float $scale = .scale;
float $size = rand((($scale/100.0)*80),$scale);
float $sizeX = .sizeX;
float $sizeY = .sizeY;
spriteScaleXPP = $size * $sizeX * $scale;
spriteScaleYPP = $size * $sizeY * $scale;
6. criamos uma outra expressão para rodar após o processo:
// connect this runBefore expression to the particleShape:
string $partShape = "particleShape1";
float $divisor = 305;
int $cicleId = $partShape.spriteNumPP / $divisor;
int $currentSpriteId = $partShape.spriteNumPP;
int $currentFrame = ($currentSpriteId-($cicleId * $divisor));
float $fast = $partShape.fast;
if ($currentFrame >= $divisor-1){
$partShape.directionPP = 0;
}
else if ($currentFrame <= 0) {
$partShape.directionPP = 1;
}
if ($partShape.directionPP == 1){
$partShape.spriteNumPP += 1 * $fast;
}
else{
$partShape.spriteNumPP -= 1 * $fast;
}
7. precisamos forçar uma conecção para habilitar atributos por linha de comando, usando o codigo:
connectAttr -f ($objShape[0]+".worldMesh[0]") ($part[0]+"Shape.goalGeometry[0]");
8. configuramos o goalWeight como 1 e o maxCount 100 do shape da particula para elas grudaren nos vertices do poligono.
9. criamos um shader para aplicar os arquivos de texturas animadas.
10. finalizamos escondendo o poligono e configurando ele como não renderizavel.

Tambem participei ajudando a fazer simulações de tecido juntamente com o Richard Kazuo, Rogério Masao e Henrique Freitas, do setor de Rigging.
Uma breve descrição do metodo utilizado:

1. Após a animação finalizada, iniciamos o processo de simulação exportando o cache de geometrias proxies que estavam escondidas no rig dos personagens, esses proxies são deformados por wrap deformers do modelo final skinado (mas durante a animação, colocamos o efeito do wrap deformer desligado, para o rig não ficar lento).
2. numa nova cena, importamos os modelos proxies e aplicamos o cache de geometria da cena animada
3. aplicamos shaders coloridos aos modelos de corpo, camisa e calca pra facilitar visualizar interpenetrações de geometrias.
4. usamos o nCloth do Maya para simular as geometrias proxies deixando o corpo como objeto passivo e as roupas como ativos.
5. configuramos alguns valores inicialmente, como por exemplo:
nucleus:
    Start Frame (como o frame que inicia a cena)
    Space Scale = 0.1
nClothShape:
    replace (load 100%) do Preset tshirt
    Thickness = 0.02
    Self Collide Width Scale = 0.25
    Friction = 0.3
    Stretch Resistance = 80.0
    Compression Resistance = 10.0
    Bend Resistance = 0.02
    Mass = 1.0
    Lift = 0.05
    Drag = 0.02
    Damp = 1.3
    Stretch Damp = 0.1
esses valores realmente mudam muito de cena pra cena dependendo da animação.
6. algumas vezes precisamos usar nConstraints dinamicos de Point to Surface em situações em que o tecido escapava muito da posição onde ele deveria estar, então animamos o atributo de Glue Strength nos frames em que era necessario "segurar" um pouco a simulação.
7. gravamos o chache da simulação do nCloth.
8. criamos um wrap deformer do modelo proxy para o modelo final.
9. exportamos o chache de geometria do modelo final que será importado na cena de render.

Embora na verdade tivemos que refazer muitas vezes a simulação já pronta pois alteravam a animação final do personagem..., gostei de trabalhar nesse projeto pois aprendi um bom workflow de nCloth, além de desenvolver um script util para a pipeline da empresa.



Coca Cola - Copa do Mundo 2010 from Danilo Pinheiro on Vimeo.

0 comments: