3D ohjelmointikykyni ovat alkeelliset. Tiedän kuinka x,y,z koordinaatta projisoidaan screenin kaksiulotteiselle pinnalle:
;projisoi jakaja: maxx - (z + origz) if jakaja = 0 [jakaja: 0.000000001] temp: maxx / jakaja xscreen: x0 + ((x + origx) * temp) yscreen: y0 - ((y + origy) * temp)
... ja jotenkuten kuinka pisteitä kierretään x,y ja z-akselin ympäri. Siihen se jääkin.
Nyt pitäisi saada tietää, että miten otetaan selville koska jokin tasainen pinta näytetään. Intuitio sanoo jotain, että "silloin kun pinnasta piirretty kohtisuorainen jana osoittaa katsojan suuntaan", tai jotain muuta ehkä liian monimutkaista minulle - kuitenkin muistan joskus 80-luvulla lukeneeni Pelin tekijän oppaasta, että ongelmaan on hyvin yksinkertainen testikin, missä käytetään pelkästään yhteen- ja kertolaskuja.
Kuten tuosta pyörivästä kuutio videosta näette, niin kuution takaseinäkin, mikä osoittaa katsojasta poispäin, aina näytetään, mikä siis on se ongelmani.
Ja ei: REBOL:ssa ei ole mitään 3D kirjastoja, vaan kaikki on ohjelmoitava itse alusta loppuun.
Kannattanee tutustua vektorien piste- ja ristituloon ja vektorin normalisointiin, joita yhdistelemällä onnistuu suurin osa kaikesta 3d-grafiikkaan tarvittavasta matematiikasta. En anna suoraa kaavaa, koska jos et opi itse laskemaan ja soveltamaan, olet huomenna taas uuden samanlaisen kysymyksen kanssa täällä.
Täältä kannatusta Metabolixin neuvolle. Ottamalla ristitulon kahdesta vektorista mitkä muodostavat polygonin kaksi sivua saat laskettua polygonille normaalin ja tiedät, että polygoni on näkyvä, jos se osoittaa katsojaa kohti. Tämä metodi on yksinkertainen, mutta asettaa joitain rajoituksia polygonille joihin kannattaa tutustua ettei tule yllätystä.
Metabolix kirjoitti:
Kannattanee tutustua vektorien piste- ja ristituloon ja vektorin normalisointiin,...
Sivu käsittelee blankkoja sillä tavalla, että en voi esittää viestiäni täällä, mutta esitän sen kuvana:
Viestissä on linkki, tämä: https://petke.info/nelio.png
Koetapa Petri käyttää kooditagia tasalevyisen tekstin esittämiseen. Teksti kuvassa on aika kelju tapa esittää "viesti".
Tekemäsi laskutoimitukset näyttävät vilkaisten oikeilta ja noista voi lähteä liikkeelle, eli kulmien koordinaateista voi muodostaa vähennyslaskulla vektorit, näiden ristitulona sitten saa kohtisuoran eli tasosta ulospäin osoittavan vektorin, josta katseen suuntavektorin kanssa laskettavan pistetulon etumerkistä selviää, onko tason etupuoli katsojaan päin.
Yksi laskuissa huomioitava asia on vielä, onko koordinaatisto oikea- vai vasenkätinen ja onko kulmion kulmat lueteltu myötäpäivään vai vastapäivään. Valitsemalla jonkin näistä väärin voi saada laskuissa vastakkaisen etumerkin.
Metabolix kirjoitti:
Koetapa Petri käyttää kooditagia
No tässä kooditägeilla (joiden niidenkään käyttö ei niin kätevää ole, kun rivit jatkuvat reunan yli).
Mod. korjasi kooditagien järkevän käytön.
Hienoa Metabolix, että kannustat itseopiskeluun. Googlailu johti mm. tänne Ohjelmointiputkaan. Kuvittelisin, että osasin muodostaa kahden vektorin ristitulon:
kohta 1):
[x1} [x2] [(y1 * z2) - (z1 * y2)] [y1} * [y2] = [(z1 * x2) - (x1 * z2)] [z1} [z2] [(x1 * y2) - (y1 * x2)]
Siinä siis vektoreiden alkupisteet ovat origossa, siksi yhden vektorin
määrittää kolme lukua eli x,y ja z koordinaatta, mikä matriisein merkitään:
[x] [y] [z]
Kuvittelisin myös, että osaan ottaa kahden vektorin pistetulon:
kohta 2):
[x1] [x2] [y1] * [y2] = (x1 * x2) + (y1 * y2) + (z1 * z2) [z1] [z2]
Pistetulo ei siis ole vektori vaan luku.
Vektorin x,y,z normalisointi taas tarkoittanee sitä, että vektori
jaetaan sen pituudella eli kun pituus:
pituus=Squre-Root((x*x)+(y*y)+(z*z))
kohta 3):
Niin vektorin (x,y,z) normalisoitu vektori on (x/pituus,y/pituus,z/pituus))
Ennen kuin alan pureskelemaan sitä vaikeaa pähkinää, että miten näillä laskutoimituksilla saadaan selville osoittaako neliö katsojaa kohti, niin kysyn, että ovatko nuo laskutoimitukset oikein?
kohta 4)
Ja lopuksi kysyn, että onko siis kyseessä siis tällainen neliö: https://petke.info/nelio.png
Ei tarvitse neuvoa pidemmääle kunhan sanotte ei tai kyllä, että onko oikein vai väärin ja mikä kohta 1, 2, 3 tai 4, jos jokin on väärin.
Eipä kuutiohommasta tunnu paljo mitään tulevan, ainakaan vielä. En hallitse teoriasta käytäntöön vääntämistä enkä näköjään osaa edes tuolla -> https://retro64.altervista.org/blog/another-look-at-3d-graphics-fast-hidden-faces-removal-back-face-culling/ olevasta hyvästä oppaasta apinoida. Mulla oli enkku 5 lukiossa, että sekin vaikeuttaa luetun ymmärtämistä.
Tätä en ymmärrä sieltä:
'Please note that x(9) must be rotated along with the other points.'
Minä lasken sen aina uudestaan kun en ymmärrä miten sitä voitaisiin rotatoida? Kierroilla x,y,z-akseleiden ympärikö?
Apinointia hankaloitti tosi paljon myös se, että mulla on kulmapisteet numeroitu eri tavalla: https://petke.info/munnumerointi.png
Enkä osannut/ruvennut/jaksanut ajatella edes aliohjelman tekoa vaan manuaalisesti kopsasin koodia jokaiselle kuudelle tahkolle erikseen.
Ainahan tosin voin perustella aikaansaannostani sillä, että en ole koodari, vaan olen taiteilija ja tämän tuotoksen voi tulkita hyvinkin taiteellisena:
(on error...)
PS: Ei välttämättä tarvitse neuvoa, kun en kerta teidän aiemmistakaan hyvistä neuvoista huolimatta osannut. Toivottavasti mulla on huomenna tai ylihuomenna parempi koodauspäivä. Olen näissä koodausharrastuksissani oppinut, että päätä kannattaa seinään lyödä. Voi se Aurinko lopulta risukasaankin paistaa.
rebol[] maxx: 1880 ;kuvan leveys maxy: 1080 ; ja korkeus alfax: 1 ;monta astetta x-akselin ympäri pyöritään framejen välillä? alfay: 2 ; -,,- y -,,- alfaz: 3 ; -,,- z -,,- x0: 0 y0: 0 z0: 0 kuva1: load %kuva1.png ;jokaiseen kuuteen tahkoon tulee oma kuva kuva2: load %kuva2.png kuva3: load %kuva3.png kuva4: load %kuva4.png kuva5: load %kuva5.png kuva6: load %kuva6.png origx: 0 origy: 0 origz: -10 x: copy[] ;blockki (on niinkuin taulukko) kuution kulmien x koordinaataoille y: copy[] z: copy[] xp: copy[] ;3D avaruuden x,y,z:sta saatu 2D tason koordinaatta yp: copy[] apux: copy[] apuy: copy[] apuz: copy[] for i 1 8 1 [ ;asetetaan blockkiin 0-alkiot, jotta alkioon voidaan append x 0 ;viitata indeksillä. append y 0 append z 0 append xp 0 append yp 0 append apuz 0 append apuy 0 append apux 0 ] pituus: 300 x/1: x0 - pituus ;Asetetaan kuution kahdeksan kulman koordinaatat. x/2: x0 + pituus x/3: x/2 x/4: x/1 x/5: x/1 x/6: x/2 x/7: x/3 x/8: x/4 y/1: y0 - pituus y/2: y/1 y/3: y0 + pituus y/4: y/3 y/5: y/1 y/6: y/2 y/7: y/3 y/8: y/4 z/1: pituus z/2: z/1 z/3: z/1 z/4: z/1 z/5: - pituus z/6: z/5 z/7: z/5 z/8: z/5 for kuvaind 1 600 1 [ ;tuotetaan 600 framea plot: copy[] ;projisoi. Lasketaan pisteen x,y,z screenikoordinaatat xp,yp for i 1 8 1 [ jakaja: (maxx - (z/(i) + origz)) if jakaja = 0 [jakaja: 0.00000000001] ;nollalla ei saa jakaa temp: maxx / jakaja xp/(i): x0 + ((x/(i) + origx) * temp) xp/(i): xp/(i) + (maxx / 2) yp/(i): y0 - ((y/(i) + origy) * temp) yp/(i): yp/(i) + (maxy / 2) ] x1: x/2 - x/3 y1: y/2 - y/3 z1: z/2 - z/3 x2: x/2 - x/6 y2: y/2 - y/6 z2: z/2 - z/6 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale2: 0.01 x9: (xn * scale2) + x/1 y9: (yn * scale2) + y/1 z9: (zn * scale2) + z/1 k2: (((x/2 * x/2) - x/4) + (y/2 * (y/2 - y/4)) + (z/2 - z/4)) / origz vis2: k2 - z/2 + z9 ;oikereuna if vis2 < 0 [ append plot compose [ image (as-pair xp/2 yp/2) (as-pair xp/6 yp/6) (as-pair xp/7 yp/7) (as-pair xp/3 yp/3) (as-pair xp/2 yp/2) (kuva2) ;oikereuna ] ] x1: x/6 - x/7 y1: y/6 - y/7 z1: z/6 - z/7 x2: x/6 - x/5 y2: y/6 - y/5 z2: z/6 - z/5 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale1: 0.01 x9: (xn * scale1) + x/6 y9: (yn * scale1) + y/6 z9: (zn * scale1) + z/6 k3: (((x/4 * x/4) - x9) + (y/4 * (y/4 - y9)) + (z/4 - z9)) / origz vis3: k3 - z/6 + z9 ;Takaseinä if vis3 < 0 [ append plot compose [ image (as-pair xp/5 yp/5) (as-pair xp/6 yp/6) (as-pair xp/7 yp/7) (as-pair xp/8 yp/8) (as-pair xp/5 yp/5) (kuva3) ;takaseinä ] ] x1: x/2 - x/6 y1: y/2 - y/6 z1: z/2 - z/6 x2: x/2 - x/1 y2: y/2 - y/1 z2: z/2 - z/1 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale1: 0.01 x9: (xn * scale1) + x/2 y9: (yn * scale1) + y/2 z9: (zn * scale1) + z/2 k4: (((x/2 * x/2) - x9) + (y/2 * (y/2 - y9)) + (z/2 - z9)) / origz vis4: k4 - z/2 + z9 ;yläpuoli if vis4 < 0 [ append plot compose [ image (as-pair xp/1 yp/1) (as-pair xp/2 yp/2) (as-pair xp/6 yp/6) (as-pair xp/5 yp/5) (as-pair xp/1 yp/1) (kuva5) ;yläpuoli ] ] x1: x/3 - x/7 y1: y/3 - y/7 z1: z/3 - z/7 x2: x/3 - x/4 y2: y/3 - y/4 z2: z/3 - z/4 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale1: 0.01 x9: (xn * scale1) + x/3 y9: (yn * scale1) + y/3 z9: (zn * scale1) + z/3 k5: (((x/3 * x/3) - x9) + (y/3 * (y/3 - y9)) + (z/3 - z9)) / origz vis5: k5 - z/3 + z9 ;alapuoli if vis5 < 0 [ append plot compose [ image (as-pair xp/4 yp/4) (as-pair xp/3 yp/3) (as-pair xp/7 yp/7) (as-pair xp/8 yp/8) (as-pair xp/4 yp/4) (kuva6) ;alapuoli ] ] x1: x/5 - x/8 y1: y/5 - y/8 z1: z/5 - z/8 x2: x/5 - x/1 y2: y/5 - y/1 z2: z/5 - z/1 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale1: 0.01 x9: (xn * scale1) + x/5 y9: (yn * scale1) + y/5 z9: (zn * scale1) + z/5 k6: (((x/5 * x/5) - x9) + (y/5 * (y/5 - y9)) + (z/5 - z9)) / origz vis6: k6 - z/5 + z9 ;vasenreuna if vis6 < 0 [ append plot compose [ image (as-pair xp/1 yp/1) (as-pair xp/5 yp/5) (as-pair xp/8 yp/8) (as-pair xp/4 yp/4) (as-pair xp/1 yp/1) (kuva4) ;vasenreuna ] ] x1: x/1 - x/4 y1: y/1 - y/4 z1: z/1 - z/4 x2: x/1 - x/2 y2: y/1 - y/2 z2: z/1 - z/2 xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) scale1: 0.01 x9: (xn * scale1) + x/1 y9: (yn * scale1) + y/1 z9: (zn * scale1) + z/1 k1: (((x/1 * x/1) - x9) + (y/1 * (y/1 - y9)) + (z/1 - z9)) / origz vis1: k1 - z/1 + z9 ;etuseinä if vis1 < 0 [ 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) (as-pair xp/1 yp/1) (kuva1) ;etuseinä ] ] ;kierto y-akselin ympäri for i 1 8 1 [ apu: y/(i) y/(i): ((cosine alfay) * y/(i)) + ((sine alfaz) * z/(i)) z/(i): (- (sine alfay) * apu) + ((cosine alfaz) * z/(i)) ] ;kierrot x-akselin ympäri for i 1 8 1 [ apu: x/(i) x/(i): ((cosine alfax) * x/(i)) + (- (sine alfaz) * z/(i)) z/(i): (((sine alfax)) * apu) + ((cosine alfaz) * z/(i)) ] ;kierrot z-akselin ympäri for i 1 8 1 [ apu: x/(i) x/(i): ((cosine alfax) * x/(i)) + ((sine alfay) * y/(i)) y/(i): ((- (sine alfax)) * apu) + ((cosine alfay) * y/(i)) ] main: layout [ box (as-pair (maxx) (maxy)) white effect reduce ['draw plot] ] kuv: copy/part skip to-image main 20x20 (as-pair maxx maxy) save/png to-file rejoin ["kuutio" kuvaind ".png"] kuv print kuvaind ] halt
Minulla oli skaalaustekijänä vakio 0.01 Unohdin, että skalaaritulolla saatu vektori (xn,yn,zn) piti normalisoida siten, että sen komponentit jaetaan sen pituudella - näin saadaan vektori, minkä pituus on yksi. Mutta tulee ongelmia:
** Math Error: Math or number overflow
** Where: do-body
** Near: xn * xn
>>
Yritin kaiken näköistä, jotta tuosta ongelmasta päästäisiin, mutta en ole vielä onnistunut ratkomaan sitä...palaan asiaan huomenna. EDIT: silee, että xn,yn ja zn kerrotaan 1.0:lla päästään ongelmasta.
Hei piiiitkästä aikaa! Sain kuution pyörimään ja sain aikaiseksi tällaisen videon Maamme laulusta: https://youtu.be/BjpkPuhLiyo
Ärsyttävä väärintoiminto siinä on: se tahko, mikä aluksi on alatahko tulee kolme framea liian aikaisin näkyviin ja lähtee kolme framea myöhässä. Ja näyttää muutakin pientä häikkää välillä olevan... Olen kokeillut kaikenlaista, mutta virhe ei ole korjaantunut. Johtuukohan se jotenkin siitä, että olen luetellut kärkipisteitä väärässä järjestyksessä aliohjelmalle, joka tahkon piirtämisestä huolehtii? Kokeilin kyllä monelaisia järjestyksiä, mutta se ei auttanut :( Ongelma ei ratkonnut edes sillä tavalla, että piirrän tahkon ensimäisenä! Muitten tahkojenhan pitäisi itsestään selvästi silloin peittää se. En tosiaan tajua! Tarkoitus olisi ehdottaa tuota videota Yö ry:n videomakasiiniin, joten tuo virhe pitäisi saada korjattua, eli olisin todella kiitollinen neuvoista.
Koska kärkipisteiden numerointini on ehkä vähän outo, niin tässä kuva: https://petke.info/boxi.jpg siinä siis etutahko on väritetty violetilla ja sen kärkipisteiden numerointi myötäpäivään on 1, 2, 3 ja 4.
Koska video on 48 fps, niin melko tarkasti kuutiota saa tarkkailla, että virheen huomaa, mutta kyllä se pienenä ajoittaisena vilkkumisena ilmenee.
Vaikka tämä on ohjelmointiputka, niin teoksen taitelliseen laatuun/laaduttomuuteenkin saa ottaa kantaa, ellei YP:llä ole toista mielipidettä.
Vaikka animaation framet tuottanut koodi on pitkä, niin laitan sen tänne näkyville. Jos joku tosiaan löytäisi siitä selityksen tuolle virheelliselle toiminnolle. Toisaalta alkoi nyt teoksen läpikatsottuani tuntumaan, että miksi nähdä vaivaa - ja nukutun yön jälkeen teos tuntunee melko surkealta...Tosin hauskaa itse teoksen ohjelmointi oli!!
rebol[] maxx: 1920 ;kuvan leveys maxy: 1080 ; ja korkeus -> FullHD x000: maxx / 2 y000: maxy / 2 alfax: 2 ;monta astetta x-akselin ympäri pyöritään framejen välillä? alfay: 0 ; y alfaz: 0 ; z x0: 0 y0: 0 z0: 0 print "odota" images: copy[] for i 1 50 1 [ ;ladataan 50 kuvaa pic: load to-file rejoin ["x" i ".png"] append images pic ] ki: 0 origx: 1 origy: 1 origz: 1 x: copy[] ;blockki (on niinkuin taulukko) kuution kulmien x koordinaataoille y: copy[] z: copy[] xp: copy[] ;3D avaruuden x,y,z:sta saatu 2D tason koordinaatta yp: copy[] pituus: 200 for i 1 8 1 [ ;asetetaan blockkiin 0-alkiot, jotta alkioon voidaan append x 0 ;viitata indeksillä. append y 0 append z 0 append xp 0 append yp 0 ] x/1: x0 - pituus ;aSetetaan manuaalisesti kuution kulmien koordinaatat. x/2: x0 + pituus ;kulmia on kahdeksan. Tämä on siis alkutilanne. x/3: x/2 x/4: x/1 x/5: x/1 x/6: x/2 x/7: x/3 x/8: x/4 y/1: y0 - pituus y/2: y/1 y/3: y0 + pituus y/4: y/3 y/5: y/1 y/6: y/2 y/7: y/3 y/8: y/4 z/1: 100 z/2: 100 z/3: 100 z/4: 100 z/5: z/1 - (2 * pituus) z/6: z/2 - (2 * pituus) z/7: z/3 - (2 * pituus) z/8: z/4 - (2 * pituus) värit: copy[] for i 255 0 5 [ append värit to-tuple compose [(255) (255) (i)] ] for i 255 0 -5 [ append värit to-tuple compose [(i) (i) (255)] ] color: 1 dc: 1 maxcolor: length? värit substr: func [string start length][ copy/part at string start length ] font-obj2: make face/font [name: "Arial" size: 80] print "odota" sanat: [ "Oi maamme, Suomi, synnyinmaa, " "soi, sana kultainen! " "Ei laaksoa, ei kukkulaa, " "ei vettä rantaa rakkaampaa, " "kuin kotimaa tää pohjoinen, " "maa kallis isien! " "On maamme köyhä, siksi jää, " "jos kultaa kaivannet " "Sen vieras kyllä hylkäjää, " "mut meille kallein maa on tää, " "sen salot, saaret, manteret, " "ne meist on kultaiset. " "Ovatpa meille rakkahat " "koskemme kuohuineen, " "ikuisten honkain huminat, " "täht'yömme, kesät kirkkahat, " "kaikk'kuvineen ja lauluineen " "mi painui sydämeen. " "Täss auroin, miekoin, miettehin " "isämme sotivat, " "kun päivä piili pilvihin " "tai loisti onnen paistehin, " "täss Suomen kansan vaikeimmat " "he vaivat kokivat. " "Tään kansan taistelut ken voi " "ne kertoella, ken? " "Kun sota laaksoissamme soi, " "ja halla näläntuskan toi, " "ken mittasi sen hurmehen " "ja kärsimykset sen? " "Täss on sen veri virrannut " "hyväksi meidänkin, " "täss iloaan on nauttinut " "ja murheitansa huokaillut " "se kansa, jolle muinaisin " "kuormamme pantihin. " "Tääll' olo meill on verraton " "ja kaikki suotuisaa, " "vaikk onni mikä tulkohon, " "maa isänmaa se meillä on. " "Mi maailmass on armaampaa " "ja mikä kalliimpaa? " "Ja tässä, täss' on tämä maa, " "sen näkee silmämme. " "me kättä voimme ojentaa " "ja vettä rantaa osoittaa " "ja sanoa: kas tuoss' on se, " "maa armas isäimme. " "Jos loistoon meitä saatettais " "vaikk' kultapilvihin, " "mis itkien ei huoattais, " "vaan tärkein riemun sielu sais, " "ois tähän köyhään kotihin " "halumme kuitenkin. " "Totuuden, runon kotimaa " "maa tuhatjärvinen " "miss' elämämme suojan saa, " "sa muistojen, sa toivon maa, " "ain ollos, onnees tyytyen, " "vapaa ja iloinen. " "Sun kukoistukses kuorestaan " "kerrankin puhkeaa, " "viel lempemme saa nousemaan " "sun toivos, riemus loistossaan, " "ja kerran, laulus synnyinmaa " "korkeemman kaiun saa. " ] sanat2: copy[] foreach s sanat [ append sanat2 s ] sanat: "" for i 1 length? sanat2 1 [ for j 1 length? sanat2/(i) 1 [ sanat: join sanat substr sanat2/(i) j 1 ] ] print length? sanat frameja: (length? sanat) * 6 print rejoin ["frameja yhteensä " frameja] ;9876 sek: frameja / 40 minuutit: round/down sek / 60 seksek: sek - (60 * minuutit) print rejoin ["Video kestää siis " sek " sekuntia, eli " minuutit " minuuttia ja " seksek "sekuntia."] merkit: copy[] for i 1 length? sanat 1 [ append merkit substr sanat i 1 ] merkit: unique/case merkit print "Teen kuvia..." tehty: "" merkki: 1 kuvaind: 1 dkuvaind: (maxx * 0.74) / (40 * 6) ;paljon merkkijonoa siirretään vasemmalle... ku: copy[] for i 1 50 1 [ append ku i ] apukuvaind: 20 rand: func [][ ;palauttaa arvon satunnaislukuarvon -3...3 return -3 + random 7 - 1 ] piirrä: func [n1 n2 n3 n4 kuva][ ;tutkii näytetäänkö tahko... x1: x/(n1) - x/(n2) y1: y/(n1) - y/(n2) z1: z/(n1) - z/(n2) x2: x/(n1) - x/(n3) y2: y/(n1) - y/(n3) z2: z/(n1) - z/(n3) xn: (y1 * z2) - (y2 * z1) yn: -1 * ((x1 * x2) - (x2 * z1)) zn: (x1 * y2) - (x2 * y1) xn: 1.0 * xn yn: 1.0 * yn zn: 1.0 * zn npituus: square-root ((xn * xn) + (yn * yn) + (zn * zn)) + 1.0E-99 xn2: xn / npituus yn2: yn / npituus zn2: zn / npituus npituus2: square-root ((xn2 * xn2) + (yn2 * yn2) + (zn2 * zn2)) + 1.0E-99 scale: npituus / npituus2 x9: (xn * scale) + x/(n1) y9: (yn * scale) + y/(n1) z9: (zn * scale) + z/(n1) k: (x/(n1) * (x/(n1) - x/(n2))) + (y/(n1) * (y/(n1) - y/(n2))) + (z/(n1) * (z/(n1) - z/(n2))) / origz vis: k - z/(n1) + z9 if vis < 0 [ append plot compose [ image (as-pair (a + xp/(n1)) (b + yp/(n1))) (as-pair (a + xp/(n3)) (b + yp/(n3))) (as-pair (a + xp/(n4)) (b + yp/(n4))) (as-pair (a + xp/(n2)) (b + yp/(n2))) (images/(ku/(kuva))) ] ] if (vis > 0) and ((mod kuvaind 197) = 0) [ ;jos tahko on piilossa ja kuvaind on jaollinen 197:lla vaihdetaan kuvaa ku/(kuva): maxkuva + 1 maxkuva: maxkuva + 1 if maxkuva = length? images [ maxkuva: 1 ku/(kuva): maxkuva ] ] ] maxkuva: 6 halkaisija: square-root ((maxx * maxx) + (maxx * maxx)) kk: 0 sx1: x000 + (-0.5 * halkaisija) sx2: x000 + (0.5 * halkaisija) sy1: y000 + (-0.5 * halkaisija) sy2: y000 + (0.5 * halkaisija) salfa: 0 for i 1 length? sanat 1 [ ; käydään läpi kaikki Maamme laulun sanojen kirjaimet kirjain: substr sanat i 1 tehty: join tehty kirjain indexi: index? find merkit kirjain dkorkeus: 1.5 * indexi korkeus: 0 for apuri 1 6 1 [ ;jokaisen kirjaimen kohdalla 6 framea plot: copy[] color: 1 prin kirjain append plot compose [ font (font-obj2) line-width 4 ] for siniy sy1 sy2 2 [ append plot compose [ pen (värit/(color)) line ] for sinix sx1 sx2 4 [ py: siniy + (korkeus * cosine sinix) ;siirrot sinix: sinix - x000 py: py - y000 apu: sinix sinix: (sinix * cosine salfa) - (py * sine salfa) py: (apu * sine salfa) + (py * cosine salfa) ;siirrot takaisin sinix: sinix + x000 py: py + y000 append plot compose [ (as-pair sinix py) ] ] color: color + dc if (color = maxcolor) or (color = 0) [dc: - dc color: color + dc] ] ;projisoi. Lasketaan pisteen x,y,z screenikoordinaatat xp,yp for i 1 8 1 [ jakaja: (maxx - (z/(i) + origz)) if jakaja = 0 [jakaja: 0.00000000001] ;nollalla ei saa jakaa temp: maxx / jakaja xp/(i): x0 + ((x/(i) + origx) * temp) xp/(i): xp/(i) + (maxx / 2) yp/(i): y0 - ((y/(i) + origy) * temp) yp/(i): yp/(i) + (maxy / 2) ] a: 0 b: 70 piirrä 4 8 3 7 ku/5 ;alapuoli piirrä 1 4 2 3 ku/1 ;etu puoli piirrä 8 5 7 6 ku/2 ;taka puoli piirrä 2 3 6 7 ku/3 ;vasen puoli piirrä 5 8 1 4 ku/4 ;oikea puoli piirrä 1 2 5 6 ku/6 ; yläpuoli ;siirrot for i 1 8 1 [ x/(i): x/(i) - x0 y/(i): y/(i) - y0 z/(i): z/(i) - z0 ] ;kierrot x-akseli for i 1 8 1 [ apu: y/(i) y/(i): ((cosine alfax) * y/(i)) + ((sine alfax) * z/(i)) z/(i): ((- sine alfax) * apu) + ((cosine alfax) * z/(i)) ] ;kierrot y-akseli for i 1 8 1 [ apu: x/(i) x/(i): ((cosine alfay) * x/(i)) + ((- sine alfay) * z/(i)) z/(i): ((sine alfay) * apu) + ((cosine alfay) * z/(i)) ] ;kierrot z-akseli for i 1 8 1 [ apu: x/(i) x/(i): ((cosine alfaz) * x/(i)) + ((sine alfaz) * y/(i)) y/(i): ((- (sine alfaz)) * apu) + ((cosine alfaz) * y/(i)) ] ;siirrot for i 1 8 1 [ x/(i): x/(i) + x0 y/(i): y/(i) + y0 z/(i): z/(i) + z0 ] append plot compose [ pen black text (as-pair (20 - ((kuvaind - 1) * dkuvaind)) 10) (substr sanat 1 length? sanat) pen white text (as-pair (20 - ((kuvaind - 1) * dkuvaind) + 4) 14) (substr sanat 1 length? sanat) ] main: layout [ box (as-pair (maxx) (maxy)) black effect reduce ['draw plot] ] kuv: copy/part skip to-image main 20x20 (as-pair maxx maxy) save/png to-file rejoin ["_testi" kuvaind ".png"] kuv print kuvaind kuvaind: kuvaind + 1 salfa: salfa + 0.4 if apuri = 4 [dkorkeus: - dkorkeus] korkeus: korkeus + dkorkeus if (mod kuvaind (40 * 5)) = 0 [ ;vaihdetaan kiertokulmia 5 sekunnin välein kun .fps on 40 alfax: rand alfay: rand alfaz: rand ] ] ] halt
Koodi ei ole selvimmästä päästä, mutta tuo näkyvyyden laskenta ei ihan minulle aukea. Voisit laskea pistetulon tahkon normaalista ja tahkon ja katsojan välisestä vektorista, niin saisit tuloksen, onko tahko näkyvään suuntaan. Videossa näyttää, että laskisit tämän suhteessa vaakasuoraan (etkä katsojaan), jolloin perspektiivi jää huomiotta.
Metabolix kirjoitti:
Koodi ei ole selvimmästä päästä
Juu, sori. Koodi ei ole selvimmästä päästä, kun se oli apinoitu modifioiden tuolta: https://retro64.altervista.org/blog/another-look-at-3d-graphics-fast-hidden-faces-removal-back-face-culling/
Teoriasta ja ehkäkin melko helposta ja yksinkertaisesta sellaisesta huolimatta, en osannut itse koodata :) ... ei sittenkään :) vaan :( Eli ei paljo hymyilytäkään. Kun en tiedä ees mitkä ovat katsojan koordinaatit!
Onko ne nää:
origx: 1
origy: 1
origz: 1
?
Lähetin kyllä jo videon, että liian myöhäistä alkaa korjaaamaan. MakeAvilla kesti noin 10 tuntia tehdä 9876:sta framesta video eli ei ehkä huvittaisikaan - en jaksaisi kärsimättömänä taas odottaa. EDIT: MakeAvi teki nopeasti videon! Mutta framejen teko kesti yli 10 tuntia. Oon taas yö valvonnut liikaaa - pää on piimää.
PetriKeckman kirjoitti:
Onko ne [katsojan koordinaatit] nää:
Tuosta en äkkiseltään saa selvää, tätä olisi kannattanut miettiä jo muuttujia nimetessä. :)
Onneksi voit väistää ongelman. Projektio toimii, joten back face culling onnistuu helposti myös 2D-kuvaan projisoiduista koordinaateista. Jos ristitulon etumerkki (eli kulmien kiertosuunta) on väärä, kulmio näyttää takapuolta ja se pitää jättää piirtämättä.
Eli koodissasi arvot k ja vis ovat jotain minulle käsittämätöntä, mutta niiden tilalla voisi olla jotain tämmöistä:
; vektorit kulmasta 1 kulmiin 2 ja 3 (kulmion 2D-projektiossa) dx2: xp/(n2) - xp/(n1) dy2: yp/(n2) - yp/(n1) dx3: xp/(n3) - xp/(n1) dy3: yp/(n3) - yp/(n1) ; ristitulo kertoo kiertosuunnan; tarkista itse, kuuluuko + vai - olla näkyvä. vis: dx2 * dy3 - dx3 * dy2
Jos tämän jälkeen osa tahkoista näkyy väärin, tarkista tahkojen kulmien järjestys noilla piirrä-riveillä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.