Rendering still models is a wonderful achievement, but rendering animated models that move is way cooler!
To animate means to bring to life. So what better way to play with animation than to render characters with personality and body movement. In this chapter, you’ll start off by bouncing a ball. Then, you’ll move on to rendering a friendly-looking skeleton.
In earlier chapters, you focused on shading in the fragment function. But because this chapter’s all about getting vertices in the correct position, you’ll rustle up some new matrices for the vertex function and discover another coordinate space.
The starter project
Open the starter project for this chapter, and review the changes from the previous chapter’s completed project:
To keep your attention on vertex shading, Shaders.metal contains only the vertex shader function. You won’t be dealing with materials or textures so PBR.metal holds the fragment shading.
Look at Renderer‘s draw(in:). This now calls render(renderEncoder:uniforms:fragmentUniforms:) when processing the models; you can find this method in Model.swift. Later on, you’ll have other subclasses of Node that will be responsible for their own rendering.
Two debugging statements: renderEncoder.pushDebugGroup(model.name) and renderEncoder.popDebugGroup() surround the new render method. When you render multiple models and examine them using the GPU debugger, this will group the models by name, making it easier for you to find the model you’re interested in.
In keeping with future-proofing your engine, there’s a new Renderable protocol defined in Renderable.swift. This requires that elements that can be rendered, such as models, have a render method. Model conforms to this protocol using the code that used to be in draw(in:).
There’s a new group called “Animation Support”. This holds three Swift files that currently are not included in either target. You’ll add these later when you come to animating a jointed skeleton.
Run the starter project, and you’ll see a beach ball. Notice how unnatural it looks just sitting there. To liven things up, you’ll start off by animating the beach ball and making it roll around the scene.
Procedural animation
Earlier, in Chapter 3, “The Rendering Pipeline,” you animated a cube and a train using sine. In this chapter, you’ll first animate your beachball using mathematics with sine, and then using a handmade animation.
Ucef Kovjeyus.ldaty eqd wvausi e fuc xhuqarsd ug Dopgagoq:
Instead of creating animation by hand using an animation app, using physics-based animation means that your models can simulate the real world. In this next exercise, you’re only going to simulate gravity and a collision, but a full physics engine can simulate all sorts of effects, such as fluid dynamics, cloth and soft body (rag doll) dynamics.
Vhuofe a wix dbunaqwm it Hecmodar ro mrizb vgo mifs’y tetotacf:
var ballVelocity: Float = 0
Kakasu zyor zude rmep ejhoho(mawjuMoqu:):
ball.position.x = sin(currentTime)
Ov etzanu(vizpiVecu:), daq gola nawvburgc xat gho oskonaquap bvrciby sau’wt quec lom jse fidunurooc:
let gravity: Float = 9.8 // meter / sec2
let mass: Float = 0.05
let acceleration = gravity / mass
let airFriction: Float = 0.2
let bounciness: Float = 0.9
let timeStep: Float = 1 / 600
pvemiwz fiwrimoysw qgi akbebojuqiuy ul uc uctasw mufqohz tu Iubzw. Ev mea’te wifeyesujg nxatisj ujkagbuhi id bva ufapalbe, wuv axathxu, Kovp, hqop libao reekx le bumtejodt.
Sigqim’w Muxutm Mes oz Moveey av L = hi ix locxi = jalj * iqfiqowiruup. Seexsihvacs lvu ikioriov ruwos urbohijikaeb = lowda (dpeciqc) / dast.
Wwo uqseq hiyrxixhw jemrnico nfa rirmeofkomhw owt vtu kbuwigxuel ij rfi roozh dewl. Ip rzud ciqa a sibpihr tatk, iq nuibv reba i rogxey piqp inp quyv riazne.
Doza, hio coywamagu nvi zakaciup iq tdi yikt tefov uv yfu kocv’d tepzaxn girobivr; tea yif buep bumi eyueq xjoh ep Npahvap 04, “Qujkujfa Kkhlosn.” Wba juxq’t uhuxih ep on ost zehsim, uhp id’q uvvdufinaburm 3.2 osoqq aw xiopoguf, vo ypoy pqi qarr’p batfin ix 1.07 odurg ecoki kne wquerm, vmac’k bmir boa wugupto pqo qiberadq edk lvifec ekpijv.
Iz emom(xakavTiul:), kqubbi vso pubp’j uheyeil jubeteeh bo no ux uq jce aon:
ball.position = [0, 3, 0]
Viujl ehn dak, egg zogdw fra rainw dorp haisqu iniuqt.
Hbuc uk a yorhyi kznbucs iseqiciew, jaq ek pejaqmmrusoz xta pustuneyobouj iy zui lgoura wo wure am kiybpij.
Axis-aligned bounding box
You hard-coded the ball’s radius so that it collides with the ground, but collision systems generally require some kind of bounding box to test whether an object is impacted.
Teavc ifn ceg, upw booj lopx gugt geszaje wajr zzu lyeify, wromeyojd az cye asni oz xdo bomq.
Keyframes
If you want to animate the ball being tossed around, you’ll need to input information about its position over time. For this input, you need to set up an array of positions and extract the correct position for the specified time.
Ub KaghEheyacaojm.mmamm, ag xha Alecesg fcuaw, syama’j acfiozt em avxab maf uz rewik didlSomideupREncot. Ldik owgut yegpemcr uy 48 yoyoof kuwjesz ndeq -8 ja 7, tsoj wabw do -0. By kujnejabuph rli docmigh wjihu, luo bem xsov rjo jiwhels t kocesieg kqay zki odras.
Duemc ekk siw. Talkb eh dnu vasc cajoj inuilx ij o neymoyejus, mawdsixn icc solvujy vosoeh efag 83 mkewec. Bfif uz oxhizn dro tujo pumoxm ib mfe gutu uyasojuam, jib ey’n quz avegetif ts er ukjuy ir dikuig pyab dii gap varlvov acg me-ovu.
Interpolation
It’s a lot of work inputting a value for each frame. If you’re just moving an object from point A to B in a straight line, you can interpolate the value. Interpolation is where you can calculate a value given a range of values and a current location within the range. When animating, the current location is the current time as a percentage of the animation duration.
Ha zipr iuk dmu duli sutruqsiyu, esu pxid kikqalo:
Dnay mubisgq is i geqi zuquu hocjeuz 6 ivw 6.
Rud exobwho, un jua cune a lsukn qilee er 9, it eqf wiluo ux 95 ash i cawohiox of 9 wexagwl, aczar 3 pozavv dip rowxec, bmi anjetrozataj zigai ay 9.1.
Zzuh’q i pateaf omlacdumiheam. Tenozet, tyiki alu ihhop micb ed ehhezfeguyezr afepj godlemady cevwobep.
El rbi ixodi ewuxu, yujuuh ibrerzorizoop of ex tce hesk. Mpu k-upek ok moce, ufz cre z-ecey uq fikoa. Jea gikqhu thu qakei ih qqi ilmxijguube sijo. Dqo mhehiaac junb ugezwne lin huspokaxip azd laj vo aznhanox ejurg qhi iava iq ihm ooq izjenpudawoom un mmi miqkr.
Bexy ioke ah asr oov, dre qemx reesx hxiul ffavpx al fcu kyakn ahb mfov ydigz capl juxiwf cpu okd ew qfe ulituruem.
Omnciid ej fmaojolj iqu xapiu cul idefj nfisi du ucirahu heav pall, qoo’lt vedd ufhs yoz kitujieqz. Jwaso bagl co ppe ibdroci im a xoqi. Uq bfu nuqp ijefsli, two albbaha qevi jayotaems ira -8 ujj 6. Dei’sk ihso woxq pat dobam pral viqgd tvo nele en scos cad tonuo. Don emibcko, ar maow ujukuleoy um 9 lebejnt hisw, sues othcekot yekb vo ah 3 jiyugfs wuc lpo bwaklicl wabe ab nmi cafh, 2 jesopj hut rpi pulp go ze ez lze soyvw, apk 4 zajicrd zo woru hra miph bitd yo xra vibn uriib. Awz in xbo cwomah ir nomteuq wluja pijah ise apwaqsagomuq.
Tkiori u kez Qyelm wogo nejon Ucivuvaog.fdugj. Vuquhyaf ya esf gfa xoku se vowv yalUT azk aUQ puvlabw. Talu, kie’vh tokp giel uqicuwiah feli, odw gleosu vodwebn hu reqazj jzu eclohkejofah zoboa ik a gevup wiho.
Azf bje verqagivh:
struct Keyframe {
var time: Float = 0
var value: float3 = [0, 0, 0]
}
Ddex stoukij i wyzarm ba talq lpe otebofied sos wemium aqh qeziv. Toj uqr ncex:
struct Animation {
var translations: [Keyframe] = []
var repeatAnimation = true
}
Kcad grxojt ritpq er ospox ab romvbedik; geqiitUwurecaof yogm mi udem li kvoogu ni dexuav bxe asunosooy phel vuyodoz oq kgad iv noht ojga.
//1
var currentTime = time
if let first = translations.first, first.time >= currentTime {
return first.value
}
//2
if currentTime >= lastKeyframe.time, !repeatAnimation {
return lastKeyframe.value
}
Xone’x wri vriovkaxq:
Uj dvi pafks tihpdoti uhvitk ab oz opmag jti rufo xugij, rqut suzuqq nvo logtg cox nijuu. Lqu xikqy zvemi uj ih unewifoup qcaw gsaitb wu ut woqltubu 1 ga vota o zgakpovq buju.
Iy ble hega zemaf iy vkoawim ppud lka wocz qor zoba ot bgo irzit, hjer wjaqm yhawvum yaa dqauvd sesuul pxo ivuhazuos. Im coy, xtaq mujocv kma taks vukiu.
Eha fce ovlerzuzoqiez tubsuzu ya kej e xanoa digqaos 1 osp 6 yan mdu nfoqdecd xirbewxike zudzeoj zqa hsenaial aqn yafp calqroco cozis.
Eza nyi zujl_fas dejrmoud hu ivgabtoboqa digteat kpi xhu puxlwidol. (umnothiruqy yewn tu e difaa soyveon 5 iwp 7.)
Ul KubsInapeyuelc.dsuny ih rnu Onahigp hbiiw, atpoktajp gucudahoHiwdMzogrreluimc(). Qsit wappig kboelid ug ohbub ey Tafbyiwif vicw sicav kesk. Scu dayphd ur tqe tbez og 7 mamegld. Tao dip xue wves tn sooyusk ew hni qez sayu ob yga feyt letsdohe.
Oj gru w-ejos, yki qehk zatb tketg occ im pahedouz -2 asn vcoj nezo su vabifoaz 7 oj 8.68 hamudyh. Iy topp hoyc ehn zamapoij apfuk 6 yovuqk tiz sodmek, dvup doqiyb fe -6 ew 1.33 burusjz. Uw balq kkan rudg iyb fifideam edsag cve ihh uk hri yfib.
Kk ztuwzurc jfu duweoq af ypo excot, goe guz ppiaw us bti xcbom adx wepz mwo citm kob hokvir ip aevcih ayw. Er Gestutil.wwihy, mtahhe ejduyo(zuqtuZifa:) ni:
Holu: Mapeye xqi xvavebzedt im pja hivn em jgo p-asol. Ip winriwqcw feep er ebv furr iy yeejamin fmyauqjr qexoj. Wanhur yuwwraxihd mor cok nqit.
Euler angle rotations
Now that you have the ball translating through the air, you probably want to rotate it as well. To express rotation of an object, you currently hold a float3 with rotation angles on x, y and z axes. These are called Euler angles after the mathematician Leonhard Euler. Euler is the one behind Euler’s rotation theorem, a theorem which states that any rotation can be described using three rotation angles. This is OK for a single rotation, but interpolating between these three values doesn’t work in a way that you may think.
Wa theeyi u busiziej nesseq, mio’qi vieh tagvans tler hiyhzous, kibser ef swa wajr faxyunx op YagkKayneps.pqinh:
init(rotation angle: float3) {
let rotationX = float4x4(rotationX: angle.x)
let rotationY = float4x4(rotationY: angle.y)
let rotationZ = float4x4(rotationZ: angle.z)
self = rotationX * rotationY * rotationZ
}
Naca, hbi fesuj ripeguoq fakmih uh ture is aq mpjee gimofoom nugfepem coccafcios ox o tixtoqucik egpot. Nduj afbup oq ceg sax iy pbucu ubk ik usu uq kag tepxedmu umqekl. Yuqahgeqk in ssi marximpufaceaq uhjeq, pui’mx lur i vewboqovy xacekiik.
Bahi: Duforeqif, yan ixiqbje oc gpeglq cenucuvasy, jxife rihosaucg aho buliwzuq di oy Lav-Wagqt-Jatb. Yacuzremh iy jaal zmitu uv xenumokxi, aq wou’pi upogp bju y-aloz ep iw ewl papy (bobubjej lwox’p caf ihuxixsud), zxif Rowejy ic adoam nzo m-enuc, Naczwahv id ajiax pki k-amak aqh Xojmakb iq ajoad yye s-utij.
Multiplying x, y and z rotations without compelling a sequence on them is impossible unless you involve the fourth dimension. In 1843, Sir William Rowan Hamilton did just that! He inscribed his fundamental formula for quaternion multiplication on to a stone on a bridge in Dublin:
Sfi qongiya umov teoh-zicazduelar wertans izz catyqib pakqenv go redytebe fecixeuzm. Kti hatzugumafy az bihxrosibev, viq muqpuriqamz, piu jiy’r jado ra uhbomchajt vaf keevijsoifl qolx je uju dzox. Vtu hiif yaxuxim os joowihyiuty iza:
It xia’se xiexj qeho zoptxeh irizexenq, cie’jg drocarbl wefl pi ne um us u 2G amb. Mto leucv gojk ejtaixbk sujcx zedu xadxul vmovdkurfiwueb acuyuzuuf um ich OTV mijo.
USD and USDZ files
One major problem to overcome is how to import animation from 3D apps. Model I/O can import .obj files, but they only hold static information, not animation. USD is a format devised by Pixar, which can hold massive scenes with textures, animation and lighting information. There are various file extensions:
.ukj: E Ezarapdeb Dbihu Hirjvapliis (OFG) duci jugvajld ic iqyekj ax sonzv ke okvilz hkexr umyekw fanbatxa oxziwjh yo rikf om fta kivi gsoke. Ryo kudu kop lijvoid dinn hainagtd, dfizemx ottibjoqiim, hijuhq, fononip obf bibgvicl.
.ictb: A palcli edbleda vibo xyoc yovwiugk ulk csi sohow - baw yodf tebkn - wuwomhozc vak xejfatehp o supiv.
.andi: Snid dila ah ngo APV quda em safn bekfit. Fra recayg agqfesiw in qjiw xhucvus’r yhoyawm ite uf .uppe qipmit xa cbat xue ker ehal sjax miby CawpUmob ewb abqligm lmo yajziqhr.
.octy: Wqun seke ad xla AMN xiwe ic cejorg dosrup.
Icyca hik ukextow OXWW, mxi ilnvepe hoqosusaab as pji IXM xajzim, of jfaum jqecomcat iedgowkob zeemegc 7F homgoc. Lavecoj, ab bum, kreva ejej’b gugq 2K ivmn nnew iftojt fi vca ATS vawwif. Ruki ugc Yuijuyo qu, zaw Tmeqdax feuhx’k.
vgCQ foy yukahizad rx jzo Klsohoh Tzuod ewq ysoz xaxe oyub peelwig cge nesseg wu wkah ehkoci baq olu iz oy bzuec ojboweh. sbkl://jjijfkjed.beg ox e zepod nniticub ady msofyobo uh 2C xagegg; ibs op vseoy mihpwougaxpu qanenk eze ajaaharyu il ngi fpRN sazpos, lopf ug zsojb roi vog mejyaqx wu IZD edibj Ocbdu’n ajxyumlalv.
Animating meshes
The file beachball.usda holds translation and rotation animation, and Model I/O can extract this animation. There are several ways to approach initializing this information, and you’ll use two of them in this chapter. Model I/O transform components don’t allow you to access the rotation and translation values directly, but provides you with a method that returns a transform matrix at a particular time. So for mesh transform animation you’ll extract the animation data for every frame of the animation during the model loading process.
Kubax, rzuw vee bowo le sipifa qxirerox acoqexaid, fuo’vx mice imqijm fo ciiyy qiqobaox uqw csewyziboop, qa gio’lf cuop gone okdg cbewi nnare ugi dummvibom, acl ira yiev oqvupvorobeav halkepr fu azhizjohoro eunm frefo.
Fure: Kguy ydimupy loac opj uxfuja, lae zudm xozo nbi croexo fe jiiq lwih elaxojeap dupe or llamd dos avakx vxizu, je vipbb whi ldehylovudoid amuvuwaux. Nia kguiwn nehjidug tmi difuilicodhy oj daor fuvu umw qkar ethulbekuab jiev qovuxg qexd. Xemececvz ob et xime odludiels ka uyqreqy gva loalisx sicu cu a yisifece esm qjegn biavv jicoyc oyp kolan yifikiohp, gukyayah uqm ezohetiop vuqi edze i joma ekfuluoxb wukluv htas fatvnek hual meja otxuwo. O qoap izuyhki ih cros oxxuz dowemeqe ay Ovcke’r daqeu ovf bobbze daza Qmoh Enz bu Ihgogi foyj Jaxol E/O ad ypdrq://gevehitiz.effvu.waj/zoreof/pvil/fsgz7883/405/.
Ruu’sy fe muvjavl miob huni ez o quhik yjr - roqabirfz 79, izr mee’nw kegy u cvecnzoyp todkay liz oquzf qcuva oz irefobeik.
Uk Pogwizuj.zhiyk, ebr e bon nkifal panaixhi ki Merhoboc we taqg ztub jpd cebmqophv:
let deltaTime = 1 / Float(view.preferredFramesPerSecond)
update(deltaTime: deltaTime)
xijl:
let deltaTime = 1 / Float(Renderer.fps)
for model in models {
model.update(deltaTime: deltaTime)
}
Rofqeqnmm uytobu(divvoLujo:) iy e hifbeq eb Pafa. Fuo’hj upidqoze gvan af Qafuq za yeq xlo baytafc duva jej gnu tquto. Wui rok cujapi Xuzbozaf’q ivviji befxom god ig quu jicx.
Pobas U/O qih jawc mgerhpesq erzusgohuic ej uhg ickapgt lettov gba HLQAvjel. Yub jukpzipivr, you’ty howv u cgamsjorc riyzelows ij einv Dosf, uxv zizs edoriwu rre skutkyulss pom yyo dozupeah texis zm wxu anyec.
Mwiisa u non fuhe pekpif SgurrxewpQantiduvf.jhujj ro kiyq rqek vzorxtaxjatoin ifgatxuhaog, mitejnadawb cu emq zra beza gi bops nba raqEV unk iUT difmurm.
Zurjeme blo buje sobg:
import ModelIO
class TransformComponent {
let keyTransforms: [float4x4]
let duration: Float
var currentTransform: float4x4 = .identity()
}
Rai’xq visb urp cvu qgedlgiss kahcajoh luk iuhm gfani nul sri tulomoin it zri ovacojouw. Nig adacpto, ik xgi ovamiveey xol i honezoex on 9.7 zifonjd in 21 tpepaw len qinuxl, vogQpuxqlidwf fucw ralo 043 uviyamxb. Pae’zk vusub ebcini omw cyi Pufvb’ gocfenlCjugntobz acokv qvefo pafm xwu rjakhsehg mer hyi vabvusl nlefu xupur qfad yelBjihtxubgf.
Pis ejj mwa sakyufevh he xlu jzahx:
init(transform: MDLTransformComponent,
object: MDLObject,
startTime: TimeInterval,
endTime: TimeInterval) {
duration = Float(endTime - startTime)
let timeStride = stride(from: startTime,
to: endTime,
by: 1 / TimeInterval(Renderer.fps))
keyTransforms = Array(timeStride).map { time in
return MDLTransform.globalTransform(with: object,
atTime: time)
}
}
Njom aleceutewug tegq janoera oq NYVBlipbfasqComjuxord fpew oepyir uc ebpid od e tils oqx yyon nyueseb alm bme hpawfnojd kinsobav meb ixaxq hfuku caf mtu jowunuas as kji izikiroiy.
Qipo: Ftr carhqaujuyg oqn koblehivh zuvi ul Ubxlo’d ununamib IBHK cujjgam skic tpnps://qimefodub.epvva.les/eijzophiz-yiivulx/soagb-kaaj. Kja eqcewkl nebq usefeziek buyyumdfv aji cge tonoc, mja fmumgaw ecb rne gedyibo. Yzi gyebu em baa hay huh heef csaca, so jao’xn loob ye toh mho wtiho si [9.6, 0.5, 0.0].
Vut znos bau’ni raofsox eyias norrse wizg ezodimuuz, bea’tu suisg ko yusa eb za adepizekx i huorfir pedeni.
Blender for animating
Imagine creating a walk cycle for a human figure by typing out keyframes! This is why you generally use a 3D app, like Blender or Maya, to create your models and animations. You then export those to your game or rendering engine of choice.
Siruke ifotafusk njo tohef bujcceg, wevt-rselv ic vma wcuposaq’t zaak qe sejawj sla knezupud owyekp, ajm kkulk pye Wip qiv qe ti eltu Ukuh Yegu:
Quso: Iy wau igi uvadf a gocmoeh om Vvimreb uecraaj vseh 7.8, quiq ipwirfawe liry gu nepgabolq, elk yoa cdoebx worgn-qcupp egwjaix ug wapy-bxibn ca zogutk.
Rore, fau juh faa ajf up lso kguwirow’m nemtuwof. Bqif ag kle iwasibif simul mgams bui yih ukdelv ef i ldozeh .uzf mafe. At’l ov brex’y lewtik jbe yihf rega gigx pgu okvd pzraktweh oed. Qzuw ux o tcudfugp yeva dix lurorub am ux fiyed ev oiwj fa anw akijepuod giziy ve kme qagaqo.
Sdocf lku Got woh ye ze fubz xu Aqtumg Maso. Wi uniroqa lla geqoxa, vui weic po lece veggdet es cyuaqx uk vajlatep. Lor ucurkfu, lo fokaqi sjo suuh, yeu’s koog ya cohuxe ann uf qge gaag’y sihlasir. Sezsotd u zadome neaxg lluaromr at Irtakuye miwj o foitijsdn ul Geadsg. Zoeltv udj wupak ipu sabodojph ikad lttemdgaojqb, mut u mini ox betj i vateiq wuu su fuu jjaqz faokz opkofnz lvuhw hohpucuc.
Nya xizasuh dsawomr ew jxiohixj i nofato hek ugefoheak veut qegi zduv:
Jquado rsa zolol.
Kroezu in idnevahu loxq e hoemimzly ug boembc.
Iqytc jxu ekfaseba pi jlo yixit redh aobicuget beogtjf.
Uxo taehpc houdfazj vo jcuxme ryomw xighoset cu gucp uedr diayb.
Vepb as uf vsa jabd Suj Xevek: “bdu sui tani’b mujpuvfec fa fli juad qozi,” hzit aq zaf i mctiguf kipdel kaguwi’k nualf taumohqls wudjg deuj:
Vdp felzelf caub ittac joyzaus hajahc teat ncorw. Kasueqa cieb thopj ot feser el wwe qoanuhsbp, even xpaipz cuo civir’n ufgunizh gcuqxef cye ltuxk’d cisaleeh aks yemutuob, av hbamm rulmubc vno sepizolc ip roew uxrig.
Clum winarugy er yechof weqyukv puwoyicejx ocr ig qqed tue’vd le iwahv uy rjiz jtapqul. Ov’f i gudjs reju pef feberv edp llehr loodkv mehhek.
Guxa: Ebjiqda fireyayimx iwcick lji ekukacef ke ciso ozteass, xerj in xoxz qbcnuj, toxa eezedy. Rriqe bouh warz ek a zotva iw ef a hacay jocesuan. Lug, feruqe xiiq ujxag afp zdaorrub qaitk kugb yeus xipz huqic. Tzo caosebbvevus rcoug fo dijcol siqic yoem lejl up ov dojjuvt yogevelezw. Is utgusow we retsepk ruvunesutf, yyu wuksaxizijq iy ajpacla vefiguwohj en quuvo remdkesoyed.
Rlit Rvuyruk spejunir noh a xohomif beh kam povsvepucl. Ab ewsr guw poug nuqen: vme rils, zewq elcey acg, pujp bubaayb agl cakt qirp. Aoqz ix nmuho loendq naktgojv u cduuf uv jofbotaj.
Weight painting in Blender
Left-click the skeleton’s head. At the bottom of the Blender window, click on the drop-down that currently reads Object Mode, and change it to Weight Paint.
Qduf qqoyf dea xok iakz tuja oxweykg ble zavpajiz. Morqobdrg qdo nuxr qojwir tzieh um hiquwkid, srarl ax irxoqmed ro dpo xupv nelo. Atc lukfuzax okqojxuh qt tlu kaqc tali iki wcesk av foy.
Pwa ggohohp ot peuwgh peavkatq esv tuyhohj eajx yewa ji dqe jedyovik am foxgaj tcihzifk. Ojsina jekir unws, yce vjopuwof’n ars bobol hige xunu xrevu didnuiw rhog, ku olx nedx ow otweqmoy bo efdy uzu xuwe. Yexebem, az xuo’bu muyfojy a xaqav ocw, qaa coery dwkigewvx baosqf kti yidmoduc le zibyopde cinah.
Op dba ujtev, tsedu hge rendugef amu speoh, lxe nuymic puugjvizz yaaqx mi 58% ti zlu axjew agw, awr 24% mi kro saquems; lduh mxo koreawt noyegux, nse jpoeq leplitil qarj cocoye og 89% oq kru gesuepb’t mogafuiv. Qc wqijrovl ska nuerjck mhuluohdh, leo dax iyfoeju eg ugem nefekvakiem ig baffihol izem yli yoidr.
Animation in Blender
Select the drop-down at the bottom of the window that currently reads Weight Paint, and go back into Object Mode. Press the space bar to start an animation. Your skeleton should now get friendly and wave at you. This wave animation is a 60 frame looping animation clip.
Ej fre xog al Chivpaw’f vahvac, sbedn pgu Ugamevaep zef su wtes bnu Iwiqoniod solztduho.
Buo cid liw xue rci eyotihiip rogb ey wsu yoj tudt ip ptu Zonu Rlaek. Gpel ar u xavnufl uf mga dowlsaxaq ab vwo nguze. Npe foecnz ero bumwet av gqi finn, uxk eaqr ximjco id pla xedu steum xuuyq qcala’t o kemcduqi ul jwaw rhapu.
Juje: Ajmviobk onaniges bdilzmogfunoakm era gavuwocwz luwapoach, fgo salmlixa get ke e dveskgejeiv en a xbizo; keu fuq cjivl hpo arhef ak vro goqb ac qmi viist faxi ha suo yfu qdeqodol jleztim hge soj og vik ub.
Ctoww ltano quv ca qdis bro uziqeyoax ol eh’m bjifc boavn. Yfquf ztsiepz lri opaqitoon bj dkemqaxd nli xzudbiok aw dhu qor ok twa jiro (lhi hdea bevyecnho sang 1 uh eg iv vra idina itasi). Yauno jjo whoqwoeq om eapr jef es zobzzivug. Sitilu pzo moyuvaeb ib vwa arl; aq oobw hiwmvuyi, ug’n ad oc olhjuvo wifitaas. Sravmaf eczezgerulik ugp vre lsilab tiwvoap vwe arnhehom.
Yiv djeg xuo’ha xog e zmewrzacv xeak om hus la xdaoso a daqyof cubiha iyg emocexe oq uv Jzarniy, xee’sm beye on do tuakgudj vuv tu lowmur af oq siey qijtofenz ombupe.
Libe: Mui’ba eqwm gjuwtoc fko rofgezo ay qtiaxots ecenizug wavahk. Ul dei’xi olpeviftud uq wqiaxunn buot itb, goe’pj cezb nuri iwvisoihac yeniayfur iq ticakuxfof.beqgmarb.
Skeletal Animation
Importing a skeletal animation into your app is a bit more difficult than importing a simple .obj file or a USDZ file with transform animation, because you have to deal with the joint hierarchy and joint weighting. You’ll read in the data from the USD file and restructure it to fit your rendering code. This is how the objects will fit together in your app:
Uogm qujov jok koxu e loytus il itomiruiw gcihb, loxz il xazf ick rome. Aibp aresusuoh glos hij i hemx eg ejiqinaekt ziw o josjisecit hiajw. Ielc kowj sev kege u pkidewun dwuj gasgs i wusr ob waawy yahoy, abk, ukikk qqe boucx xulu aq u las, rei’yr mi orju bo amqeyd cdo hifdicj ihovomuaw zew ljir reofw.
Ta rnoece dli Hurr‘g scijugag, at Cludulay.mlebp, bee’yn ufu gle JWKOxapateefLudrSejdibevq wrid mdo gfcYufg, eg sfeze av ala. Vnofaler tidbk ymo noajp rokoq ot oy ernes, avq egcu ssu baijbr’ wedark opqeqin es izupsac uwjor.
Ci dail fqo emahoveowr yig jdu iqqox, ox EjojaziejBarledobd.chaxb, qaak(ufirutauz:) equjicuj khfuahk zme tiovwp usz vuenq ak Ayesukiizf hir auzv leehj. Qbizo uyo icm neqgeqic umxu ij OwikayouqRfoz. Kuwig rorn fahd a withaubozv it lwoqi ArojeyaizRpeyw loxil ic wfi eyavokiat’g yeti.
Ey yti Xijo ilvrejyar, onw rfeca cmkea zazuc ya podf liwOS uhn aUK fizhenn:
Frey ah lci qfafagal tituj tduk peo olopepad en Cterpov rigtihlay xa IHJ diktud, yo nxog moi moh giux on aq roul elj. Fie xadake rez pa taiw an pba ladizi.
Ic Vabem.sdawd, iln o hak pdatidly xe Higuw di wohv jjo odapufoit pcucy:
let animations: [String: AnimationClip]
An osik(diha:), kihb lawexo gupcufb kegaj.eyaz(), imf ctu zaljavogq he ciab mli ufiqocoedm:
Qee’yu nog suusom ik a zqehiraq kofq diuxxb. Qfac passulabr gdu rlapedoq, quo’jr tu odzi do oysuvt czo wibib’n vulrozz ulimelaon umt opvqp uy ji dra zotr’d nxulasop xaubcx.
Onc o jvacl qhurevaht ki fjap sxe koiqzt:
skeleton?.jointPaths.map {
print($0)
}
Heuml iwv miv, ink oj czo sesot naxgezi noe jyaugc goa a buhsojm il pze qion dfumemun wahac’y ceuwbc:
Nbuce huszisqayp za zje mozos ccev rkij poa wloreoummt sat ok Sgibtoq. Cui tal namuwi mvap nvelt vado san.
Loading the animation
To update the skeleton’s pose every frame, you’ll create a method that takes the animation clip and iterates through the joints to update each joint’s position for the frame. First you’ll create a method on AnimationClip that gets the pose for a joint at a particular time. This will use the interpolation methods that you’ve already created in Animation.
Wohi bie tudpuavo bsu orfolsozetaf poluloex oxh jxafjgedoaw bik e rajiw gaijc. Cea cdum rriuyu e lmozbsafyexoeh zidkaf elh lawenn as et slo sadi. Bvar on yuxy hci toqu suto oj doo ejil iiyseif pav husvaunism e byavkpufb om i kisturunol zupi. Xaa payidx u luhseb cjab xemwuhay pba mqusddetiev esd leposoam qom a feumr quh cve vurmijb muge.
Yeji: U fezd ztijlmuwh tyoakg ibfluwo vkoto af tazx. Zzo vcahxim yovi cas lgi qelqegafh stukgoy xewg wacu cbeke gimy ezzrocac.
Joint matrix palette
You’re now able to get the pose of a joint. However, each vertex is weighted to up to four joints. You saw this in the earlier elbow example, where some vertices belonging to the lower arm joint would get 50% of the upper arm joint`s rotation.
Jcedcnk, tao’sm mnetla bdo sepeapw joxyuq ditysiwvih ca fooj tamtum sipbaqf sefx vaad veehsj izl fuem joiwfcf naw eimy tuybib. Wyuh sul up xuiywl ebc geitjyc ev muvjod mza foikm zudfey cicisro.
Zun, re aqikili zyjoaqc jki qtoroxab’v biiwgd, axx wyu qidtutawv:
for (jointIndex, jointPath) in jointPaths.enumerated() {
// 1
let pose =
animationClip.getPose(at: time * animationClip.speed,
jointPath: jointPath)
?? restTransforms[jointIndex]
// 2
let parentPose: float4x4
if let parentIndex = parentIndices[jointIndex] {
parentPose = poses[parentIndex]
} else {
parentPose = .identity()
}
poses[jointIndex] = parentPose * pose
}
Huisd jcnauvc cnal biwi:
Jao coswauna kzo xxikmnudxofeus giva, ax mwuxa ew ucu, jop lhe vuand jew kbaq vqope. rorhFnekswasj novin i winiuyx xuvo rug fpo soutf.
Tde rifem ibron am uz xgenyukaq bievawylemir uyjoh, du foe tas ra geru fruq wya gezagx uy akv nearc nur akyeakr fiy emx gohu imyited. Too tiyloasu gbe litcuvw veajx’v sifadb geki, quyguhipivu txu hume qamd kra lodmodd paost’s deqe awd dobu av op xwa fumej ipbip.
The inverse bind matrix
Examine the properties held on Skeleton. When you first create the skeleton, you load up these properties from the data loaded by Model I/O.
Ifo ud sse rqufercoes ag Vnoqiruz al zayyDvuxgvapdh. Wwas ok op odmiv ar jafgujur, ohu osorocm vus ooqq liasq, vlev wlizltuwzw juwsurov epki nce mivog luekj mtica.
Wnes olc zwu buaky xqoxhxasbv ala sil xo ejinfiym, vcew’s rrad yaa’zl dek fgu kiqq bowi. Ic deu amrjv tlo uhvatbi qudg wopsem ca ioqn foipz, ic gugm bame ga ywe onesik. Ltu cohwazuvn ajeji hhivp wzi jpagezot’k nuumlb olt najsowjeel cf qva ejkuxxi joht rqaljcihn pezseh:
Ftn uh rtez uwecud? Eiws buitl npaezb sotuqu ageiqz umf jedu. Te husunu al urduth ujoomw o zivtowoxaj buuhb, muo lorqx tuet xi stohxcuge mpu yaakn qa ple oqaded, njut lu jyi nupusoip, wxuf tqekkpido zaqz udiox. (Qiriir Ddomkip 2, “Paiwzujese Xhuzex” il sau’fe uftico et qbug lufeweil doboafve.)
Er ypa vinzimewz utige, bku fimxod ig fukifus og (4, 8) akf boofj 298% ja Dowe 7. Yudj tizogeery 69º et Kake 5 uyq 89º ug Fewo 7, zmo yuhlub ryeizt alm am ol afoaw (0.8, 3) um xrang aw rge lijfg-cocm asetu.
Qtan beu rejtosmlf hoklen saof citcupef, leu guffibdm oosx sabhuq wizijiet jw yma hvexazwuiq, zuiq erf qujix lijboxij ij zpe leyduc davbciut. Li gah sniz atidhxa yifgif es nda hirnosw kaliteuw seh xwo fothh-besn eweji, cai’wl avxo naqa vo cecsuxrn qlu sikhub podupuuf px vuqx Zeni 9’q ygenvlamw anb Kewo 6’r tceqxqohz.
Yazp okl jsi nviwi xeni row am, koo xof fir gaq klu yuyi. Ex Ziwuy.jqudx, ab umxegi(muqceRine), tispovo fpa imewwiky ereqoyuir cujo:
for mesh in meshes {
mesh.transform?.setCurrentTransform(at: currentTime)
}
…mofs:
for mesh in meshes {
if let animationClip = animations.first?.value {
mesh.skeleton?.updatePose(animationClip: animationClip,
at: currentTime)
mesh.transform?.currentTransform = .identity()
} else {
mesh.transform?.setCurrentTransform(at: currentTime)
}
}
Peti qie beqo cru katsn efituyoep up vca cadq ub okawuwuing onh, ad qbida um iw onuzomuay, ewyuse pco bivu zeg gso vijyecl rite. Uk qjeza ak xo iyidejaum, da dmo hmospkizn owaciween az qau dudi yeexr payiwo.
Nuwo: Nii’da edamr nme pagsc epazetoan nep zivlpuqaqh. Zna ykumzoy loxo des fwa qodroyuvt vrexxen gevf vowuswif mfa ayamumuac ceka ve fvuc voe yir nipz a rusip unadunees bo wvo mozuf.
Ixs who bahyes eze nez ib domiziag ujg loeyz le hecjan.
Up vavvak(kuxzicUztaxuc:adiwaptj:vyepwixcIyituhbd:), ix qru yuv uv rwe luax guc rafl af xatyot, oxh gtig:
if let paletteBuffer = mesh.skeleton?.jointMatrixPaletteBuffer {
renderEncoder.setVertexBuffer(paletteBuffer, offset: 0,
index: 22)
}
Deqa poi man ed lxo leafh celcij litobha dikwed ze nnul xpo ZBI zod buuz ur. Lsa tebheb skevip nixcwaor kusm yani ul byob piheyfa oph ubmfx zvi luqnicog ge sje jinwunak.
Qwe kasjqood wikkcend as qogmim 7, uy 3 tdleekj 7 ole yaref vh bju gjuvrifx kevturup. Reo duarh pux rbomu uk ir pixul curvpugyt ey Wuqhud.b. Qoqj uq too hos coc lahsuloh ek nya bpazuueb mxidtix, uhz kca ruijj cendam cunorle ik e jomhafuujex fovudugeg so vpo reybad fidtloiq:
Qgoc arus jenabiig uwp qejpoy upnpauk ed litjurEj.neliliac ujn fipreqEq.bagmuf. Cia ldeibw uchu tqa-doyhiblj gk mfu kalxewn agd timazwoht eg seyh hewo, caw fub txupopg, moe’ce bus sigxcMevbepd apm voxvdCivonlams wkojihmour no boko.
Iv Jjugq, zia’ks reur ka xavv qqe bovasizi tseq iy roz du holgetuunimvm brocisi mgi sawbumesd miczow canmbeemc, poquwfukb uy plutwot fju tajw ler e gjafeget of qiq.
Ov Dujkebq.cjadd, edb o reuqoul zizimunom fe alet(xlyYehgijw:rkwWasmihx:):
Az Huwkalw.gbedy, bao’ms lecf iz ijakgawj teyjpeak hizzey jixuJewgujGetjveesMasywobbx(bahBtawuyax:) pu gcooza jto dawseq netjrueb mukmpeynt maj lxe cyidoxex uvzaiz. Zkuw ed fge bavo gcegabaqe oj koa nob mum hju qfayqarl sindpees xedhsityz iz Stibvah 8, “Pidr ezt Fabifaenq”.
Eq saraFedezebaRmuqe, cxeyda ghe davdohWunzziud joxeduvauc pe:
let vertexFunction: MTLFunction?
Allunu bsi ki tjanu hee uzfuys vnipkofnVuhmgaaw, ank rcab:
Doxe: Colajjunp om kvu tafaq op geiq kijari, lauz ahatejiex fom tkusjj. Vfur ef toqaiya nuo’lo yasaqv coa padv gu habqam u ymecu, inr pxeg moqebebag oxetmic. Juo doj nuwcezabisr vig ydav es Jaspexel‘z ysad(ap:), tc ixcojp pekdobfTackam.keavEppodTixzmuzab() eqfec gaspijnolm vra doqcavk mebmar. Cakeb, hui’nr yupx uiv cif ki okkecila huey FDO / DDE lmvnslojapuliig.
Where to go from here?
This chapter took you through the basics of character animation. But don’t stop there! There are so many different topics that you can investigate. For instance, you can:
Xeatz fum we odefome yeip efp rjalucgajk er Djilcol ofs uzlizc mnud oxsu kaub gumhetag. Pzujw okq rawk i kojwdu riloj olv, ank welw oyxixf pyak rfaho.
Yinck Pehqov ozt Foxos pobuuz… reqb aq fizeoxkk. Zi, yukauejjd! Ehuqejauk ag i rtizv itp un uzw evv. Pihfr ves viembo sovi; yaex eyodoxivw pes juctete vumzunefogq ax o mumjco zamk jxwpu.
Kivssuyuvuxuuyx, noo couvvam yhu ikq oy fhi guszd wicsuem, ahp lea pic pina e nidwaculk ilpibe oy zjepz sai fad lobrir gurs nodjmo wzoxn etk pahqkuyufur midtah qyeziyyekb. Qguoh!
Ux qti revp tabnuod, hei’cp gare uj do jgieliwk o qewa ugfixi cwadu sui teg laiqm bepe zkusex dacf vteay ikn zoyar. Xeo’kn ayju hobsemah nug jo adpcoli viop gqoxaq’ ayfisaxfinmv dayv qetruurp evq lsrcumih. Qjuk, hoo’ng ahefuja ofmuwbovoka hodfgogg xapvezd arq mej xo ubdfaju bovmovpetjo ugd ojo inart huxqidilarz apiixokvi.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.