Skip to content

Commit b9e7236

Browse files
Merge pull request #54 from matejsemancik/feature/sem008
Add SEM008 loop
2 parents 3f2bd02 + e24fb6f commit b9e7236

File tree

3 files changed

+153
-3
lines changed

3 files changed

+153
-3
lines changed

core/src/main/kotlin/dev/matsem/astral/core/tools/extensions/PAppletExtensions.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,10 @@ fun PApplet.colorModeHsb() = colorMode(
7474
ColorConfig.SATURATION_MAX,
7575
ColorConfig.BRIGHTNESS_MAX,
7676
ColorConfig.ALPHA_MAX
77-
)
77+
)
78+
79+
val PApplet.widthF: Float
80+
get() = width.toFloat()
81+
82+
val PApplet.heightF: Float
83+
get() = height.toFloat()

playground/src/main/kotlin/dev/matsem/astral/playground/PlaygroundApp.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package dev.matsem.astral.playground
22

33
import dev.matsem.astral.core.di.coreModule
4-
import dev.matsem.astral.playground.sketches.Blank
4+
import dev.matsem.astral.playground.sketches.Sem008
55
import org.koin.core.KoinComponent
66
import org.koin.core.context.startKoin
77
import org.koin.core.inject
@@ -27,7 +27,7 @@ class PlaygroundApp : KoinComponent {
2727
fun run(processingArgs: Array<String>) {
2828
startKoin {
2929
printLogger(Level.ERROR)
30-
modules(coreModule + playgroundModule { Blank() })
30+
modules(coreModule + playgroundModule { Sem008() })
3131
}
3232

3333
PApplet.runSketch(processingArgs + arrayOf("ProcessingPlayground"), sketch)
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package dev.matsem.astral.playground.sketches
2+
3+
import ch.bildspur.postfx.builder.PostFX
4+
import dev.matsem.astral.core.tools.animations.AnimationHandler
5+
import dev.matsem.astral.core.tools.animations.radianSeconds
6+
import dev.matsem.astral.core.tools.animations.saw
7+
import dev.matsem.astral.core.tools.audio.beatcounter.BeatCounter
8+
import dev.matsem.astral.core.tools.audio.beatcounter.OnKick
9+
import dev.matsem.astral.core.tools.audio.beatcounter.OnSnare
10+
import dev.matsem.astral.core.tools.extensions.centerX
11+
import dev.matsem.astral.core.tools.extensions.colorModeHsb
12+
import dev.matsem.astral.core.tools.extensions.mapSin
13+
import dev.matsem.astral.core.tools.extensions.mapp
14+
import dev.matsem.astral.core.tools.extensions.pushPop
15+
import dev.matsem.astral.core.tools.extensions.quantize
16+
import dev.matsem.astral.core.tools.extensions.shorterDimension
17+
import dev.matsem.astral.core.tools.extensions.translateCenter
18+
import dev.matsem.astral.core.tools.videoexport.VideoExporter
19+
import org.koin.core.KoinComponent
20+
import org.koin.core.inject
21+
import processing.core.PApplet
22+
23+
/**
24+
* VJ loop for SEM008 release https://soundcloud.com/semfree/sem008-offish-evasion-straight-shootingcalculated-risk-out-300922
25+
*/
26+
class Sem008 : PApplet(), KoinComponent, AnimationHandler {
27+
28+
sealed class ExportConfig(
29+
val width: Int,
30+
val height: Int,
31+
val outputFile: String,
32+
val travelLength: Int
33+
) {
34+
object Square : ExportConfig(1080, 1080, "sem008_loop_sqr.mp4", 200_000)
35+
object Story : ExportConfig(1080, 1920, "sem008_loop_story.mp4", 300_000)
36+
}
37+
38+
private val exportConfig = ExportConfig.Square
39+
40+
private lateinit var fx: PostFX
41+
42+
private val beatCounter: BeatCounter by inject()
43+
private val videoExporter: VideoExporter by inject()
44+
45+
override fun provideMillis(): Int = videoExporter.videoMillis()
46+
47+
private var ures: Float = 3f
48+
private var uresTarget: Float = 3f
49+
private var vres: Float = 3f
50+
private var vresTarget: Float = 3f
51+
private var zoom: Float = 1f
52+
private var invert: Boolean = false
53+
54+
override fun settings() {
55+
size(exportConfig.width, exportConfig.height, P3D)
56+
}
57+
58+
override fun setup() {
59+
colorModeHsb()
60+
surface.setAlwaysOnTop(true)
61+
fx = PostFX(this)
62+
63+
beatCounter.addListener(OnKick, 2) {
64+
uresTarget = random(1f, 5f)
65+
vresTarget = random(1f, 5f)
66+
}
67+
68+
beatCounter.addListener(OnKick, 4) {
69+
invert = true
70+
}
71+
72+
beatCounter.addListener(OnSnare, 2) {
73+
zoom = random(0.7f, 1f)
74+
}
75+
76+
videoExporter.prepare(
77+
audioFilePath = "music/sem0081minclip.mp3",
78+
movieFps = 30f,
79+
dryRun = true,
80+
audioGain = 2f,
81+
outputVideoFileName = exportConfig.outputFile
82+
) { drawSketch() }
83+
}
84+
85+
override fun draw() = drawSketch()
86+
87+
private fun PApplet.drawSketch() {
88+
ures = lerp(ures, uresTarget, 0.2f)
89+
vres = lerp(vres, vresTarget, 0.2f)
90+
91+
clear()
92+
background(0f, 0f, 10f)
93+
94+
sphereDetail(ures.toInt(), vres.toInt())
95+
96+
pushPop {
97+
translateCenter()
98+
scale(zoom)
99+
100+
for (travel in 0 until exportConfig.travelLength step 1000) {
101+
strokeWeight(4f)
102+
if (travel < saw(1 / 5f).mapp(0f, exportConfig.travelLength.toFloat())) {
103+
fill(0f, 0f, 10f)
104+
stroke(0f, 0f, 90f)
105+
} else {
106+
fill(0f, 0f, 60f)
107+
stroke(0f, 0f, 0f)
108+
}
109+
110+
pushPop {
111+
rotateZ(radianSeconds(20f) + travel)
112+
translate(0f, 0f, millis().toFloat())
113+
114+
pushPop {
115+
translate(-centerX() * 1.2f, 0f)
116+
translate(0f, 0f, -travel.toFloat())
117+
rotateY(radianSeconds(10f).quantize(0.05f))
118+
rotateZ(-radianSeconds(30f))
119+
sphere(shorterDimension() * 0.50f)
120+
}
121+
122+
pushPop {
123+
translate(centerX() * 1.2f, 0f)
124+
translate(0f, 0f, -travel.toFloat())
125+
rotateY(-radianSeconds(10f).quantize(0.05f))
126+
rotateZ(radianSeconds(30f))
127+
sphere(shorterDimension() * 0.50f)
128+
}
129+
}
130+
}
131+
}
132+
133+
fx.render().apply {
134+
noise(0.3f, 0.5f)
135+
rgbSplit(50f)
136+
bloom(0.5f, 20, 5f)
137+
pixelate(sin(radianSeconds(5f)).mapSin(width * 1f, width * 0.4f))
138+
if (invert) {
139+
invert()
140+
invert = false
141+
}
142+
}.compose()
143+
}
144+
}

0 commit comments

Comments
 (0)