Skip to content

Commit 5eae404

Browse files
author
Brian Holdsworth
committed
Update plasma sample app; use Lua to calculate the pattern
1 parent 285bc5f commit 5eae404

File tree

5 files changed

+436
-77
lines changed

5 files changed

+436
-77
lines changed

samples/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
*.app
2+
plasma

samples/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mandelbrot.app\
55
cube.app
66
ACME=acme --dialect 0.94.12
77

8-
all: $(APPS)
8+
all: $(APPS) plasma
99

1010
hello.app: hello.asm hello.app.d/app.asm ../cbm/toolx/*/*
1111
$(ACME) --cpu 6510 -f plain -o hello.app -I../cbm hello.asm
@@ -19,5 +19,8 @@ mandelbrot.app: mandelbrot.asm mandelbrot.app.d/app.asm ../cbm/toolx/*/*
1919
cube.app: cube.asm cube.app.d/app.asm ../cbm/toolx/*/*
2020
$(ACME) --cpu 6510 -f plain -o cube.app -I../cbm cube.asm
2121

22+
plasma: plasma.asm
23+
$(ACME) --cpu 6510 plasma.asm
24+
2225
clean:
23-
rm $(APPS)
26+
rm $(APPS) plasma

samples/ease.lua

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
-- ease - a modified remix of flux and bezier-easing.
2+
-- https://github.com/poke1024/ease.git
3+
4+
-- the following code is adapted from flux, Copyright (c) 2016 rxi,
5+
-- https://github.com/rxi/flux/.
6+
7+
local ease = { linear = function(p) return p end }
8+
9+
local penner = {
10+
quad = "p * p",
11+
cubic = "p ^ 3",
12+
quart = "p ^ 4",
13+
quint = "p ^ 5",
14+
expo = "2 ^ (10 * (p - 1))",
15+
sine = "-cos(p * (pi * .5)) + 1",
16+
circ = "-(sqrt(1 - (p * p)) - 1)",
17+
back = "p * p * (2.7 * p - 1.7)",
18+
elastic = "-(2^(10 * (p - 1)) * sin((p - 1.075) * (pi * 2) / .3))",
19+
bounce = "bounce(p)"
20+
}
21+
22+
local bounce = function(t)
23+
t = 1 - t
24+
if t < (1 / 2.75) then
25+
return 1 - 7.5625 * t * t
26+
elseif t < (2 / 2.75) then
27+
t = t - 1.5 / 2.75
28+
return 1 - (7.5625 * t * t + .75)
29+
elseif t < (2.5 / 2.75) then
30+
t = t - 2.25 / 2.75
31+
return 1 - (7.5625 * t * t + .9375)
32+
else
33+
t = t - 2.625 / 2.75
34+
return 1 - (7.5625 * t * t + .984375)
35+
end
36+
end
37+
38+
local load = loadstring or load
39+
40+
local symbols = {
41+
math = math,
42+
bounce = bounce
43+
}
44+
45+
local compile = function(name, str, expr)
46+
ease[name] = load([[
47+
local sin = math.sin; local cos = math.cos; local pi = math.pi; local sqrt = math.sqrt;
48+
return function(p) ]] .. str:gsub("%$e", expr) .. " end", name, "t", symbols)()
49+
end
50+
51+
for k, v in pairs(penner) do
52+
compile("in" .. k, "return $e", v)
53+
compile("out" .. k, [[
54+
p = 1 - p
55+
return 1 - ($e)
56+
]], v)
57+
compile("inout" .. k, [[
58+
p = p * 2
59+
if p < 1 then
60+
return .5 * ($e)
61+
else
62+
p = 2 - p
63+
return .5 * (1 - ($e)) + .5
64+
end
65+
]], v)
66+
end
67+
68+
-- the following code is a lua port of Gaëtan Renaudeau's JavaScript library bezier-easing,
69+
-- https://github.com/gre/bezier-easing (ported from v2.0.3, e0036aa16e36d3647413013fa774d3df37f348f1).
70+
71+
-- These values are established by empiricism with tests (tradeoff: performance VS precision)
72+
local NEWTON_ITERATIONS = 4
73+
local NEWTON_MIN_SLOPE = 0.001
74+
local SUBDIVISION_PRECISION = 0.0000001
75+
local SUBDIVISION_MAX_ITERATIONS = 10
76+
77+
local kSplineTableSize = 11
78+
local kSampleStepSize = 1.0 / (kSplineTableSize - 1.0)
79+
80+
local function A (aA1, aA2) return 1.0 - 3.0 * aA2 + 3.0 * aA1 end
81+
local function B (aA1, aA2) return 3.0 * aA2 - 6.0 * aA1 end
82+
local function C (aA1) return 3.0 * aA1 end
83+
84+
-- Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
85+
local function calcBezier (aT, aA1, aA2) return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT end
86+
87+
-- Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
88+
local function getSlope (aT, aA1, aA2) return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1) end
89+
90+
local abs = math.abs
91+
92+
local function binarySubdivide (aX, aA, aB, mX1, mX2)
93+
local currentX, currentT
94+
for i = 1, SUBDIVISION_MAX_ITERATIONS do
95+
currentT = aA + (aB - aA) / 2.0
96+
currentX = calcBezier(currentT, mX1, mX2) - aX
97+
if currentX > 0.0 then
98+
aB = currentT
99+
else
100+
aA = currentT
101+
end
102+
if abs(currentX) <= SUBDIVISION_PRECISION then
103+
break
104+
end
105+
end
106+
return currentT
107+
end
108+
109+
local function newtonRaphsonIterate (aX, aGuessT, mX1, mX2)
110+
for i = 1, NEWTON_ITERATIONS do
111+
local currentSlope = getSlope(aGuessT, mX1, mX2)
112+
if currentSlope == 0.0 then
113+
return aGuessT
114+
end
115+
local currentX = calcBezier(aGuessT, mX1, mX2) - aX
116+
aGuessT = aGuessT - currentX / currentSlope
117+
end
118+
return aGuessT
119+
end
120+
121+
local newSampleValues
122+
if type(jit) == "table" then -- running under LuaJIT?
123+
local ffi = require("ffi")
124+
local spec = "float[" .. tostring(kSplineTableSize + 1) .. "]"
125+
newSampleValues = function() return ffi.new(spec) end
126+
else
127+
newSampleValues = function() return {} end
128+
end
129+
130+
ease.cubicbezier = function (mX1, mY1, mX2, mY2)
131+
if not (0 <= mX1 and mX1 <= 1 and 0 <= mX2 and mX2 <= 1) then
132+
error('bezier x values must be in [0, 1] range')
133+
end
134+
135+
if mX1 == mY1 and mX2 == mY2 then
136+
return ease.linear
137+
end
138+
139+
local sampleValues = newSampleValues()
140+
for i = 0, kSplineTableSize - 1 do
141+
sampleValues[i + 1] = calcBezier(i * kSampleStepSize, mX1, mX2)
142+
end
143+
local lastSample = kSplineTableSize - 1
144+
145+
local function getTForX (aX)
146+
local intervalStart = 0.0
147+
local currentSample = 1
148+
149+
while currentSample ~= lastSample and sampleValues[currentSample + 1] <= aX do
150+
currentSample = currentSample + 1
151+
intervalStart = intervalStart + kSampleStepSize
152+
end
153+
currentSample = currentSample - 1
154+
155+
-- Interpolate to provide an initial guess for t
156+
local dist = (aX - sampleValues[currentSample + 1]) / (sampleValues[currentSample + 2] - sampleValues[currentSample + 1])
157+
local guessForT = intervalStart + dist * kSampleStepSize
158+
159+
local initialSlope = getSlope(guessForT, mX1, mX2)
160+
if initialSlope >= NEWTON_MIN_SLOPE then
161+
return newtonRaphsonIterate(aX, guessForT, mX1, mX2)
162+
elseif initialSlope == 0.0 then
163+
return guessForT
164+
else
165+
return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2)
166+
end
167+
end
168+
169+
return function (x)
170+
-- Because Lua numbers are imprecise, we should guarantee the extremes are right.
171+
if x == 0 then
172+
return 0
173+
elseif x == 1 then
174+
return 1
175+
else
176+
return calcBezier(getTForX(x), mY1, mY2)
177+
end
178+
end
179+
end
180+
181+
return ease

0 commit comments

Comments
 (0)