0,]']±>Sï}WÿÍu§ðp8·d%qy)6o;]ÉA¦ösï÷ôôô”°ÂVl†3žžžžžžžžžžžžžžžžžžžžžžžžžžžžžt b OOOOOOOOOOOOOOOOOOOOOOOOO2iGK3]___________________________ \ ]PPPPPPPPPPPPPPPPPPPPPPPPPPPPd 0bcp`p`pPpPpP@p@p@p0p0p0p p p ppppppppppppppˆ €€€€€€€€€€€€€€€€€€€€€€€€€€€€€dococodoeofogohohoiojokolomonorW X ðàðpgikno`````````````````````````d7jkko````````````````````````t£¢¢£¤ ¥ ¦§¨©ª«¬­®¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯`«ª© ¨§¦§¨©ª«¬­                 t@p`P@0 ðàÐÀ° �€€€rB@D0F H@@@@@@@@@@@@@@@@@@@@@@@@@@ý é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``é`)`©``¡þ££´¢þ£´¢þ££´¢þ£´¢þ££´¢þ£´¢þ££´¢þ£´¢¢þ££´¢þ£´¢þ££´¢þ£´¢þ££´¢þ£´¢þ££´¢þ£´¢¢ô$¡ôÃö¢ôö¢ôÃö¢ôö¢ôÃö¢ôö¢ôÃö¢ôö¢¢ôÃö¢ôö¢ôÃö¢ôö¢ôÃö¢ôö¢ôÃö¢ôö¢¢ö$%%%%%%%%%%%%%%%%ôfFfF FFfFfF FFfFfFfFfF FFfFfF FFfF FFfFfF FFfFfF FFfFfFfFfF FFfFfF FFfF FF¤‡ö¯¦¯ö¯¦¯ö¯¦¯ö¯¦¯ ¯ö¯¦¯ö¯¦¯ö¯¦¯ö¯¦¯FF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFé jéé jéé jéé jéé jéé jéé jéé jéö¯¦¯ÃƯôö¢ö¯¦¯ÃƯôö¢ö¯¦¯ÃƯôö¢ö¯¦¯ÃƯôö¢ù¯¦¯ÃƯôö¢ôÃö¢ôö¢ö¯¦¯ÃƯôö¢ôÃö¢ôö¢¢f† f†f ff† f†f ff† f†f ff† ff†fd„ d„d dd„ d„d dd„ d„d dd„ dd„dééééééééééééééé j j j jFF FFfFF FFfFF FFfFF FF fFF FF fFF FFfFF FFfFF FFfFF FF fFF FFfFF FF%%%%%%%%%%%%„„ d d d dd d dþ££´¢þ£££´¢þ£þ£é`)`©``é`)`©``EE E E E EE E„ééé jééééé jééééé jééééé j j j jééé jééééé jé饥 … … … …… … „ôffFfôffFffFFFF F F F F Fff F F F FF F%ôk$k÷k'kùk)k)kkôk$k÷k'kùk)k)kkôŒ$Œ÷Œ'ŒùŒ)ŒŒ)ŒôŒ$Œ÷Œ'ŒùŒ)ŒŒ)Œééééééééééééééééô�t�ô­T­û��~�ý�]�û�ô�t�ô­T­û��~�ý�]�û�ô�t�ô­T­û��~�ý�]�û��t�ô­T­ô�t�û��­FF FFMFMF FMFMF ùF ðð ðð ðð FFf F M F M FFMFMFôfð ðð ðð ðff ffmfmffmfmfùf ðð ðð ðð ff† f m f m ffmfmfô†ð ðð ðð ýj j j j%ök%ök%ùk%ùk% k% k% k% k%ök%ök%ùk%ùk% k% k% k% k%ôk%ôk%÷k%÷k% k% k% k% k%ôk%ôk%÷k%÷k% k% k% k% k(H (( ( ((H (( ( ((H (( ( ((H ( (( (ééé jééééé jééééé jééééé jééééé jééééé jééééé jééééé jéé(H (H( ((H (H( ((H (H( ((H ((H(%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jééé jéééfFF f F F f F f F F f F F f FfFF f F F f F f F F f F F f FfFF f F F f F f F F f F F f FfFF f F F f F f F F f F F f F„„ d d d dd d.ff F F F FF F.EE E E E EE E.¥¥ … … … …… ….­w­ô­T­4­û��­ ­y­÷­W­7­û��­­w­ô­T­4­û��­ ­y­÷­W­ô­t­û­{­[­—Â@Â@‚q ‚q ‰r,‰r, s4‰t4Éã4Éã4ÐsDÉ5É5“EUê¦eÆf×y¡HŒ¡HŒyŒyŒ x4 x4 ( ( È4eÉ4eyšhª®ñìÀ?ÿÌÌÌìÏÍÀÌÏÝÌ ÍÌÌíÍÌÐÌQÍÌÌìQUÌ îÀÍ%UÐÌ àÞÌìR%U!ÐÌ  Ý ÀÌUU%QÐÌ ÝÞÜQRU%ÐÌÚÝ QU%ÐìÌUUUUUÛÌ Ý QUU%QòÀ ÀÜìUUURÁÝÌ ÚíUUU%!ïÀÌÌÌü "UURUQÍ ÍÌ!U!«Þ P%UU%ò ÀÍÜÍÌQUUUUQÜ ÀÍ PU%Q¡íÝPUUU%Q ÌÜÌÌýQUU%UÌ ÍìUR%QëÝQUUU%ÌÍÜÌRUU%UÒÌ ÍìPUU%QªÝQ"RU%QÐÍÜÌÌQUUUU!QÌÝÐÍÌËìQRU%¡ÚPUU%"UÌÌÍÌ QUURUÌÌàÎÜÝíîRUU%áªÎPUUUUU"QÜÍÌ ÐQ%URRÁÍ îÌÌÌ»îUUU%UQîîÎUUUUUUÀÜÌ ÐÍ-UUURÊÌ ÝÌ̼ËìUUU%Uªª¼QUUUUQÝÌ ÌÌÝÜ%UU‘™Ì àÎÝÌ »ëUUUUªªËàüÿ_UUUÀÌÝÝÌÍ]%™™íÌÌÌ˼þRUUUU%Qªª¼ÿîÌÿÿÿ%UñÀÝÜÜÍÁ ÝÜÝ̰»ÿQUUUUªª þïßËËË[UËËÌÌÍÌÜÌÝÜàÍÌÜ Ë+UUU%Uñªª °¾îϼ¼¼\%±¼Ë ÐÍÍÍÜÍÝÝÜÍàÎÌÌ»»RUUÿÿÿªª °þ¿ßËËËËË»Ì ÐÜÍÜÝÌÝÜÍÍÝ ÞÍÍÜËËRUËËûªÊ àÿþ̼¼¼¼¼ÌËËËÀÌÜÜÍÝÜÜÍÜÌÌÍÌÌ ¼»»ËË»»»ªË îüîÜËËË˼¼ÌËË ÀÝÝÍÌÝÜÍÜÝÌÍÜÜÌ»ËË»»ËË˼ÊüþÎ̼ÌËËË»¼Ë¼ ÝÍÍÍÝÌÝÍÜÌÍÍÜÌÝÌ»»ËË»»»ËÀÌÏÜË»¼¼ÌË»ª»¼ÝÜÌÝÝÜÍÜÜÌÍÜ Ê »Ë»¼»»ËËËÀÌ̼ÌË˼Ì˪˼ÜÝÝÜÌÍÍÜÌÝÌÜ   ¼Ë»»¼¼»Ë¼ÐÌÜË»¼¼»¼¼ »Ë ÍÍÌÌÜÍÜÌÌÍÜÍ ¼»»¼¼»»Ì ÀÍ̼ËËÌËËË » ÐÌÌÍÍÍÜÝÌÍÜÜ̻̻»»¼¼Ë ÐÌÌ˼̼¼¼Ë» ÀÝÜÝÍÍÜÌÍÍÜÍͰ»»¼¼»»Ì ÀÍ̼ËËËË» »ËÀÍÌÜÌÜÜÌÍÜÝÌ °Ë»¼»¼¼Ë ÐÍÌ˼¼¼ÌË  »ÀÍÍÝÝÜÌÝÌÜÍÝ °Ì»»¼¼»¼ ÀÌ̼ËÌ˼¼ °»ÝÝÍÍÍÌÌÍÜÍÌݰ»Ë¼»»¼Ì ÐÍÌ˼»ÌËË Ê ÌÌÌÌÌÍÍÜÜÌÝ̰¼»»ËË»ËÀÜÌ̻̻¼¼°ÌÝÝÜÝÝÍÜÍÍÝ À¼»»¼»Ë¼ÐÍ̻̼̻˰ ÝÍÍÌÜÌÜÝÌÝÜ °»Ì»»Ë»ÌÐÌÌ̼˻¼¼»ÐÌÌÌÍÍÜÜÌÝÍÜÀ»»»¼»»ËÀÝ̻˼ÌÌËÀÝÝÝÝÍÝÍÌÝÜÝÀ»»ËËÌÐÌÌ̼˼»ÌÀÍÌÜÌÌÌÌÝÌÜ ÀÌÍݽËË ÀÝÌÌ˼»Ë ÀÌÍÍÝÜÝÍÍÜÍ ÀÜÝÝÝÝÛ ÏÌ»ÌËÿÿÏÝÝÝÍÍÝÜÌÜÝÌÀÜÝÝÝÝÝ ÐÝÜÜÜÜÜÜÌÍÌÌÌÌÍÌÜÜÍÝÐÝÝÝÝþßÐÝÝÜÜÜÜÜÌÀÝÝÜÝÝÝÝÍÌ ÝÝÝàïÝ ÐÝÝÜÜÜÜÜÌÍÝÜÌÌÍÌÝ ÝÜÍ ïßÝ ÐÝÝÝÜÜÜÜÌÀÍÜÜÍÍÍàÍÝÜͪÚÍÝÐÝþðÎÜ àÝÝÜÍÜÍÝÝÝ  «ÝÝÐÝýîàÎÍÜ ðÞÝÍÌÌ ÐÜÝÝݪÌÍ ÝÜÝý®ðÌÍÜÌàßÝÝÝÝÝ ÞÝÍÝ ºÚÝ ÜÍݬ  ÜÍÝÜ ÞÝÝÝÝÝÿÿÝÝÜͰÚÍ ÐÝÜÝ­ÛÍÝÜ ÿÝÝÝÝÝÿÏÍ ÐÜÝ ªÝÐÜÍݪ°ÝÝÜÌÝÝÝÝÝÌÍÜÜ ÀÿÝ «Ý ÝÍݬ ÍÝÝÌ ÛÝÝÝÜÜÍÍ ÀÝ ÀÌ ÝÜÍ­ÀÜÜÝ ÐÝÝíîÎÍÜÜ ÀÝ ÀÜ ÐÝÍݺÌÌÝ  ÝíîîÞÜÍÍ ÐÍ ÀÌ Ýݬ ÀÌÍíîîîÎÝÜÍ ÐÝ ÀÝ ÀͽÍÿÏëîîîîÌÜÜ ÐÌÀÌ ÐÿÝ ÐÜÌàîîîîÜÍÍ ÐÝÀÝ ÐÝÍ ÀÍÌàîîîîÍÜÜ ÀÜÀÌÐÝÌ ÐÜÌàîîîîÜÌÍ ÜÝÐÝÀÝÍ ÀÍÌÀîîîîÍÝÜ ÌÝÀÌÐÝÍ ÐÝ̰îîîîÜÌÍ ÜÝÐÍÀÜÝ ÀÍÍîîîîÍÍÜ ÝÌðÿÍÍ ÐÜÌîîîîÜÜÍ ÝÀÍýÏÌÝ ÀÍÍîîîîÍÍÜ üÀÍ ÝÌ ÐÌÌìîîîþÿÉÍÍÌÀÍÍëîîîÞÌ À ÝÍÍÐÜÌàîîîÎÝ ÝÜÌÀÍÍàîî®ÚÌ ÝÍÌÿ ªúÌÝ ÜÝÐÌÿÿðÿÜÌ ðÿÌÐÍÌ ðÿÿÌÝ ðÿÍ À ÐÍÌÜÌ ÝÍ ÀÌÌÌÝ ÌÍÐÌÜÌÌ ÀÌÌÜÝ ÐÌÜÌÌ °ÌÌÛÝ °ÌÝÌÌ ÀÌÌÛÝ °ÜÝÌÌ ÀÌÌÜÝ °ÝÍüÿÌÌüÿÝÍÌÿÌÌ ÿÿÝÌ ÍÜÌÿÌ ëþðÿðÿÀÝÝÝÝ"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""!!!!""""""""""""""""""""""""""!!!!""""""""""""""""""""""""""3333#3!!3323#!333#1333!!3313!333""""""""""""""""""""""""""333333!!333#2333#!3333#1333!!333#1#!3!333""""""""""""""""""""""""""333333!1333333333!333331333!233332313!333""""""""""""""""""""""""""3333!23!3!3#23!32313!33!#3313!3""""""""""""""""""""""""""333#3!3#213!3!3!313!!3#3323!3""""""""""""""""""""""""""33333!!3233#!33#13!!333333!3""""""""""""""""""""""""""3333333!!3233#!33#1333!3333!33#33#!333""""""""""""""""""""""""""3333#33!!3233#!33#1333!2333313#3#33!333""""""""""""""""""""""""""33333#3!!3233#!33#1333!233313333!333""""""""""""""""""""""""""33233!!3233#!33#13!23#13333!3""""""""""""""""""""""""""33133!3#213!3!3!313!!3#13333!3""""""""""""""""""""""""""33!33!23!3!3#23!32313!!#2323233!3""""""""""""""""""""""""""333333!1333333333!333331333!2333333123!333""""""""""""""""""""""""""333323!!333#2333#!3333#1333!!333#33113!333""""""""""""""""""""""""""333313!!3323#!333#1333!!3#33!13!333""""""""""""""""""""""""""!!!!""""""""""""""""""""""""""!!!!"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""e-- title: Countdown Hoedown -- author: RiFT -- desc: A dance number inspired by the gameshow. Released at NOVA 2025 -- version: 1.0 -- script: lua -- using 1.0.2164 Pro rift_partstestvram=function() R=R or {} rift_demopart()(R) rift_gfxvram()(R) local T=0 return R.DemoPart:new({ tic=function(pMetrics) if pMetrics.isFirstRun then end local bpp = 1 cls() for xTile=0,3 do for yTile=0,3 do for x=0,7 do for y=0,7 do local c = (x+y*8)%16 pix(xTile * 8 + x, yTile * 8 + y, c) end end print(xTile + yTile*2, xTile*8+2,yTile*8+1, 1) end end local destX = (T>>5)%16 local destY = (T>>5)//16 R.VRAM.screenToTiles(0,0, 4,4, destX,destY, bpp) -- cls() local drawFromVRAM = true bppToValue = { [1] = 0x8, [2] = 0x4, [4] = 0x2, } if drawFromVRAM then local quadSrcX = 0 local quadSrcY = 0 local quadDestX = 0 local quadDestY = 40 local w,h = 256,128 local dx0,dy0,dx1,dy1 = quadDestX,quadDestY,quadDestX + w,quadDestY + h local sx0,sy0,sx1,sy1 = quadSrcX,quadSrcY,quadSrcX + w,quadSrcY + h local sSrc = 0 -- (1 is map, but needs map layout) poke4(0x3FFC*2, bppToValue[bpp]) -- set bpp ttri( dx0,dy0, dx1,dy0, dx0,dy1, sx0,sy0, sx1,sy0, sx0,sy1, sSrc, -1 ) ttri( dx1,dy0, dx1,dy1, dx0,dy1, sx1,sy0, sx1,sy1, sx0,sy1, sSrc, -1 ) end T=T+1 end, cleanup=function() end, }) end rift_partsdancebox=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress local dancer = stage3d.dancers[1] dancer.isVisible = true local danceT = progress * 16 - 3.5 dancer:setPosition(R.V3:new(0, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("box", dancer, danceT) local danceT = progress * 16 - 3.5 local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(15, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(.3, mPi +.2, 0)) animations.applyToSkeleton("slapstick-run", dancer, danceT) local dancer = stage3d.dancers[3] dancer.isVisible = true local danceT = progress * 16 - 3.5 dancer:setPosition(R.V3:new(-15, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(.3, mPi - .2, 0)) animations.applyToSkeleton("slapstick-run", dancer, danceT) stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_3d2material=function() -- NB triangles and quads are clockwise for front-facing -- 1\ 1__2 -- | \ | | -- 3__2 4__3 return function(R) R=R or {} local Material={} -- Interface isn't right for this - ensure all of these are set function Material:new() local o={ fnTransform = nil, fnDistance = nil, fnDraw = nil, order = 0, } setmetatable(o,self) self.__index=self return o end -- chainable function Material:setFnTransform(fnTransform) self.fnTransform=fnTransform return self end -- chainable function Material:setFnDraw(fnDraw) self.fnDraw=fnDraw return self end -- One colour tri function Material.triFlat(ci) return Material:new():setFnTransform(function(d, psView, psWorld) return { v1=psView[d.v1], v2=psView[d.v2], v3=psView[d.v3], } end):setFnDraw(function(d) tri(d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y,ci) end) end -- One colour quad function Material.quadFlat(ci) return Material:new():setFnTransform(function(d, psView, psWorld) return { v1=psView[d.v1], v2=psView[d.v2], v3=psView[d.v3], v4=psView[d.v4], } end):setFnDraw(function(d) tri(d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y,ci) tri(d.v3.x,d.v3.y,d.v4.x,d.v4.y,d.v1.x,d.v1.y,ci) end) end function Material.triFlatLit(ciLow,ciHigh, lightVec) local ciMid,ciRangeHalf=(ciLow+ciHigh)/2,(ciHigh-ciLow)/2 return Material:new():setFnTransform(function(d, psView, psWorld) return { v1=psView[d.v1], v2=psView[d.v2], v3=psView[d.v3], normal = R2.V3.normal(psWorld[d.v1], psWorld[d.v2], psWorld[d.v3]) } end):setFnDraw(function(d) local angle = R.V3.dot(d.normal, lightVec) local ci = ciMid + ciRangeHalf*angle tri(d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y,ci) end) end -- Assumes the quad is a plane! -- function generator... -- we can change lightVec after it has been sent in here (ensure it is normalised) function Material.quadFlatLit(ciLow, ciHigh, lightVec) local ciMid,ciRangeHalf=(ciLow+ciHigh)/2,(ciHigh-ciLow)/2 return Material:new():setFnTransform(function(d,ps) return {v1=ps[d.v1],v2=ps[d.v2],v3=ps[d.v3],v4=ps[d.v4]} end):setFnDraw(function(d) local normal = R.V3.normal(d.v1,d.v2,d.v3) local angle = R.V3.dot(normal, lightVec) local ci = ciMid + ciRangeHalf*angle tri(d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y,ci) tri(d.v3.x,d.v3.y,d.v4.x,d.v4.y,d.v1.x,d.v1.y,ci) end) end function Material.triTextured(sSrc,chromakey,sx,sy,sw,sh,pixelmode,palMap,hackBackface) pixelmode = pixelmode or 2 -- 8: 1bpp, 4 = 2bpp, 2 = 4bpp palMap = palMap or {} return Material:new():setFnTransform(function(d,ps,psWorld) return { v1=ps[d.v1],v2=ps[d.v2],v3=ps[d.v3], t1=d.t1,t2=d.t2,t3=d.t3, } end):setFnDraw(function(d) if hackBackface then --[[ normal = R2.V3.normal(d.v1, d.v2, d.v3) if normal.z > 0 then return end --]] end -- This needs figuring out (which points) and cleaning... local st1x, st1y = sx + d.t1.x * sw, sy + d.t1.y * sh local st2x, st2y = sx + d.t2.x * sw, sy + d.t2.y * sh local st3x, st3y = sx + d.t3.x * sw, sy + d.t3.y * sh local oldPixelMode = peek4(0x3FFC*2) poke4(0x3FFC*2,pixelmode) -- set pixel mode for i=0,#palMap do poke4(0x3FF0*2+i,palMap[i]) end ttri( d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y, st1x, st1y, st2x, st2y, st3x, st3y, sSrc, chromakey, d.v1.z,d.v2.z,d.v3.z ) poke4(0x3FFC*2,oldPixelMode) -- reset pixel mode for i=0,#palMap do poke4(0x3FF0*2+i,i) end end) end function Material.quadTextured(sSrc,chromakey,sx,sy,sw,sh,pixelmode,palMap) pixelmode = pixelmode or 2 -- 8: 1bpp, 4 = 2bpp, 2 = 4bpp palMap = palMap or {} return Material:new():setFnTransform(function(d, psView) return {v1=psView[d.v1],v2=psView[d.v2],v3=psView[d.v3],v4=psView[d.v4]} end):setFnDraw(function(d) -- clockwise... local sx0,sx1,sy0,sy1 = sx,sx+sw,sy,sy+sh local oldPixelMode = peek4(0x3FFC*2) for i=0,#palMap do poke4(0x3FF0*2+i,palMap[i]) end poke4(0x3FFC*2,pixelmode) -- set pixel mode ttri( d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y, sx0,sy0,sx1,sy0,sx1,sy1, sSrc, chromakey, d.v1.z,d.v2.z,d.v3.z ) ttri( d.v3.x,d.v3.y,d.v4.x,d.v4.y,d.v1.x,d.v1.y, sx1,sy1,sx0,sy1,sx0,sy0, sSrc, chromakey, d.v3.z,d.v4.z,d.v1.z ) poke4(0x3FFC*2,oldPixelMode) -- reset pixel mode for i=0,#palMap do poke4(0x3FF0*2+i,i) end end) end function Material.line(colour) return Material:new():setFnTransform(function(d,ps) return {v1=ps[d.v1],v2=ps[d.v2]} end):setFnDraw(function(d) line(d.v1.x,d.v1.y,d.v2.x,d.v2.y,colour) end) end R.Material = Material end end rift_datamaterialletter=function() return function(R2) local tileFont = rift_datagfxtilefont() local mMin, mMax, mRandom = math.min, math.max, math.random -- function generator... -- we can change lightVec after it has been sent in here (ensure it is normalised) -- Ensure you reset palette map after local function materialQuad(ci1, ci2, ci3) return R2.Material:new():setFnTransform(function(d, psView, psWorld, actorData) return { pv1 = psView[d.v1], pv2=psView[d.v2], pv3=psView[d.v3], pv4=psView[d.v4], letter = actorData.letter, } end):setFnDraw(function(d) if d.letter == " " then return end local sx0,sy0,sx1,sy1 = tileFont.getLetterUVs(d.letter) local pv1, pv2, pv3, pv4 = d.pv1, d.pv2, d.pv3, d.pv4 poke4(0x3FFC*2, 4) poke4(0x3FF0*2+0,ci1) poke4(0x3FF0*2+1,ci2) poke4(0x3FF0*2+2,ci3) ttri( pv1.x,pv1.y,pv2.x,pv2.y,pv3.x,pv3.y, sx1,sy1, sx0,sy1, sx0,sy0, 0, -1, pv1.z,pv2.z,pv3.z ) ttri( pv1.x,pv1.y,pv3.x,pv3.y,pv4.x,pv4.y, sx1,sy1, sx0,sy0, sx1,sy0, 0, -1, pv1.z,pv2.z,pv3.z ) -- optimise this by only doing it when we need to! poke4(0x3FF0*2+0,0) poke4(0x3FF0*2+1,1) poke4(0x3FF0*2+2,2) poke4(0x3FFC*2, 2) end) end return { quad=materialQuad, } end end rift_partsmakeclock=function() R=R or {} rift_demopart()(R) local fnsDrawClockface = rift_datagfxdrawclockface() return R.DemoPart:new({ tic=function(pMetrics) if pMetrics.isFirstRun then R.setRGB(0, R.RGB:new(0,0,0)) R.setRGB(1, R.RGB:new(.3,.3,.3)) R.setRGB(2, R.RGB:new(0,0,.5)) for i=0,7 do -- R.setRGB(3+i, R.RGB:new(.6,.6,.6)) end end cls() fnsDrawClockface.quarter(64) end, cleanup=function() end, }) end rift_partsthanks=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local tileFont = rift_datagfxtilefont() local stage3d local mPi, mTau = math.pi, 2 * math.pi local mMin, mMax = math.min, math.max local function rotLetters(letters, iFirstLetter, iLastLetter, turn) for iLetter = iFirstLetter,iLastLetter do local rotX = mMax(mMin(turn * mTau * 4, 0), -mPi/2) local letterActor = letters[iLetter] letterActor:setRotation(R.Quaternion:newFromEuler(rotX, 0, 0)) end end return R.DemoPart:new({ bdr=setup2d.bdrNoConundrum, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() clip() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() end local progress = pMetrics.progress vbank(1) cls() local iFreeLetter = 1 iFreeLetter = letters.setTextActors("RADIDOL", R.V3:new(0,1.25,-7), stage3d.lettersFG, iFreeLetter) -- mibritune iLastLetterAldroid = iFreeLetter - 1 iFreeLetter = letters.setTextActors("BAMBANGERS", R.V3:new(0,-.25,-7), stage3d.lettersFG, iFreeLetter) -- mibritune iLastLetterBeanbag = iFreeLetter - 1 iFreeLetter = letters.setTextActors("THANKS", R.V3:new(0,4.5,-12), stage3d.lettersFG, iFreeLetter) -- mibritune iFreeLetter = letters.setTextActors("FOR LICENCING", R.V3:new(0,-3.5,-12), stage3d.lettersFG, iFreeLetter) -- mibritune iFreeLetter = letters.setTextActors("THE PATARTY POTATO", R.V3:new(0,-5,-12), stage3d.lettersFG, iFreeLetter) -- mibritune letters.rotLetters(stage3d.lettersFG, 1, iLastLetterAldroid, progress, .1, .5, "ALDROID") letters.rotLetters(stage3d.lettersFG, iLastLetterAldroid+1, iLastLetterBeanbag, progress, .2, .6, "MRSBEANBAG") stage3d.cameraFG:setPosition(R.V3:new(-2, 0, 5 - progress * 5)) local cameraRot = R.Quaternion:newFromEuler(0,.2,0) stage3d.cameraFG:setRotation(cameraRot) setup2d.fadeScene(progress, .2, .8) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) end, cleanup=function() end, }) end rift_codeletters=function() local tileFont = rift_datagfxtilefont() CONUNDRUM = "PORTANAVY" local mPi, mTau = math.pi, 2 * math.pi local mMin, mMax = math.min, math.max local function sceneClip() clip(0, 0, 240, 115) end local function drawConundrum() clip(0, 115, 240, 21) rect(0,115,240,25,2) tileFont.drawText(CONUNDRUM, 30, 116) end local palette = { [1]={40, 40, 120}, [2]={80, 80, 200}, [3]={255, 255, 255}, } local function setTextActors(txt, v, lettersFG, iFreeLetter, scale) scale = scale or 1 local letterD = 1.1 * scale for i=1,#txt do local letter = txt:sub(i,i) local x = v.x + ((#txt-1)/2 -(i-1))*letterD local letterActor = lettersFG[iFreeLetter] letterActor:setPosition(R.V3:new(x, v.y-.5, v.z)) letterActor.isVisible = true letterActor:setData({letter=letter}) letterActor:setScale(R.V3:new(scale, scale, scale)) iFreeLetter = iFreeLetter + 1 end return iFreeLetter end local function rotLetters(letters, iFirstLetter, iLastLetter, progress, tSpin1, tSpin2, altText) local rotX = 0 local switchLetters = false if progress >= tSpin1 then if progress < tSpin2 then rotX = rotX + mMin((progress-tSpin1)/.1,1) * mPi/2 else local spinProgress = mMin((progress-tSpin2)/.1,1) if spinProgress > .75 then switchLetters = true end rotX = rotX + mPi/2 + spinProgress * mTau end end local iLetter = 1 for indexLetter = iFirstLetter,iLastLetter do local letterActor = letters[indexLetter] letterActor:setRotation(R.Quaternion:newFromEuler(rotX -mPi/2, 0, 0)) if switchLetters then letterActor:setData({letter=altText:sub(iLetter,iLetter)}) iLetter = iLetter + 1 end end end return { drawConundrum=drawConundrum, setConundrum=function(c) CONUNDRUM = c end, setTextActors=setTextActors, rotLetters=rotLetters, screenSplit=119, sceneClip=sceneClip, palette=palette, } end rift_partstestticmctile=function() R=R or {} rift_demopart()(R) rift_gfxticmctile24()(R) local gfxPatarty = rift_datagfxpatarty() local gfxClockface = rift_datagfxclockface() local gfxTileFont = rift_datagfxtilefont() local isSprites = true local T=0 local GFX_PATARTY return R.DemoPart:new({ tic=function(pMetrics) if pMetrics.isFirstRun then --[[ setRGB(0, 255, 0, 0) setRGB(1, 255, 255, 0) setRGB(2, 255, 0, 255) setRGB(3, 0, 255, 0) --]] -- dataToMem(rleUnpack(gfxPatarty.pal)) dataToMem(rleUnpack(gfxTileFont.img), 32768 + 64*0) dataToMem(rleUnpack(gfxPatarty.img), 32768+64*8) -- dataToMem(rleUnpack(gfxPatarty.img), 32768) --GFX_PATARTY = R.TicMcTile:new(gfxPatarty.img, true, 4, 0,0, 64,96) end cls() rectb(0,0,239,127,12) --GFX_PATARTY:draw(148, 20) -- GFX_RIFT_LOGO:draw(150, 32) poke4(0x3FFC*2, 4)--GFX_HATCHING.blitSegment) local drawFromVRAM = true if drawFromVRAM then local w,h = 128,128 local dx0,dy0,dx1,dy1 = 0,0,w,h local sx0,sy0,sx1,sy1 = 0,0,w,h local sSrc = 0 -- (1 is map, but needs map layout) ttri( dx0,dy0, dx1,dy0, dx0,dy1, sx0,sy0, sx1,sy0, sx0,sy1, sSrc, -1 ) ttri( dx1,dy0, dx1,dy1, dx0,dy1, sx1,sy0, sx1,sy1, sx0,sy1, sSrc, -1 ) end print("ABCDEV ALL GOOD") T=T+1 end, cleanup=function() end, }) end rift_partsdancewarmup=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") if isCrazy then letters.setConundrum("STOLENART") else letters.setConundrum("ENCODESME") end end local progress = pMetrics.progress local dancer = stage3d.dancers[1] dancer:setVisible(true) dancer:setPosition(R.V3:new(-10,0,-30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi * .4, 0)) animations.applyToSkeleton("stretch-twist", dancer, progress * 8) local dancer = stage3d.dancers[2] dancer:setVisible(true) dancer:setPosition(R.V3:new(10,0,-30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi * -.3, 0)) animations.applyToSkeleton("stretch-toe-touch", dancer, progress * 12) stage3d.cameraFG:setPosition(R.V3:new(10-progress*20,15,0)) local lookAtPos = R.V3:new(0,5,-25) local cameraUp = R.V3:new(0, 1, 0) cameraUp:normalize() local cameraRot = R.Quaternion.lookAt(stage3d.cameraFG.pos, lookAtPos, cameraUp) stage3d.cameraFG:setRotation(cameraRot) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdanceshadows=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mSin = math.pi,math.pi * 2, math.sin local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) stage3d = setup3d.init() animations.init() stage3d.clock.isVisible = false for i, dancer in ipairs(stage3d.dancers) do dancer:setData({ci=i}) local scale = 1+((i-1)/(#stage3d.dancers-1))*10 dancer:setScale(R.V3:new(scale, scale, scale)) dancer:setVisible(true) end setup2d.setVBankRGBs(1, setup2d.standardPalette) setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress for i, dancer in ipairs(stage3d.dancers) do local iAdj = (i-1)-1.5 local danceT = progress * 24 - i * .12 + .75 local rY = mSin(danceT) local bump = 0--mSin(animT * mPi * 2) local y = ((i-1)/#stage3d.dancers)*10 local z = (i-1) * -60 dancer:setPosition(R.V3:new(0, bump*.1 + y, z)) dancer:setRotation(R.Quaternion:newFromEuler(0, rY + mPi, 0)) animations.applyToSkeleton("kicksailor", dancer, danceT) end --camera:setPosition(R.V3:new(-mSin(progress * mPi * 3)*4, mSin(progress * mPi * 5), 15)) local zCam = 0--mSin(progress * mPi * 16) * 10 stage3d.cameraFG:setPosition(R.V3:new(0, 3, 30+zCam)) stage3d.cameraFG:setRotation(R.Quaternion:newFromEuler(0, mSin(progress * mPi * 8) * .1,0)) --local fov = 90 + mSin(progress * mPi * 16) * 5 -- camera:setFOV(fov) -- clock:setPosition(R.V3:new(0, 15, -50)) -- clock.skeleton:setJoint({"miFace","jCentre"}, R.Quaternion:newFromEuler(0, 0, progress * mPi)) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_3d2engine=function() -- Gonna try for right-handed coordinate system -- Y:up=positive, X:right=positive, Z:out-of-screen=positive return function(R) R=R or {} local Engine={} function Engine:new() local o={ models={}, materials={}, viewportXC=120, viewportYC=68, viewportScale=80, } setmetatable(o,self) self.__index=self return o end function Engine:addModel(model) local id = #self.models + 1 self.models[id]=model return id end function Engine:getModel(modelID) return self.models[modelID] end function Engine:setMaterial(materialID, material) self.materials[materialID]=material end function Engine:material(materialID) return self.materials[materialID] end -- transforms a 3D projected vector into a 2D screen position, retaining z so that we can use it for depth sorting function Engine:transformForViewport(v) local zD = 1/v.z return R.V3:new( self.viewportXC - self.viewportScale * (v.x * zD), self.viewportYC - self.viewportScale * (v.y * zD), v.z ) end R.Engine = Engine end end rift_3d2skeleton=function() return function(R) R=R or {} local Skeleton={} local mPi = math.pi function Skeleton:new() local o={ -- indexed by {meshID} => {jointID} joints={}, jointRanges={}, } setmetatable(o,self) self.__index=self return o end function Skeleton:setJoint(jointRef, quaternion) local meshID, jointID = jointRef[1], jointRef[2] if self.joints[meshID] == nil then self.joints[meshID] = {[jointID] = quaternion} else self.joints[meshID][jointID] = quaternion end end function Skeleton:getJoint(jointRef) local meshID, jointID = jointRef[1], jointRef[2] if self.joints[meshID] == nil then return nil end return self.joints[meshID][jointID] or nil end -- NB the ranges get multiplied by PI! function Skeleton:setJointRange(jointRef,q1m,q1r,q2m,q2r,q3m,q3r) local meshID, jointID = jointRef[1], jointRef[2] if self.jointRanges[meshID] == nil then self.jointRanges[meshID] = {[jointID] = {q1m=q1m*mPi,q1r=q1r*mPi,q2m=q2m*mPi,q2r=q2r*mPi,q3m=q3m*mPi,q3r=q3r*mPi}} else self.jointRanges[meshID][jointID] = {q1m=q1m*mPi,q1r=q1r*mPi,q2m=q2m*mPi,q2r=q2r*mPi,q3m=q3m*mPi,q3r=q3r*mPi} end end function Skeleton:getJointRange(jointRef) local meshID, jointID = jointRef[1], jointRef[2] if self.jointRanges[meshID] == nil then return nil end return self.jointRanges[meshID][jointID] or nil end -- NB we do not cap these values to -1 to +1, this is expected of the caller function Skeleton:setJointWithRange(jointRef,q1,q2,q3) local jointRange = self:getJointRange(jointRef) -- assume jointRange is not nil and we find one self:setJoint(jointRef, R.Quaternion:newFromEuler( jointRange.q1m+q1*jointRange.q1r, jointRange.q2m+q2*jointRange.q2r, jointRange.q3m+q3*jointRange.q3r )) end R.Skeleton = Skeleton end end rift_syscatmullrom=function() --- Helpers for Maths - catmull-rom -- @module sys.math return function(R) R=R or {} local CatmullRomSpline={} local mMax, mMin = math.max, math.min function CatmullRomSpline:new() local o={ values={}, -- We can override this to get, for example, a vector value -- By default, it returns a single 'float' fnValueInterpolater = function(t, v0, v1, v2, v3) return R.catmullRom(t, v0, v1, v2, v3) end, } setmetatable(o,self) self.__index=self return o end -- NB You must add these in order! (#TODO: we could supply a sort function) function CatmullRomSpline:addValue(time, value) self.values[#self.values+1] = {t=time, v=value} end function getValueIndexV1(t, values) for i=2,#values do if t <= values[i].t then return i-1 end end return #values end function CatmullRomSpline:setValueInterpolater(fnValueInterpolater) self.fnValueInterpolater = fnValueInterpolater end function CatmullRomSpline:getValue(time) local values = self.values local p1 = getValueIndexV1(time, values) local p0 = mMax(p1 - 1, 1) local p2 = mMin(p1 + 1, #values) local p3 = mMin(p1 + 2, #values) local t1 = values[p1].t local t2 = values[p2].t local t = (time - t1) / (t2 - t1) return self.fnValueInterpolater(t, values[p0].v, values[p1].v, values[p2].v, values[p3].v) end -- @param t Time (0-1) -- @param v0 The value at T=0 -- @param v1 The first mid-value modifier -- @param v2 The second mid-value modifier -- @param v3 The value at T=1 R.catmullRom = function(t, v0, v1, v2, v3) return 0.5 * ( (2 * v1) + (-v0 + v2) * t + (2 * v0 - 5 * v1 + 4 * v2 - v3) * t * t + (-v0 + 3 * v1 - 3 * v2 + v3) * t * t * t ) end -- Catmull-Rom spline interpolation -- Multiply these terms by v0,v1,v2,v3 and sum to get the interpolated value -- tension 0 - 1 --[[ e.g. local term0,term1,term2,term3 = R.catmullRomGetTerms(t, tension) return R.V3:new( v0.x * term0 + v1.x * term1 + v2.x * term2 + v3.x * term3, v0.y * term0 + v1.y * term1 + v2.y * term2 + v3.y * term3, v0.z * term0 + v1.z * term1 + v2.z * term2 + v3.z * term3 ) --]] R.catmullRomGetTerms = function(t, tension) local tSq,tCb = t*t, t*t*t return (-.5 * tension * tCb + tension * tSq - .5 * tension * t), (1 + .5 * tSq * (tension - 6) + .5 * tCb * (4 - tension)), (.5 * tCb * (tension - 4) + .5 * tension * t - (tension - 3) * tSq), (-.5 * tension * tSq + .5 * tension * tCb) end R.CatmullRomSpline = CatmullRomSpline end end rift_data3dbillboard=function() return function(R) local mPi,mTau,mSin,mCos = math.pi, math.pi * 2, math.sin, math.cos -- style: "regular", "outline" local function makeMeshTemplateBillboard(w,h, texBillboardID) local mesh=R.Mesh:new() for y=0,h do for x=0,w do local tx = x -w/2 local ty = y -h/2 mesh:addVertex(nil, R.V3:new(tx,ty,0)) end end for y=0,h-1 do for x=0,w-1 do local v00,v10,v01,v11 = 1+y*(w+1)+x, 1+y*(w+1)+x+1, 1+(y+1)*(w+1)+x, 1+(y+1)*(w+1)+x+1 -- mesh:addRenderable(texBillboardID, {v1=1,v2=2,v3=3,v4=4}) mesh:addRenderable(texBillboardID, { v4=v00,v1=v01,v2=v11,v3=v10, }) end end return mesh end local function makeModelBillboard(w,h, texBillboardID) local model=R.Model:new() model:addMeshTemplate("mtBillboard",makeMeshTemplateBillboard(w,h, texBillboardID)) model:addMeshInstance("miBillboard",nil,"mtBillboard",R.Quaternion:newFromEuler(0,0,0)) return model end return { makeModel=makeModelBillboard, } end end rift_fontsysfont=function() --- Functions to handle System font data. -- These are system fonts, so use the standard print function. -- @module gfx.sysfont -- @author Decca, Mantratronic return function(R) R=R or {} --- Overwrite the current system font -- @tparam table font Font data (RLE, or RAW) R.sysfontLoad=function(font) if font.rle then R._sysfontLoadRLE(font) else R._sysfontLoadRAW(font) end end --- Load Font Data -- @tparam table font Font data (RLE) -- @local R._sysfontLoadRLE=function(font) local str=font.rle local o=tonumber(str:sub(1,5),16) -- get (o)ffset local w=tonumber(str:sub(6,7),16)*8-1 -- get (w)idth local e=str:sub(8,str:len()) -- remove header to get (e)ncoded data local d = "" -- (d)ecoded data for m, c in e:gmatch("(%u+)([^%u]+)") do -- decode rle, (m)atch & (c)ounter d = d .. m .. (m:sub(-1):rep(c)) end local y=0 for x = 1,#d,1 do -- write to mem local c=string.byte(d:sub(x,x))-65 -- get (c)olor value poke4(o+y,c) y=y+1 if w>0 and y>w then y=0 o=o+1024 end end end --- Load Font Data -- @tparam table font Font data (RAW) -- @local R._sysfontLoadRAW=function(font) local str=font.raw local tnb=tonumber local o=tnb(str:sub(1,5),16) -- get (o)ffset local w=tnb(str:sub(6,7),16)*8-1 -- get (w)idth local d=str:sub(8,str:len()) -- remove header to get (d)ata local y=0 for x = 1,#d,1 do -- write to mem local c=tnb(d:sub(x,x),16) -- get (c)olor value poke4(o+y,c) y=y+1 if w>0 and y>w then y=0 o=o+1024 end end end end end rift_partsdancesystematic=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) local dancer = stage3d.dancers[1] dancer.isVisible = true local danceT = progress * 8 + .75 dancer:setPosition(R.V3:new(0, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("systematic", dancer, danceT) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdancehaka=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true end local progress = pMetrics.progress local danceT = progress * 16 + .3 if isCrazy then danceT = danceT * 2 end local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(-20, 0, -30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("haka", dancer, danceT + .12) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(-10, 0, -40)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("haka", dancer, danceT + 2 + .18) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(10, 0, -40)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("haka", dancer, danceT + 2 + .06) local dancer = stage3d.dancers[4] dancer.isVisible = true dancer:setPosition(R.V3:new(20, 0, -30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("haka", dancer,danceT + .10) local shakeT = danceT/4 * mTau - mPi - .2 local shakeY = .5*mSin(shakeT)^16 if shakeY < 0 then shakeY = 0 end local shakeX = .8*mSin(shakeT*4)*shakeY stage3d.cameraFG:setPosition(R.V3:new(shakeX,shakeY + 5,shakeX+shakeY)) local clockBounce = shakeY stage3d.clock:setPosition(R.V3:new(0, 10 + shakeY * 4, -50)) fnsClock.setClock(stage3d.clock, 10 + progress * 20) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdancerun=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then clip() vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true for i, dancer in ipairs(stage3d.dancers) do dancer:setVisible(true) end end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(40 - progress * 50, -5 + progress * 20, 0)) local lookAtPos = R.V3:new(progress * 10, 20 -progress * 10, -50) local cameraUp = R.V3:new(0, .7, -.7) cameraUp:normalize() local cameraRot = R.Quaternion.lookAt(stage3d.cameraFG.pos, lookAtPos, cameraUp) stage3d.cameraFG:setRotation(cameraRot) for i, dancer in ipairs(stage3d.dancers) do local a = (-progress*8) + (i-1) * mTau / #stage3d.dancers if isCrazy then a = -a end local x = mCos(a) * 10 local roll = -mSin(a*4) * .1 local z = -mSin(a) * 10 local iAdj = (i-1)-1.5 dancer:setPosition(R.V3:new(x*4, 0, -50+z*2)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi + a, roll)) animations.applyToSkeleton("run", dancer, progress * 16 * 2) end stage3d.clock:setPosition(R.V3:new(0, 10, -50)) local seconds = progress * 8 fnsClock.setClock(stage3d.clock, seconds) stage3d.clock.skeleton:setJoint({"miFace","jCentre"}, R.Quaternion:newFromEuler(0, 0, seconds/60 * mTau)) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdanceslide=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) local danceT = progress * 8 + .75 if isCrazy then danceT = danceT * 2 end local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cute-slide", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(-15, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, -1.3, 0)) animations.applyToSkeleton("cute-slide", dancer, danceT + .06) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(15, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, 1.3, 0)) animations.applyToSkeleton("cute-slide", dancer, danceT - .09) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_soundmusic=function() return function(R) R=R or {} R.music={} -- These are hard reset here, otherwise, you can call music() and these may or may not update for a frame -- because music() doesn't necessarily start immediately poke(0x13FFc,0) poke(0x13FFd,0) poke(0x13FFe,0) R.music.getPos=function() return { track=peek(0x13FFc), pattern=peek(0x13FFd), row=peek(0x13ffe), } end -- (https://github.com/nesbox/TIC-80/wiki/RAM#music-tracks) -- NB Some swizzling required here because there are signed values to decode... R.music.getTrackMeta=function(track) local aTrack=0x13E64+track*51 local tempo=peek(aTrack+48) tempo = (tempo&128)>0 and (150-(256-tempo)) or (150+tempo) local rows=64-peek(aTrack+49) local speed=peek(aTrack+50) speed = (speed&128)>0 and (6-(256-speed)) or (6+speed) local bpm=(6*tempo)/speed return { tempo=tempo, rows=rows, speed=speed, bpm=bpm, rowsPerSec=bpm/(60/4) } end --[[ Looks like it's possible to poke track and pattern, when music is running, but not row? R.music.setPos=function(track,pattern,row) poke(0x13FFc,track) poke(0x13FFd,pattern) poke(0x13ffe,row) end --]] end end rift_gfxvram=function() return function(R) R=R or {} local VRAM = {} -- This is not optimised for speed. -- Copies multiple 8x8 tiles from the screen to VRAM (either tile or sprite area). -- srcTileX, ySrcTile: source tile (which 8x8?). -- xDstTile: 0->15, yDstTile: 0->31 [0->15 for tiles, 16->31 for sprites]. -- These can be drawn with ttri src=0. -- Or can be used as tiles in map memory and drawn with ttri src=1. -- bpp: 1,2,4 (1=monochrome, 2=4 colors, 4=16 colors) <- see: poking at 03FFC. function VRAM.screenToTiles(srcTileX, srcTileY, tilesW, tilesH, dstTileX, dstTileY, bpp) for yTile=0,tilesH-1 do for xTile=0,tilesW-1 do for sTileDy=0,7 do local bitAcc = 0 for sTileDx=0,7 do local addrSrc = ((yTile*8 + sTileDy)*120)*2 + (xTile*8) + sTileDx if bpp == 4 then bitAcc = bitAcc + (peek4(addrSrc)<<(sTileDx%2)*4) if sTileDx%2 == 1 then local addrDest = 0x4000 + (dstTileY+yTile)*512 + sTileDy*4 + (dstTileX+xTile)*32 + sTileDx//2 poke(addrDest, bitAcc) bitAcc = 0 end elseif bpp == 2 then bitAcc = bitAcc + ((peek4(addrSrc)&3)<<(sTileDx%4)*2) if sTileDx%4 == 3 then local addrDest = 0x4000 + (dstTileY+yTile)*512 + sTileDy*4 + (dstTileX*16+xTile)*2 + sTileDx//4 poke(addrDest, bitAcc) bitAcc = 0 end elseif bpp == 1 then bitAcc = bitAcc + ((peek4(addrSrc)&1)< link to model, (root matrix + joints state) + (anim state - overrides joint state?) local Actor={} -- rootNodeID can change for different animations? function Actor:new(modelID, pos, rootNodeID) local o={ modelID = modelID, isVisible = true, skeleton = R.Skeleton:new(), skinIDs = {"default"}, pos = pos, rot = R.Quaternion:identity(), scale = R.V3:new(1, 1, 1), rootNodeID = rootNodeID, data = nil, } setmetatable(o,self) self.__index=self return o end function Actor:setSkins(skinIDs) self.skinIDs = skinIDs end function Actor:setVisible(isVisible) self.isVisible = isVisible end function Actor:setPosition(vec3) self.pos = vec3 end function Actor:getPosition() -- Improve return R2.V3:new(self.pos.x, self.pos.y, self.pos.z) end function Actor:rotate(q) self.rot = R.Quaternion.multiply(self.rot, q) end function Actor:setRotation(q) self.rot = q end function Actor:setScale(sc) self.scale = sc end function Actor:setData(data) self.data = data end function Actor:getModelData(engine) return engine:getModel(self.modelID).data end function Actor:addToRenderlist(engine, scene, renderlist) if not self.isVisible then return end local model=engine:getModel(self.modelID) -- #TODO (pass this through instead?) -- local modelMat = R.Matrix:newFromQuaternion(self.rot) -- modelMat:translate(self.pos) -- TODO: draw all root nodes, rather than specifying rootNodeID? Or continue to allow specific setting? model:addToRenderlist(engine, scene, self.pos, self.rot, self.scale, self.skeleton, self.rootNodeID, self.skinIDs, self.data, renderlist) end R.Actor = Actor end end rift_data3dfigure=function() return function(R) local mPi = math.pi -- style: "regular", "outline" local function makeMeshTemplate(type, style, scx, scy, scz, texFaceID, counterClock) counterClock = counterClock or false local verts={{-1,1,-1},{1,1,-1},{1,-1,-1},{-1,-1,-1},{-1,1,1},{1,1,1},{1,-1,1},{-1,-1,1}} local quads={{1,2,3,4},{6,5,8,7},{5,1,4,8},{2,6,7,3},{5,6,2,1},{4,3,7,8}} local tx,ty,tz=0,0,0 local dx,dy,dz=1,1,1 if type == "pelvis" then dx,dy,dz=2,.5,.6 elseif type == "legHigh" then ty=-1 dx,dy,dz=.8,1.5,.5 local w=1.2 verts={{-w,1,-1},{w,1,-1},{1,-1,-1},{-1,-1,-1},{-w,1,1},{w,1,1},{1,-1,1},{-1,-1,1}} elseif type == "legLow" then ty=-1 dx,dy,dz=.5,1.7,.5 elseif type == "foot" then ty,tz=-1,-.5 dx,dy,dz=.4,.2,1 elseif type == "torso" then ty=1 dx,dy,dz=2,2.7,.8 local w=1.3 verts={{-w,1,-1},{w,1,-1},{1,-1,-1},{-1,-1,-1},{-w,1,1},{w,1,1},{1,-1,1},{-1,-1,1}} elseif type == "head" then ty=1 dx,dy,dz=1,1,.8 local w1=1.2 local w2=1.1 verts={{-w1,1,-1},{w1,1,-1},{w2,-1,-1},{-w2,-1,-1},{-w1,1,1},{w1,1,1},{w2,-1,1},{-w2,-1,1}} elseif type == "armHigh" then tx=-1.3 dx,dy,dz=1.3,.5,.5 local w=1.3 -- wider verts={{-w,1,-1},{w,1,-1},{1,-1,-1},{-1,-1,-1},{-w,1,1},{w,1,1},{1,-1,1},{-1,-1,1}} elseif type == "armLow" then tx=-1 dx,dy,dz=1.4,.2,.4 elseif type == "hand" then tx,tz=-1,-1 dx,dy,dz=.5,.4,.1 end dx,dy,dz = dx*scx,dy*scy,dz*scz local mesh=R.Mesh:new() for _,v in ipairs(verts) do mesh:addVertex(nil, R.V3:new((v[1]+tx)*dx, (v[2]+ty)*dy, (v[3]+tz)*dz)) end for i,t in ipairs(quads) do if counterClock then t={t[1],t[4],t[3],t[2]} -- counter-clockwise end mesh:addRenderable("quad", {v1=t[1],v2=t[2],v3=t[3],v4=t[4]}) -- mesh:addRenderable("quadTex" .. i, {v1=t[1],v2=t[2],v3=t[3],v4=t[4]}, "textured") mesh:addRenderable("line", {v1=t[1],v2=t[2]}, "outline") mesh:addRenderable("line", {v1=t[2],v2=t[4]}, "outline") mesh:addRenderable("line", {v1=t[3],v2=t[4]}, "outline") mesh:addRenderable("line", {v1=t[3],v2=t[1]}, "outline") end if type == "pelvis" then mesh:addVertex("jLeftHip", R.V3:new((.5+tx)*dx,(-1.5+ty)*dy,0)) mesh:addVertex("jRightHip", R.V3:new((-.5+tx)*dx,(-1.5+ty)*dy,0)) mesh:addVertex("jWaist", R.V3:new(0,(1.5+ty)*dy,0)) elseif type == "legHigh" then mesh:addVertex("jKnee", R.V3:new(0,(-1.2+ty)*dy,0)) elseif type == "legLow" then mesh:addVertex("jAnkle", R.V3:new(0,(-1.2+ty)*dy,0)) elseif type == "torso" then mesh:addVertex("jNeck", R.V3:new(0,(1.2+ty)*dy,0)) mesh:addVertex("jLeftShoulder", R.V3:new(1.4*dx,(.8+ty)*dy,.2*dz)) mesh:addVertex("jRightShoulder",R.V3:new(-1.4*dx,(.8+ty)*dy,.2*dz)) mesh:addVertex("jLogo", R.V3:new(0,(.25+ty)*dy,1.05*dz)) elseif type == "armHigh" then mesh:addVertex("jElbow", R.V3:new((-1.4+tx)*dx,.5*dy,0)) elseif type == "armHigh" then mesh:addVertex("jElbow", R.V3:new((-1.4+tx)*dx,0,0)) elseif type == "armLow" then mesh:addVertex("jWrist", R.V3:new((2.1 * tx)*dx,0,0)) elseif type == "head" then mesh:addVertex("jFace", R.V3:new(0,1*dy,-1.3*dz)) end return mesh end local function makeMeshFace(scx, scy, texFaceID) local mesh=R.Mesh:new() local verts={{-1.1,1,0},{1,1,0},{1,-1,0},{-1.1,-1,0}} for _,v in ipairs(verts) do mesh:addVertex(nil, R.V3:new(v[1]*scx, v[2]*scy, 0)) end mesh:addRenderable(texFaceID, {v1=1,v2=2,v3=3,v4=4}, "mask") return mesh end -- style: nil, outline local function makeModelFigure(style, scx, scy, scz, texFaceID) local model=R.Model:new() style = style or "regular" texFaceID = texFaceID or "quadTexFace" model:addMeshTemplate("mtPelvis",makeMeshTemplate("pelvis", style, scx, scy, scz)) model:addMeshTemplate("mtLegHigh", makeMeshTemplate("legHigh", style, scx, scy, scz)) model:addMeshTemplate("mtLegLow", makeMeshTemplate("legLow", style, scx, scy, scz)) model:addMeshTemplate("mtFoot", makeMeshTemplate("foot", style, scx, scy, scz)) model:addMeshTemplate("mtTorso", makeMeshTemplate("torso", style, scx, scy, scz)) model:addMeshTemplate("mtHead", makeMeshTemplate("head", style, scz, scz, scz)) model:addMeshTemplate("mtArmLeftHigh", makeMeshTemplate("armHigh", style, -scx, scy, scz, nil, true)) model:addMeshTemplate("mtArmRightHigh", makeMeshTemplate("armHigh", style, scx, scy, scz)) model:addMeshTemplate("mtArmLeftLow", makeMeshTemplate("armLow", style, -scx, scy, scz, nil, true)) model:addMeshTemplate("mtArmRightLow", makeMeshTemplate("armLow", style, scx, scy, scz)) model:addMeshTemplate("mtHandLeft", makeMeshTemplate("hand", style, -scx, scy, scz, nil, true)) model:addMeshTemplate("mtHandRight", makeMeshTemplate("hand", style, scx, scy, scz)) model:addMeshTemplate("mtFace", makeMeshFace(scx * 2, scy * 2, texFaceID)) model:addMeshInstance("miPelvis",nil,"mtPelvis",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftLegHigh",{"miPelvis","jLeftHip"},"mtLegHigh",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftLegLow",{"miLeftLegHigh","jKnee"},"mtLegLow",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftFoot",{"miLeftLegLow","jAnkle"},"mtFoot",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miRightLegHigh",{"miPelvis","jRightHip"},"mtLegHigh",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miRightLegLow",{"miRightLegHigh","jKnee"},"mtLegLow",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miRightFoot",{"miRightLegLow","jAnkle"},"mtFoot",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miTorso",{"miPelvis","jWaist"},"mtTorso",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miHead",{"miTorso","jNeck"},"mtHead",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftArmHigh",{"miTorso","jLeftShoulder"},"mtArmLeftHigh",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftArmLow",{"miLeftArmHigh","jElbow"},"mtArmLeftLow",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miLeftHand",{"miLeftArmLow","jWrist"},"mtHandLeft",R.Quaternion:newFromEuler(mPi/2,0,0)) model:addMeshInstance("miRightArmHigh",{"miTorso","jRightShoulder"},"mtArmRightHigh",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miRightArmLow",{"miRightArmHigh","jElbow"},"mtArmRightLow",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miRightHand",{"miRightArmLow","jWrist"},"mtHandRight",R.Quaternion:newFromEuler(mPi/2,0,0)) model:addMeshInstance("miFace",{"miHead","jFace"},"mtFace",R.Quaternion:newFromEuler(0,0,0)) return model end local function constrainSkeleton(actor) local skeleton = actor.skeleton skeleton:setJointRange({"miPelvis","jLeftHip"},.05,.4,.1,.3,-.1,.25) skeleton:setJointRange({"miLeftLegHigh","jKnee"},-.4,.4,0,0,0,0) skeleton:setJointRange({"miLeftLegLow","jAnkle"},-.1,.3,.1,.15,0,.1) skeleton:setJointRange({"miPelvis","jRightHip"},.05,.4,-.1,-.3,.1,-.25) skeleton:setJointRange({"miRightLegHigh","jKnee"},-.4,.4,0,0,0,0) skeleton:setJointRange({"miRightLegLow","jAnkle"},-.1,.3,-.1,.15,0,.1) skeleton:setJointRange({"miPelvis","jWaist"},-.35,.4,0,.25,0,.25) skeleton:setJointRange({"miTorso","jNeck"},.15,.3,0,.4,0,.15) skeleton:setJointRange({"miTorso","jLeftShoulder"},0,.2,-.4,.45,-.1,.5) skeleton:setJointRange({"miLeftArmHigh","jElbow"},-.45,.45,0,.1,0,0) skeleton:setJointRange({"miLeftArmLow","jWrist"},-.45,.35,0,.2,0,.15) skeleton:setJointRange({"miTorso","jRightShoulder"},0,.2,.4,-.45,.1,-.5) skeleton:setJointRange({"miRightArmHigh","jElbow"},-.45,.45,0,.1,0,0) skeleton:setJointRange({"miRightArmLow","jWrist"},-.45,.35,0,.2,0,.15) end return { makeModel=makeModelFigure, constrainSkeleton=constrainSkeleton, } end end rift_datamaterialflat=function() return function(R2) local function materialQuad() return R2.Material:new():setFnTransform(function(d, psView, psWorld, actorData) return { pv1 = psView[d.v1], pv2=psView[d.v2], pv3=psView[d.v3], pv4=psView[d.v4], ci = actorData.ci, } end):setFnDraw(function(d) local pv1,pv2,pv3,pv4,ci = d.pv1,d.pv2,d.pv3,d.pv4,d.ci local a = 0x3ff0*2 poke4(a,ci) poke4(a+1,ci) poke4(a+2,ci) poke4(a+3,ci) ttri( pv1.x,pv1.y,pv2.x,pv2.y,pv3.x,pv3.y, 0,0,1,0,0,1, 1, -1, pv1.z,pv2.z,pv3.z ) ttri( pv1.x,pv1.y,pv3.x,pv3.y,pv4.x,pv4.y, 0,0,1,1,0,1, 1, -1, pv1.z,pv3.z,pv4.z ) -- optimise this by only doing it when we need to! poke4(a,0) poke4(a+1,1) poke4(a+2,2) poke4(a+3,3) end) end return { quad=materialQuad, } end end rift_partsdancewelcome=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local flow = rift_codeflow() local fnsClock = rift_data3dclock()(R) local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress local isCrazy = flow.isCrazy() local dancer = stage3d.dancers[1] dancer.isVisible = true local danceT = progress * 8 if isCrazy then danceT = danceT * 4 end local tY = mSin(danceT * mTau/2 + mPi/2) * .7 local rY = progress * mTau * 1.5 dancer:setPosition(R.V3:new(-10, tY, -10)) dancer:setRotation(R.Quaternion:newFromEuler(0, rY, 0)) animations.applyToSkeleton("welcome", dancer, danceT) local iFreeLetter = 1 iFreeLetter = letters.setTextActors("COUNTDOWN", R.V3:new(5,4,-40), stage3d.lettersFG, iFreeLetter, 5) local txt = "HOEDOWN" if isCrazy then txt = "SUNDOWN" end iFreeLetter = letters.setTextActors(txt, R.V3:new(10,-3,-40), stage3d.lettersFG, iFreeLetter, 5) stage3d.cameraFG:setPosition(R.V3:new(mSin(progress * 8) * 2 - progress * 4, -8 + progress * 10, 0)) stage3d.cameraFG:setRotation(R.Quaternion:newFromEuler(0, 0, mSin(progress * 4)*.3)) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdancetuck=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then clip() vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) local danceT = progress * 8 if isCrazy then danceT = danceT * 4 end local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("tuck", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(5, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("tuck", dancer, danceT) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(-5, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("tuck", dancer, danceT) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdanceclock=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") --stage3d.clock.isVisible = true end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(0,0,0)) local z = -50 local danceT = progress * 16 - .5 local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, z)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("clockdance", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(15, 0, z)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi/2, 0)) animations.applyToSkeleton("clockedge", dancer, 0) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(-12, -13, z)) dancer:setRotation(R.Quaternion:newFromEuler(mTau * .33, mPi/2, 0)) animations.applyToSkeleton("clockedge", dancer, 0) local dancer = stage3d.dancers[4] dancer.isVisible = true dancer:setPosition(R.V3:new(-8, 18, z)) dancer:setRotation(R.Quaternion:newFromEuler(mTau * .67, mPi/2, 0)) animations.applyToSkeleton("clockedge", dancer, 0) camZ = -40 + progress * 30 stage3d.cameraFG:setPosition(R.V3:new(0, 3, camZ)) stage3d.cameraFG:setRotation(R.Quaternion:newFromEuler(0, 0, 2.5 -progress * mPi)) if progress > .5 then if isCrazy then letters.setConundrum("SALTERTON") else letters.setConundrum("DEMOSCENE") end end letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) setup2d.fadeScene(progress, 0.1, .4) letters.drawConundrum() end, cleanup=function() end, }) end rift_codeanimations=function() return function(R) local animations = { ['welcome'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.250,vy=0.320,vz=0.040},{m='miTorso',j='jNeck',vx=0.000,vy=-0.390,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=1.720,vy=1.050,vz=-1.210},{m='miLeftArmHigh',j='jElbow',vx=-0.020,vy=-0.170,vz=-0.890},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.220,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-1.762,vy=-1.402,vz=-3.112},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.080,vz=0.710},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=1.420}},[2]={{m='miPelvis',j='root',vx=0.080,vy=0.210,vz=-0.000},{m='miPelvis',j='jLeftHip',vx=0.620,vy=-0.270,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-1.290,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.790,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.610,vy=0.440,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-1.300,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.590,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.320,vy=-0.440,vz=0.030},{m='miTorso',j='jNeck',vx=-0.100,vy=0.630,vz=-0.090},{m='miTorso',j='jLeftShoulder',vx=0.790,vy=0.680,vz=-1.440},{m='miLeftArmHigh',j='jElbow',vx=-0.080,vy=0.000,vz=-0.890},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-1.720},{m='miTorso',j='jRightShoulder',vx=0.900,vy=-1.230,vz=0.030},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['run'] = {[1]={{m='miPelvis',j='root',vx=-0.170,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.880,vy=-0.110,vz=-0.000},{m='miLeftLegHigh',j='jKnee',vx=-1.970,vy=0.030,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.330,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.010,vy=0.110,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.120,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=-0.320,vz=-1.410},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=1.502,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=-0.160,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.020,vy=-0.370,vz=1.410},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.370,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=-0.120,vy=0.270,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.070,vy=-0.090,vz=0.170},{m='miLeftLegHigh',j='jKnee',vx=-0.420,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.430,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.680,vy=-0.260,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-0.640,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.360,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.450,vz=0.040},{m='miTorso',j='jNeck',vx=0.150,vy=0.070,vz=-0.080},{m='miTorso',j='jLeftShoulder',vx=-0.010,vy=0.710,vz=-1.400},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.020,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.040,vy=0.830,vz=1.210},{m='miRightArmHigh',j='jElbow',vx=3.142,vy=-1.032,vz=3.142},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.140,vy=-0.070,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.060,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.020,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.140,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=0.160,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-2.120,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.380,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.020},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=0.120,vz=-1.380},{m='miLeftArmHigh',j='jElbow',vx=0.300,vy=1.220,vz=-0.330},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.070,vy=0.220,vz=1.350},{m='miRightArmHigh',j='jElbow',vx=3.012,vy=-1.312,vz=-3.142},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=-0.170,vy=-0.360,vz=-0.000},{m='miPelvis',j='jLeftHip',vx=-0.830,vy=0.370,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.620,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.400,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.040,vy=0.350,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.530,vy=0.160,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.450,vy=-0.210,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.000,vy=0.480,vz=-0.100},{m='miTorso',j='jNeck',vx=0.140,vy=-0.060,vz=0.140},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=-0.760,vz=-1.280},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=1.062,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.080,vy=-0.430,vz=1.540},{m='miRightArmHigh',j='jElbow',vx=0.400,vy=-1.320,vz=-0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['rock'] = {[1]={{m='miPelvis',j='root',vx=0.290,vy=-0.150,vz=-0.050},{m='miPelvis',j='jLeftHip',vx=0.000,vy=-0.950,vz=0.950},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.020,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.820,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.000,vy=0.710,vz=-0.910},{m='miRightLegHigh',j='jKnee',vx=-1.110,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.440,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.650,vy=-0.640,vz=0.320},{m='miTorso',j='jNeck',vx=0.190,vy=0.590,vz=0.100},{m='miTorso',j='jLeftShoulder',vx=-0.300,vy=1.130,vz=-0.080},{m='miLeftArmHigh',j='jElbow',vx=-0.080,vy=1.520,vz=-0.310},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.060,vy=-0.010,vz=-1.120},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.030,vz=-0.980},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.250,vy=0.210,vz=0.100},{m='miPelvis',j='jLeftHip',vx=-0.030,vy=-0.920,vz=0.990},{m='miLeftLegHigh',j='jKnee',vx=-1.020,vy=0.000,vz=0.050},{m='miLeftLegLow',j='jAnkle',vx=0.230,vy=-0.000,vz=0.060},{m='miPelvis',j='jRightHip',vx=-0.000,vy=0.800,vz=-0.900},{m='miRightLegHigh',j='jKnee',vx=0.020,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.730,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.480,vy=0.610,vz=-0.260},{m='miTorso',j='jNeck',vx=-0.560,vy=-0.780,vz=-0.110},{m='miTorso',j='jLeftShoulder',vx=-0.050,vy=-0.130,vz=1.330},{m='miLeftArmHigh',j='jElbow',vx=-0.000,vy=-0.000,vz=0.730},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.570,vy=-0.890,vz=0.110},{m='miRightArmHigh',j='jElbow',vx=3.142,vy=-1.212,vz=3.122},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['kicksailor'] = {[1]={{m='miPelvis',j='root',vx=-0.060,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.050,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.110,vy=0.280,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-1.100,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.180,vy=-0.230,vz=0.000},{m='miTorso',j='jNeck',vx=-0.230,vy=0.130,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.050,vy=0.740,vz=-0.630},{m='miLeftArmHigh',j='jElbow',vx=-0.970,vy=0.290,vz=-1.990},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.460,vy=0.050,vz=1.540},{m='miRightArmHigh',j='jElbow',vx=0.080,vy=-0.740,vz=-0.080},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=-0.330,vy=-0.240,vz=0.000},{m='miPelvis',j='jLeftHip',vx=2.140,vy=-1.250,vz=-0.290},{m='miLeftLegHigh',j='jKnee',vx=-2.230,vy=-0.090,vz=0.050},{m='miLeftLegLow',j='jAnkle',vx=1.000,vy=0.770,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.050,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.200,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.160,vz=0.000},{m='miTorso',j='jNeck',vx=0.040,vy=0.330,vz=0.140},{m='miTorso',j='jLeftShoulder',vx=-2.532,vy=1.272,vz=-2.842},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.200,vz=-0.300},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.030,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.330,vy=-0.440,vz=1.220},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.280,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.120,vy=-0.720,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.760,vy=-0.690,vz=-0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.420,vy=0.120,vz=0.020},{m='miLeftLegLow',j='jAnkle',vx=-1.360,vy=0.080,vz=-0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.550,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.180,vy=1.020,vz=-0.180},{m='miTorso',j='jNeck',vx=-0.150,vy=1.010,vz=0.230},{m='miTorso',j='jLeftShoulder',vx=-0.430,vy=0.380,vz=-1.610},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.350,vy=-1.130,vz=0.700},{m='miRightArmHigh',j='jElbow',vx=-0.580,vy=-1.430,vz=1.160},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.610,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-1.150,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=-0.040,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.180,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.350,vy=-0.060,vz=-0.000},{m='miTorso',j='jLeftShoulder',vx=0.470,vy=0.330,vz=-1.440},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.380},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.450,vy=-0.640,vz=0.780},{m='miRightArmHigh',j='jElbow',vx=-1.140,vy=-0.540,vz=1.930},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=-0.220,vy=0.260,vz=0.000},{m='miPelvisE',j='jLeftHip',vx=0.000,vy=-0.500,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=2.420,vy=0.770,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-2.220,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.870,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.510,vz=0.000},{m='miTorso',j='jNeck',vx=-0.010,vy=-0.790,vz=-0.110},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=0.450,vz=-1.440},{m='miLeftArmHigh',j='jElbow',vx=-0.200,vy=-0.030,vz=-0.900},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.040},{m='miTorso',j='jRightShoulder',vx=-2.882,vy=-1.482,vz=-1.472},{m='miRightArmHigh',j='jElbow',vx=-0.030,vy=0.430,vz=1.200},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=-0.280,vy=0.600,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=-0.800,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=-0.230},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.790,vy=0.800,vz=0.060},{m='miRightLegHigh',j='jKnee',vx=-0.290,vy=0.050,vz=0.050},{m='miRightLegLow',j='jAnkle',vx=-1.440,vy=0.000,vz=-0.070},{m='miPelvis',j='jWaist',vx=-0.010,vy=-1.040,vz=-0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.450,vz=-0.170},{m='miTorso',j='jLeftShoulder',vx=0.190,vy=0.560,vz=-1.520},{m='miLeftArmHigh',j='jElbow',vx=-0.270,vy=-0.060,vz=-1.260},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.880,vy=-0.530,vz=1.450},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['dab'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.350,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.740,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.470,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.410,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.730,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.410,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.580,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.050,vy=-0.110,vz=-1.290},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.200,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.890,vy=-1.110,vz=1.390},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.270,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.030,vy=0.360,vz=-0.190},{m='miPelvis',j='jLeftHip',vx=0.070,vy=-0.240,vz=0.550},{m='miLeftLegHigh',j='jKnee',vx=-0.530,vy=-0.130,vz=-0.270},{m='miLeftLegLow',j='jAnkle',vx=0.470,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.220,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.870,vy=0.030,vz=-0.000},{m='miRightLegLow',j='jAnkle',vx=0.440,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.380,vy=-0.870,vz=0.070},{m='miTorso',j='jNeck',vx=0.370,vy=0.360,vz=0.320},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.570,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=0.952,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.030,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.040,vy=-0.040,vz=0.380},{m='miRightArmHigh',j='jElbow',vx=0.010,vy=0.090,vz=0.520},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=0.070,vy=0.300,vz=-0.280},{m='miPelvis',j='jLeftHip',vx=-0.300,vy=-0.240,vz=0.550},{m='miLeftLegHigh',j='jKnee',vx=-0.010,vy=-0.130,vz=-0.270},{m='miLeftLegLow',j='jAnkle',vx=0.110,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.540,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.870,vy=0.030,vz=-0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.380,vy=-0.250,vz=-0.310},{m='miTorso',j='jNeck',vx=0.300,vy=0.890,vz=0.090},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.970,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=0.952,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.030,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.000,vy=-0.080,vz=-0.110},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.430,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.920,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.490,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.440,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.840,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.570,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.640,vy=-0.030,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.500,vz=-0.750},{m='miLeftArmHigh',j='jElbow',vx=0.070,vy=0.700,vz=0.860},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=-0.200,vz=1.480},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.270},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=-0.280,vy=0.150,vz=0.060},{m='miPelvis',j='jLeftHip',vx=0.090,vy=-0.330,vz=0.250},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.420,vz=-0.350},{m='miLeftLegLow',j='jAnkle',vx=-0.000,vy=-0.100,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.280,vy=-0.110,vz=-0.300},{m='miRightLegHigh',j='jKnee',vx=-0.170,vy=-0.320,vz=0.160},{m='miRightLegLow',j='jAnkle',vx=0.410,vy=0.530,vz=0.000},{m='miPelvis',j='jWaist',vx=0.010,vy=-0.220,vz=0.110},{m='miTorso',j='jNeck',vx=0.230,vy=-0.740,vz=-0.540},{m='miTorso',j='jLeftShoulder',vx=0.010,vy=0.500,vz=-0.280},{m='miLeftArmHigh',j='jElbow',vx=-0.320,vy=-0.050,vz=-0.410},{m='miLeftArmLow',j='jWrist',vx=-0.000,vy=-0.050,vz=0.010},{m='miTorso',j='jRightShoulder',vx=-0.440,vy=-1.110,vz=0.350},{m='miRightArmHigh',j='jElbow',vx=-2.892,vy=-1.462,vz=3.062},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=0.030,vy=-0.190,vz=0.200},{m='miPelvis',j='jLeftHip',vx=0.090,vy=-0.330,vz=-0.060},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.420,vz=-0.250},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.280,vy=0.580,vz=-0.640},{m='miRightLegHigh',j='jKnee',vx=-0.700,vy=0.030,vz=0.160},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.160,vz=0.000},{m='miPelvis',j='jWaist',vx=0.010,vy=-0.220,vz=0.110},{m='miTorso',j='jNeck',vx=0.230,vy=-0.610,vz=0.040},{m='miTorso',j='jLeftShoulder',vx=0.010,vy=0.000,vz=0.190},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.040},{m='miLeftArmLow',j='jWrist',vx=-0.000,vy=-0.050,vz=0.010},{m='miTorso',j='jRightShoulder',vx=-0.440,vy=-1.110,vz=0.350},{m='miRightArmHigh',j='jElbow',vx=-2.892,vy=-1.462,vz=3.082},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['slapstick-run'] = {[1]={{m='miPelvis',j='root',vx=-0.750,vy=0.170,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.460,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.460,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.040,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-1.100,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.470,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.400,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.250,vy=-0.050,vz=0.000},{m='miTorso',j='jNeck',vx=-0.000,vy=-0.660,vz=-0.020},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=-1.220,vz=-1.540},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.050,vy=-1.370,vz=1.620},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=-0.470,vy=-0.210,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-1.170,vy=0.040,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.460,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.510,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.300,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.350,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.080,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.030,vy=0.110,vz=-0.010},{m='miTorso',j='jNeck',vx=0.030,vy=0.510,vz=-0.020},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=1.280,vz=-1.540},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=1.500,vz=1.580},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['stretch-twist'] = {[1]={{m='miPelvis',j='root',vx=-0.000,vy=-0.090,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.810,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.020,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.890,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.360,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-1.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.370,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.120,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.060,vy=-0.250,vz=-0.100},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-1.030,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.140,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.730,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.220,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.720,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.370,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.180,vy=-1.010,vz=0.010},{m='miTorso',j='jNeck',vx=-0.070,vy=1.520,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.090,vy=-0.580,vz=-0.050},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=-0.240,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=-0.570,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.570,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['stretch-toe-touch'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.280,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.320,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.040,vy=-0.320,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.460,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.700,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.770,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.122,vy=1.362,vz=3.132},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=-0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=3.142,vy=-1.432,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.050,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.450,vy=0.020,vz=0.080},{m='miTorso',j='jLeftShoulder',vx=0.060,vy=1.210,vz=-0.010},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.760,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=-0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.000,vy=-1.010,vz=-0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.680,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.700,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.770,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.122,vy=1.362,vz=3.132},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=-0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=3.142,vy=-1.432,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['clap'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.080,vz=0.020},{m='miPelvis',j='jLeftHip',vx=0.260,vy=-0.390,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.430,vy=-0.080,vz=-0.000},{m='miLeftLegLow',j='jAnkle',vx=0.370,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.030,vy=0.150,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-0.370,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.390,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.240,vz=0.000},{m='miTorso',j='jNeck',vx=-0.210,vy=-0.570,vz=0.060},{m='miTorso',j='jLeftShoulder',vx=3.080,vy=0.010,vz=-0.960},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.130},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=3.050,vy=-0.000,vz=0.970},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.150},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.360}},[2]={{m='miPelvis',j='root',vx=0.000,vy=-0.160,vz=-0.030},{m='miPelvis',j='jLeftHip',vx=0.260,vy=-0.390,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.430,vy=-0.080,vz=-0.000},{m='miLeftLegLow',j='jAnkle',vx=0.370,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.030,vy=0.150,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-0.370,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.390,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.030,vy=-0.230,vz=-0.000},{m='miTorso',j='jNeck',vx=-0.220,vy=0.550,vz=-0.090},{m='miTorso',j='jLeftShoulder',vx=3.130,vy=-0.000,vz=1.750},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.740},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.920},{m='miTorso',j='jRightShoulder',vx=3.050,vy=0.000,vz=-1.780},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.700},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.600}}}, ['clap2'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=-0.090},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.120},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.080},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.000,vy=0.320,vz=-0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.280,vz=0.150},{m='miTorso',j='jLeftShoulder',vx=1.540,vy=0.220,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.920},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=1.760,vy=-0.350,vz=-0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.520},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.300,vz=-0.020},{m='miPelvis',j='jLeftHip',vx=-0.000,vy=-0.320,vz=0.060},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.020},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.000,vy=-0.110,vz=-0.020},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-1.642,vy=1.092,vz=-3.142},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.410},{m='miTorso',j='jRightShoulder',vx=-1.562,vy=-1.082,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.410}},[3]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.110},{m='miPelvis',j='jLeftHip',vx=-0.000,vy=0.000,vz=-0.070},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.170},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.070,vy=-0.300,vz=0.040},{m='miTorso',j='jNeck',vx=0.030,vy=0.200,vz=-0.070},{m='miTorso',j='jLeftShoulder',vx=1.540,vy=0.220,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.920},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=1.760,vy=-0.350,vz=-0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.520},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=-0.230,vz=0.020},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.060},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-1.602,vy=1.002,vz=-3.142},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.410},{m='miTorso',j='jRightShoulder',vx=-1.562,vy=-1.062,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.410}}}, ['cheer'] = {[1]={{m='miPelvis',j='root',vx=0.130,vy=0.180,vz=-0.000},{m='miPelvis',j='jLeftHip',vx=-0.400,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.120,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.270,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.250,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.300,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.160,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.140,vy=0.510,vz=-0.160},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-1.310,vy=1.170,vz=-1.410},{m='miLeftArmHigh',j='jElbow',vx=2.392,vy=0.902,vz=2.362},{m='miLeftArmLow',j='jWrist',vx=-0.000,vy=0.050,vz=1.040},{m='miTorso',j='jRightShoulder',vx=0.180,vy=-1.290,vz=-0.120},{m='miRightArmHigh',j='jElbow',vx=3.022,vy=-1.162,vz=3.022},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.170,vz=-1.780}},[2]={{m='miPelvis',j='root',vx=0.130,vy=0.160,vz=-0.050},{m='miPelvis',j='jLeftHip',vx=-0.400,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.120,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.270,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.250,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.300,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.160,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.050,vy=-0.680,vz=0.180},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-1.400,vy=1.170,vz=-1.410},{m='miLeftArmHigh',j='jElbow',vx=2.392,vy=0.902,vz=2.362},{m='miLeftArmLow',j='jWrist',vx=-0.000,vy=0.050,vz=1.040},{m='miTorso',j='jRightShoulder',vx=0.180,vy=-1.290,vz=-0.120},{m='miRightArmHigh',j='jElbow',vx=3.022,vy=-1.162,vz=3.022},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.170,vz=-1.780}}}, ['haka'] = {[1]={{m='miPelvis',j='root',vx=-0.300,vy=-0.190,vz=-0.510},{m='miPelvis',j='jLeftHip',vx=0.370,vy=-0.530,vz=1.570},{m='miLeftLegHigh',j='jKnee',vx=-0.740,vy=-1.080,vz=-0.140},{m='miLeftLegLow',j='jAnkle',vx=-0.390,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=1.140,vz=-0.370},{m='miRightLegHigh',j='jKnee',vx=-1.170,vy=0.320,vz=-0.540},{m='miRightLegLow',j='jAnkle',vx=0.550,vy=-0.010,vz=0.200},{m='miPelvis',j='jWaist',vx=0.240,vy=0.780,vz=-0.200},{m='miTorso',j='jNeck',vx=0.520,vy=-0.750,vz=0.470},{m='miTorso',j='jLeftShoulder',vx=0.270,vy=1.060,vz=-0.980},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=1.552,vz=2.252},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.150,vy=0.030,vz=-0.210},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.040,vz=-0.070},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.120}},[2]={{m='miPelvis',j='root',vx=-0.240,vy=-0.000,vz=-0.100},{m='miPelvis',j='jLeftHip',vx=0.370,vy=-0.530,vz=1.210},{m='miLeftLegHigh',j='jKnee',vx=-1.140,vy=-1.100,vz=-0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=1.140,vz=-0.100},{m='miRightLegHigh',j='jKnee',vx=-1.170,vy=0.200,vz=0.030},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.060},{m='miPelvis',j='jWaist',vx=-0.670,vy=0.000,vz=-0.000},{m='miTorso',j='jNeck',vx=0.780,vy=-0.330,vz=-0.000},{m='miTorso',j='jLeftShoulder',vx=0.250,vy=0.090,vz=-0.980},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.890},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.150,vy=0.030,vz=0.940},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=1.100},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.240,vy=-0.000,vz=0.240},{m='miPelvis',j='jLeftHip',vx=0.370,vy=-0.530,vz=1.430},{m='miLeftLegHigh',j='jKnee',vx=-1.140,vy=-1.100,vz=-0.020},{m='miLeftLegLow',j='jAnkle',vx=0.800,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=1.140,vz=-0.550},{m='miRightLegHigh',j='jKnee',vx=-1.020,vy=0.200,vz=0.040},{m='miRightLegLow',j='jAnkle',vx=-0.330,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.060,vy=-1.010,vz=0.040},{m='miTorso',j='jNeck',vx=0.370,vy=0.990,vz=-0.030},{m='miTorso',j='jLeftShoulder',vx=0.270,vy=0.000,vz=0.230},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.040},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.290},{m='miTorso',j='jRightShoulder',vx=0.420,vy=-1.010,vz=1.900},{m='miRightArmHigh',j='jElbow',vx=-0.000,vy=0.650,vz=1.070},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=-0.240,vy=-0.000,vz=-0.100},{m='miPelvis',j='jLeftHip',vx=0.370,vy=-0.530,vz=1.200},{m='miLeftLegHigh',j='jKnee',vx=-1.140,vy=-1.100,vz=-0.110},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=1.140,vz=-0.150},{m='miRightLegHigh',j='jKnee',vx=-1.170,vy=0.200,vz=0.080},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.090},{m='miPelvis',j='jWaist',vx=-0.700,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.840,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.250,vy=0.090,vz=-0.980},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.890},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.150,vy=0.030,vz=0.940},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=1.100},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['cancan'] = {[1]={{m='miPelvis',j='root',vx=-0.120,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.340,vy=-0.100,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.610,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.200,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.070,vy=0.340,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.150,vy=-0.550,vz=-0.010},{m='miPelvis',j='jLeftHip',vx=2.180,vy=1.050,vz=0.060},{m='miLeftLegHigh',j='jKnee',vx=0.100,vy=0.000,vz=0.050},{m='miLeftLegLow',j='jAnkle',vx=-1.280,vy=-0.110,vz=-0.210},{m='miPelvis',j='jRightHip',vx=0.090,vy=0.340,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.230,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=1.170,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.990,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.070,vy=0.810,vz=0.070},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.130,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.090,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.720,vy=-0.400,vz=0.140},{m='miRightLegHigh',j='jKnee',vx=-2.160,vy=-0.040,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.480,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.800,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=-0.330,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=-0.530,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=-0.200,vy=0.000,vz=0.020},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.670,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.900,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.410,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=0.160,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=2.250,vy=-0.870,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-1.190,vy=0.160,vz=0.110},{m='miPelvis',j='jWaist',vx=0.000,vy=0.800,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-1.100,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=-0.790,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=-1.060,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[7]={{m='miPelvis',j='root',vx=-0.090,vy=0.030,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.070,vy=-0.120,vz=-0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.220,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.070,vy=0.340,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[8]={{m='miPelvis',j='root',vx=0.120,vy=-0.250,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.410,vy=0.610,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-2.190,vy=-0.010,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.090,vy=0.340,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.240,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.800,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.810,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.620,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['clockdance'] = {[1]={{m='miPelvis',j='root',vx=-0.220,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.890,vy=0.000,vz=0.280},{m='miLeftLegHigh',j='jKnee',vx=-1.520,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.960,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.340},{m='miRightLegHigh',j='jKnee',vx=0.090,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.950,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.210,vy=-0.230,vz=-0.060},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=0.010,vz=1.590},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.300},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=-0.090},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.340},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.920,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.760,vy=0.000,vz=-0.150},{m='miRightLegHigh',j='jKnee',vx=-1.110,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.970,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.130,vy=0.260,vz=0.080},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=3.113,vy=-0.000,vz=1.170},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.690},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.040,vy=-0.010,vz=0.030},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.200,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.140},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.860,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.730,vy=-0.000,vz=-0.070},{m='miRightLegHigh',j='jKnee',vx=-1.170,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.960,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.200,vy=-0.270,vz=-0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=-0.000,vz=0.850},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.300},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.050},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.240},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.930,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.870,vy=0.000,vz=-0.310},{m='miRightLegHigh',j='jKnee',vx=-1.240,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.930,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.090,vy=0.210,vz=-0.070},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=-0.000,vz=0.390},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.440},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.080},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=-0.160,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.020,vy=-0.030,vz=0.300},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-1.270,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.930,vy=0.000,vz=-0.210},{m='miRightLegHigh',j='jKnee',vx=-1.130,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-1.110,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.240,vy=0.160,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.170},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=-0.060},{m='miPelvis',j='jLeftHip',vx=1.120,vy=-0.020,vz=0.160},{m='miLeftLegHigh',j='jKnee',vx=-1.640,vy=0.090,vz=-0.000},{m='miLeftLegLow',j='jAnkle',vx=-1.080,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.080},{m='miRightLegHigh',j='jKnee',vx=0.060,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.930,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.100,vy=0.320,vz=0.070},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=-0.000,vz=-0.400},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.600},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[7]={{m='miPelvis',j='root',vx=-0.220,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.070,vy=0.000,vz=0.310},{m='miLeftLegHigh',j='jKnee',vx=-1.690,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.890,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.130},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.970,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.230,vy=-0.240,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=0.000,vz=-0.760},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.410},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[8]={{m='miPelvis',j='root',vx=-0.000,vy=0.000,vz=0.050},{m='miPelvis',j='jLeftHip',vx=0.760,vy=0.000,vz=0.320},{m='miLeftLegHigh',j='jKnee',vx=-1.460,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.970,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.410},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.820,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.100,vy=0.290,vz=-0.070},{m='miTorso',j='jNeck',vx=0.000,vy=0.100,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.110,vy=-0.040,vz=1.000},{m='miLeftArmHigh',j='jElbow',vx=-0.000,vy=0.020,vz=-1.650},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.032,vy=-0.112,vz=1.532},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.160},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['clockedge'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.440,vy=0.030,vz=0.040},{m='miLeftLegHigh',j='jKnee',vx=0.130,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.830,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.460,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.070,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.890,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.140,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.580,vy=-0.080,vz=-0.020},{m='miTorso',j='jLeftShoulder',vx=1.980,vy=0.410,vz=1.710},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=-0.040,vz=-0.400},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.450},{m='miTorso',j='jRightShoulder',vx=1.270,vy=-0.450,vz=-1.530},{m='miRightArmHigh',j='jElbow',vx=-0.050,vy=0.100,vz=0.460},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.460}}}, ['tuck'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.060,vy=0.070,vz=-1.060},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.370},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.810},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=1.070},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=1.470},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-1.070}},[2]={{m='miPelvis',j='root',vx=0.140,vy=0.150,vz=0.260},{m='miPelvis',j='jLeftHip',vx=0.180,vy=-0.370,vz=0.610},{m='miLeftLegHigh',j='jKnee',vx=2.812,vy=-1.442,vz=2.482},{m='miLeftLegLow',j='jAnkle',vx=-1.550,vy=0.520,vz=0.060},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.180,vz=-0.300},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=-0.000},{m='miPelvis',j='jWaist',vx=0.250,vy=-0.960,vz=-0.240},{m='miTorso',j='jNeck',vx=-0.440,vy=0.650,vz=0.070},{m='miTorso',j='jLeftShoulder',vx=-3.022,vy=0.892,vz=0.552},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.630},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.600},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=1.070},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=1.470},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-1.070}},[3]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.060,vy=0.070,vz=-1.060},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.370},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.810},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=1.070},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=1.470},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-1.070}},[4]={{m='miPelvis',j='root',vx=0.000,vy=-0.030,vz=-0.270},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.270},{m='miLeftLegHigh',j='jKnee',vx=0.010,vy=0.000,vz=0.050},{m='miLeftLegLow',j='jAnkle',vx=-0.090,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.580,vy=0.890,vz=-0.280},{m='miRightLegHigh',j='jKnee',vx=-0.440,vy=0.770,vz=0.830},{m='miRightLegLow',j='jAnkle',vx=-1.820,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.040,vy=0.580,vz=0.180},{m='miTorso',j='jNeck',vx=0.980,vy=0.210,vz=0.100},{m='miTorso',j='jLeftShoulder',vx=-0.060,vy=0.070,vz=-1.060},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.370},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.810},{m='miTorso',j='jRightShoulder',vx=1.940,vy=-1.140,vz=1.070},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.520,vz=1.470},{m='miRightArmLow',j='jWrist',vx=-0.120,vy=-0.210,vz=0.070}}}, ['ballet-twirl'] = {[1]={{m='miPelvis',j='root',vx=0.220,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.260,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.810,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-1.280,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-1.160,vy=0.060,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-1.310,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-1.780,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.190,vy=-0.130,vz=0.050},{m='miTorso',j='jNeck',vx=0.400,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.810,vy=1.010,vz=-1.150},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=-0.390,vz=-1.550},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.010,vz=-0.690},{m='miTorso',j='jRightShoulder',vx=3.030,vy=-0.320,vz=-1.790},{m='miRightArmHigh',j='jElbow',vx=0.150,vy=-0.410,vz=0.340},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.830}},[2]={{m='miPelvis',j='root',vx=0.220,vy=0.330,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.260,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.810,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-1.280,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-1.220,vy=-0.440,vz=0.070},{m='miRightLegHigh',j='jKnee',vx=-1.310,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-1.780,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.100,vy=-0.470,vz=-0.020},{m='miTorso',j='jNeck',vx=0.400,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.910,vy=1.010,vz=-1.150},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=-0.390,vz=-1.550},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.010,vz=-0.690},{m='miTorso',j='jRightShoulder',vx=-3.083,vy=-0.400,vz=-1.520},{m='miRightArmHigh',j='jElbow',vx=0.150,vy=-0.410,vz=0.340},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.830}}}, ['systematic'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.260,vy=-0.360,vz=0.610},{m='miLeftLegHigh',j='jKnee',vx=-0.070,vy=-0.410,vz=-0.560},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.200,vy=0.280,vz=-0.640},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.010,vz=0.620},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.260,vy=-0.970,vz=0.000},{m='miTorso',j='jNeck',vx=-0.350,vy=1.020,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=-0.780},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.190},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.280,vy=-0.800,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=-0.220},{m='miPelvis',j='jLeftHip',vx=-0.260,vy=-0.360,vz=0.920},{m='miLeftLegHigh',j='jKnee',vx=-0.070,vy=-0.410,vz=-0.560},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.200,vy=0.280,vz=-0.440},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.010,vz=0.620},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.420,vy=0.940,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.290,vz=-0.120},{m='miTorso',j='jLeftShoulder',vx=2.772,vy=1.022,vz=3.132},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.960,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.000,vy=-0.110,vz=1.130},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.840},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.260,vy=-0.360,vz=0.730},{m='miLeftLegHigh',j='jKnee',vx=-0.070,vy=-0.410,vz=-0.560},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.200,vy=0.280,vz=-0.730},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.010,vz=0.620},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.600,vy=0.960,vz=-0.290},{m='miTorso',j='jNeck',vx=0.000,vy=-0.550,vz=-0.050},{m='miTorso',j='jLeftShoulder',vx=-3.142,vy=0.342,vz=1.392},{m='miLeftArmHigh',j='jElbow',vx=-0.030,vy=-0.070,vz=-0.660},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=-0.870},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.070},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.040,vz=0.250},{m='miPelvis',j='jLeftHip',vx=-0.260,vy=-0.360,vz=0.410},{m='miLeftLegHigh',j='jKnee',vx=-0.070,vy=-0.410,vz=-0.560},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.200,vy=0.280,vz=-1.010},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.010,vz=0.620},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.860,vy=-1.150,vz=0.600},{m='miTorso',j='jNeck',vx=0.590,vy=-0.290,vz=-0.000},{m='miTorso',j='jLeftShoulder',vx=-3.062,vy=1.502,vz=2.272},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-1.710},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=2.582,vy=-0.732,vz=-1.832},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.670},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['cute-slide'] = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.810,vz=-0.180},{m='miPelvis',j='jLeftHip',vx=0.000,vy=-0.790,vz=0.310},{m='miLeftLegHigh',j='jKnee',vx=-0.260,vy=0.110,vz=-0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=-0.630,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.580,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.090,vy=-0.630,vz=0.160},{m='miRightLegLow',j='jAnkle',vx=0.440,vy=0.670,vz=0.260},{m='miPelvis',j='jWaist',vx=-0.180,vy=-0.610,vz=0.320},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=-0.530},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=-0.100,vz=-1.220},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.170},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.360},{m='miTorso',j='jRightShoulder',vx=0.100,vy=-0.370,vz=-1.450},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-0.120,vz=-0.560},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.170}},[2]={{m='miPelvis',j='root',vx=0.000,vy=-0.740,vz=0.210},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=-0.360},{m='miLeftLegHigh',j='jKnee',vx=-0.830,vy=0.340,vz=0.150},{m='miLeftLegLow',j='jAnkle',vx=0.190,vy=0.550,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=2.852,vy=0.722,vz=3.132},{m='miPelvis',j='jWaist',vx=-0.280,vy=0.330,vz=-0.370},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.580},{m='miTorso',j='jLeftShoulder',vx=-0.030,vy=0.210,vz=1.500},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.540},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.190},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=1.180},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.290},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.740}}}, ['box'] = {[1]={{m='miPelvis',j='root',vx=0.370,vy=0.000,vz=-0.300},{m='miPelvis',j='jLeftHip',vx=-0.330,vy=-0.000,vz=0.380},{m='miLeftLegHigh',j='jKnee',vx=-0.160,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.280},{m='miRightLegHigh',j='jKnee',vx=-0.440,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.250,vy=-0.990,vz=0.320},{m='miTorso',j='jNeck',vx=0.890,vy=-0.010,vz=-0.050},{m='miTorso',j='jLeftShoulder',vx=-1.180,vy=1.070,vz=-0.080},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.340,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.180,vz=0.000},{m='miTorso',j='jRightShoulder',vx=3.142,vy=-1.232,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.520,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.360,vy=-0.000,vz=0.330},{m='miPelvis',j='jLeftHip',vx=-0.710,vy=0.000,vz=-0.390},{m='miLeftLegHigh',j='jKnee',vx=-0.080,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.220,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.240,vy=0.000,vz=-0.460},{m='miRightLegHigh',j='jKnee',vx=0.030,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.200,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.820,vy=0.750,vz=-0.380},{m='miTorso',j='jNeck',vx=-0.260,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=1.050,vz=-0.600},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.340,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.180,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-1.582,vy=-1.382,vz=3.142},{m='miRightArmHigh',j='jElbow',vx=0.090,vy=-0.970,vz=-0.250},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=0.310,vy=-0.000,vz=-0.330},{m='miPelvis',j='jLeftHip',vx=-0.470,vy=0.000,vz=0.390},{m='miLeftLegHigh',j='jKnee',vx=-0.110,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.320},{m='miRightLegHigh',j='jKnee',vx=-0.430,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.390,vy=-0.330,vz=0.330},{m='miTorso',j='jNeck',vx=0.200,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=1.450,vz=-1.150},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.340,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.180,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-2.092,vy=0.098,vz=-1.522},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.940,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.390,vy=0.020,vz=0.570},{m='miPelvis',j='jLeftHip',vx=-0.460,vy=0.000,vz=-0.520},{m='miLeftLegHigh',j='jKnee',vx=-0.150,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=-0.550},{m='miRightLegHigh',j='jKnee',vx=-0.340,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-1.440,vy=-0.130,vz=-0.780},{m='miTorso',j='jNeck',vx=-0.670,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-3.112,vy=1.302,vz=3.112},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.340,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.180,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.090,vy=-1.350,vz=-0.000},{m='miRightArmHigh',j='jElbow',vx=3.142,vy=-1.392,vz=3.142},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}}, ['hip-wobble'] = {[1]={{m='miPelvis',j='root',vx=0.110,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.110,vy=0.000,vz=0.090},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.180,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.190,vy=0.040,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=2.930,vy=0.020,vz=0.670},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.350},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.970},{m='miTorso',j='jRightShoulder',vx=2.960,vy=-0.000,vz=-0.770},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.210},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.900}},[2]={{m='miPelvis',j='root',vx=0.110,vy=-0.000,vz=0.480},{m='miPelvis',j='jLeftHip',vx=-0.130,vy=-0.000,vz=-0.460},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.450,vy=0.040,vz=-0.390},{m='miRightLegHigh',j='jKnee',vx=-0.680,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.160,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.140,vy=0.000,vz=-0.830},{m='miTorso',j='jNeck',vx=0.390,vy=0.880,vz=0.280},{m='miTorso',j='jLeftShoulder',vx=3.020,vy=0.060,vz=1.410},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.350},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.970},{m='miTorso',j='jRightShoulder',vx=2.960,vy=-0.000,vz=-0.300},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.210},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.900}},[3]={{m='miPelvis',j='root',vx=0.150,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=-0.160,vy=0.000,vz=0.140},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.170,vy=0.000,vz=-0.030},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.110,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=2.930,vy=0.020,vz=0.670},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.350},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.970},{m='miTorso',j='jRightShoulder',vx=2.960,vy=-0.000,vz=-0.770},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.210},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.900}},[4]={{m='miPelvis',j='root',vx=0.130,vy=-0.030,vz=-0.500},{m='miPelvis',j='jLeftHip',vx=0.280,vy=0.000,vz=0.640},{m='miLeftLegHigh',j='jKnee',vx=-0.540,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.240,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.200,vy=-0.000,vz=0.510},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.120,vy=0.000,vz=0.810},{m='miTorso',j='jNeck',vx=0.490,vy=-0.800,vz=-0.400},{m='miTorso',j='jLeftShoulder',vx=2.930,vy=0.020,vz=0.080},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.350},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.970},{m='miTorso',j='jRightShoulder',vx=2.960,vy=0.210,vz=-1.320},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.210},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.900}}}, } local animationPoses = {} local jointRefs = { {"miPelvis", "root"}, {"miPelvis","jLeftHip"}, {"miLeftLegHigh","jKnee"}, {"miLeftLegLow","jAnkle"}, {"miPelvis","jRightHip"}, {"miRightLegHigh","jKnee"}, {"miRightLegLow","jAnkle"}, {"miPelvis","jWaist"}, {"miTorso","jNeck"}, {"miTorso","jLeftShoulder"}, {"miLeftArmHigh","jElbow"}, {"miLeftArmLow","jWrist"}, {"miTorso","jRightShoulder"}, {"miRightArmHigh","jElbow"}, {"miRightArmLow","jWrist"}, } local function makeZeroPose() local pose = R.Pose:new() for _, joint in pairs(jointRefs) do pose:setJoint(joint, R.Quaternion:newFromEuler(0,0,0)) end return pose end local function init() for animName,animation in pairs(animations) do local poses = {} for i,poseData in ipairs(animation) do local pose = makeZeroPose() for _, joint in pairs(poseData) do pose:setJoint({joint.m, joint.j}, R.Quaternion:newFromEuler(joint.vx,joint.vy,joint.vz)) end poses[i] = pose end animationPoses[animName] = poses end end local function applyToSkeleton(animationName, actor, t) local poses = animationPoses[animationName] local tFloor = t//1 local tPos = t - tFloor local mainViewTweenFrame = tFloor%#poses local pose1 = mainViewTweenFrame local pose2 = (mainViewTweenFrame + 1) % #poses local pose3 = (mainViewTweenFrame + 2) % #poses local pose4 = (mainViewTweenFrame + 3) % #poses -- local poseTween = getPoseCatmullRomInterpolate(tPos, poses[pose1 + 1], poses[pose2 + 1], poses[pose3 + 1], poses[pose4 + 1], 1) local poseTween = R.GetPoseSlerp(tPos, poses[pose1 + 1], poses[pose2 + 1]) -- Weighed interpolation? R.ApplyPoseToSkeleton(poseTween, actor.skeleton) end return { init=init, applyToSkeleton=applyToSkeleton } end end rift_3d2model=function() return function(R) R=R or {} local Model={} function Model:new(rootMeshID) local o={ meshTemplates={}, -- We can use a meshTemplate multiple times in our mesh tree meshTree={}, -- The skeleton... id -> [quaternion, distance, meshID, children] meshLookup={}, -- meshID -> mesh in meshTree (saves us searching it all) data=nil, } setmetatable(o,self) self.__index=self return o end function Model:__tostring() return string.format("Model(no representation yet)") end function Model:setData(data) self.data = data end -- meshID can/should be an indexable ID function Model:addMeshTemplate(id, mesh) self.meshTemplates[id]=mesh end -- parentRef: {meshInstanceID,jointID} or nil function Model:addMeshInstance(id, parentRef, meshID, quaternion, meshData) local meshInstance={ meshID=meshID, quaternion=quaternion, children={}, data=meshData, } id = (id == nil and #self.meshInstances+1) or id if parentRef == nil then -- this is a root node (special case - should it be?) self.meshTree[id] = meshInstance self.meshLookup[id] = self.meshTree[id] else local parentMeshNode = self.meshLookup[parentRef[1]] parentMeshNode.children[id]={meshInstance=meshInstance,joint=parentRef[2]} self.meshLookup[id] = parentMeshNode.children[id].meshInstance end end -- rootNodeID ~> suggest "root", but I think we could use this to do morphing / other things? function Model:addToRenderlist(engine, scene, position, modelQuaternion, scale, skeleton, rootNodeID, skinIDs, actorData, renderlist) local meshInstance = self.meshTree[rootNodeID] -- rootJoint is a special case, if it exists... local rootJointQuaternion = skeleton:getJoint({rootNodeID, 'root'}) if rootJointQuaternion then modelQuaternion = R.Quaternion.multiply(modelQuaternion, rootJointQuaternion) end self:_addSelfAndChildrenToRenderlist(engine, scene, position, modelQuaternion, scale, rootNodeID, meshInstance, skeleton, skinIDs, actorData, renderlist) end function Model:_addSelfAndChildrenToRenderlist(engine, scene, basePosition, baseQuaternion, scale, meshInstanceID, meshInstance, skeleton, skinIDs, actorData, renderlist) local meshQuaternion = R.Quaternion.multiply(baseQuaternion, meshInstance.quaternion) local meshTemplate = self.meshTemplates[meshInstance.meshID] meshTemplate:addToRenderlist(engine, scene, basePosition, meshQuaternion, scale, skinIDs, actorData, self.data, meshInstance.data, renderlist) for childID, childNode in pairs(meshInstance.children) do local jointQuaternion = skeleton:getJoint({meshInstanceID, childNode.joint}) if jointQuaternion == nil then jointQuaternion = R.Quaternion:newFromEuler(0,0,0) end local vertex = R.V3.scaleByV3(meshTemplate:vertex(childNode.joint), scale) local childPosition = basePosition + R.Quaternion.rotateV3(meshQuaternion, vertex) local childQuaternion = R.Quaternion.multiply(meshQuaternion, jointQuaternion) self:_addSelfAndChildrenToRenderlist(engine, scene, childPosition, childQuaternion, scale, childID, childNode.meshInstance, skeleton, skinIDs, actorData, renderlist) end end R.Model = Model end end rift_datamaterialflatlitpalmap=function() return function(R2) local mapHatch4 = rift_datapalettemaphatch4()(R) local mMin, mMax, mRandom = math.min, math.max, math.random -- Assumes the quad is a plane! -- function generator... -- we can change lightVec after it has been sent in here (ensure it is normalised) -- Ensure you reset palette map aft local function materialQuad(lightVec, ciLow, ciHigh) local palMap = mapHatch4.makeLinear(ciLow, ciHigh) local palMapMid = (#palMap-.5)/2 return R2.Material:new():setFnTransform(function(d, psView, psWorld) return { pv1 = psView[d.v1], pv2=psView[d.v2], pv3=psView[d.v3], pv4=psView[d.v4], normal = R2.V3.normal(psWorld[d.v1], psWorld[d.v2], psWorld[d.v3]) -- tri (assuming a planar quad!) } end):setFnDraw(function(d) local angle = R2.V3.dot(d.normal, lightVec) local palMapRender = palMap[1+(palMapMid+palMapMid*angle)//1] local pv1,pv2,pv3,pv4 = d.pv1,d.pv2,d.pv3,d.pv4 local xdiff = mMax(pv1.x, pv2.x, pv3.x, pv4.x) - mMin(pv1.x, pv2.x, pv3.x, pv4.x) local ydiff = mMax(pv1.y, pv2.y, pv3.y, pv4.y) - mMin(pv1.y, pv2.y, pv3.y, pv4.y) local sW = mMax(8, mMin(xdiff,127)) local sH = mMax(8, mMin(ydiff,127)) local s1xSh, s1ySh = mRandom(0,7), mRandom(0,7) local s1x0, s1y0 = s1xSh, s1ySh local s1x1, s1y1 = s1x0 + sW, s1y0 + sH local a = 0x3ff0*2 poke4(a,palMapRender[1]) poke4(a+1,palMapRender[2]) poke4(a+2,palMapRender[3]) poke4(a+3,palMapRender[4]) ttri( pv1.x,pv1.y,pv2.x,pv2.y,pv3.x,pv3.y, s1x0,s1y0,s1x1,s1y0,s1x1,s1y1, 1, -1, pv1.z,pv2.z,pv3.z ) ttri( pv1.x,pv1.y,pv3.x,pv3.y,pv4.x,pv4.y, s1x0,s1y0,s1x1,s1y1,s1x0,s1y1, 1, -1, pv1.z,pv3.z,pv4.z ) -- optimise this by only doing it when we need to! poke4(a,0) poke4(a+1,1) poke4(a+2,2) poke4(a+3,3) end) end -- function generator... -- we can change lightVec after it has been sent in here (ensure it is normalised) -- Ensure you reset palette map after local function materialTri(lightVec, ciLow, ciHigh) local palMap = mapHatch4.makeLinear(ciLow, ciHigh) local palMapMid = (#palMap-.5)/2 return R2.Material:new():setFnTransform(function(d, psView, psWorld) return { pv1 = psView[d.v1], pv2=psView[d.v2], pv3=psView[d.v3], normal = R2.V3.normal(psWorld[d.v1], psWorld[d.v2], psWorld[d.v3]), } end):setFnDraw%(function(d) local angle = R2.V3.dot(d.normal, lightVec) local palMapRender = palMap[1+(palMapMid+palMapMid*angle)//1] local pv1,pv2,pv3,pv4 = d.pv1,d.pv2,d.pv3,d.pv4 local xdiff = mMax(pv1.x, pv2.x, pv3.x) - mMin(pv1.x, pv2.x, pv3.x) local ydiff = mMax(pv1.y, pv2.y, pv3.y) - mMin(pv1.y, pv2.y, pv3.y) local sW = mMax(8, mMin(xdiff,127)) local sH = mMax(8, mMin(ydiff,127)) local s1xSh, s1ySh = mRandom(0,7), mRandom(0,7) local s1x0, s1y0 = s1xSh, s1ySh local s1x1, s1y1 = s1x0 + sW, s1y0 + sH local a = 0x3ff0*2 poke4(a,palMapRender[1]) poke4(a+1,palMapRender[2]) poke4(a+2,palMapRender[3]) poke4(a+3,palMapRender[4]) ttri( pv1.x,pv1.y,pv2.x,pv2.y,pv3.x,pv3.y, s1x0,s1y0,s1x1,s1y0,s1x1,s1y1, 1, -1, pv1.z,pv2.z,pv3.z ) -- optimise this by only doing it when we need to! poke4(a,0) poke4(a+1,1) poke4(a+2,2) poke4(a+3,3) end) end return { tri=materialTri, quad=materialQuad, } end end rift_datamaterialmask=function() return function(R) local function quadTextured(sSrc,chromakey,sx,sy,sw,sh,pixelmode,palMap) pixelmode = pixelmode or 2 -- 8: 1bpp, 4 = 2bpp, 2 = 4bpp palMap = palMap or {} return R.Material:new():setFnTransform(function(d, psView, psWorld, actorData) return { v1=psView[d.v1],v2=psView[d.v2],v3=psView[d.v3],v4=psView[d.v4], isPatarty = (actorData and actorData.isPatarty) or false, } end):setFnDraw(function(d) -- clockwise... local sx0,sx1,sy0,sy1 = sx,sx+sw,sy,sy+sh if not d.isPatarty then sy0,sy1 = sy0 + 64,sy1 + 64 else for i,r in pairs(palMap) do poke4(0x3FF0*2+i,r) end end local oldPixelMode = peek4(0x3FFC*2) poke4(0x3FFC*2,pixelmode) -- set pixel mode ttri( d.v1.x,d.v1.y,d.v2.x,d.v2.y,d.v3.x,d.v3.y, sx0,sy0,sx1,sy0,sx1,sy1, sSrc, chromakey, d.v1.z,d.v2.z,d.v3.z ) ttri( d.v3.x,d.v3.y,d.v4.x,d.v4.y,d.v1.x,d.v1.y, sx1,sy1,sx0,sy1,sx0,sy0, sSrc, chromakey, d.v3.z,d.v4.z,d.v1.z ) poke4(0x3FFC*2,oldPixelMode) -- reset pixel mode for i,r in ipairs(palMap) do poke4(0x3FF0*2+i,i) end end) end return { quad = quadTextured, } end end rift_partsdanceclaps=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local flow = rift_codeflow() local fnsClock = rift_data3dclock()(R) local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true end local progress = pMetrics.progress local dancerZ = -35 local dancer = stage3d.dancers[1] dancer.isVisible = true local danceT = progress * 16 + .3 if isCrazy then danceT = danceT * 2 end dancer:setPosition(R.V3:new(-15, 0, dancerZ)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("clap", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, dancerZ)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("clap2", dancer, danceT) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(15, 0, dancerZ)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("clap", dancer, danceT) local clockDrop = math.min(progress + .3, 1) stage3d.clock:setPosition(R.V3:new(0, 80 - math.sin(clockDrop) * 85, -50)) local seconds = progress * 8 fnsClock.setClock(stage3d.clock, seconds) stage3d.cameraFG:setPosition(R.V3:new(0, 6, -20 + progress * 20)) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsend=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local tileFont = rift_datagfxtilefont() local stage3d local mPi, mTau = math.pi, 2 * math.pi local mMin, mMax = math.min, math.max local function rotLetters(letters, iFirstLetter, iLastLetter, turn) for iLetter = iFirstLetter,iLastLetter do local rotX = mMax(mMin(turn * mTau * 4, 0), -mPi/2) local letterActor = letters[iLetter] letterActor:setRotation(R.Quaternion:newFromEuler(rotX, 0, 0)) end end return R.DemoPart:new({ bdr=setup2d.bdrNoConundrum, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() clip() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() end local progress = pMetrics.progress vbank(1) cls() local iFreeLetter = 1 iFreeLetter = letters.setTextActors("I LOVE", R.V3:new(0,1.25,-5), stage3d.lettersFG, iFreeLetter) iLastLetterCheat1 = iFreeLetter - 1 iFreeLetter = letters.setTextActors("RICHARD WHITELEY", R.V3:new(0,-.25,-5), stage3d.lettersFG, iFreeLetter) iLastLetterCheat2 = iFreeLetter - 1 iFreeLetter = letters.setTextActors("TYPE", R.V3:new(0,4.5,-12), stage3d.lettersFG, iFreeLetter, 2) iFreeLetter = letters.setTextActors("TO UNLOCK THE", R.V3:new(0,-3.5,-12), stage3d.lettersFG, iFreeLetter, 1.5) iFreeLetter = letters.setTextActors("DANCE ANIMATOR", R.V3:new(0,-5.5,-12), stage3d.lettersFG, iFreeLetter, 1.5) letters.rotLetters(stage3d.lettersFG, 1, iLastLetterCheat1, progress, .4, .8, " ") letters.rotLetters(stage3d.lettersFG, iLastLetterCheat1+1, iLastLetterCheat2, progress, .5, .9, " ") stage3d.cameraFG:setPosition(R.V3:new(0, 10 - progress * 12, 6)) local cameraRot = R.Quaternion:newFromEuler(-.3 + .5 * progress,0,-.3 + progress * .3) stage3d.cameraFG:setRotation(cameraRot) setup2d.fadeScene(progress, .2, .8) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) end, cleanup=function() end, }) end rift_demopart=function() --- A section of a demo (usually viewed for a few seconds upwards, or one/multiple frames of music) -- @module demo.demopart -- @author jtruk return function(R) R=R or {} R.DemoPart={} --- Create a new DemoPart object. -- @tparam {tab} -- preboot (func) () -- cleanup (func) () -- tic (func) (partMetrics) -- partMetrics={ -- isFirstRun -- isLastRun, -- progress -- musFrameProgress -- } -- bdr (func) (y, partMetrics) function R.DemoPart:new(o) setmetatable(o,self) self.__index=self return o end --[[ function R.DemoPart:setPos(pos) self.pos=pos end --]] end end rift_datagfxpatarty=function() return { pal="07F8001eA5EEPCFAEKLHNCEMLJNEP5", img="08000180A86BA5BBA4BDDA3BD2A2BD3A2BD3A4B2AB4DDBD35C2D5CCB2A4DB4AAD5BBD39A15BA6B2A4DDBBA3D3BA2D4BAAD5BA131BD3AABBD3AABBD3AABBD3AABD4AABD4AABD4AABD133C2DDBBDC3DDBDDC2D42A15BA6BA6BBA5DBA5DBA5DBA71BD4AABD4AABDCCDDAABDCCDDAABDCCDDAABDCCDDABDDCCDDABD2CD53B3D2B3ED47BD4BBEBD2B2D47B2D4BEEBD5BA4DDBA4DDBA4DDBA4DDBA4DDBA4DDBA4DDBA69BD2CDDABD5ABD5ABD5BBD5BD6BD6BD8B5DDB5DDB5D2B4D2B4D3B3D15EBD2B4DDB5DDB5D2B4D2B3D4BBD15BBEBD3B3D3B3D3B3D3B3DC2B2DDC2D4C2D4C2DDBA4DDBA4DDBA4DDBA4DDBA4DDBA4DDBA4DDBA19BA6BA6BA6BA5BBA5BDA5BDBD44CCD5CCD4C2D39C4D2C5DDC5D70C2D57BA4DDBA4DDBA4DBA5DBA5DBA5DBA5DBA11BDA5BDA4BDDA4BCDA4BCDA4BCCA4BCCA3BBCCD4C2D4C2D5CCD6CD23CD6C6DC6DC6DC5DDC4D41CD5CCD4C2D4C2D3C3D3C3D3C3D7CD6CCD5CCD5CCD5CCD5CCD5CD5BDBA5BBA5BA6BA6BA6BA6BA18BBCCA4BCCA4BCCA4BCCA4BBCA5BCA5BCA6BCCD5CCD5C2D4C3D3C5DDC23D47CD6C3D7C3D62BD6BD6BD5BBD5BAD5BAD4BBAD2CCBA72BA55BC6BC6ABC5ABBC4AABBC3A3BBCCA4B2A6BC6DC47B7D6C23BC5BBC3BBAACB2A3BBA5C2BBA2CCBBA3CBBA4BA102", } end rift_datapalettemaphatch4=function() -- For constructing tables that contain a palette map for a hatch4 material. return function(R) -- Spreads linearly between the two colour indices local function makeLinear(ciLow, ciHigh) local palmap = {} palmap[#palmap+1]={ciLow,ciLow,ciLow,ciLow} for c0 = ciLow,ciHigh-1 do local c1 = c0 + 1 palmap[#palmap+1]={c0,c1,c0,c0} palmap[#palmap+1]={c1,c0,c0,c1} palmap[#palmap+1]={c1,c1,c1,c0} palmap[#palmap+1]={c1,c1,c1,c1} end return palmap end -- Adds the hatching for a continuous loop between the two colour indices local function makeCircular(ciLow, ciHigh) local palmap = makeLinear(ciLow, ciHigh) palmap[#palmap+1]={ciHigh,ciLow,ciHigh,ciHigh} palmap[#palmap+1]={ciLow,ciHigh,ciHigh,ciLow} palmap[#palmap+1]={ciLow,ciLow,ciLow,ciHigh} palmap[#palmap+1]={ciLow,ciLow,ciLow,ciLow} return palmap end local function palmapAppendAppendSolid(palmap, c) palmap[#palmap+1]={c,c,c,c} end local function palmapAppendGradientToSolid(palmap, c0, c1) palmap[#palmap+1]={c0,c1,c0,c0} palmap[#palmap+1]={c1,c0,c0,c1} palmap[#palmap+1]={c1,c1,c1,c0} palmap[#palmap+1]={c1,c1,c1,c1} end local function palmapAppendLinear(palmap, ciLow, ciHigh) for c0 = ciLow,ciHigh-1 do local c1 = c0 + 1 palmap[#palmap+1]={c0,c1,c0,c0} palmap[#palmap+1]={c1,c0,c0,c1} palmap[#palmap+1]={c1,c1,c1,c0} palmap[#palmap+1]={c1,c1,c1,c1} end end return { makeLinear = makeLinear, makeCircular = makeCircular, palmapAppendAppendSolid = palmapAppendAppendSolid, palmapAppendGradientToSolid = palmapAppendGradientToSolid, palmapAppendLinear = palmapAppendLinear, } end end rift_3d2camera=function() return function(R) R=R or {} local Camera={} local mTan, mRad, mPi = math.tan, math.rad, math.pi -- pos V3 -- rot Quaternion -- up V3 function Camera:new(pos, rot, up) -- ?fov, near, far (aspect?)? local o={ pos=pos and pos or R.V3:new(0,0,0), rot=rot and rot or R.Quaternion:identity(), up=up and up or R.V3:new(0,1,0), fov = 60, -- degrees near = .01, far = 1000, -- matWorldToView is a cached [matWorldToCamera -> matCameraToView] matWorldToView, matWorldToCamera, matCameraToView, } setmetatable(o,self) self.__index=self return o end function Camera.newM44OrthogonalProj(b,t,l,r,n,f) return R.M44:new( 2 / (r-l), 0,0,0, 0, 2 / (t-b), 0, 0, 0, 0, 2 / (n-f), 0, (l+r)/(l-r), (t+b)/(b-t), (f+n)/(n-f), 1 ) end function Camera.newM44PersProj(fov, near, far) local scale = 1 / mTan(mRad(fov * .5)) local range = near - far return R.M44:new( scale, 0, 0, 0, 0, scale, 0, 0, 0, 0, far / range, far * near / range, 0, 0, -1, 0 ) end function Camera:setPosition(pos) self.pos = pos self.matWorldToCamera = nil self.matWorldToView = nil end function Camera:setRotation(q) self.rot = q self.matWorldToCamera = nil self.matWorldToView = nil end function Camera:setFOV(fov) self.fov = fov self.matCameraToView = nil self.matWorldToView = nil end function Camera:getMatWorldToView() if not self.matWorldToView then self.matWorldToView = self:getMatCameraToView() * self:getMatWorldToCamera() end return self.matWorldToView end function Camera:getMatWorldToCamera() if not self.matWorldToCamera then -- #TODO: Optimise... local matWorldToCamera = R.M44:new( 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 ) -- TODO: Invert rotation? matWorldToCamera = R.M44.rotateByQuaternion(matWorldToCamera, self.rot) matWorldToCamera.m03 = -self.pos.x matWorldToCamera.m13 = -self.pos.y matWorldToCamera.m23 = -self.pos.z self.matWorldToCamera = matWorldToCamera end return self.matWorldToCamera end function Camera:getMatCameraToView() if not self.matCameraToView then self.matCameraToView = Camera.newM44PersProj(self.fov, self.near, self.far) end return self.matCameraToView end R.Camera = Camera end end rift_syssys=function() --- Helpers for System level functions -- @module sys.sys return function(R) R=R or {} rift_uimouse()(R) local mouse=R.Mouse:new() local mouseState=nil local tics=0 local startTime=nil local _clip={x=0,y=0,w=240,h=136} --- Exit immediately if a specified key is pressed. -- Useful for some (not-latest) versions of TIC where CTRL-C is erroneously disabled. -- -- [!] Call at the start of the TIC loop. -- @param key The key to break on, defaults to 51 (ESC). [Keycodes here](https://github-wiki-see.page/m/nesbox/TIC-80/wiki/key) e.g. 48 is spacebar. -- @usage -- function TIC() -- R.tryBreak() -- ... -- end R.tryBreak=function(key) key=key or 51 if keyp(key) then exit() end end --- Removes the mouse cursor from the screen. -- -- [!] Call at the start of the TIC loop. R.hideMouse=function() poke(0x3FFB,0) end --- Returns the number of times the TIC loop has been run. -- -- [!] Wrap your TIC loop in R.ticWrap to use this. R.getTics=function() return tics end --- Returns the time in milliseconds since the first TIC loop. -- -- [!] Wrap your TIC loop in R.ticWrap to use this. R.getTimeMS=function() return time()-startTime end --- Enables some system level tracking, and mouse state support. -- @usage -- R.ticWrap(function() -- -- your usual tic loop -- end) R.ticWrap=function(tic) return function() if startTime==nil then startTime=time() end mouseState=mouse:update() tic() tics=tics+1 end end --- Returns the mouse state. -- -- [!] Wrap your TIC loop in R.ticWrap to use this. function R.getMouse() return mouseState end --- Wrappers for TIC's clip functionality. -- This wrapping allows us (and system calls) to check the currently set clip area. -- -- [!] Mixing this with the regular, unwrapped 'clip()' will cause confusion! function R.clearClip() _clip={x=0,y=0,w=240,h=136} clip() end --- Wrappers for TIC's clip functionality. -- This wrapping allows us (and system calls) to check the currently set clip area. -- -- [!] Mixing this with the regular, unwrapped 'clip()' will cause confusion! -- @param x top -- @param y left -- @param w width -- @param h height function R.setClip(x,y,w,h) _clip={x=x,y=y,w=w,h=h} clip(x,y,w,h) end --- Wrappers for TIC's clip functionality. -- This wrapping allows us (and system calls) to check the currently set clip area. -- -- [!] Mixing this with the regular, unwrapped 'clip()' will cause confusion! -- @return {x,y,w,h} function R.getClip() return _clip end end end rift_partsposer=function() R=R or {} rift_demopart()(R) rift_3d2camera()(R) rift_3d2engine()(R) rift_3d2model()(R) rift_3d2mesh()(R) rift_3d2actor()(R) rift_3d2skeleton()(R) rift_3d2pose()(R) rift_3d2quaternion()(R) rift_3d2material()(R) rift_3d2scene()(R) rift_3d2v3()(R) rift_3d2m44()(R) rift_syscatmullrom()(R) local matLine = R.Material.line(15) local fnsFigure = rift_data3dfigure()(R) local materialFlatLitPalmap = rift_datamaterialflatlitpalmap()(R) --local IMPORT_POSES = nil --local IMPORT_POSES = {[1]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=3.142,vy=1.542,vz=3.142},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}} --local IMPORT_POSES = {[1]={{m='miPelvis',j='root',vx=-0.170,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.880,vy=-0.110,vz=-0.000},{m='miLeftLegHigh',j='jKnee',vx=-1.970,vy=0.030,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.330,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.010,vy=0.110,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.120,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=-0.320,vz=-1.410},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=1.502,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=-0.160,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.020,vy=-0.370,vz=1.410},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.370,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=-0.120,vy=0.270,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.070,vy=-0.090,vz=0.170},{m='miLeftLegHigh',j='jKnee',vx=-0.420,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.430,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=-0.680,vy=-0.260,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-0.640,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.360,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.450,vz=0.040},{m='miTorso',j='jNeck',vx=0.150,vy=0.070,vz=-0.080},{m='miTorso',j='jLeftShoulder',vx=-0.010,vy=0.710,vz=-1.400},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.020,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.040,vy=0.830,vz=1.210},{m='miRightArmHigh',j='jElbow',vx=3.142,vy=-1.032,vz=3.142},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.140,vy=-0.070,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.060,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.020,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.140,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.080,vy=0.160,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-2.120,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.380,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.020},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=0.120,vz=-1.380},{m='miLeftArmHigh',j='jElbow',vx=0.300,vy=1.220,vz=-0.330},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.070,vy=0.220,vz=1.350},{m='miRightArmHigh',j='jElbow',vx=3.012,vy=-1.312,vz=-3.142},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=-0.170,vy=-0.360,vz=-0.000},{m='miPelvis',j='jLeftHip',vx=-0.830,vy=0.370,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.620,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.400,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.040,vy=0.350,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=-0.530,vy=0.160,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.450,vy=-0.210,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.000,vy=0.480,vz=-0.100},{m='miTorso',j='jNeck',vx=0.140,vy=-0.060,vz=0.140},{m='miTorso',j='jLeftShoulder',vx=0.000,vy=-0.760,vz=-1.280},{m='miLeftArmHigh',j='jElbow',vx=3.142,vy=1.062,vz=3.142},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.080,vy=-0.430,vz=1.540},{m='miRightArmHigh',j='jElbow',vx=0.400,vy=-1.320,vz=-0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}} local IMPORT_POSES = {[1]={{m='miPelvis',j='root',vx=-0.060,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.050,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.110,vy=0.280,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-1.100,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.180,vy=-0.230,vz=0.000},{m='miTorso',j='jNeck',vx=-0.230,vy=0.130,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.050,vy=0.740,vz=-0.630},{m='miLeftArmHigh',j='jElbow',vx=-0.970,vy=0.290,vz=-1.990},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.460,vy=0.050,vz=1.540},{m='miRightArmHigh',j='jElbow',vx=0.080,vy=-0.740,vz=-0.080},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=-0.330,vy=-0.240,vz=0.000},{m='miPelvis',j='jLeftHip',vx=2.140,vy=-1.250,vz=-0.290},{m='miLeftLegHigh',j='jKnee',vx=-2.230,vy=-0.090,vz=0.050},{m='miLeftLegLow',j='jAnkle',vx=1.000,vy=0.770,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.050,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.200,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=0.160,vz=0.000},{m='miTorso',j='jNeck',vx=0.040,vy=0.330,vz=0.140},{m='miTorso',j='jLeftShoulder',vx=-2.532,vy=1.272,vz=-2.842},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=1.200,vz=-0.300},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.030,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.330,vy=-0.440,vz=1.220},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=-1.280,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-0.120,vy=-0.720,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.760,vy=-0.690,vz=-0.000},{m='miLeftLegHigh',j='jKnee',vx=-0.420,vy=0.120,vz=0.020},{m='miLeftLegLow',j='jAnkle',vx=-1.360,vy=0.080,vz=-0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=0.550,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.180,vy=1.020,vz=-0.180},{m='miTorso',j='jNeck',vx=-0.150,vy=1.010,vz=0.230},{m='miTorso',j='jLeftShoulder',vx=-0.430,vy=0.380,vz=-1.610},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.350,vy=-1.130,vz=0.700},{m='miRightArmHigh',j='jElbow',vx=-0.580,vy=-1.430,vz=1.160},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[4]={{m='miPelvis',j='root',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.610,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=-1.150,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.000,vy=-0.040,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.180,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=-0.350,vy=-0.060,vz=-0.000},{m='miTorso',j='jLeftShoulder',vx=0.470,vy=0.330,vz=-1.440},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=-0.380},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.450,vy=-0.640,vz=0.780},{m='miRightArmHigh',j='jElbow',vx=-1.140,vy=-0.540,vz=1.930},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[5]={{m='miPelvis',j='root',vx=-0.220,vy=0.260,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=-0.500,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=2.420,vy=0.770,vz=-0.000},{m='miRightLegHigh',j='jKnee',vx=-2.220,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.870,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=0.000,vy=-0.510,vz=0.000},{m='miTorso',j='jNeck',vx=-0.010,vy=-0.790,vz=-0.110},{m='miTorso',j='jLeftShoulder',vx=-0.000,vy=0.450,vz=-1.440},{m='miLeftArmHigh',j='jElbow',vx=-0.200,vy=-0.030,vz=-0.900},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=-0.040},{m='miTorso',j='jRightShoulder',vx=-2.882,vy=-1.482,vz=-1.472},{m='miRightArmHigh',j='jElbow',vx=-0.030,vy=0.430,vz=1.200},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[6]={{m='miPelvis',j='root',vx=-0.280,vy=0.600,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.000,vy=-0.800,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=-0.230},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.790,vy=0.800,vz=0.060},{m='miRightLegHigh',j='jKnee',vx=-0.290,vy=0.050,vz=0.050},{m='miRightLegLow',j='jAnkle',vx=-1.440,vy=0.000,vz=-0.070},{m='miPelvis',j='jWaist',vx=-0.010,vy=-1.040,vz=-0.000},{m='miTorso',j='jNeck',vx=0.000,vy=-0.450,vz=-0.170},{m='miTorso',j='jLeftShoulder',vx=0.190,vy=0.560,vz=-1.520},{m='miLeftArmHigh',j='jElbow',vx=-0.270,vy=-0.060,vz=-1.260},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.880,vy=-0.530,vz=1.450},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}}} -- six step (in progress) -- {[1]={{m='miPelvis',j='root',vx=-1.820,vy=-0.070,vz=0.480},{m='miPelvis',j='jLeftHip',vx=2.330,vy=-0.380,vz=0.040},{m='miLeftLegHigh',j='jKnee',vx=-1.160,vy=-0.170,vz=-0.610},{m='miLeftLegLow',j='jAnkle',vx=-0.160,vy=-0.030,vz=-0.000},{m='miPelvis',j='jRightHip',vx=2.010,vy=-0.450,vz=0.010},{m='miRightLegHigh',j='jKnee',vx=-0.080,vy=-0.000,vz=0.010},{m='miRightLegLow',j='jAnkle',vx=-1.260,vy=-0.000,vz=-0.110},{m='miPelvis',j='jWaist',vx=1.400,vy=-0.210,vz=-0.450},{m='miTorso',j='jNeck',vx=0.820,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.030,vy=-0.050,vz=0.730},{m='miLeftArmHigh',j='jElbow',vx=0.180,vy=-0.940,vz=1.280},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.060,vy=-0.750,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[2]={{m='miPelvis',j='root',vx=0.990,vy=0.230,vz=0.000},{m='miPelvis',j='jLeftHip',vx=1.090,vy=0.000,vz=0.330},{m='miLeftLegHigh',j='jKnee',vx=-1.730,vy=0.240,vz=0.330},{m='miLeftLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=1.040,vy=0.260,vz=-0.410},{m='miRightLegHigh',j='jKnee',vx=-1.520,vy=-0.160,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=0.000,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.000,vy=-0.110,vz=0.020},{m='miTorso',j='jNeck',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=-0.020,vy=-0.530,vz=-1.250},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=-0.030,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=-0.350,vy=0.580,vz=1.530},{m='miRightArmHigh',j='jElbow',vx=0.000,vy=0.000,vz=0.000},{m='miRightArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000}},[3]={{m='miPelvis',j='root',vx=-1.350,vy=0.000,vz=0.000},{m='miPelvis',j='jLeftHip',vx=0.570,vy=0.000,vz=0.000},{m='miLeftLegHigh',j='jKnee',vx=0.000,vy=0.000,vz=0.000},{m='miLeftLegLow',j='jAnkle',vx=-0.530,vy=0.000,vz=0.000},{m='miPelvis',j='jRightHip',vx=0.540,vy=0.000,vz=0.000},{m='miRightLegHigh',j='jKnee',vx=0.070,vy=0.000,vz=0.000},{m='miRightLegLow',j='jAnkle',vx=-0.560,vy=0.000,vz=0.000},{m='miPelvis',j='jWaist',vx=-0.140,vy=0.000,vz=0.000},{m='miTorso',j='jNeck',vx=1.040,vy=0.000,vz=0.000},{m='miTorso',j='jLeftShoulder',vx=0.500,vy=0.780,vz=0.000},{m='miLeftArmHigh',j='jElbow',vx=0.000,vy=0.330,vz=0.000},{m='miLeftArmLow',j='jWrist',vx=0.000,vy=0.000,vz=0.000},{m='miTorso',j='jRightShoulder',vx=0.000,vy=-0.960,vz=0.000},{m='miRightArmHigh',j='jElbow',vx=0.060,vy=-0.440,vz=0.000},{m='miRightArmLow',j='jWrist',vx=-0.030,vy=0.000,vz=0.000}}} local ENGINES = {} local SCENES = {} local CAMERA, LIGHT local ACTORS = {} local mPi, mSin, mCos = math.pi, math.sin, math.cos local mTau = mPi*2 local JOINT_REFS = { {"miPelvis", "root"}, {"miPelvis","jLeftHip"}, {"miLeftLegHigh","jKnee"}, {"miLeftLegLow","jAnkle"}, {"miPelvis","jRightHip"}, {"miRightLegHigh","jKnee"}, {"miRightLegLow","jAnkle"}, {"miPelvis","jWaist"}, {"miTorso","jNeck"}, {"miTorso","jLeftShoulder"}, {"miLeftArmHigh","jElbow"}, {"miLeftArmLow","jWrist"}, {"miTorso","jRightShoulder"}, {"miRightArmHigh","jElbow"}, {"miRightArmLow","jWrist"}, } local POSES = {} local COPIED_POSE = nil function makeZeroPose() local pose = R.Pose:new() for _, joint in pairs(JOINT_REFS) do pose:setJoint(joint, R.Quaternion:newFromEuler(0,0,0)) end return pose end local JOINT_V3 = nil local isEditView = true local iPoseLeft = 0 local iSelectedPose = 0 local iSelectedJoint = 0 local rotX, rotY, rotZ = 0, mPi, 0 local windowWidth = 78 local windowHeight = 80 local ANIMSPEED = 1 local function printc(text, x, y, c) local w = print(text, 0,140, c) print(text, x-w/2,y, c) end local function printr(text, x, y, c) local w = print(text, 0,140, c) print(text, x-w,y, c) end local function exportPoses() local exportString = '' for i,pose in ipairs(POSES) do exportString = exportString .. string.format('[%d]={', i) for _,jointRef in ipairs(JOINT_REFS) do local joint = pose:getJoint(jointRef) local v3 = joint:toEuler() exportString = exportString .. string.format( "{m='%s',j='%s',vx=%.3f,vy=%.3f,vz=%.3f},", jointRef[1], jointRef[2], v3.x, v3.y, v3.z ) end exportString = exportString .. "}," end exportString = "{" .. exportString .. "}" trace(exportString) end local function importPoses() if not IMPORT_POSES then POSES[1] = makeZeroPose() else for i,poseData in ipairs(IMPORT_POSES) do local pose = makeZeroPose() for _, joint in pairs(poseData) do pose:setJoint({joint.m, joint.j}, R.Quaternion:newFromEuler(joint.vx,joint.vy,joint.vz)) end POSES[i] = pose end end end local function exportPoses() local exportString = '' for i,pose in ipairs(POSES) do if i>1 then exportString = exportString .. "," end exportString = exportString .. string.format('[%d]={', i) for j,jointRef in ipairs(JOINT_REFS) do if j>1 then exportString = exportString .. "," end local joint = pose:getJoint(jointRef) local v3 = joint:toEuler() exportString = exportString .. string.format( "{m='%s',j='%s',vx=%.3f,vy=%.3f,vz=%.3f}", jointRef[1], jointRef[2], v3.x, v3.y, v3.z ) end exportString = exportString .. "}" end exportString = "{" .. exportString .. "}" trace(exportString) end return R.DemoPart:new({ tic=function(pMetrics) if pMetrics.isFirstRun then importPoses() LIGHT = R.V3:new(0,1,.25) LIGHT:normalize() CAMERA = R.Camera:new(R.V3:new(0,0,0), R.Quaternion:newFromEuler(0,0,0)) local model = fnsFigure.makeModel("regular", .95, 1.05, 1, "quadTexFace1") for i,name in ipairs({'left', 'tween', 'right'}) do local engine = R.Engine:new() local zActor = -40 local portY = 50 local portWidth = windowWidth if i==2 then portWidth = windowWidth * 2 zActor = -27 portY = 70 end engine.viewportXC = 120 + (i - 2) * windowWidth engine.viewportYC = portY engine:setMaterial("quad", materialFlatLitPalmap.quad(LIGHT, 1, 15)) engine:setMaterial("quadTex1", R.Material.quadTextured(0,-1, 32,0,32,32)) engine:setMaterial("quadTex2", R.Material.quadTextured(0,-1, 64,0,32,32)) engine:setMaterial("quadTex3", R.Material.quadTextured(0,-1, 80,0,32,32)) engine:setMaterial("quadTex4", R.Material.quadTextured(0,-1, 32,32,32,32)) engine:setMaterial("quadTex5", R.Material.quadTextured(0,-1, 64,32,32,32)) engine:setMaterial("quadTex6", R.Material.quadTextured(0,-1, 80,32,32,32)) engine:setMaterial("line", matLine) local modelID = engine:addModel(model) local scene = R.Scene:new(CAMERA) local actor = scene:newActor(modelID, R.V3:new(0,0,0), "miPelvis") actor:setPosition(R.V3:new(0,0,zActor)) -- actor:setSkins({"textured"}) ENGINES[name] = engine SCENES[name] = scene ACTORS[name] = actor end end vbank(1) cls() local progress = pMetrics.progress local moveAmount = 0.01 local halfRange = mPi local range = mTau local tweenTime = time() * 0.0005 * ANIMSPEED local tweenTimeFloor = tweenTime//1 local tweenPos if isEditView then tweenPos = .5 + mSin(tweenTime * mTau) * .5 else -- I think this needs to be a spline tween tweenPos = (tweenTime - tweenTimeFloor) end if keyp(53) then -- insert pose table.insert(POSES, iSelectedPose + 1, makeZeroPose()) JOINT_V3 = nil elseif keyp(52) then -- delete pose if #POSES > 1 then table.remove(POSES, iSelectedPose + 1) end iSelectedPose = iSelectedPose % #POSES -- old pose may have been deleted if it was the last one iPoseLeft = iPoseLeft % #POSES JOINT_V3 = nil end -- model/joint change controls if btnp(0) then -- previous joint iSelectedJoint = (iSelectedJoint - 1) % #JOINT_REFS JOINT_V3 = nil elseif btnp(1) then -- next joint iSelectedJoint = (iSelectedJoint + 1) % #JOINT_REFS JOINT_V3 = nil end if btnp(2) then -- previous pose if iSelectedPose == iPoseLeft then -- currently selecting the left pose iPoseLeft = (iPoseLeft - 1) % #POSES end iSelectedPose = (iSelectedPose - 1) % #POSES JOINT_V3 = nil elseif btnp(3) then -- next pose if iSelectedPose ~= iPoseLeft then -- currently selecting the right pose iPoseLeft = (iPoseLeft + 1) % #POSES end iSelectedPose = (iSelectedPose + 1) % #POSES JOINT_V3 = nil end local pose = POSES[iSelectedPose + 1] local jointRef = JOINT_REFS[iSelectedJoint + 1] if keyp(3) then -- copy COPIED_POSE = pose:clone() elseif keyp(22) then -- paste if COPIED_POSE then if key(64) then -- shift POSES[iSelectedPose + 1] = COPIED_POSE:clone() pose = POSES[iSelectedPose + 1] JOINT_V3 = nil else local joint = COPIED_POSE:getJoint(jointRef) JOINT_V3 = joint:toEuler() end end end if not JOINT_V3 then local joint = pose:getJoint(jointRef) JOINT_V3 = joint:toEuler() end -- joint modify controls if key(17) then JOINT_V3.x = (JOINT_V3.x + moveAmount)%range elseif key(1) then JOINT_V3.x = (JOINT_V3.x - moveAmount)%range end if key(23) then JOINT_V3.y = (JOINT_V3.y + moveAmount)%range elseif key(19) then JOINT_V3.y = (JOINT_V3.y - moveAmount)%range end if key(5) then JOINT_V3.z = (JOINT_V3.z + moveAmount)%range elseif key(4) then JOINT_V3.z = (JOINT_V3.z - moveAmount)%range end pose:setJoint(jointRef, R.Quaternion:newFromEuler(JOINT_V3.x, JOINT_V3.y, JOINT_V3.z)) if keyp(26) then -- zero JOINT_V3.x, JOINT_V3.y, JOINT_V3.z = 0, 0, 0 end local skeleton = ACTORS['left'].skeleton R.ApplyPoseToSkeleton(POSES[iPoseLeft + 1], skeleton) skeleton = ACTORS['right'].skeleton local iPoseRight = (iPoseLeft + 1) % #POSES R.ApplyPoseToSkeleton(POSES[iPoseRight + 1], skeleton) -- Tweening skeleton = ACTORS['tween'].skeleton local pose1, pose2 = iPoseLeft, iPoseRight local pose3, pose4 = iPoseLeft, iPoseRight if not isEditView then local mainViewTweenFrame = tweenTimeFloor%#POSES pose1 = mainViewTweenFrame pose2 = (mainViewTweenFrame + 1) % #POSES pose3 = (mainViewTweenFrame + 2) % #POSES pose4 = (mainViewTweenFrame + 3) % #POSES end --local poseTween = R.GetPoseTween(tweenPos, POSES[pose1 + 1], POSES[pose2 + 1]) local poseTween = R.GetPoseSlerp(tweenPos, POSES[pose1 + 1], POSES[pose2 + 1]) --local poseTween = getPoseCatmullRomInterpolate(tweenPos, POSES[pose1 + 1], POSES[pose2 + 1], POSES[pose3 + 1], POSES[pose4 + 1], 1) R.ApplyPoseToSkeleton(poseTween, skeleton) -- view controls if keyp(48) then -- switch view isEditView = not isEditView end if key(28) then ANIMSPEED = 1 end if key(29) then ANIMSPEED = 2 end if key(30) then ANIMSPEED = 4 end if key(31) then ANIMSPEED = 8 end if key(85) then rotY = (rotY - moveAmount)%mTau elseif key(83) then rotY = (rotY + moveAmount)%mTau end if key(81) then rotX = (rotX - moveAmount)%mTau elseif key(87) then rotX = (rotX + moveAmount)%mTau end if keyp(24) then trace("\n--- Export [start] ---\n") exportPoses() trace("--- Export [end] ---\n\n") end for _,actor in pairs(ACTORS) do actor:setRotation(R.Quaternion:newFromEuler(rotX,rotY,rotZ)) end for name,scene in pairs(SCENES) do scene:render(ENGINES[name]) end local xMid = 120 + ((((iSelectedPose - iPoseLeft) % #POSES) * 2) - 1) * 78 rectb(xMid-40,0, 80,windowHeight + 10, 3) printc("POSE " .. (iPoseLeft + 1), 120-windowWidth,windowHeight + 2, 13) printc("POSE " .. ((iPoseLeft + 1) % #POSES + 1), 120+windowWidth,windowHeight + 2, 13) local mainText if isEditView then mainText = string.format("TWEEN POSE %d>%d OF %d", pose1 + 1, pose2 + 1, #POSES) else mainText = string.format("ALL TWEEN %d>%d OF %d", pose1 + 1, pose2 + 1, #POSES) end printc(mainText, 120,0, 13) clip(0, 120, 240, 18) for i=1, #JOINT_REFS do local jointRef = JOINT_REFS[i] local jointID = jointRef[1] .. "-" .. jointRef[2] local c = iSelectedJoint == (i-1) and 2 or 14 print(jointID, 0, 118 + (i-iSelectedJoint) * 7, c, false, 1, true) end clip() print("UP/DOWN: joint C: copy\nLEFT+RIGHT: pose V: paste\nQ/A: X joint W/S: Y joint\nE/D: Z joint Z: zero", 0, 94, 15, true, 1, true) print(" NUMPAD 4/6 2/8: rotate\n SPACE: switch tweening\nINS/DEL: add/remove pose\nX: export 1-4 animspeed", 142, 94, 15, true, 1, true) print(jointRef[1] .. "-" .. jointRef[2], 110,122 ,12) print(JOINT_V3, 120,130, 13) end, cleanup=function() end, }) end rift_partsdancedab=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mSin,mAbs = math.pi,math.pi * 2, math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() setup2d.setVBankRGBs(1, setup2d.standardPalette) setup2d.setVBankRGBs(0, { [1]={40, 40, 120}, [2]={120, 120, 0}, [3]={160, 160, 120}, [4]={190, 190, 200}, }) R.setRGB(0,R.RGB:new(0,0,0)) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true for i, dancer in ipairs(stage3d.dancers) do dancer:setVisible(true) end if isCrazy then stage3d.billboard.isVisible = true end end local progress = pMetrics.progress for i, dancer in ipairs(stage3d.dancers) do local iAdj = (i-1)-1.5 local animT = progress * 16 + .75 local rX = 0---mSin(animT * mPi * .5 - mPi) local rY = 0 ---mSin(animT * mPi * .25 - mPi) local bump = 0 --mAbs(mSin(animT * mPi * .25 - mPi/2)) dancer:setPosition(R.V3:new(iAdj*15, bump*.8, 0)) dancer:setRotation(R.Quaternion:newFromEuler(rX *.1, mPi + iAdj*.6 + rY * .5, 0)) --animations.applyToSkeleton("rock", dancer, animT) animations.applyToSkeleton("dab", dancer, animT) end stage3d.cameraFG:setPosition(R.V3:new(0, 4, 30)) stage3d.cameraFG:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) -- local pos = dancers[lookAt].pos -- local cameraRot = R.Quaternion.lookAt(camera.pos, pos, camera.up) -- stage3d.cameraFG:setRotation(cameraRot) stage3d.clock:setPosition(R.V3:new(0, 15, -50)) local seconds = 8+progress * 8 fnsClock.setClock(stage3d.clock, seconds) stage3d.clock.skeleton:setJoint({"miFace","jCentre"}, R.Quaternion:newFromEuler(0, 0, seconds/60 * mTau)) stage3d.billboard:setPosition(R.V3:new(0, 0, -3.5 + mAbs(mSin(progress * mPi * 16)) * .5)) stage3d.billboard:setRotation(R.Quaternion:newFromEuler(0, 0, mSin(progress * mPi * 8)*.2)) letters.sceneClip() vbank(0) cls() stage3d.sceneBG:render(stage3d.engineBG) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdancekicksailor=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mSin,mAbs = math.pi,math.pi * 2, math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) setup2d.setVBankRGBs(0, { [2]={68,80,0}, [3]={168,80,0}, [4]={238,100,0}, [5]={168,80,0}, [6]={238,220,150}, }) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true for i, dancer in ipairs(stage3d.dancers) do dancer:setVisible(true) end if isCrazy then stage3d.billboard.isVisible = true end end local progress = pMetrics.progress for i, dancer in ipairs(stage3d.dancers) do local iAdj = (i-1)-1.5 local animT = progress * 24 + 1 local rX = 0---mSin(animT * mPi * .5 - mPi) local rY = -mSin(animT * mPi * .25 - mPi) local bump = mAbs(mSin(animT * mPi * .25 - mPi/2)) dancer:setPosition(R.V3:new(iAdj*15, bump*.8, 0)) dancer:setRotation(R.Quaternion:newFromEuler(rX *.1, mPi + iAdj*.6 + rY * .5, 0)) --animations.applyToSkeleton("rock", dancer, animT) animations.applyToSkeleton("kicksailor", dancer, animT) end stage3d.cameraFG:setPosition(R.V3:new(20-progress*20, 5, 40)) stage3d.cameraFG:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) -- local pos = dancers[lookAt].pos -- local cameraRot = R.Quaternion.lookAt(camera.pos, pos, camera.up) -- stage3d.cameraFG:setRotation(cameraRot) stage3d.clock:setPosition(R.V3:new(0, 15, -50)) local seconds = 8+progress * 8 fnsClock.setClock(stage3d.clock, seconds) stage3d.clock.skeleton:setJoint({"miFace","jCentre"}, R.Quaternion:newFromEuler(0, 0, seconds/60 * mTau)) stage3d.billboard:setPosition(R.V3:new(0, 0, -3.5 + mAbs(mSin(progress * mPi * 16)) * .5)) stage3d.billboard:setRotation(R.Quaternion:newFromEuler(0, 0, mSin(progress * mPi * 8)*.2)) letters.sceneClip() vbank(0) cls() stage3d.sceneBG:render(stage3d.engineBG) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_datagfxdrawclockface=function() local mTau = 2 * math.pi local mCos = math.cos local mSin = math.sin local function drawClock(xc, yc, r, isQuarter, isMono) local ro1=r - .5 local ro2=ro1-r*.05 local ro3=ro1-r*.10 local ro4=ro1-r*.15 local ro5=(ro1 * .8)//1 - .5 local ro6=(ro1 * .6)//1 - .5 local ri=(ro1 * .35)//1 - .5 local ad = .085 if isQuarter then clip(xc + .5, yc-ro1, ro1 + .5, ro1 + .5) end circ(xc, yc, ro1, 1) circ(xc, yc, ro2, 2) circ(xc, yc, ro3, 5) for i=0,59 do local a1 = .01 + (i / 60) * mTau local x1 = xc + ro3 * mSin(a1) local y1 = yc - ro3 * mCos(a1) local x2 = xc + ro3 * mSin(a1 + ad) local y2 = yc - ro3 * mCos(a1 + ad) local color = isMono and (i<22 and 1 or 5) or 8+(i % 8) tri(xc, yc, x1, y1, x2, y2, color) end circ(xc, yc, ri, 5) line(xc, yc - ro2 + .5, xc, yc + ro2, 2) line(xc + 1, yc - ro2 + .5, xc + 1, yc + ro2, 2) line(xc - ro2, yc-1, xc + ro2 - 1, yc-1, 2) line(xc - ro2, yc, xc + ro2 - 1, yc, 2) for i=0,59, 5 do if i % 5 == 0 and i%15 > 0 then local a = (i / 60) * mTau + .01 local ad2 = .025 local a1 = a - ad2 local a2 = a + ad2 local c1 = mCos(a1) local s1 = mSin(a1) local c2 = mCos(a2) local s2 = mSin(a2) local x1,y1 = xc + ro5 * s1, yc - ro5 * c1 local x2,y2 = xc + ro5 * s2, yc - ro5 * c2 local x3,y3 = xc + ro6 * s1, yc - ro6 * c1 local x4,y4 = xc + ro6 * s2, yc - ro6 * c2 tri(x1,y1, x2,y2, x3,y3, 2) tri(x2,y2, x3,y3, x4,y4, 2) end end clip() end local function drawQuarter(r) drawClock(0, r, r, true, false) end local drawFull = function(r) drawClock(r/2, r/2, r/2, false, true) end return { quarter=drawQuarter, full=drawFull, } end rift_codesetup3d=function() local N_DANCERS = 5 local N_LETTER_TILES = 60 local IS_INIT_DONE = false local light local engineFG local sceneFG local cameraFG local dancers = {} local clock local engineBG local sceneBG local billboard local lettersFG = {} return function(R) rift_gfxticmctile24()(R) rift_gfxvram()(R) local fnsFigure = rift_data3dfigure()(R) local fnsClock = rift_data3dclock()(R) local fnsBillboard = rift_data3dbillboard()(R) local fnsTile = rift_data3dtile()(R) local materialFlat = rift_datamaterialflat()(R) local materialFlatLitPalmap = rift_datamaterialflatlitpalmap()(R) local materialClockface = rift_datamaterialclockface()(R) local materialLetter = rift_datamaterialletter()(R) local materialMask = rift_datamaterialmask()(R) local gfxPatarty = rift_datagfxpatarty() local fnsDrawClockface = rift_datagfxdrawclockface() local gfxTileFont = rift_datagfxtilefont() local flow = rift_codeflow() local function init() isCrazy = flow.isCrazy() if not IS_INIT_DONE then cls() fnsDrawClockface.quarter(64) R.VRAM.screenToTiles(0,0, 8,8, 0,16, 4) cls() fnsDrawClockface.full(64) R.VRAM.screenToTiles(0,0, 8,8, 8,24, 4) cls() --cls() --tileFont.drawSource() --R.VRAM.screenToTiles(0,0, 10,16, 6,0, 4) dataToMem(rleUnpack(gfxTileFont.img), 32768+(0)*(64)+(1)*1024) --cls() -- dataToMem(rleUnpack(gfxClockface.img), 32768 + 64*7) dataToMem(rleUnpack(gfxPatarty.img), 32768+(9)*(64)+(16)*1024) cameraFG = R.Camera:new(R.V3:new(0,0,0), R.Quaternion:newFromEuler(0,0,0)) engineFG = R.Engine:new() engineFG.viewportYC = 116/2 sceneFG = R.Scene:new(cameraFG) light = R.V3:new(0,1,.25) light:normalize() engineFG:setMaterial("quadTexFace", materialMask.quad(0,0, 64,128,64,64, 2, {[1]=3, [2]=7, [3]=5, [4]=2} )) engineFG:setMaterial("triTexClockFace", materialClockface.tri(0,128,64,64, 5,4)) engineFG:setMaterial("triTexClockHand", R.Material.triTextured(0,0, 0,150,1,1)) engineFG:setMaterial("line", matLine) engineFG:setMaterial("quadTexLetterTile", materialLetter.quad(3,2,1)) local model = fnsFigure.makeModel("regular", .95, 1.05, 1, "quadTexFace") local modelID = engineFG:addModel(model) for i=1,N_DANCERS do local actor = sceneFG:newActor(modelID, R.V3:new(0,0,0), "miPelvis") dancers[#dancers+1] = actor end local model = fnsClock.makeModel(20) local modelID = engineFG:addModel(model) clock = sceneFG:newActor(modelID, R.V3:new(0,0,0), "miFace") cameraBG = R.Camera:new(R.V3:new(0,0,0), R.Quaternion:newFromEuler(0,0,0)) engineBG = R.Engine:new() engineBG.viewportYC = 116/2 sceneBG = R.Scene:new(cameraBG) light = R.V3:new(0,1,.25) light:normalize() engineBG:setMaterial("quadTexBillboard", R.Material.quadTextured(0,0, 64,128,64,64)) local model = fnsBillboard.makeModel(8,4, "quadTexBillboard") local modelID = engineBG:addModel(model) billboard = sceneBG:newActor(modelID, R.V3:new(0,0,0), "miBillboard") local model = fnsTile.makeModel(1,1, "quadTexLetterTile") local modelID = engineFG:addModel(model) for i=1,N_LETTER_TILES do lettersFG[#lettersFG+1] = sceneFG:newActor(modelID, R.V3:new(0,0,0), "miTile") end IS_INIT_DONE = true end -- Reset all positions... for i, dancer in ipairs(dancers) do dancer:setScale(R.V3:new(1, 1, 1)) dancer:setSkins({"default", "mask"}) dancer:setData({isPatarty=isCrazy}) dancer:setVisible(false) end for i, letter in ipairs(lettersFG) do letter:setVisible(false) end clock:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) clock.isVisible = false billboard:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) billboard.isVisible = false cameraFG:setPosition(R.V3:new(0,0,0)) cameraFG:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) cameraBG:setPosition(R.V3:new(0,0,0)) cameraBG:setRotation(R.Quaternion:newFromEuler(0, 0, 0)) return { engineFG=engineFG, sceneFG=sceneFG, cameraFG=cameraFG, dancers=dancers, clock=clock, engineBG=engineBG, sceneBG=sceneBG, cameraBG=cameraBG, billboard=billboard, lettersFG=lettersFG, } end function setStyle(style) if style == "flat" then engineFG:setMaterial("quad", materialFlat.quad()) elseif style == "flatlit-palmap" then engineFG:setMaterial("quad", materialFlatLitPalmap.quad(light, 9, 15)) else error("Unknown style: " .. tostring(style)) end end return { init=init, setStyle=setStyle, } end end rift_datagfxtilefont=function() --[[ local function drawSource() local nInRow = 4 -- Number of letters in a row local letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" for iLetter=1,#letters do local c = letters:sub(iLetter,iLetter) local i=iLetter-1 local x = (i%nInRow)*20 local y = (i//nInRow)*20 rect(x,y,19,19,2) local w=print(c,0,140,12,true,3) print(c,x+11-w/2,y+2,12,true,3) end end --]] local function getLetterUVs(letter) local l=string.byte(letter)-65 local lx,ly = l%6,l//6 local sx,sy = lx*20,ly*20+8 return sx,sy,sx+20,sy+19 end local function drawText(text,dx,dy) poke4(0x3FFC*2, 4) poke4(0x3FF0*2+0,1) poke4(0x3FF0*2+1,2) poke4(0x3FF0*2+2,3) for i=1,#text do local letter = text:sub(i,i) if letter == " " then dx = dx + 11 else local sx0,sy0,sx1,sy1 = getLetterUVs(letter) local w,h = 20,19 local dx0,dy0,dx1,dy1 = dx,dy,dx+w,dy+h ttri( dx0,dy0, dx1,dy0, dx0,dy1, sx0,sy0, sx1,sy0, sx0,sy1, 0, -1 ) ttri( dx1,dy0, dx1,dy1, dx0,dy1, sx1,sy0, sx1,sy1, sx0,sy1, 0, -1 ) dx = dx + 21 end end poke4(0x3FF0*2+0,0) poke4(0x3FF0*2+1,1) poke4(0x3FF0*2+2,2) poke4(0x3FFC*2, 2) end return { -- drawSource=drawSource, drawText=drawText, getLetterUVs=getLetterUVs, pal="07F80012AACDIJP6HHJKM0", img="08000200A19JKBA4KKCA4KKCA3EKKGA3IK2A3IK2A20IKKGA3IK2A3IK2A3IKEKA3IKAJA3IKEKA23CA5EGA5IKA5JGA5KCA4EKA15EKKBA3K2GA3K3A3KBEKA3GAAJA3CA22K2GA3K3GA2K4A2KCAJKBAAKCAEKCAAKCAAKGA20K2CA3K2CA3K2CA3KCA5KCA5KCA23K2A4K2A4K2A4KCA5KCA5KCA16CA6CA6CA33JKJKBA2KKIKCA2KGEKCAAEK3GAAIK4AAIK4AAJKBAJKAAKKAAIKA3IK2A3IK2A3IK2A3IKAJA3IKAEA3IKAJBA2IK2CA2IK2BA4EKGA4EKKA4EKKBA3EKKCA4KKBA4JKA5IGA5ECA6CA6CA6CA6GAAJA3KBEKA3K3A3K2GA3KCAAKGAAKCAAKGAAKCAAKGAAKCAAKGAAKCAEKCAAKCAJKBAAK4A2K3GA5K2CA3K2CA3K2CA3KCA5KCA5KCA5K2CA3K2CA5K2A4K2A4K2A4KCA5KCA5KCA5KCA5KCACA6CA6CA48KGAAEKA42EKKBA2EK2GACA2IKKGA43IKA5IKA49IKA5IKA5EKKBA43IKA5IKA5K2GA46IKA5IKA5K2CA42IKAIKCAAIKAJKBA4KCA45KCA5KCA66IK3BAAJKBEGA2KGAABAAEKCA4EKCAK2AEKCAK2AEKCAK2AEKCAAIKA3IKA5IKA5IKA5IKAABA2IK2BA2IK2BA2IK2BA2IKAAIKA5IKA5IKA5IKA5KKA5KKA5KKA5IKA5IKA5IKA5IKA5IKA5IKA5IKA5IKA5IKA8IKA5IKA5IKA5IKA5IKA5IKA5IKA5IKA4IKAKKA2IKEKGA2IKJKCA2IK2BA2IK2A3IKKGA3IK2A3IK2BA5KCA5KCA5KCA5KCA5KCA5KCA5KCA5KCA66KGAAJKAAJKBEKGAAIK3CAAEK3BA2EKKBA28IKA5IKA5IKA5IKA5IKA25IKA5IKA5IKA5IKA5IKA29IKA5IKA5IKA5IKA5IKA30BAJKA2EGEKGA2JK2CA2EK2BA3JKBA29IKJKCA2IKEKGA2IKAKKA2IKAJKBAAIKAIKCA28KCA5KCA5K2A4K2A4K2A39CA6CA6CA49KAAICA2KBAJCAAEKCAKGAAIKCAKKAAIKGEKKAAIKKIKKA19IKBA4IKCA4IKGA4IKKA4IKKBA3IKKCA15IKA4EIKA3EKIKA3IKIKA3JKIKA3KGIKA2EKCA15KKBA4K2BA3K2CA3BEKGA5JKA5IKBA18IKKGA3IK2GA2IK3A2IKAJKBAAIKAEKCAAIKAEKCA20EKKBA2EK3BAAIK3CAAJKBEKGAAKGAAJKAEKCAAIKA19IKKGA3IK2A3IK2A3IKAJA3IKAEBA2IKAEA23GA6KA6KBA5KCA5KCA7JKKJKKAAKKJKJKAAKKIKIKAAKKIKIKAAKKIKIKAEKKEGIKAIKGACEKAIKCACAKBA2IKKGCA2IKJKCA2IKIKCA2IKEKCA2IKAKGA2IKAJKA2IKAIKA2IKAEIKA2EKCIKA2EKCJKA2EKCKKA2EKCKKA3KGKKA3JK2A3IK2A3EKAAIKBA4IKBA4IKBA4IKBA4JKA3BEKGA3K2CA3K2BA3IKAJKBAAIK3A2IK2GA2IKKGA3IKA5IKA5IKA5IKA6EKCAAIKAEKCAAIKAEKCAAIKAEKCAKJKAAKGAKKGAAJKBJKCAAIK3GAAEK4BA2IKAJBA2IK2BA2IK2A3IK2A3IKJKA3IKEKA3IKAKA3IKAJKBA5KA6GA6BA6CA6GA6KA6KBA6IKCABAKA42EKKBA2EK2GAKA2IKA46K2A4K4A4EA39KCA3IKKCA3IK2BA46IKA5IKA3IKA45KGAAEKCAKKAAIKCA3EKGEKA40IKCABAKAIKCACAKA3IKAIA39KA2IKCAKA2EKGEKGA45KKA5KGA7JK3BAAKKBEGAAEKGAABAAEKKBA4K3BA2JK3BA2JK2CA4JKGA4K2A5IKA5IKA5IKA5IKA5IKA5IKA5IKKCA3IKA5IKA5IKA5IKA5IKA5IKA5IKA5IKAAIKA5IKA5IKA5IKA5IKA5IKA5IKA5IKA3JKAAIKBAIKBAJKAAIKCAKKAAEKCAKGA2KGEKCA2KKIKCA2JKJKBA2IK2A3IKGACEKAEKKEGIKAAKKIKIKAAKKIKIKAAKKIKIKAAKKJKJKAAJKKJKKAAIKKIK2A3KKIGA3JKJCA3IKKCA3EKKCA4KKCA4JKBA4KKA4EK2CA5KBA5KA6GA6CA6BA6CA6GA9BAEKGAAEGAJKCAAJK3BAAEK2GA3EKGA31IKA5IKA5IKA5IKA5IKA29IKA5EKA6KA6JA31BAJKA3GEKGA3K2CA3K2BA3JKBA29IK2A3EKKGA4KKCA4KKCA4JKBA28IKGEKKAAIKCAKKAAEKCAKGA2KBAJCA2KAAICA28IKKA4JKJA4KKIA3EKGEA3IKCA24KA6KBA5KCA5KGA5KKA47IKCAKKAAEKGEKGA2KKIKCA2JKJKBA2IK2A3EKKGA20IK2A3IK2A3IK2A6JA6KA5EKA15KKA5KGA5KCA5KBA5KA6GA330KKCA4JKBA4IKA5IKA5IKA5IKA5IKA5IKA7IKA5JKA5KKA4EKGA4IKCA4JKBA4K2A3EK2CA6BA38KKA5KKA329IKA61IK2A55KKA381", } end rift_3d2v3=function() return function(R) R=R or {} local V3 = {} local mSqrt = math.sqrt function V3:new(x,y,z) local o={ x=x,y=y,z=z } setmetatable(o,self) self.__index=self return o end function V3:__tostring() return string.format("V3(%.3f,%.3f,%.3f)",self.x,self.y,self.z) end function V3:set(x, y, z) self.x, self.y, self.z = x, y, z end function V3:length() return mSqrt(self.x*self.x + self.y*self.y + self.z*self.z) end function V3:scale(d) self.x,self.y,self.z = self.x*d,self.y*d,self.z*d end function V3.scaleV3(v, d) return V3:new(v.x*d, v.y*d, v.z*d) end function V3.scaleByV3(v1, v2) return V3:new(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z) end function V3:normalize() local len = self:length() if len == 0 then len = 0.001 end self:scale(1/len) end function V3.normalizeV3(v) local len = v:length() if len == 0 then len = 0.001 end return V3.scaleV3(v, 1/len) end function V3.__add(u, v) return V3:new(u.x+v.x, u.y+v.y, u.z+v.z) end function V3.__sub(u, v) return V3:new(u.x-v.x, u.y-v.y, u.z-v.z) end function V3.__mul(v, m) return V3:new(v.x*m, v.y*m, v.z*m) end function V3.__unm(v) return V3:new(-v.x, -v.y, -v.z) end function V3.cross(u,v) -- #TODO: not sure if local is optimal here local ux,uy,uz = u.x,u.y,u.z local vx,vy,vz = v.x,v.y,v.z return V3:new(uy*vz - uz*vy, uz*vx - ux*vz, ux*vy - uy*vx) end function V3.dot(u,v) return u.x*v.x + u.y*v.y + u.z*v.z end function V3.normal(v1,v2,v3) return R.V3.normalizeV3(V3.cross(v2 - v1, v3 - v2)) end R.V3 = V3 end end rift_3d2m44=function() return function(R) R=R or {} local M44 = {} -- local mSqrt = math.sqrt function M44:new(m00,m01,m02,m03, m10,m11,m12,m13, m20,m21,m22,m23, m30,m31,m32,m33) local o={ m00=m00,m01=m01,m02=m02,m03=m03, m10=m10,m11=m11,m12=m12,m13=m13, m20=m20,m21=m21,m22=m22,m23=m23, m30=m30,m31=m31,m32=m32,m33=m33 } setmetatable(o,self) self.__index=self return o end function M44.identity() return M44:new(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1) end function M44:__tostring() return string.format( "M44\n%.3f %.3f %.3f %.3f\n%.3f %.3f %.3f %.3f\n%.3f %.3f %.3f %.3f\n%.3f %.3f %.3f %.3f", self.m00,self.m01,self.m02,self.m03, self.m10,self.m11,self.m12,self.m13, self.m20,self.m21,self.m22,self.m23, self.m30,self.m31,self.m32,self.m33 ) end function M44:clone() return M44:new( self.m00,self.m01,self.m02,self.m03, self.m10,self.m11,self.m12,self.m13, self.m20,self.m21,self.m22,self.m23, self.m30,self.m31,self.m32,self.m33 ) end function M44.__add(u, v) return M44:new( u.m00+v.m00,u.m01+v.m01,u.m02+v.m02,u.m03+v.m03, u.m10+v.m10,u.m11+v.m11,u.m12+v.m12,u.m13+v.m13, u.m20+v.m20,u.m21+v.m21,u.m22+v.m22,u.m23+v.m23, u.m30+v.m30,u.m31+v.m31,u.m32+v.m32,u.m33+v.m33 ) end function M44.__sub(u, v) return M44:new( u.m00-v.m00,u.m01-v.m01,u.m02-v.m02,u.m03-v.m03, u.m10-v.m10,u.m11-v.m11,u.m12-v.m12,u.m13-v.m13, u.m20-v.m20,u.m21-v.m21,u.m22-v.m22,u.m23-v.m23, u.m30-v.m30,u.m31-v.m31,u.m32-v.m32,u.m33-v.m33 ) end -- Is this efficient? -- (or scale and then assign to metatable?) function M44:scale(n) self.m00,self.m01,self.m02,self.m03 = self.m00*n,self.m01*n,self.m02*n,self.m03*n self.m10,self.m11,self.m12,self.m13 = self.m10*n,self.m11*n,self.m12*n,self.m13*n self.m20,self.m21,self.m22,self.m23 = self.m20*n,self.m21*n,self.m22*n,self.m23*n self.m30,self.m31,self.m32,self.m33 = self.m30*n,self.m31*n,self.m32*n,self.m33*n end function M44.__mul(u, v) return M44:new( u.m00*v.m00+u.m01*v.m10+u.m02*v.m20+u.m03*v.m30, u.m00*v.m01+u.m01*v.m11+u.m02*v.m21+u.m03*v.m31, u.m00*v.m02+u.m01*v.m12+u.m02*v.m22+u.m03*v.m32, u.m00*v.m03+u.m01*v.m13+u.m02*v.m23+u.m03*v.m33, u.m10*v.m00+u.m11*v.m10+u.m12*v.m20+u.m13*v.m30, u.m10*v.m01+u.m11*v.m11+u.m12*v.m21+u.m13*v.m31, u.m10*v.m02+u.m11*v.m12+u.m12*v.m22+u.m13*v.m32, u.m10*v.m03+u.m11*v.m13+u.m12*v.m23+u.m13*v.m33, u.m20*v.m00+u.m21*v.m10+u.m22*v.m20+u.m23*v.m30, u.m20*v.m01+u.m21*v.m11+u.m22*v.m21+u.m23*v.m31, u.m20*v.m02+u.m21*v.m12+u.m22*v.m22+u.m23*v.m32, u.m20*v.m03+u.m21*v.m13+u.m22*v.m23+u.m23*v.m33, u.m30*v.m00+u.m31*v.m10+u.m32*v.m20+u.m33*v.m30, u.m30*v.m01+u.m31*v.m11+u.m32*v.m21+u.m33*v.m31, u.m30*v.m02+u.m31*v.m12+u.m32*v.m22+u.m33*v.m32, u.m30*v.m03+u.m31*v.m13+u.m32*v.m23+u.m33*v.m33 ) end function M44.transpose(m) return M44:new( m.m00,m.m10,m.m20,m.m30, m.m01,m.m11,m.m21,m.m31, m.m02,m.m12,m.m22,m.m32, m.m03,m.m13,m.m23,m.m33 ) end function M44.multiplyVec3(m44, vec3) local x,y,z = vec3.x,vec3.y,vec3.z return R.V3:new( x*m44.m00 + y*m44.m01 + z*m44.m02 + m44.m03, x*m44.m10 + y*m44.m11 + z*m44.m12 + m44.m13, x*m44.m20 + y*m44.m21 + z*m44.m22 + m44.m23 ) end function M44.rotateByQuaternion(m44, q) q = R.Quaternion.cloneNormalized(q) local x, y, z, w = q.x, q.y, q.z, q.w -- Get a temporary 3x3 rotation matrix from the quaternion local r00, r01, r02 = 1 - 2*y*y - 2*z*z, 2*x*y - 2*w*z, 2*x*z + 2*w*y local r10, r11, r12 = 2*x*y + 2*w*z, 1 - 2*x*x - 2*z*z, 2*y*z - 2*w*x local r20, r21, r22 = 2*x*z - 2*w*y, 2*y*z + 2*w*x, 1 - 2*x*x - 2*y*y return M44:new( m44.m00*r00 + m44.m01*r10 + m44.m02*r20, m44.m00*r01 + m44.m01*r11 + m44.m02*r21, m44.m00*r02 + m44.m01*r12 + m44.m02*r22, m44.m03, m44.m10*r00 + m44.m11*r10 + m44.m12*r20, m44.m10*r01 + m44.m11*r11 + m44.m12*r21, m44.m10*r02 + m44.m11*r12 + m44.m12*r22, m44.m13, m44.m20*r00 + m44.m21*r10 + m44.m22*r20, m44.m20*r01 + m44.m21*r11 + m44.m22*r21, m44.m20*r02 + m44.m21*r12 + m44.m22*r22, m44.m23, m44.m30, m44.m31, m44.m32, m44.m33 ) end function M44.lookAt(eye, target, up) local z = R.V3.normalizeV3(eye - target) local x = R.V3.normalizeV3(R.V3.cross(up, z)) local y = R.V3.cross(z, x) return M44:new( x.x, x.y, x.z, 0, y.x, y.y, y.z, 0, z.x, z.y, z.z, 0, -R.V3.dot(x, eye), -R.V3.dot(y, eye), -R.V3.dot(z, eye), 1 ) end R.M44 = M44 end end rift_sysmath=function() --- Helpers for Maths - clamps and easing -- @module sys.math return function(R) R=R or {} --- Clamp a value -- @param v A value -- @param min The lower bound -- @param max The upper bound R.clamp=function(v,min,max) return math.min(math.max(v,min),max) end --- Linear Interpolation bewteen two values -- @param t Time (0-1) -- @param v0 The value at T=0 -- @param v1 The value at T=1 R.lerp=function(t,v0,v1) return (1-t)*v0+t*v1 end --- Quadratic Bézier -- @param t Time (0-1) -- @param v0 The value at T=0 -- @param v1 The mid-value modifier -- @param v2 The value at T=1 R.qBezier=function(t,v0,v1,v2) local tInv=1-t return (tInv*tInv*v0)+(tInv*t*v1)+(t*t*v2) end --- Cubic Bézier -- @param t Time (0-1) -- @param v0 The value at T=0 -- @param v1 The first mid-value modifier -- @param v2 The second mid-value modifier -- @param v3 The value at T=1 R.cBezier=function(t,v0,v1,v2,v3) local tInv=1-t return (tInv*tInv*tInv*v0)+(3*tInv*tInv*t*v1)+(3*tInv*t*t*v2)+(t*t*t*v3) end --- Smoothstep Easing function -- @param t Time (0-1) -- @param e0 The value at T=0 -- @param e1 The value at T=1 R.smoothStep=function(t,e0,e1) local s = (t-e0)/(e1-e0) local x = R.clamp(s,0,1) return e0 + (x * x * (3.0 - 2.0 * x))*(e1-e0) end --- Smootherstep Easing function -- @param t Time (0-1) -- @param e0 The value at T=0 -- @param e1 The value at T=1 R.smootherStep=function(t,e0,e1) local s = (t-e0)/(e1-e0) local x = R.clamp(s,0,1) return e0 + (x * x * x * (3.0 * x * (2.0 * x - 5.0) + 10.0))*(e1-e0) end end end rift_codeflow=function() IS_CRAZY = false local function goCrazy() IS_CRAZY = true end local function isCrazy() return IS_CRAZY end return { goCrazy=goCrazy, isCrazy=isCrazy, } end rift_partsdanceballet=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then clip() vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress local danceT = progress * 8 local rotX = 0 if isCrazy then rotX = mCos(progress * mTau * 2) * 0.5 end local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, -25 + progress * 10)) dancer:setRotation(R.Quaternion:newFromEuler(rotX, -progress * mTau * 2, 0)) animations.applyToSkeleton("ballet-twirl", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, -45 - progress * 10)) dancer:setRotation(R.Quaternion:newFromEuler(rotX, -progress * mTau * 2, 0)) animations.applyToSkeleton("ballet-twirl", dancer, danceT) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(10 + progress * 10, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(rotX, progress * mTau * 2, 0)) animations.applyToSkeleton("ballet-twirl", dancer, danceT) local dancer = stage3d.dancers[4] dancer.isVisible = true dancer:setPosition(R.V3:new(-10 - progress * 10, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(rotX, progress * mTau * 2, 0)) animations.applyToSkeleton("ballet-twirl", dancer, danceT) stage3d.cameraFG:setPosition(R.V3:new(0, 10+progress*20, 20-progress * 20)) local pos = R.V3:new(0, 0, -35) local cameraUp = R.V3:new(0, 1, 0) local cameraRot = R.Quaternion.lookAt(stage3d.cameraFG.pos, pos, cameraUp) stage3d.cameraFG:setRotation(cameraRot) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_sysrgb=function() --- Helpers for RGB colour -- @module sys.rgb return function(R) R=R or {} R.RGB={} --- Create a new RGB object -- @tparam number r 0-1 -- @tparam number g 0-1 -- @tparam number b 0-1 function R.RGB:new(r,g,b) local o={r=r,g=g,b=b} setmetatable(o,self) self.__index=self return o end --- Create a new RGB object by blending between to other RGB objects -- @param toRgb The RGB object to blend to -- @tparam number t (0 is all of self) -> (1 is all of toRgb) -- @return A new RGB object function R.RGB:getBlendTo(toRgb,t) local tInv=1-t return R.RGB:new( self.r*tInv+toRgb.r*t, self.g*tInv+toRgb.g*t, self.b*tInv+toRgb.b*t ) end --- Sets a colour in the TIC palette -- @tparam int i index (0-15) -- @param rgb An RGB object R.setRGB=function(i,rgb) local a=0x3FC0+i*3 poke(a,(rgb.r*255)//1) poke(a+1,(rgb.g*255)//1) poke(a+2,(rgb.b*255)//1) end }¯ --- Gets a colour from the TIC palette -- Useful for finding the current colour to blend from -- @tparam int i index (0-15) -- @return An RGB object R.getRGB=function(i) local a=0x3FC0+i*3 return R.RGB:new( peek(a)/255, peek(a+1)/255, peek(a+2)/255 ) end R.setColour=function(i,r,g,b) local a=16320 + i * 3 poke(a,r) poke(a+1,g) poke(a+2,b) end end end rift_gfxticmctile24=function() --- Functions to handle TicMcTile data -- @module gfx.TicMcTile -- @author Decca, Mantratronic, jtruk return function(R) R=R or {} local toNum = tonumber -- data is a string -- addr is either taken from the string or provided as a parameter function dataToMem(data, addr) local o = addr or toNum(data:sub(1,5),16) -- get (o)ffset, from param or string local w = toNum(data:sub(6,8),16)-1 -- get (w)idth local d = data:sub(9,data:len()) -- remove header to get (d)ata local y = 0 for x = 1,#d,1 do -- write to mem local c = toNum(d:sub(x,x),16) -- get (c)olor value poke4(o+y,c) y = y + 1 if y > w then y = 0 o = o + 1024 end end end -- the rle-decoder function rleUnpack(data) local r = data:sub(1,5) -- get (o)ffset into (r)aw data local r = r .. data:sub(6,8) -- get (w)idth into (r)aw data local e = data:sub(9,data:len()) -- remove header to get (e)ncoded data local d = "" -- (d)ecoded data for m, c in e:gmatch("(%u+)([^%u]+)") do -- decode rle, (m)atch & (c)ounter d = d .. m .. (m:sub(-1):rep(c)) -- (d)ecoded data end for x = 1,#d,1 do -- get (d)ecoded data into (r)aw data r = r .. string.format("%x",(string.byte(d:sub(x,x))-65)) end return r end R.TicMcTile = TicMcTile end end rift_3d2quaternion=function() return function(R) R=R or {} local Quaternion = {} local mAbs,mSqrt,mSin,mCos,mPi,mAtan2,mAsin,mAcos = math.abs,math.sqrt,math.sin,math.cos,math.pi,math.atan2,math.asin,math.acos -- References: -- https://imadr.me/rotations-with-quaternions/ -- https://github.com/topameng/CsToLua -- https://carbon-for-lua.readthedocs.io/en/stable/Classes/Math.Quaternion/ function Quaternion:new(x,y,z,w) local o={ x=x,y=y,z=z,w=w, } setmetatable(o,self) self.__index=self return o end function Quaternion:__tostring() return string.format("Q(%.3f,%.3f,%.3f->%.3f)",self.x,self.y,self.z,self.w) end function Quaternion.identity() return Quaternion:new(0,0,0,1) end -- axis is type v3 --[[ function Quaternion:newFromAxisAngle(v3, angle) local halfAngle = angle / 2 local sinHalfA = mSin(halfAngle) return Quaternion:new( v3.x * sinHalfA, v3.y * sinHalfA, v3.z * sinHalfA, mCos(halfAngle) ) end --]] -- NB quaternions are not normalised function Quaternion:newFromEuler(rx, ry, rz) local rxh, ryh, rzh = rx / 2, ry / 2, rz / 2 local cx,cy,cz, sx,sy,sz = mCos(rxh), mCos(ryh), mCos(rzh), mSin(rxh), mSin(ryh), mSin(rzh) return Quaternion:new( sx * cy * cz - cx * sy * sz, cx * sy * cz + sx * cy * sz, cx * cy * sz - sx * sy * cz, cx * cy * cz + sx * sy * sz ) end function Quaternion:newFromM44(m) local q = {} local trace = m.m00 + m.m11 + m.m22 if trace > 0 then local s = mSqrt(trace + 1.0) * 2 q.w = 0.25 * s q.x = (m.m21 - m.m12) / s q.y = (m.m02 - m.m20) / s q.z = (m.m10 - m.m01) / s elseif m.m00 > m.m11 and m.m00 > m.m22 then local s = mSqrt(1.0 + m.m00 - m.m11 - m.m22) * 2 q.w = (m.m21 - m.m12) / s q.x = 0.25 * s q.y = (m.m01 + m.m10) / s q.z = (m.m02 + m.m20) / s elseif m.m11 > m.m22 then local s = mSqrt(1.0 + m.m11 - m.m00 - m.m22) * 2 q.w = (m.m02 - m.m20) / s q.x = (m.m01 + m.m10) / s q.y = 0.25 * s q.z = (m.m12 + m.m21) / s else local s = mSqrt(1.0 + m.m22 - m.m00 - m.m11) * 2 q.w = (m.m10 - m.m01) / s q.x = (m.m02 + m.m20) / s q.y = (m.m12 + m.m21) / s q.z = 0.25 * s end return Quaternion:new(q.x, q.y, q.z, q.w) end function Quaternion:clone() return Quaternion:new(self.x,self.y,self.z,self.w) end function Quaternion:assign(x,y,z,w) self.x,self.y,self.z,self.w = x,y,z,w end function Quaternion.length(q) return mSqrt(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w) end function Quaternion.imaginaryLength(q) return mSqrt(q.x*q.x + q.y*q.y + q.z*sqelf.z) end function Quaternion.cloneNormalized(q) local l = Quaternion.length(q) if l == 0 then return Quaternion:new(0,0,0,0) end return Quaternion:new(q.x/l,q.y/l,q.z/l,q.w/l) end function Quaternion:normalize() local l = Quaternion.length(self) if l == 0 then self.x,self.y,self.z,self.w = 0,0,0,0 end self.x,self.y,self.z,self.w = self.x/l,self.y/l,self.z/l,self.w/l end function Quaternion:scale(s) self.x,self.y,self.z,self.w = self.x*s,self.y*s,self.z*s,self.w*s end function Quaternion:invert() self.x,self.y,self.z,self.w = -self.x,-self.y,-self.z,self.w end -- aka conjugate function Quaternion:cloneInvert() return Quaternion:new(-self.x,-self.y,-self.z,self.w) end function Quaternion.multiply(q1, q2) local q1x,q1y,q1z,q1w,q2x,q2y,q2z,q2w = q1.x,q1.y,q1.z,q1.w,q2.x,q2.y,q2.z,q2.w return Quaternion:new( q1w*q2x + q1x*q2w + q1y*q2z - q1z*q2y, q1w*q2y - q1x*q2z + q1y*q2w + q1z*q2x, q1w*q2z + q1x*q2y - q1y*q2x + q1z*q2w, q1w*q2w - q1x*q2x - q1y*q2y - q1z*q2z ) end function Quaternion.rotateV3(q, v3) local v = Quaternion.multiply( Quaternion.multiply(q, Quaternion:new(v3.x,v3.y,v3.z,0)), q:cloneInvert() ) return R.V3:new(v.x,v.y,v.z) end function Quaternion.dot(q1, q2) return q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w end function Quaternion.lerp(q1, q2, t) if(Quaternion.dot(q1, q2) < 0) then q2 = -q2 end return Quaternion.cloneNormalized(Quaternion:new( q1.x + t*(q2.x - q1.x), q1.y + t*(q2.y - q1.y), q1.z + t*(q2.z - q1.z), q1.w + t*(q2.w - q1.w) )) end function Quaternion:toEuler() local x,y,z,w = self.x, self.y, self.z, self.w local sinp = 2 * (w * y - x * z) local yaw if mAbs(sinp) >= 1 then -- Clamp for out-of-range values (gimbal lock) yaw = mPi / 2 * (sinp >= 0 and 1 or -1) else yaw = mAsin(sinp) end return R.V3:new( mAtan2( 2 * (w * x + y * z), 1 - 2 * (x * x + y * y) ), yaw, mAtan2( 2 * (w * z + x * y), 1 - 2 * (y * y + z * z) ) ) end function Quaternion.Slerp(t, q1, q2) local dot = Quaternion.dot(q1, q2) -- Clamp dot to avoid acos domain errors if dot < 0.0 then q2 = -q2 -- Reverse one quaternion to take shortest path dot = -dot end if dot > 0.9995 then -- Quaternions are nearly identical, use linear interpolation local q = Quaternion:new( q1.x + t*(q2.x - q1.x), q1.y + t*(q2.y - q1.y), q1.z + t*(q2.z - q1.z), q1.w + t*(q2.w - q1.w) ) q:normalize() return q end local theta_0 = mAcos(dot) -- angle between input vectors local theta = theta_0 * t -- angle at time t local sin_theta = mSin(theta) local sin_theta_0 = mSin(theta_0) local s0 = mCos(theta) - dot * sin_theta / sin_theta_0 local s1 = sin_theta / sin_theta_0 return Quaternion:new( s0*q1.x + s1*q2.x, s0*q1.y + s1*q2.y, s0*q1.z + s1*q2.z, s0*q1.w + s1*q2.w ) end Quaternion.__unm = function(q) q.x, q.y, q.z, q.w = -q.x, -q.y, -q.z, -q.w return q end Quaternion.__eq = function(a,b) return Quaternion.dot(a, b) > 0.999999 end Quaternion.lookAt = function(from, to, up) return Quaternion:newFromM44(R.M44.lookAt(from, to, up)) end R.Quaternion = Quaternion end end rift_datamaterialclockface=function() return function(R2) local mapHatch4 = rift_datapalettemaphatch4()(R) local mMin, mMax, mRandom = math.min, math.max, math.random -- function generator... -- we can change lightVec after it has been sent in here (ensure it is normalised) -- Ensure you reset palette map after local function materialTri(texX0,texY0,texW,texH,ciDark,ciLight) return R2.Material:new():setFnTransform(function(d, psView, psWorld, actorData) return { pv1 = psView[d.v1], pv2=psView[d.v2], pv3=psView[d.v3], t1 = d.t1, t2 = d.t2, t3 = d.t3, seconds = actorData and actorData.seconds or 0, secondsOffset = d.secondsOffset, flipped = d.flipped, } end):setFnDraw(function(d) local pv1,pv2,pv3 = d.pv1,d.pv2,d.pv3 local brightUntil = math.min(math.max((d.seconds - d.secondsOffset),0),8) local a = 0x3ff0*2 if d.flipped then for i=0,7 do poke4(a+15-i,i .5 then stage3d.clock.isVisible = true end setup2d.fadeScene(progress, .2, .9) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) end, cleanup=function() end, }) end rift_data3dclock=function() return function(R) local mPi,mTau,mSin,mCos = math.pi, math.pi * 2, math.sin, math.cos -- style: "regular", "outline" local function makeMeshTemplateFace(radius) local mesh=R.Mesh:new() mesh:addVertex(nil, R.V3:new(0,0,0)) local v2s = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}} for _,v in pairs(v2s) do mesh:addVertex(nil, -R.V3:new(v[1]*radius, v[2]*radius, 0)) end for i=0,#v2s do local p2,p3 = i%#v2s, (i+1)%#v2s local flipped = false if i%2==1 then p2,p3 = p3,p2 flipped = true end local secondsOffset = (i*7.5)//1 mesh:addRenderable("triTexClockFace", { v1=1,v2=2+p2,v3=2+p3, t1={x=0,y=1},t2={x=0,y=0},t3={x=1,y=0}, flipped=flipped, secondsOffset=secondsOffset, }) end -- hand attachment point mesh:addVertex("jCentre", R.V3:new(0,0,.01)) return mesh end local function makeMeshTemplateHand(radius) local mesh=R.Mesh:new() mesh:addVertex(nil, R.V3:new(0,-radius,0)) mesh:addVertex(nil, R.V3:new(-.1*radius,0,0)) mesh:addVertex(nil, R.V3:new(.1*radius,0,0)) mesh:addRenderable("triTexClockHand", { v1=1,v2=2,v3=3, t1={x=0,y=0},t2={x=1,y=0},t3={x=0,y=1} }) local iVertexCentre = mesh:addVertex(nil, R.V3:new(0,0,0)) local nSides=12 local iVertex for i=0,nSides do local a = (i/nSides) * mTau local x = mSin(a) * radius * .15 local y = -mCos(a) * radius * .15 iVertex = mesh:addVertex(nil, R.V3:new(x,y,0)) --[[ mesh:addRenderable("triTexClockHand", { v1=iVertexCentre,v2=iVertex-1,v3=iVertex, t1={x=0,y=0},t2={x=1,y=0},t3={x=0,y=1} }) --]] end return mesh end -- style: nil, outline local function makeModelClock(radius) local model=R.Model:new() model:addMeshTemplate("mtFace",makeMeshTemplateFace(radius)) model:addMeshTemplate("mtHand", makeMeshTemplateHand(radius*.9)) model:addMeshInstance("miFace",nil,"mtFace",R.Quaternion:newFromEuler(0,0,0)) model:addMeshInstance("miHand",{"miFace","jCentre"},"mtHand",R.Quaternion:newFromEuler(0,0,mPi)) return model end local function setClock(clock, seconds) clock:setData({seconds=seconds//1}) clock.skeleton:setJoint({"miFace","jCentre"}, R.Quaternion:newFromEuler(0, 0, seconds/60 * mTau)) end return { makeModel=makeModelClock, setClock=setClock, } end end rift_3d2pose=function() return function(R) R=R or {} rift_sysmath()(R) local Pose={} local mAbs,mPi,mPiHalf,mTau = math.abs, math.pi, math.pi/2,math.pi*2 function Pose:new() local o={ -- indexed as joints[meshID][jointID] joints={}, } setmetatable(o,self) self.__index=self return o end function Pose:setJoint(jointRef, quaternion) local meshID, jointID = jointRef[1], jointRef[2] if self.joints[meshID] == nil then self.joints[meshID] = {[jointID] = quaternion} else self.joints[meshID][jointID] = quaternion end end function Pose:getJoint(jointRef) local meshID, jointID = jointRef[1], jointRef[2] return self.joints[meshID][jointID] end function Pose:clone() local pose = Pose:new() for meshID, joints in pairs(self.joints) do pose.joints[meshID] = {} for jointID, quaternion in pairs(joints) do pose.joints[meshID][jointID] = quaternion:clone() end end return pose end function applyPoseToSkeleton(pose, skeleton) for meshID, joints in pairs(pose.joints) do for jointID, quaternion in pairs(joints) do skeleton:setJoint({meshID, jointID}, quaternion) end end end function getPoseTween(progress, pose1, pose2) local tween = Pose:new() -- NB this is using mesh1 as an index. We might want to see what's missing from mesh2 -> mesh1? for meshID, meshJoints1 in pairs(pose1.joints) do local meshJoints2 = pose2.joints[meshID] if meshJoints2 ~= nil then tween.joints[meshID] = {} for jointID, quaternion1 in pairs(meshJoints1) do local quaternion2 = meshJoints2[jointID] if quaternion2 ~= nil then tween.joints[meshID][jointID] = R.Quaternion.lerp(quaternion1, quaternion2, progress) end end end end return tween end -- returns a modification of v that is the shortest path from vbase to v local function shortestEuler(vbase, v) local diff = v - vbase -- trace(diff) if (diff.x % mTau) >= mPi then v.x = v.x + mPi end if diff.y % mTau > mPi then --v.y = v.y - mPi end if diff.z % mTau > mPi then --v.z = v.z - mPi end return v end function getPoseCatmullRomInterpolate(progress, pose1, pose2, pose3, pose4, tension) local tween = Pose:new() local term0,term1,term2,term3 = R.catmullRomGetTerms(progress, tension) -- Use pose1 as the joint index - all poses should have the same mesh-joint structure for meshID, meshJoints1 in pairs(pose1.joints) do local meshJoints2 = pose2.joints[meshID] local meshJoints3 = pose3.joints[meshID] local meshJoints4 = pose4.joints[meshID] tween.joints[meshID] = {} for jointID, q0 in pairs(meshJoints1) do local q1 = meshJoints2[jointID] local q2 = meshJoints3[jointID] local q3 = meshJoints4[jointID] -- YUCK... We shouldn't be switching between quaternion and Euler angles like this local v0 = q0:toEuler() local v1 = q1:toEuler() local v2 = q2:toEuler() local v3 = q3:toEuler() --local v1 = q1:toEuler() --local v2 = q2:toEuler() --local v3 = q3:toEuler() tween.joints[meshID][jointID] = R.Quaternion:newFromEuler( v0.x * term0 + v1.x * term1 + v2.x * term2 + v3.x * term3, v0.y * term0 + v1.y * term1 + v2.y * term2 + v3.y * term3, v0.z * term0 + v1.z * term1 + v2.z * term2 + v3.z * term3 ) end end return tween end function getPoseSlerp(progress, pose1, pose2) local tween = Pose:new() -- Use pose1 as the joint index - all poses should have the same mesh-joint structure for meshID, meshJoints1 in pairs(pose1.joints) do local meshJoints2 = pose2.joints[meshID] tween.joints[meshID] = {} for jointID, q1 in pairs(meshJoints1) do local q2 = meshJoints2[jointID] tween.joints[meshID][jointID] = R.Quaternion.Slerp(progress, q1, q2) end end return tween end R.Pose = Pose R.ApplyPoseToSkeleton = applyPoseToSkeleton R.GetPoseTween = getPoseTween R.GetPoseCatmullRomInterpolate = getPoseCatmullRomInterpolate R.GetPoseSlerp = getPoseSlerp end end rift_3d2scene=function() return function(R) R=R or {} rift_3d2camera()(R) local Scene={} function Scene:new(camera) local o={ actors={}, camera=camera, -- lights={}, } setmetatable(o,self) self.__index=self return o end function Scene:newActor(...) local actor=R.Actor:new(...) self.actors[#self.actors+1]=actor return actor end function Scene:render(engine) local renderlist = {} for _, actor in pairs(self.actors) do actor:addToRenderlist(engine, self, renderlist) end -- rough sorting (better just using ttri's zbuffer if possible) table.sort(renderlist, function(a,b) return a.material.order < b.material.order end) for _, r in pairs(renderlist) do r.material.fnDraw(r.data) end end function Scene:setCamera(camera) self.camera = camera end R.Scene = Scene end end rift_demorunner=function() --- Functions to control demo timing and coordinate parts -- @module demo.demorunner -- @author jtruk return function(R) R=R or {} rift_soundmusic()(R) rift_sysmath()(R) R.DemoRunner={} --- Create a new DemoRunner object. function R.DemoRunner:new() local o={ isShowDebug=false, parts={}, currentPart=nil, isPartFirstRun=true, prevMusicFrame=0, cuedMusic=nil, musicFrames=0, prevFrameBDRms=nil, } setmetatable(o,self) self.__index=self return o end --- Add a demo part that runs for a number of tics. -- @tparam DemoPart part -- @tparam ?int tics (default=100) function R.DemoRunner:addPartTics(part, tics) tics=tics or 100 self.parts[#self.parts+1]={type='tics',part=part,tics=tics} end --- Add a demo part that runs for [frames] music frames. -- @tparam DemoPart part -- @tparam int frames (default=1) function R.DemoRunner:addPartMusic(part, frames) frames=frames or 1 self.parts[#self.parts+1]={type='music',part=part,frames=frames} end --- Cue a track to start. -- @tparam int track function R.DemoRunner:addCueMusic(track, frame) frame = frame or -1 self.parts[#self.parts+1]={type='cue-music',track=track,frame=frame} end --- Cue a track to stop at this point. function R.DemoRunner:addStopMusic() self.parts[#self.parts+1]={type='stop-music'} end --- Cue a track to stop at this point. function R.DemoRunner:addFnCallback(fn) self.parts[#self.parts+1]={type='callback',fn=fn} end --- Switch the debug display on or off. -- @tparam bool flag function R.DemoRunner:setShowDebug(flag) self.isShowDebug=flag end --- Run the demorunner (call this once per tic). -- @treturn value isExit - currently always returns non-false. true for natural exit, or exitSignal if supplied by a part. function R.DemoRunner:run() if self.currentPart==nil then -- do preboots... for i=1,#self.parts do local part=self.parts[i] -- yuk if part.part and part.part.preboot then part.part.preboot() end end self.currentPart=1 end -- Repeat over the non-frame ending operations. -- Also manage exiting. repeat local partDef = self.parts[self.currentPart] local partHasEnded, exitRunnerSignal = self:doCurrentPart(partDef) -- cleanup... if partHasEnded or exitRunnerSignal then if partDef.part and partDef.part.cleanup then partDef.part.cleanup() end end if exitRunnerSignal then return exitRunnerSignal end if partHasEnded then self.currentPart = self.currentPart+1 if self.currentPart > #self.parts then return true end self.isPartFirstRun = true end until(true) end --- Run the demorunner (call this once per tic). -- @local -- @tparam DemoPart partDef -- @treturn {partHasEnded, exitRunnerSignal} -- -- partHasEnded -> Natural end to this part - move on to next demopart. -- exitRunnerSignal -> non-false if we should end the demorunner. If it's false then keep running through demoparts as normal. function R.DemoRunner:doCurrentPart(partDef) if partDef.type=='cue-music' then self.cuedMusic={track=partDef.track,frame=partDef.frame} return true,false elseif partDef.type=='stop-music' then music() return true,false elseif partDef.type=='callback' then partDef.fn() return true,false end local part=partDef.part local partMetrics={ isFirstRun=self.isPartFirstRun, isLastRun=false, progress=0, musFrameProgress=nil, } partMetrics.ticsTotal=R.getTics() if partMetrics.isFirstRun then self.startTics=partMetrics.ticsTotal self.musicFrames=0 end partMetrics.tics=partMetrics.ticsTotal-self.startTics local musPos=R.music.getPos() local musMeta=R.music.getTrackMeta(musPos.track) local isEndOfPart=false if partMetrics.isFirstRun and self.cuedMusic then music(self.cuedMusic.track,self.cuedMusic.frame) musPos.pattern=self.cuedMusic.frame self.prevMusicFrame=self.cuedMusic.frame self.cuedMusic=nil end if partDef.type == 'tics' then partMetrics.progress = partMetrics.tics/partDef.tics partMetrics.isLastRun = partMetrics.progress>=1 elseif partDef.type == 'music' then -- #TODO: This won't work if we're jumping music frames if musPos.pattern ~= self.prevMusicFrame then self.musicFrames = self.musicFrames+1 partMetrics.isLastRun = self.musicFrames>=partDef.frames end local elapsed = partMetrics.tics/60 local rowsDone = elapsed*musMeta.rowsPerSec local frames, frameProgress=math.modf(rowsDone / musMeta.rows) partMetrics.musFrameProgress=frames+frameProgress -- This is the actual music progress: -- #TODO~: Sync if this falls behind? -- partMetrics.musFrameProgress=self.musicFrames+musPos.row/64 partMetrics.progress = partMetrics.musFrameProgress / partDef.frames self.prevMusicFrame=musPos.pattern end partMetrics.progress = R.clamp(partMetrics.progress,0,1) local ts=time() -- Return non-false from a tic() to end this part. Return anything other than true to end the entire runner loop, for an abort or secret part :) local exitRunnerSignal = part.tic(partMetrics) local elapsed = time()-ts -- This means extra function calls when debugging on each scanline, which is suboptimal! if not part.bdr then self.prevFrameBDRms=nil BDR=nil elseif self.isShowDebug==false then -- run as optimally as possible... BDR=function(y) part.bdr(y,partMetrics) end else -- NB The palette switch sets vbank to 1 behind the user's back - not ideal -- But I don't think we have access to the current vbank id to reset it -- Assume vbank=0 is desirable for exit -- #TODO: Maybe wrap vbank() call to track it? local stashPal={} local debugPal={64,64,64,255,255,255,255,64,128} BDR=function(y) if y==0 then ts=time() end if y==140 then -- Unstash palette (see stashing below) for i=1,#stashPal do poke(0x3fc0+i+2,stashPal[i]) end end part.bdr(y,partMetrics) -- Switch to alternate palette for rendering the debug info... if y>=132 and y<=139 then vbank(1) if y==132 then -- stash palette for i=1,#debugPal do stashPal[i]=peek(0x3fc0+i+2) end end for i=1,#debugPal do poke(0x3fc0+i+2,debugPal[i]) end end if y==143 then -- Final BDR line - get frame time self.prevFrameBDRms=time()-ts end end end self.isPartFirstRun=false if self.isShowDebug then vbank(1) rect(0,128,240,136,1) rect(0,128,partMetrics.progress*240,136,3) print(string.format("T:%.1f", R.getTimeMS()/1000),2,129,2,true) print(string.format("TIC:%d", R.getTics()),50,129,2,true) -- NB: This is the previous frame's BDR time! local prevFrameBDRms=(self.prevFrameBDRms==nil) and 0 or self.prevFrameBDRms local allTime=elapsed+prevFrameBDRms print(string.format("FR:%2d(%2d/%2d)", allTime//1, elapsed//1, prevFrameBDRms//1),100,129,2,true) local musText=musPos.track==255 and "M: (none)" or string.format("M:%02d-%02d-%02d", musPos.track, musPos.pattern, musPos.row) print(musText,180,129,2,true) local doTimeBar=function(x,h) local ySt=127-h line(x,ySt,x,127,1) rect(x+1,ySt,10,h+1,8) line(x+11,ySt,x+11,127,15) end doTimeBar(20*6,allTime) doTimeBar(23*6,elapsed) doTimeBar(26*6,prevFrameBDRms) end return partMetrics.isLastRun, exitRunnerSignal end end end rift_partscredits=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local tileFont = rift_datagfxtilefont() local stage3d local mSin = math.sin local mMin, mMax = math.min, math.max return R.DemoPart:new({ bdr=setup2d.bdrNoConundrum, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() clip() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() end local progress = pMetrics.progress vbank(1) cls() local iFreeLetter = 1 iFreeLetter = letters.setTextActors("MINIBRUTE", R.V3:new(0,1.5,-7), stage3d.lettersFG, iFreeLetter) iLastLetterMibri = iFreeLetter - 1 iFreeLetter = letters.setTextActors("CONEDFACT", R.V3:new(0,0,-7), stage3d.lettersFG, iFreeLetter) iLastLetterDecca = iFreeLetter - 1 iFreeLetter = letters.setTextActors("DUCTJOKER", R.V3:new(0,-1.5,-7), stage3d.lettersFG, iFreeLetter) iLastLetterJtruk = iFreeLetter - 1 letters.rotLetters(stage3d.lettersFG, 1, iLastLetterMibri, progress, .1, .4, "TUNEMIBRI") letters.rotLetters(stage3d.lettersFG, iLastLetterMibri+1, iLastLetterDecca, progress, .2, .5, "FONTDECCA") letters.rotLetters(stage3d.lettersFG, iLastLetterDecca+1, iLastLetterJtruk, progress, .3, .6, "CODEJTRUK") stage3d.cameraFG:setPosition(R.V3:new(0, 2 - progress, 4 - progress * 5)) local cameraRot = R.Quaternion:newFromEuler(.2,0,-.4 + progress * .4) stage3d.cameraFG:setRotation(cameraRot) setup2d.fadeScene(progress, .2, .8) vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) end, cleanup=function() end, }) end rift_datagfxclockface=function() return { pal="07F80060KBMBMCNFHCNFBLODDFPONHHFPPNMFHHKAPAHIDHLEGFCBHJHJCGDPGLDNFJMBEGKGPDHPOHPEPEPEPEJALCMGFMGGIDDMDHF0", img="08000400A19B3A3C3A3CD2A3CF2A3CF2A3CF2A15BBA5CCDBBDBBDDC5FFDFH2DFFDFH3FFDH4A23BA6CBDB2AADC4DBHDHHGECCFDH4DA39BA6CDBBA3C3B2A772CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF4DH4FFDH4FFDH4FFDH4F2H3F3H3F3H3DFDFH3DFDH4DDGH4DDH5DDH4GEDH4DGGH4DGGH3GEGH4DGGEGEC2DBG4ECCG5DCG4EDEG4DEEG4DEEG3DE2G3DE2BA6CBBA4C2BBA2EEC2BBAE3CCDBE3DC2E2DDC2E2DC3A39DBA5CCBA4C2BBA646CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF3DH4DFDH3FDFDH3FGFDH3DHFFH3DHFFH3DHFFH2FGHFFH2FGH5DGGH3GEGGH3G3H3DG2H2GEG2H2G4H2DG3HHGEG6DE3G2DE3GGDE4GGDE4GGE5GDE4DGDE4DDE4CCEEDDC3EEDC4EDDC4EDC5DC5DDC4DDC5DIC4DEIC3DBAACDDC2BACDI2CCBDEI3CCEI5CI6DI5DEI4DEJA23BBA5CDBA4CCDBA3JICDBA2JJICDBA581CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF2A3CF3H3FHHFH3DHHDH3GHHDH2FGHHDH2FH2FH2DH2FH2DH2FH2GH4G5HHDG3DHGEG3DHG5EHDG3DEHG4EEG4DEEDG3E2DE3C2E4C2E3C3E3C3E2C4EEC5EEC5EC5DC3DEIIC3DI2C2DI3CCDEI3CDEI4CDI5DI5DEI4DI4EEJJI2EEJ2IIEEJ3IEDJ4IDIJ4DIJ5IJ5EJ4IDDJ2ICDBAJ3CCDBJ2EDCCBJJEDFFCCJEDF3CEDF5DF14A23BA6CBA5CDBA4DCBA4DCCBA519CF2A3CF2A3CF2A3CF2A3CFFDA3CF2A3CF2A3CF3HHFGH5FH2GH2DH2DH2GH2GH2GHHGGHHFH2GGHHFH2GGHHGHHG6DE2G3DE2G2E4G2E4G2E3DGGE3DCGGE3DCGE3DCCEC5EC5DIC4DIIC3DEIIC3EI2C2DI3CCDI4CCEI3EI4EIJI3EEJJI2EEJ2IIEEJ3IIEJ4IEJ4EEJ4EDJ4EDFJ3IDFFJ2IDF2JJIDF3JJDF4IDF5DF13DF4DDHF6DF4DDF4DDHHF2DFH2FDDH4DFH5FH13FFHCCBA2HHFCDBAAH2DCBAAH3CCBAH3DCDAH2DDCCBHFDDHGCBDDH3ECA55BA458CF2A3CF2A3CFFHA3CFFHA3CFFHA3CFFHA3CFFHA3CD2H4G2HHGHHG2HFHHG3H3G3H3G2EH3G2EH2G2EEDGHG2EEGE3DCCE3DC2E3C3E2DC2E3C2EIEEDC2IIEEC2I2EC2EI2CEI3EIDI3EJJI3EIJJI2EIJ2I3J2I3J2IDIEJ2IDFEJ2IF2J3EF2J2EF3JIDF4JDF5DF4DF5DFHF4H2FFDFH3F3DFHHF3H3FDFH4DFH11FCH3FDCCH2DC2EHDC3EH6DDH3FDGHHFDDGH2DCCGH3C2GH3CEGH4GH5GH4GDDGH4GCH6EH6DH5DDH3D2GHGDDEG2DDG13BA6CBA5CBA5CCBA4ECBA4GCCBA3GCCBA3GGCDA455CD2A3CD2A3CD2A3CD2A3CD2A3CD2A3CD2A3CD6GE2D5EED47ECCDI3C2I3JDCI3JJDDIIEJ2D2EIJJD4IIDFD5FFD5FFJ2EF3JJEF4JEF5DF4HHF4H2F2H4FFH3FGH3FGHHFFH4FFH4FCH4FGEH2FGH3FGH4FGH11GGH2G4C3EH2CCEH4EH4GDH3GDEGHHGDG4DG20EH2DDEGGHGDG4DG27EDDGGEDDE2DDE5G21EDG2EDDE2DDE28GGCCBA2GDCCBA2DDECDA2E2CCBAAE2CCBAAE3CBAAE3CDAAE3CCBA452CD2A3CD2A3CD2A3CD2A3CD2A3CD2A3CD2A3CD73FD6FD47H14GDH3G2DHHG4DG6DDG2E2DDE5DDE5HG20EDG2E27DEED2C2G3EDEEGEDE31D3CDDC13E27D7C27E12D2ED4CCDC33D4ED2CCBAD2C2BAC5DAC5DAC6BC6BC2DDCCBD4CCBA451CD2A3CD2A3CD2A3CD2A3CD2A3C3A15D39C7A15D39C7A15D2E2D4C4D2C4D2EI3D2EI3C7A15C19DDEI16C7A15C8D2CD2IEEI20C7A15CCD5E4I26C7A15D2E4I31C7A15I5CBI5CDI5CDI5CDI5CDC6BA463", } end rift_uimouse=function() return function(R) R=R or {} R.Mouse={} function R.Mouse:new() local o={ last=nil, now=nil, } setmetatable(o,self) self.__index=self return o end function R.Mouse:update() self.last=self.now local x,y,lb,mb,rb,sx,sy=mouse() self.now={ x=x,y=y, lb=lb,mb=mb,rb=rb, sx=sx,sy=sy, } local lastLb,lastMb,lastRb=false,false,false if self.last~=nil then lastLb,lastMb,lastRb=self.last.lb,self.last.mb,self.last.rb end self.now.lbp=self.now.lb and not lastLb self.now.mbp=self.now.mb and not lastMb self.now.rbp=self.now.rb and not lastRb return self.now end end end rift_partsdancehipwobble=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") end local progress = pMetrics.progress stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) local dancer = stage3d.dancers[1] dancer.isVisible = true local danceT = progress * 32 dancer:setPosition(R.V3:new(0, 0, -25)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("hip-wobble", dancer, danceT) local dancer = stage3d.dancers[2] dancer.isVisible = true local danceT = progress * 8 + .75 dancer:setPosition(R.V3:new(15, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("systematic", dancer, danceT) local dancer = stage3d.dancers[3] dancer.isVisible = true local danceT = progress * 8 + .75 + 2 dancer:setPosition(R.V3:new(-15, 0, -35)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("systematic", dancer, danceT) local xCam = mCos(progress * mPi) * 20 local zCam = mSin(progress * mPi) * 5 stage3d.cameraFG:setPosition(R.V3:new(xCam, 5, zCam)) local pos = stage3d.dancers[1].pos local cameraRot = R.Quaternion.lookAt(stage3d.cameraFG.pos, pos, stage3d.cameraFG.up) stage3d.cameraFG:setRotation(cameraRot) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_partsdancecancan=function() R=R or {} rift_demopart()(R) rift_sysrgb()(R) local letters = rift_codeletters() local setup2d = rift_codesetup2d()(R, letters) local setup3d = rift_codesetup3d()(R) local animations = rift_codeanimations()(R) local fnsClock = rift_data3dclock()(R) local flow = rift_codeflow() local mPi,mTau,mCos,mSin,mAbs = math.pi,math.pi * 2,math.cos,math.sin,math.abs local stage3d return R.DemoPart:new({ bdr=setup2d.bdr, tic=function(pMetrics) local isCrazy = flow.isCrazy() if pMetrics.isFirstRun then vbank(0) cls() R.setRGB(0,R.RGB:new(0,0,0)) setup2d.setVBankRGBs(1, setup2d.standardPalette) stage3d = setup3d.init() animations.init() setup3d.setStyle("flatlit-palmap") stage3d.clock.isVisible = true end local progress = pMetrics.progress local danceT = progress * 16 + .3 if isCrazy then danceT = danceT * 2 end local dancer = stage3d.dancers[1] dancer.isVisible = true dancer:setPosition(R.V3:new(-20, 0, -30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cancan", dancer, danceT + .12) local dancer = stage3d.dancers[2] dancer.isVisible = true dancer:setPosition(R.V3:new(-10, 0, -40)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cancan", dancer, danceT + .08) local dancer = stage3d.dancers[3] dancer.isVisible = true dancer:setPosition(R.V3:new(0, 0, -50)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cancan", dancer, danceT + .02) local dancer = stage3d.dancers[4] dancer.isVisible = true dancer:setPosition(R.V3:new(10, 0, -40)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cancan", dancer, danceT + .06) local dancer = stage3d.dancers[5] dancer.isVisible = true dancer:setPosition(R.V3:new(20, 0, -30)) dancer:setRotation(R.Quaternion:newFromEuler(0, mPi, 0)) animations.applyToSkeleton("cancan", dancer, danceT + .10) stage3d.cameraFG:setPosition(R.V3:new(0, 0, 0)) local xClock, yClock = 0,0 if isCrazy then xClock = mSin(progress * mTau * 2) * progress * 20 yClock = mCos(progress * mTau * 2) * progress * 10 end local camZ = -40 + progress * 3 stage3d.clock:setPosition(R.V3:new(xClock, yClock, -60)) stage3d.clock:setRotation(R.Quaternion:newFromEuler(0, 0, -progress * mTau * .8)) fnsClock.setClock(stage3d.clock, 10 + progress * 20) letters.sceneClip() vbank(1) cls() stage3d.sceneFG:render(stage3d.engineFG) letters.drawConundrum() end, cleanup=function() end, }) end rift_codesetup2d=function() return function(R, letters) local flow = rift_codeflow() local vbankRGBs = {} vbankRGBs[0] = {} vbankRGBs[1] = {} local FADE_AMOUNT = .5 local function bdr(y, pMetrics) if y==0 then vbank(0) for i,rgb in pairs(vbankRGBs[0]) do R.setColour(i-1, rgb[1] * FADE_AMOUNT, rgb[2] * FADE_AMOUNT, rgb[3] * FADE_AMOUNT) end vbank(1) for i,rgb in pairs(vbankRGBs[1]) do R.setColour(i, rgb[1] * FADE_AMOUNT, rgb[2] * FADE_AMOUNT, rgb[3] * FADE_AMOUNT) end elseif y==letters.screenSplit then vbank(1) for i,rgb in pairs(letters.palette) do R.setColour(i, rgb[1] * FADE_AMOUNT, rgb[2] * FADE_AMOUNT, rgb[3] * FADE_AMOUNT) end end end local function bdrNoConundrum(y, pMetrics) if y==0 then vbank(0) for i,rgb in pairs(vbankRGBs[0]) do R.setColour(i-1, rgb[1] * FADE_AMOUNT, rgb[2] * FADE_AMOUNT, rgb[3] * FADE_AMOUNT) end vbank(1) for i,rgb in pairs(vbankRGBs[1]) do R.setColour(i, rgb[1] * FADE_AMOUNT, rgb[2] * FADE_AMOUNT, rgb[3] * FADE_AMOUNT) end end end local function fade(amount) FADE_AMOUNT = amount end local function fadeScene(progress, t1, t2) if progress <= t1 then fade(progress / t1) elseif progress >= t2 then fade(1-((progress - t2) / (1-t2))) end end local standardPalette = {} standardPalette[0]={0, 0, 0} standardPalette[1]={255, 255, 255} -- white standardPalette[2]={80, 80, 200} -- light blue standardPalette[3]={40, 40, 120}-- dark blue standardPalette[4]={255, 255, 220} -- light yellow standardPalette[5]={160, 160, 120}-- dark yellow standardPalette[6]={255, 255, 0} -- light brown standardPalette[7]={120, 120, 0} -- dark brown local fnRGB = function(i) local v=(i+1)/8 return {(1-v)*255, 64+v*64, v*255} end local fnRGBs = { function(i) local v=(i+1)/8 return {v*255,(1-v)*64, v*64} end, function(i) local v=(i+1)/8 return {64+v*64, v*255, v*255} end, function(i) local v=(i+1)/8 return {64+v*64, v*255, v*64} end, function(i) local v=(i+1)/8 return {(1-v)*64, (1-v)*64, v*255} end, } if flow.isCrazy() then fnRGB = fnRGBs[math.random(1,#fnRGBs)] end for i=0,7 do local v=(i+1)/8 standardPalette[i+8]=fnRGB(i) end return { bdr=bdr, bdrNoConundrum=bdrNoConundrum, fade=fade, standardPalette=standardPalette, fadeScene=fadeScene, setVBankRGBs=function(bankID, rgbs) vbankRGBs[bankID] = rgbs end, } end end rift_3d2mesh=function() return function(R) R=R or {} local Mesh={} function Mesh:new() local o={ vertices={}, -- {x,y,z} and optionally normals? renderables={default={}}, } setmetatable(o,self) self.__index=self return o end function Mesh:__tostring() -- NB This is wrong, since keyed vertices etc will not be counted return string.format("MESH(verts=%d,tris=%d,spheres=%d)",#self.vertices,#self.triangles,#self.spheres) end -- returns an ID for the vertex function Mesh:addVertex(id, v) id = (id == nil and #self.vertices+1) or id self.vertices[id]=v return id end function Mesh:vertex(id) return self.vertices[id] end -- Send in a materialID and the data it needs to render... function Mesh:addRenderable(materialID, data, skinID) skinID = skinID or "default" if self.renderables[skinID] == nil then self.renderables[skinID]={} end self.renderables[skinID][#self.renderables[skinID]+1]={materialID=materialID,data=data} end function Mesh:addToRenderlist(engine, scene, position, quaternion, scale, skinIDs, actorData, modelData, meshData, renderlist) local psView={} local psWorld={} local mat = scene.camera:getMatWorldToView() for i,vertex in pairs(self.vertices) do vertex = R.V3.scaleByV3(vertex, scale) local pWorld = position + R.Quaternion.rotateV3(quaternion, vertex) psWorld[i] = pWorld psView[i] = engine:transformForViewport( R.M44.multiplyVec3( mat, pWorld ) ) end -- We can specify that multiple skins get rendered for _, skinID in ipairs(skinIDs) do local skin = self.renderables[skinID] -- For each skin, we iterate through the renderables if skin ~= nil then for _,renderable in pairs(skin) do local material = engine:material(renderable.materialID) if material == nil then trace("Material not found: " .. renderable.materialID) exit() end renderlist[#renderlist+1]={ material = material, data = material.fnTransform(renderable.data, psView, psWorld, actorData, modelData, meshData), } end end end end R.Mesh = Mesh end end rift_data3dtile=function() return function(R) local function makeMeshTemplateTile(w,h, texTileID) local mesh=R.Mesh:new() local w2,h2 = w/2, h/2 for _,v in pairs({{-w2,-h2},{w2,-h2},{w2,h2},{-w2,h2}}) do mesh:addVertex(nil, R.V3:new(v[1],v[2],0)) end mesh:addRenderable(texTileID, { v1=1,v2=2,v3=3,v4=4, }) return mesh end local function makeModelTile(w,h, texTileID) local model=R.Model:new() model:addMeshTemplate("mtTile",makeMeshTemplateTile(w,h, texTileID)) model:addMeshInstance("miTile",nil,"mtTile",R.Quaternion:newFromEuler(0,0,0)) return model end return { makeModel=makeModelTile, } end end IS_DEBUG=false -- Copy this file into a folder within your TIC-80 code folder (e.g. ~/my-demo/) -- Check the Rift Libs out into ~/rift/ in your TIC-80 code folder -- Add your package path here - note the odd pattern matching style (Windows Example) -- You can include as many of these as you like, for each team member. No need to comment any out R=R or {} rift_syssys()(R) rift_demorunner()(R) rift_fontsysfont()(R) local flowFns = rift_codeflow() local DEMO_RUNNER=R.DemoRunner:new() DEMO_RUNNER:setShowDebug(IS_DEBUG) DEMO_RUNNER:addCueMusic(0,0) --DEMO_RUNNER:addPartMusic(rift_partstestticmctile(), 10) --DEMO_RUNNER:addPartTics(rift_partsclapometer(), 5000) --DEMO_RUNNER:addPartTics(rift_partsposer(), 10000000) --DEMO_RUNNER:addPartMusic(rift_partsmakeclock(), 1) --DEMO_RUNNER:addPartMusic(rift_partstestvram(), 10) --DEMO_RUNNER:addFnCallback(function() flowFns.goCrazy() end) DEMO_RUNNER:addPartMusic(rift_partsdancewarmup(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancewelcome(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancesystematic(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancehipwobble(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceclaps(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancehaka(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancecancan(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceslide(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancedab(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceballet(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancetuck(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancekicksailor(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancerun(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancebox(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceshadows(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceclock(), 1) DEMO_RUNNER:addStopMusic() DEMO_RUNNER:addPartTics(rift_partscredits(), 500) DEMO_RUNNER:addPartTics(rift_partsclapometer(), 800) DEMO_RUNNER:addFnCallback(function() flowFns.goCrazy() end) DEMO_RUNNER:addCueMusic(1,0) DEMO_RUNNER:addPartMusic(rift_partsdancewarmup(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancewelcome(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancesystematic(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancehipwobble(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceclaps(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancehaka(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancecancan(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceslide(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancedab(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceballet(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancetuck(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancekicksailor(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancerun(), 1) DEMO_RUNNER:addPartMusic(rift_partsdancebox(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceshadows(), 1) DEMO_RUNNER:addPartMusic(rift_partsdanceclock(), 1) DEMO_RUNNER:addStopMusic() DEMO_RUNNER:addPartTics(rift_partsthanks(), 500) DEMO_RUNNER:addPartTics(rift_partsend(), 800) local DEMO_RUNNER_HIDDEN=R.DemoRunner:new() DEMO_RUNNER_HIDDEN:addCueMusic(0,0) DEMO_RUNNER_HIDDEN:addPartTics(rift_partsposer(), 10000000) vbank(1) cls() vbank(0) cls() local demoRunner = DEMO_RUNNER TIC=R.ticWrap(function() R.tryBreak() R.hideMouse() if keyp(25) then demoRunner = DEMO_RUNNER_HIDDEN end local exitSignal = demoRunner:run() if exitSignal then trace("- Greets to you! :)",12) exit() end end)