Kirjautuminen

Haku

Tehtävät

Keskustelu: Yleinen keskustelu: Nykytaiteen museoon?

PetriKeckman [17.06.2026 19:05:07]

#

Huippukivaa taidetta 2000-luvun alun REBOL-kielellä?

Päästäänkö tällä videolla Nykytaiteen museoon?! 🤣☺️❗

Minulle on kertynyt vuosien varrella melko paljon algoritmisen taiteen kuvia: https://petke.info/uus/art.html

Toteutin nyt 3D gallerian REBOL-kielellä. Tein 20 minuuttisen videon: https://youtu.be/4-LphIISStY

Sinne mahtui 84 kuvaa, jotka valitsin 171:stä.

Videon nimi on "Risa 3D". Teos olisi tylsä, jos siinä olisi teknisesti täydellinen 3D grafiikka. Nyt se rumasti sanottuna välillä kusee.

Teoksen hakemus Suomen Taiteilijat ry:n vuosinäyttelyyn:


Hei,

haen Suomen Taiteilijat ry:n vuosinäyttelyyn videoinstallaatiollani "Risa 3D".

Teos on 20 minuutin mittainen, non-stop -loopissa esitettävä video. Se on suunniteltu esitettäväksi yksinkertaisella ja luotettavaksi testatulla laitteistolla (mediatoistin ja 24” näyttö/televisio).

Videossa liikutaan pienessä 3D-virtuaaligalleriassa, jossa on esillä 84 valitsemaani algoritmisen taiteen kuvaani. Kamera liikkuu tilassa edestakaisin samalla pyörien, minkä ansiosta näkymä ei toistu teoksen aikana. Lisäksi galleriassa tapahtuu satunnaisia muutoksia: keskimäärin noin 1000 freimin välein kaikkien teosten kuvat vaihtuvat uudelleen. Näihin hetkiin liittyy lyhyt ääniefekti, muuten teos on äänetön.

Teoksen nimi viittaa sen tarkoitukselliseen epätäydellisyyteen. Se on toteutettu 2000-luvun alun REBOL-ohjelmointikielellä, minkä seurauksena 3D-tilassa esiintyy visuaalisia poikkeamia ja “kauneusvirheitä”. Nämä eivät ole pelkkiä teknisiä rajoitteita, vaan olennainen osa teoksen estetiikkaa: tila ei ole vakaa eikä täysin hallittavissa.

Linkki videoon: https://youtu.be/4-LphIISStY

Ystävällisin terveisin,
Petri Keckman

Sitten itse Ohjelmointiputkan asiaan, eli koodeihin. Selittelemättä ehkä paras? Lopputulos ratkaisee?

rebol[]
print "odota"
maxx: 1920
maxy: 1080

alfay1: -70

origx: -6000
origy: 0
origz: -20000

dx: 100


x0: maxx / 2
y0: maxy / 2

polys: copy []

pituusx: 4000
pituusy: 12000
pituusz: 2000

bkuvat: copy[]
kind: 1
for i 1 85 1 [
	kuva: load to-file rejoin ["u" i ".png"]
	append bkuvat kuva
]

;LAitetaan taulut *****************************************************************************************

lisaaTaulu: func [p1 p2 p3 p4 pic][

    ; --- skaalatut pisteet ---
    xt: reduce [
        (pituusx * p1/1)
        (pituusx * p2/1)
        (pituusx * p3/1)
        (pituusx * p4/1)
    ]
    yt: reduce [
        (pituusy * p1/2)
        (pituusy * p2/2)
        (pituusy * p3/2)
        (pituusy * p4/2)
    ]
    zt: reduce [
        (pituusz * p1/3)
        (pituusz * p2/3)
        (pituusz * p3/3)
        (pituusz * p4/3)
    ]

    ; --- laske normaali ---
    ax: xt/2 - xt/1
    ay: yt/2 - yt/1
    az: zt/2 - zt/1

    bx: xt/3 - xt/1
    by: yt/3 - yt/1
    bz: zt/3 - zt/1

    nx: (ay * bz) - (az * by)
    ny: (az * bx) - (ax * bz)
    nz: (ax * by) - (ay * bx)

    ; --- jos normaali väärin päin ? flip ---
    if nz < 0 [
        xt: reverse xt
        yt: reverse yt
        zt: reverse zt
    ]

    ; --- lisää poly ---
    append polys make object! [
        xtb: xt
        ytb: yt
        ztb: zt
        depth: 0
        kuva: pic
    ]
]

; =========================
; SEINÄ NUMERO 1 (Z vakio)
; =========================
minx1: 9999999
alkux: 3
alkuy: -0.65
välix: 0.6
väliy: 0.3
kokox: 1.2
kokoy: 0.55
z: -7

for i 1 8 1 [
    xL: alkux - (i * kokox) - ((i - 1) * välix)
    xR: alkux - ((i + 1) * kokox) - ((i - 1) * välix)

    for j 1 2 1 [
        yT: alkuy + (j * kokoy) + ((j - 1) * väliy)
        yB: alkuy + ((j - 1) * kokoy) + ((j - 1) * väliy)

        lisaaTaulu
            reduce [xL yT z]   ; ylä-vasen
            reduce [xR yT z]   ; ylä-oikea
            reduce [xR yB z]   ; ala-oikea
            reduce [xL yB z]   ; ala-vasen
            bkuvat/(kind)

        kind: kind + 1
        if xL < minx1 [minx1: xL]
    ]
]

; =========================
; SEINÄ NUMERO 2 KAKSI TAULUA (X vakio)
; =========================

lisaaTaulu
    reduce [4  0.5   0.7]   ; ylä-vasen
    reduce [4  0.5  -2.7]   ; ylä-oikea
    reduce [4 -0.6  -2.7]   ; ala-oikea
    reduce [4 -0.6   0.7]   ; ala-vasen
    bkuvat/(kind)

kind: kind + 1

lisaaTaulu
    reduce [4  0.5   -3.2]   ; ylä-vasen
    reduce [4  0.5  -6.6]   ; ylä-oikea
    reduce [4 -0.6  -6.6]   ; ala-oikea
    reduce [4 -0.6   -3.2]   ; ala-vasen
    bkuvat/(kind)

kind: kind + 1

; =========================
; SEINÄ NUMERO 3 (Z vakio)
; =========================

sivux: 1.3
sivuy: 0.54
alkuy: -0.65
alkux: 4.4
välix: 0.2
väliy: 0.2

for i 1 6 1 [
    xL: alkux + ((i - 1) * sivux) + ((i - 1) * välix)
    xR: alkux + (i * sivux) + ((i - 1) * välix)

    for j 1 2 1 [
        yT: alkuy + (j * sivuy) + ((j - 1) * väliy)
        yB: alkuy + ((j - 1) * sivuy) + ((j - 1) * väliy)

        z: 1.2

lisaaTaulu
    reduce [xR yT z]   ; ylä-vasen
    reduce [xL yT z]   ; ylä-oikea
    reduce [xL yB z]   ; ala-oikea
    reduce [xR yB z]   ; ala-vasen
    bkuvat/(kind)

        kind: kind + 1
    ]
]

; =========================
; SEINÄ NRO 4 (X vakio)
; =========================

sivux: 3
sivuy: 0.54
alkuy: -0.7
alkux: 6.5
välix: 0.4
väliy: 0.2
alkuz: 1.4

for i 1 4 1 [
    zL: alkuz + ((i - 1) * sivux) + ((i - 1) * välix)
    zR: alkuz + (i * sivux) + ((i - 1) * välix)

    for j 1 2 1 [
        yT: alkuy + (j * sivuy) + ((j - 1) * väliy)
        yB: alkuy + ((j - 1) * sivuy) + ((j - 1) * väliy)

        lisaaTaulu
            reduce [14 yT zR]   ; ylä-vasen
            reduce [14 yT zL]   ; ylä-oikea
            reduce [14 yB zL]   ; ala-oikea
            reduce [14 yB zR]   ; ala-vasen
            bkuvat/(kind)

        kind: kind + 1
    ]
]



; =========================
; PITKÄ SEINÄ NUMERO 5 (Z vakio)
; =========================

alkux: 14
alkuy: -0.65
välix: 0.7
väliy: 0.3
kokox: 0.9
kokoy: 0.55
z: 15
minx6: 99999
maxx6: -999999
for i 1 11 1 [
    xL: alkux - (i * kokox) - ((i - 1) * välix)
    xR: alkux - ((i + 1) * kokox) - ((i - 1) * välix)

    for j 1 2 1 [
        yT: alkuy + (j * kokoy) + ((j - 1) * väliy)
        yB: alkuy + ((j - 1) * kokoy) + ((j - 1) * väliy)

        lisaaTaulu
            reduce [xR yT z]   ; ylä-vasen
            reduce [xL yT z]   ; ylä-oikea
            reduce [xL yB z]   ; ala-oikea
            reduce [xR yB z]   ; ala-vasen
            bkuvat/(kind)

        kind: kind + 1
    ]
    if xL < minx6 [minx6: xL]
    if xL > maxx6 [maxx6: xL]
]

; =========================
; VIKASEINÄ NRO 6 (X vakio)
; =========================

sivux: 4
sivuy: 1
alkuy: -1
välix: 0.8
väliy: 0.2
alkuz: -1
x: -14
minx7: 99999
maxx7: -999999
for i 1 10 1 [
    zL: alkuz + ((i - 1) * sivux) + ((i - 1) * välix)
    zR: alkuz + (i * sivux) + ((i - 1) * välix)

    for j 1 2 1 [
        yT: alkuy + (j * sivuy) + ((j - 1) * väliy)
        yB: alkuy + ((j - 1) * sivuy) + ((j - 1) * väliy)

        lisaaTaulu
            reduce [x yT zL]   ; ylä-vasen
            reduce [x yT zR]   ; ylä-oikea
            reduce [x yB zR]   ; ala-oikea
            reduce [x yB zL]   ; ala-vasen
            bkuvat/(kind)

        kind: kind + 1
    	if xL < minx7 [minx7: xL]
    	if xL > maxx7 [maxx7: xL]
    ]
]
dz: -10000
foreach poly polys [
	poly/ztb/1: poly/ztb/1 + dz
	poly/ztb/2: poly/ztb/2 + dz
	poly/ztb/3: poly/ztb/3 + dz
	poly/ztb/4: poly/ztb/4 + dz
]

print kind
print minx1
print minx6
print maxx6
print minx7
print maxx7

freimit: copy[]
for kuvaind 1 (20 * 60 * 30) 1 [
	plot: copy[]
	foreach poly polys [
	    ztb: poly/ztb

	    ; keskimääräinen z
	    depth: (
	        (ztb/1 + ztb/2 + ztb/3 + ztb/4) / 4
	    )

	    poly/depth: depth
	]

	sort/compare polys func [a b][
	    a/depth > b/depth
	]

foreach poly polys [

    xtb: poly/xtb
    ytb: poly/ytb
    ztb: poly/ztb
    kuva: poly/kuva

    xp: copy []
    yp: copy []

    kelpaa: true
    valid: true

    xrlist: copy []
    zrlist: copy []

    ; --- KIERRÄ + PROJEKTIO ---
    repeat i 4 [
        apu: xtb/:i

        xr: ((cosine alfay1) * xtb/:i) + ((- sine alfay1) * ztb/:i)
        zr: ((sine alfay1) * apu) + ((cosine alfay1) * ztb/:i)

        append xrlist xr
        append zrlist zr

        ; ?? TÄRKEIN: jos yksikin piste kameran edessä ? hylkää koko poly
        if (zr + origz) >= 0 [
            valid: false
        ]

        jakaja: (maxx - (zr + origz))
        if jakaja = 0 [jakaja: 0.00000000001]

        temp: maxx / jakaja

        append xp (x0 + ((xr + origx) * temp))
        append yp (y0 - ((ytb/:i + origy) * temp))
    ]

    ; --- PIIRTO ---
    if all [
        kelpaa
        valid
        (length? xp) >= 4
    ][
        append plot compose [
            image (as-pair xp/1 yp/1)
                  (as-pair xp/2 yp/2)
                  (as-pair xp/3 yp/3)
                  (as-pair xp/4 yp/4)
                  (kuva)
        ]
    ]
]



		main: layout [
			box (as-pair (maxx) (maxy)) white effect reduce ['draw plot]
		]
		kuva1: copy/part skip to-image main (as-pair 20 20) (as-pair maxx maxy)
		save/png to-file rejoin ["yritys" kuvaind ".png"] kuva1
		print kuvaind

		alfay1: alfay1 - 0.1
		maxxpoly: -9999999
		minpoly: 9999999
		foreach poly polys [
			poly/xtb/1: poly/xtb/1 + dx
			poly/xtb/2: poly/xtb/2 + dx
		poly/xtb/3: poly/xtb/3 + dx
		poly/xtb/4: poly/xtb/4 + dx
		if poly/xtb/4 > maxxpoly [maxxpoly: poly/xtb/4]
		if poly/xtb/4 < minpoly [minpoly: poly/xtb/4]
	]
	if (maxxpoly > 70000) or (minpoly < -108000) [dx: - dx]
	;print [minpoly maxxpoly]

	if ((random 1000) = 1) and (kuvaind > 500) [
	    repeat i length? polys [
	        ran: random length? polys

	        apu: polys/:i/kuva
	        polys/:i/kuva: polys/:ran/kuva
	        polys/:ran/kuva: apu
	    ]
	    append freimit kuvaind
	]

]
probe freimit
halt
; ffmpeg -framerate 30 -i yritys%d.png -c:v libx264 -r 30 video.mp4

No, selitetään vähän tätä toista koodia, jolla laitoin ääniefektin niihin kohtiin, joissa taulujen kuvat sekoitettiin. Freimeja tehdessä oli ehto:

if ((random 1000) = 1) and (kuvaind > 500)

..niin silloin sekoitetaan kaikki gallerian taulut. eli noin joka tuhannes freimi. Otin kuvaind muuttujan arvot talteen ja ohjelman lopuksi tulostin ne liitin tähän ohjemaan:

rebol []

lmrk: to-char 34  ; "

filters: copy ""
inputs: copy ""


; --- SYÖTE ---
freimit: [987 1750 1935 3234 3665 3848 4346 5012 6309 8638 8975 11192 12400 13517 14178 15000 15080 15266 16495
 18326 19471 19596 20429 20799 21425 22089 22266 22563 22927 23195 23526 23937 24499 24747 25838 26760
 27813 28183 31328 31443 31638 33452 33613 33938 34258 34334 34627 34758 35495 35718 35922]  ; <-- sinun data tähän

print ["PAM määrä:" length? freimit]

; --- VÄLIT ---
välit: copy []

repeat i (length? freimit) - 1 [
    append välit (freimit/(i + 1) - freimit/(i))
]

; --- PERUSARVOT ---
sum: 0
minv: 999999999
maxv: 0

foreach v välit [
    sum: sum + v
    if v < minv [minv: v]
    if v > maxv [maxv: v]
]

keski: sum / length? välit

print "---- PERUS ----"
print ["keski väli:" keski]
print ["min väli:" minv]
print ["max väli:" maxv]

; --- VARIANSSI ---
var: 0
foreach v välit [
    var: var + ((v - keski) * (v - keski))
]
var: var / length? välit

print ["varianssi:" var]

; --- KLUSTERIT ---
cluster-raja: 200

print "---- KLUSTERIT ----"
cluster-count: 0

repeat i (length? freimit) - 1 [
    väli: freimit/(i + 1) - freimit/(i)

    if väli < cluster-raja [
        print ["CLUSTER!" freimit/(i) "->" freimit/(i + 1) "väli:" väli]
        cluster-count: cluster-count + 1
    ]
]

print ["clusterien määrä:" cluster-count]

; --- HISTOGRAMMI ---
pieni: 0
normaali: 0
iso: 0

foreach v välit [
    either v < 500 [
        pieni: pieni + 1
    ][
        either v < 1500 [
            normaali: normaali + 1
        ][
            iso: iso + 1
        ]
    ]
]

print "---- JAKAUMA ----"
print ["pieni (<500):" pieni]
print ["normaali (500-1500):" normaali]
print ["iso (>1500):" iso]

; --- BONUS: ENSIMMÄISET VÄLIT ---
print "---- EKAT 10 VÄLIÄ ----"
repeat i min 10 length? välit [
    print välit/:i
]



fps: 30

repeat i length? freimit [
    freimi: freimit/:i

    suunta: 0
    if random 100 > 80 [suunta: 1 + random 2]
    if random 100 < 10 [suunta: -1 - random 2]

    frame2: freimi + suunta
    aika-ms: to-integer (frame2 * 1000 / fps)

    idx: random 11
    tied: rejoin [idx ".wav"]

    append inputs rejoin [" -i " tied]

    ; ?? EI VÄLEJÄ | ympärille!
    append filters rejoin [
        "[" i ":a]adelay=" aika-ms "|" aika-ms "[a" i "];"
    ]
]

; --- amix ---
mix: copy ""
repeat i length? freimit [
    append mix rejoin ["[a" i "]"]
]

append filters rejoin [
    mix "amix=inputs=" length? freimit
]

; --- KOMENTO ---
cmd: rejoin [
    "ffmpeg -i video.mp4"
    inputs
    " -filter_complex "
    lmrk filters lmrk
    " -c:v copy -c:a aac output.mp4"
]

write %render.cmd cmd
print "render.cmd tehty"
halt

Se teki .cmd skriptin, jossa ffmpeg:n käskyllä lisätään arvottu ääniefekti 1.wav, 2.wav,...,11.wav siihen kohtaan, missä kaikki gallerian taulut sekoitetaan. ffmpeg:n ohjelman syntaksista en paljoa tajunnut, eikä tarvinnutkaan, sillä tuon skriptin antoi ChatGPT. Huvikseni pistin sen tulostamaan (ChatGPT:n avustuksella) kaikenlaista dataa noista kohdista, joissa videossa taulut sekoitetaan ja tulee ääniefekti:

PAM määrä: 51
---- PERUS ----
keski väli: 698.7
min väli: 76
max väli: 3145
varianssi: 422605.49
---- KLUSTERIT ----
CLUSTER! 1750 -> 1935 väli: 185
CLUSTER! 3665 -> 3848 väli: 183
CLUSTER! 15000 -> 15080 väli: 80
CLUSTER! 15080 -> 15266 väli: 186
CLUSTER! 19471 -> 19596 väli: 125
CLUSTER! 22089 -> 22266 väli: 177
CLUSTER! 31328 -> 31443 väli: 115
CLUSTER! 31443 -> 31638 väli: 195
CLUSTER! 33452 -> 33613 väli: 161
CLUSTER! 34258 -> 34334 väli: 76
CLUSTER! 34627 -> 34758 väli: 131
clusterien määrä: 11
---- JAKAUMA ----
pieni (<500): 27
normaali (500-1500): 18
iso (>1500): 5
---- EKAT 10 VÄLIÄ ----
763
185
1299
431
183
498
666
1297
2329
337
render.cmd tehty

20 minuutin videoon tulee 36 000 framea, eli kohtien odotusarvo oli 36, mutta niitä tulikin 51 kpl.

En oikein jaksa selitellä! Taide puhukoon puolestaan. Jos on jotain kysyttävää, niin vastaan mielelläni.

Vastaus

Muista lukea kirjoitusohjeet.
Tietoa sivustosta