Laboration 2

Animation med skinning. ("Slangen"/"Masken")

I denna laboration skall vi arbeta med animation av en mesh och med tekniker för skinning. Vi kommer att lösa skinningproblemet både i CPU och på GPU.

Laborationsskalet

I denna labb använder vi ett enkelt, MicroGlut-baserat labbskal med en del fördefinierade funktioner. Labbskalet definierar ett antal ben med rörelse, ett antal vertexar som bygger upp en mesh samt vikter hur delar av meshen binder till de olika benen. Labbskalet är utvecklat av Johan Hedborg och Mikael Kalms efter en grund av Ingemar Ragnemalm. För 2022 tillkom en experimentell C++-version som numera är den som gäller.

I labbskalet finns en del funktioner fördefinierade. En del av dem är triviala saker som är praktiskt att slippa harva ihop, medan andra är på tok för komplicerade för att rymmas som uppgifter i labben och även om de är intressanta så får vi ta dem för givna.

Labbskalet består av filer för ett huvudprogram samt av shaders.

lab2.zip

common.zip (Alla hjälpfiler.)


Gamla versioner:

C++-version för 2023:

lab2x.tar.gz

Gamla versioner från 2022:

lab2.tar.xz

lab2x.tar.xz (Ny C++-version)


Packa upp, bygg skalet med makefilen eller en kommandorad i stil med:

g++ skinning.cpp -o skinning ../common/*.c ../common/Linux/MicroGlut.c -I../common -I../common/Linux -DGL_GLEXT_PROTOTYPES -lXt -lX11 -lGL -lm

Programmet körs med:

./skinning


Om labbskalet:

skinning.cpp är huvudprogrammet och den fil ni främst skall arbeta i.

Dessutom ingår ett antal moduler som ni känner igen från tidigare laborationer: VectorUtils3 samt GL_Utilities samt loadobj. Av dessa är VectorUtils3 speciellt viktig.

Typen vec3 är en 3-komponentvektor som används för såväl positionsvektorer som riktingsvektorer. VectorAdd, VectorSub, ScalarMult är vektoroperationer av intresse. Mult multiplicerar två matriser och MultVec3 multiplicerar en vektor med en matris. Till slut finns rotationer runt basaxlarna, Rx, Ry, Rz samt IdentityMatrix.

Del A

1. Stitching (hard-skinning) i CPU

Vi börjar labben med att implementera stitching i CPU. Stitching är skinning där varje vertex är bunden till endast ett ben, det sker alltså ingen blending här. All kod ska skrivas i C och vi behöver inte röra våra shaders i denna uppgift.

I vårt labbskal sätts vikter enligt:

weight[kMaxRow] = {0.0, 0.0, ...

Vikterna här betyder om vertexen binder till ben 1 eller ben 2 (vikten för ben 2 är (1-vikten) för ben 1). I denna del av labben ska därför vikterna vara antingen 1 eller 0.

Lägg till kod i skinning.cc som gör att varje vertex påverkas av ett bens nuvarande position. Ditt slutresultat bör bli en cylinder som böjer sig något på mitten.

2. Skinning i CPU

I förra deluppgiften så fick du ett resultat som påminner om mittenbilden nedan.


Du ska nu fortsätta labben genom att ändra koden så att den utför skinning (mjuk skinning, "soft-skinning", till skillnad från stitching) istället och därmed närmar dig utseendet i till vänster i bilden ovan. Här behöver vi sätta vikter som gör att varje vertex påverkas dels av ben 1 och dels av ben 2. Detta görs på samma sätt som i deluppgift 1 men värdena tillåts vara annat än 1 eller 0.

Lägg till kod i skinning.cc så att dina vertexpunkter påverkas av både ben 1 och 2s nuvarande position och vikt. Du måste också sätta lämpliga vikter. Ditt slutresultat bör bli en snyggare böjd cylinder.

3. Skinning på GPU

Du ska nu flytta över transformationen av dina vertexar till en vertex shader. Blending av påverkan från ben 1 och ben 2 ska fortfarande göras enligt tidigare använda vikter.

I denna uppgift behöver du lägga till kod i skinning.c och shader.vert. Ditt slutresultat bör se ut som i föregående uppgift (fast med funktionsanropen ersatta av matris- och vektoroperationer på GLSL's vis).

Ett antal tips för denna del är att skicka position och rotationsinformation till vertexshadern som uniform. Blendvikterna finns redan i texturkoodinat-attribut-arrayen.

Del B

I del B använder vi en annan huvudfil än i del A, skinning2.c (enbart huvudprogrammet, den använder initialt samma shader). Se till att spara undan dina tidigare implementationer så att du kan återvända till dem eller redovisa vid ett senare tillfälle. Modifiera makefilen för att kompilera denna eller gör en separat mapp och döp om denna till skinning.c.

4. Skinning i CPU med flera ben

I denna uppgift jobbar vi i en ny huvudfil enligt ovan. Denna huvudfil definierar ett antal ben som alla kan påverka transformationen på dina vertexar. Självklart påverkar inte alla vikter blendningen av transformationen på dina vertexar utan det beror återigen på vikter. I denna uppgift ska du implementera transformationer av dina vertexar så att din cylinder ser ut som en arm som böjs på flera olika ställen, se bild av skelett:

Observera att all transformering sker i CPU och därmed i C-kod. (En GPU-lösning godkänns också men kan vara lite knepigare att få ihop.)

OBS! Benen anges som rotation + position, positioner i samma koordinatsystem, inte relativa translationer. Ni måste alltså ta skillnader mellan positionerna (g_bones[b].pos) för att skapa translationer.

Nu måste du arbeta mer efter boken, i flera led. Dock ingår inga vilolägesrotationer. Benpositioner är givna i g_bones[].pos, men hur får du transformer från ben till ben? Benvikter ges nu individuellt per vertex och ben i g_boneWeights. Arrayen angleScales anger en vikt per ben för rotationen. Från början beskriver den en mjuk böj för hela "masken". Modifiera den för att få en lite intressantare animation.

Frågor:

I del 2, translaterade du med translationsmatris eller med addition på koordinater? Spelar det någon roll?

Hur löste du GPU-skinningen? Vilken information behövde skickas till shadern?

Om man gör skinning med en mer komplex modell (armar och ben mm), behövs vilolägesrotationer egentligen?


Del C

Del C består av extrauppgifter.

5. Skinning i CPU med indexerade ben

I vårt testexempel påverkas varje vertex som mest av tre ben. För att göra vår skinningimplementation effektivare så kan vi förberäkna vilka ben som påverkar varje vertex, och endast skinna mot dessa ben. Implementera skinning där varje vertex max kan påverkas av tre ben som anges med index.

6. Skinning på GPU med indexerade ben

Efter maxbegränsningen i förra momentet (max tre beninfluenser per vertex) så är skinningalgoritmen redo att flyttas över till GPUn. Du ska nu flytta över din transformation (och blending av transformationerna) till GPUn.  

Denna sida underhålls av Ingemar Ragnemalm.