0,]']>S}Wup8d%qy)6o;]AsVl3t 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 ff ff ff ff ff ff fffd dd dd dd dd dd dd ddd 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    ffFfffFffFFFF F F F F Fff F F F FF F%k$kk'kk)k)kkk$kk'kk)k)kk$'))$'))tT~]tT~]tT~]tTtFF FFMFMF FMFMF F    FFf F M F M FFMFMFf   ff ffmfmffmfmff    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 jfFF 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.   .wT4 yW7wT4 yWt{[@@q q r,r, s4t444sD55EUefyHHyy x4 x4 ( ( 4e4eyh? QQU %U R%U! UU%Q QRU% QU%UUUUU QUU%Q UUURUUU%! "UURUQ !U! P%UU% QUUUUQ PU%QPUUU%Q QUU%U UR%QQUUU%RUU%U PUU%QQ"RU%QQUUUU!QQRU%PUU%"U QUURURUU%PUUUUU"Q Q%URR ̻UUU%UQUUUUUU -UUUR ̼UUU%UQUUUUQ %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)