Moni varmasti muistaa noin puoli vuotta sitten julkaisemani The Linkku3D-moottorin joka saavutti vastoin kaikkia odotuksiani melko suuren suosion. Sen takia "vastoin odotuksiani", että se on omasta mielestäni suoraan sanottuna surkea buginen härpäke.
Päätinpä kuitenkin aloittaa uudestaan aivan puhtaalta pöydältä, ja tulokseksi sain tämän moottorin, joka lähti alkuun siitä kun Gwaur ja Peki kertoivat eräänlaisesta perspektiivikorjauksesta. Arvasin tietysti, että eihän tuo nyt vielä riitä mihinkään, mutta sitten keksinkin, että jos kerran kameraa ei voi pyörittää niin kuin Linkussa, ilman että syntyy buginen linkkumoottori, niin täytyy näin ollen pyörittää maailmaa kameran ympärillä, jolloin syntyy illuusio, joka näyttää siltä kuin kamera pyörisi päinvastaiseen suuntaan kuin maailma. Irkissä jotkut neuvoivat minua käyttämään matriiseja ja verteksipyörityksiä tjsp., mutta halusin edelleen kokeilla, voisinko tehdä moottorin alusta alkaen itse, opettelematta mitään mistään manuaaleista, tai muista valmiista kaavoista. Ja perspektiivikorjaus (eli tasan kaksi lyhyttä riviä koodia) on edelleenkin ainoa asia tässä moottorissa, jota en itse keksinyt. Tavallaan se on pohja, josta lähdin liikkeelle. Huomasin kuitenkin, että Gwaurin ja Pekin näyttämä korjaus oli epätäydellinen, joten jouduin tekemään siihen paljon parannuksia, jotta se toimisi täydellisesti. Myöhemmin huomasin tavallaan käyttäneenikin perspektiivikorjausta aikaisemmin ensimmäisessä koodivinkissäni, mutten ollut vielä silloin tajunnut sen merkitystä.
Aloitin tämän uuden moottorin 18.6 ja sain valmiiksi 21.7, eli reilussa kuukaudessa. Bugeja saattaa löytyä, mutta nyt kaavojen pitäisi ainakin olla kunnollisia, eikä mitään linkkuun menemistä ainakaan omasta mielestäni tapahdu.
Nimi "Optica" kuulostaa kenties vähän liian hienolta tavallisesta rautalanka-moottorista, ja googlettamalla selvisi, että nimeä on jo ennestään käytetty jossain toisessa 3d-moottorissa, mutta keksin nimen kuvastamaan sitä, että se on eräänlainen optinen korjaus verrattuna Linkkuun, ja nimi toimiikin vain etupäässä vain koodinimenä, eikä minään virallisena merkkinä.
Lisäsin koodiin kaksi esimerkki-maailmaa, jotka demonstroivat moottorin toimintaa. Ohjelma kysyy alussa kunpaa maailmaa haluaa kokeilla.
Lisäksi ohjelma kysyy, halutaanko mukaan lisähidastusta. Tämä sen vuoksi, että nopeimmilla koneilla moottori pyörisi aivan liian nopeasti.
Näppäimet, joilla liikutat kameraa:
4,6 käännä vasemmalle ja oikealle
9,3 käännä ylös ja alas
8,5 liikuta eteenpäin ja taaksepäin
Koodissa ei omasta mielestäni ole samaa purkkamaisuutta kuin Linkussa, ja se on tällä kertaa sisennetty, paremmin kommentoitu, ja muutenkin paljon selkeämpää.
Verteksit ja matriisit ovat luultavasti kuitenkin se parempi tapa 3d:n luomiseen, joten tästä ei kannata aivan vakavasti mallia ottaa, jos 3d:tä haluaa luoda. 3d:n luominen QB:llä vain on askarruttanut niin monia, eikä 3d-kirjastoja QB:lle juuri ole, niin että saattaa tästä jopa jotain hyötyä olla. Tästedes teen 3d:tä kuitekin luultavasti C:llä tai C++:lla, kunhan saan OpenGL:n, tai DirectX:n toimimaan. Näillä QB-moottoreilla pyrin siis vain kokeilemaan, kuinka paljon pystyisin tekemään alusta alkaen itse.
Niin kauan kuin en pysty C:tä, tai C++:aa käyttämään, koodailen VB:llä Eternity-nimistä peliä, jossa käytän Optica3D:tä.
Eternityn päivitykset (ja myös monet muut tekeleeni, mm. Linkku3D:llä tehty 3D-räiskintä) ovat saatavilla kotisivuiltani:
http://koodaa.mine.nu/~vohveli/
Suurkiitos tejeezille kotisivutilasta!
DECLARE SUB DrawBg (YA AS SINGLE) DECLARE SUB GenerateWorld () DECLARE FUNCTION Rndl! (ScWidth AS INTEGER) TYPE Camera 'Kamera X AS SINGLE 'ulottuvuudet Y AS SINGLE '... Z AS SINGLE '... XA AS SINGLE 'kulmat YA AS SINGLE '... END TYPE TYPE Vertex '3D-piste X AS SINGLE 'ulottuvuudet Y AS SINGLE '... Z AS SINGLE '... END TYPE TYPE Monitor '2D-piste X AS LONG 'ulottuvuudet Y AS LONG '... V AS INTEGER 'n?kyvyys-lippu END TYPE COMMON SHARED DataMode AS INTEGER COMMON SHARED Dot() AS Vertex, DAm AS INTEGER ON ERROR RESUME NEXT CLS PRINT "Optica3D engine 0.4.0" PRINT "Programmed by Hunajavohveli" PRINT PRINT "1=suorakulmioita 2=avaruus ?" INPUT "", DataMode PRINT "Lis?hidastusta? 0=ei 1=kyll?" INPUT "", SlowMode DIM Cam AS Camera 'Kamera DIM Dot(1 TO 1000) AS Vertex 'Pisteiden absoluttiset koordinaatit DIM Rot(1 TO 1000) AS Vertex 'Kameran arvojen mukaan absoluuttisista koordinaateista generoidut koordinaatit DIM Scr(1 TO 1000) AS Monitor 'N?yt?lle piirrett?v?t 2d-koordinaatit RANDOMIZE TIMER GenerateWorld 'Generoidaan maailma 'Kameran ominaisuudet Scale = 320 'Skaala (kokeile muuttaa) Cam.X = 0 'ulottuvuudet Cam.Y = -5 '... Cam.Z = 0 '... 'Vaihdetaan n?ytt?tilaa SCREEN 7, 0, , 1 'Kaksoispuskurointi CenterX = 160 'N?yt?n keskipiste CenterY = 100 '... 'K?ynnistet??n moottori... DO DrawBg Cam.YA 'Piirret??n tausta 'Projektoidaan 3d-koordinaatit 2d-tasoon FOR a = 1 TO DAm Scr(a).X = 0 'nollataan edelliset 2d-koordinaatit Scr(a).Y = 0 '... Scr(a).V = 0 '... 'suhteutetaan pisteiden absoluuttiset koordinaatit kameran koordinaatteihin rx = Dot(a).X - Cam.X ry = Dot(a).Y - Cam.Y rz = Dot(a).Z - Cam.Z 'generoidaan suhteutetuista koordinaateista uudet kameran kulmien mukaan Rot(a).X = COS(Cam.XA) * rx + SIN(Cam.XA) * rz Rot(a).Z = COS(Cam.XA) * COS(Cam.YA) * rz - SIN(Cam.XA) * COS(Cam.YA) * rx + SIN(Cam.YA) * ry Rot(a).Y = COS(Cam.YA) * ry - SIN(Cam.YA) * COS(Cam.XA) * rz - SIN(Cam.YA) * -SIN(Cam.XA) * rx 't?ysin suhteutetut 3d-koordinaatit rz = Rot(a).Z rx = Rot(a).X ry = Rot(a).Y 'perspektiivikorjaus IF rz > 0 THEN 'jos piste kameran edess?... sx = rx * Scale / rz + CenterX sy = ry * Scale / rz + CenterY Scr(a).V = -1 'n?kyvyys p??lle IF DataMode = 2 THEN PSET (sx, sy) 'pisteen piirto ELSEIF rz < 0 THEN 'takana... sx = -(rx * Scale / rz) * -rz + CenterX sy = -(ry * Scale / rz) * -rz + CenterY ELSE 'samalla syvyystasolla... IF ry <> 0 AND rx <> 0 THEN sx = rx * (200 / rx) * SGN(rx) + CenterX sy = ry * (200 / ry) * SGN(ry) + CenterY ELSEIF rx <> 0 THEN sx = CenterX + CenterX * SGN(rx) sy = CenterY ELSEIF ry <> 0 THEN sx = CenterX sy = CenterY + CenterY * SGN(ry) ELSE sx = CenterX sy = CenterY END IF END IF 't?h?n loppuu perspektiivikorjaus 'tallennetaan generoidut 2d-koordinaatit taulukkoon Scr(a).X = sx Scr(a).Y = sy NEXT a 'Piirret??n viivat n?yt?lle IF DataMode = 1 THEN FOR a = 1 TO DAm STEP 8 x1 = Scr(a).X: x2 = Scr(a + 1).X: x3 = Scr(a + 2).X: x4 = Scr(a + 3).X y1 = Scr(a).Y: y2 = Scr(a + 1).Y: y3 = Scr(a + 2).Y: y4 = Scr(a + 3).Y v1 = Scr(a).V: v2 = Scr(a + 1).V: v3 = Scr(a + 2).V: v4 = Scr(a + 3).V x5 = Scr(a + 4).X: x6 = Scr(a + 5).X: x7 = Scr(a + 6).X: x8 = Scr(a + 7).X y5 = Scr(a + 4).Y: y6 = Scr(a + 5).Y: y7 = Scr(a + 6).Y: y8 = Scr(a + 7).Y v5 = Scr(a + 4).V: v6 = Scr(a + 5).V: v7 = Scr(a + 6).V: v8 = Scr(a + 7).V IF v1 OR v2 THEN LINE (x1, y1)-(x2, y2), 0 IF v2 OR v3 THEN LINE (x2, y2)-(x3, y3), 0 IF v3 OR v4 THEN LINE (x3, y3)-(x4, y4), 0 IF v4 OR v1 THEN LINE (x4, y4)-(x1, y1), 0 IF v5 OR v6 THEN LINE (x5, y5)-(x6, y6), 0 IF v6 OR v7 THEN LINE (x6, y6)-(x7, y7), 0 IF v7 OR v8 THEN LINE (x7, y7)-(x8, y8), 0 IF v8 OR v5 THEN LINE (x8, y8)-(x5, y5), 0 IF v1 OR v5 THEN LINE (x1, y1)-(x5, y5), 0 IF v2 OR v6 THEN LINE (x2, y2)-(x6, y6), 0 IF v3 OR v7 THEN LINE (x3, y3)-(x7, y7), 0 IF v4 OR v8 THEN LINE (x4, y4)-(x8, y8), 0 NEXT a END IF PCOPY 0, 1 'n?ytet??n piirretty kuva IF SlowMode THEN WAIT &H3DA, 8 'lis?hidastusta tarpeen mukaan 'N?pp?imet a$ = INKEY$ IF a$ = "8" THEN Speed = Speed + 1 IF a$ = "5" THEN Speed = Speed - 1 IF a$ = "6" THEN Turn = Turn - .01 IF a$ = "4" THEN Turn = Turn + .01 IF a$ = "9" THEN Turn2 = Turn2 - .01 IF a$ = "3" THEN Turn2 = Turn2 + .01 Cam.Z = Cam.Z + COS(Cam.XA) * COS(Cam.YA) * Speed 'liikutetaan kameraa Cam.X = Cam.X - SIN(Cam.XA) * COS(Cam.YA) * Speed Cam.Y = Cam.Y + SIN(Cam.YA) * Speed Cam.XA = Cam.XA + Turn 'k??nnet??n kameraa Cam.YA = Cam.YA + Turn2 IF Cam.XA > ATN(1) * 2 THEN Cam.XA = -ATN(1) * 8 + Cam.XA 'ei IF Cam.XA < -ATN(1) * 6 THEN Cam.XA = ATN(1) * 8 + Cam.XA 'saa IF Cam.YA > ATN(1) * 2 THEN Cam.YA = -ATN(1) * 8 + Cam.YA 'menn? IF Cam.YA < -ATN(1) * 6 THEN Cam.YA = ATN(1) * 8 + Cam.YA 'yli LOOP UNTIL a$ = CHR$(27) 'mit?k?h?n t?m? mahtaa tehd?...
SUB GenerateWorld 'Generoidaan palikoita/t?hti? '(eli pelkk?? koordinaattien arpomista, ei kaivanne lis?selityksi?) SELECT CASE DataMode CASE 1 DAm = 8 * 40 FOR a = 1 TO DAm STEP 8 X = Rndl(300) Z = Rndl(300) H = -INT(RND * 10 + 20) Dot(a).X = -10 + X Dot(a).Y = H Dot(a).Z = Z Dot(a + 1).X = 10 + X Dot(a + 1).Y = H Dot(a + 1).Z = Z Dot(a + 2).X = 10 + X Dot(a + 2).Y = 0 Dot(a + 2).Z = Z Dot(a + 3).X = -10 + X Dot(a + 3).Y = 0 Dot(a + 3).Z = Z Dot(a + 4).X = -10 + X Dot(a + 4).Y = H Dot(a + 4).Z = Z + 20 Dot(a + 5).X = 10 + X Dot(a + 5).Y = H Dot(a + 5).Z = Z + 20 Dot(a + 6).X = 10 + X Dot(a + 6).Y = 0 Dot(a + 6).Z = Z + 20 Dot(a + 7).X = -10 + X Dot(a + 7).Y = 0 Dot(a + 7).Z = Z + 20 NEXT a CASE 2 DAm = 1000 FOR a = 1 TO DAm Dot(a).X = Rndl(300) Dot(a).Y = Rndl(300) Dot(a).Z = Rndl(300) NEXT a END SELECT END SUB
SUB DrawBg (YA AS SINGLE) 'piirret??n joko avaruus tai taivas/maa kameran Y-kulman mukaan SELECT CASE DataMode CASE 1 IF YA < ATN(1) * 2 AND YA > -ATN(1) * 2 THEN Skyline = 100 - YA * 300 LINE (0, 0)-(319, Skyline), 3, BF LINE (0, Skyline)-(319, 199), 2, BF ELSE Skyline = 100 - (YA + ATN(1) * 4) * 300 LINE (0, 0)-(319, Skyline), 2, BF LINE (0, Skyline)-(319, 199), 3, BF END IF CASE 2 LINE (0, 0)-(319, 199), 0, BF END SELECT END SUB
FUNCTION Rndl (ScWidth AS INTEGER) 'satunnaislukugeneraatiota v?lilt? -1 - +1 Rndl = -ScWidth + INT(RND * ScWidth * 2) END FUNCTION
Miten olisi kommenttien korjaaminen niin, että ääköset olisivat kunnossa?
Kysynpä nyt tässä, mihin näillä 3D-systeemeillä oikeastaan pystyy? Siis mitä kaikkia ominaisuuksia löytyy? Teksturointi? En jaksa tuota QB-koodia käydä läpi niin tarkasti, että saisin sen itse selville.
Sitten vielä, mikä mahtaa olla perspektiivikorjaus?
lainaus:
Irkissä jotkut neuvoivat minua käyttämään matriiseja ja verteksipyörityksiä tjsp.
viznut ^_^
Metabolix kirjoitti:
Kysynpä nyt tässä, mihin näillä 3D-systeemeillä oikeastaan pystyy? Siis mitä kaikkia ominaisuuksia löytyy? Teksturointi?
Teksturointia en itse osaa tällä menetelmällä luoda, mutta pisteiden projektoiminen 2d-tasoon onnistuu (tämä on siis perspektiivikorjaus), joten viivojen piirto onnistuu, vetämällä Linellä pisteestä pisteeseen. Ja Circlellä voi tietysti piirtää myös palloja. Itselleni riittää lähinnä, että maailma näyttää kolmiulotteiselta. Ääkkösten muuttumiselle en voi mitään. Koodivinkkien lähetysboxissa on ilmeisesti eri merkistökoodit ääkkösille kuin notepadissa.
Edit: Joku muuten kuitenkin kysyy taas binarya, joten tässä on:
http://koodaa.mine.nu/~vohveli/Optica3D/
Näyttää varsin hyvältä. Matriisit varmaan lähinnä nopeuttaisivat laskuja, kaikki viivathan näkyvät tuossa jo oikeilla paikoilla. Oletko muuten kokeillut täyttää viivojen muodostamia alueita väreillä?
Kokeilin sitä PAINT-käskyllä, mutta sen kanssa tuli ongelmia, ja lisäksi se oli todella hidasta.
PAINTia huomattavasti nopeampaa voisi olla tehdä väritys LINEillä - väritettävällä alueella kun on suorat reunat. Jos piirtämisen aloittaa taaimmaisesta kuviosta ja päättää lähimpänä olevaan, värityksen pitäisi mennä oikein.
Täydellisiä suorakulmioita toki saa täytettyä LINEn BF-parametrillä, niin kuin tästä Linkku3D:llä tehdystä pelistä käy ilmi, mutta tässähän kyseinen menetelmä ei kelpaa. Voisin toki värittää LINEllä niin paljon kuin mahdollista, mutta joutuisin silti turvautumaan PAINTiin.
Ajattelin siis, että värittäisit nelikulmion sopivalla määrällä viivoja kulmion reunoista toiseen...
Tuota voisin kyllä kokeilla, tosin saattaisi siitäkin tulla melko hidas..
näyttää tosi hyvältä, jännää nähdä mihin kaikkiin qb pystyy :) ja hunajavohveli saakos tuota avaruus juttua soveltaa omaan harjoitukseen? olen tässä alkanut koodata samantapaista kolmiuloitteista avaruusmaailmaa vb:llä mutta ongelmana on etäisyydet jne... tai no tästähän nyt opin nekin asiat jne... mutta hienoja ovat, täytyy myöntää, ja mitä siellä ylhäällä vinetään ääkkösistä, ennenkin annettu anteeksi koodivinkeissä se että ääkköset ei ole tule mukaan, ja kai nyt jokainen joka osaa lukea, ymmärtää että mitä sanotaan missäkin kohtaa...
ja vielä mihin näillä 3d-jutuilla pystyy? voit oppia niistä itse jotain, olen käsittänyt että koodivinkkien tarkoitus täällä on se että näytetään oma osaaminen, saadaan palautetta ja koodin testaajat vielä samalla voivat oppiakin jotain uutta, olet melko varmasti oppinut jotain silloin jos osaat tehdä samantyylisen vaikka rumemmankin toisella kielellä, kunhan idea on sama...
minä opin tästä muutamia asioita eikä koskaan voi oppia liikaa (paitsi kun aivokapasiteetti tulee vastaan ;) )
noni, vineminen loppui :) en löytänyt mitään elämää suurempaa bugia, jouduin vaan itse tekemään lisäyksen koodiin että kun painaa spacee niin se nollaa kaikki että paljon käännytään mihin suuntaan jne... kun kone on niin ärhäkkä et alkoi simu riehumaan niin että oli vaikeaa kontrolloida suuntaa jne... :)
Taas yksi syy lisää, miksi kannattaa aloittaa koodaus. Toivottavasti hamassa tulevaisuudessa voisi käydä näin:
Eieiei! Ei tuota pysty suorittamaan tekstitilassa. Lisäät tuohon SCREENin. Hyvä. Eikä INPUTtia voi laittaa tuohon tai voihan sen mutta ei siinä ole mitään järkeä... :)
Asiallista koodaustyötä jälleen kerran.
nomic kirjoitti:
saakos tuota avaruus juttua soveltaa omaan harjoitukseen?
Sitähän varten tämä koodivinkeissä on. :)
Olisi kiva, jos kuitenkin mainitsisit ohjelmissasi moottorin alkuperäisen suunnittelijan, jos esim. levität niitä netissä.
nomic kirjoitti:
olen tässä alkanut koodata samantapaista kolmiuloitteista avaruusmaailmaa vb:llä
Täältä löytyy VB:lle portattu käännetty avaruuspeli. Lähdekoodin julkaisen luultavasti, kun/jos se valmistuu.
nomic kirjoitti:
ja vielä mihin näillä 3d-jutuilla pystyy?
Vastasin tähän tuossa ylempänä. Mitään sen tarkempaa en osaa sanoa, mutta ainakin pystyisin samaan kuin tuossa Linkku3D-pelissä, ja paremmin.
nomic kirjoitti:
jouduin vaan itse tekemään lisäyksen koodiin että kun painaa spacee niin se nollaa kaikki että paljon käännytään mihin suuntaan jne...
Joo, on totta kai täysin suotavaa, että koodaa itse peliin paremman ohjauksen, jos se tuntuu helpommalla. Toivon todella, että koodin soveltaminen on nyt helpompaa kuin Linkussa.
ei pysty just nyt kokeilemaan, ku jotain häikkää dos ohjelmia käyttäessä, mutta kuulostaa loistavalta, ja kuhan saan taas koneen toimimaan kunnolla on tätä pakko testata heti :D
hunajavohveli, jooh, siis tottakai jos sovellan koodia omiin projektiini niin mainitsen alkuperäisen tekijän ja jos se julkaistaan oman koneen ulkopuolella jossain tai menee jotain reittiä levitykseen niin sitten otan yhteyttä sähköpostitse alkuperäiseen tekijään jne... :)
mutta mahtava koodivinkki, ei tästä mihinkään pääse :)
tästä on _varmasti_ hyötyä jollekkin ;)
Aika nätti on. Tajusin miksei nimi ollu Linkku 2 - en löytäny tästä mitään linkkua, kaikki näyttää toimivan mainiosti :). Ainut mikä jäi kalvamaan on näppäimet: ennemminkin ysillä jos kattois alas ja kolmosella ylös ni olis lentosimumpi.
edit: Vielä jos olisi spin-mahdollisuus, että voisi keinuttaa kameraa puolelta toiselle...
en jaksa testailla varsinkin kun ei oo ees qb:n kääntäjää nyt koneella. binääri olis kiva tai vaikka shotteja
En olis arvannu, et qb:llä pystyy mitään 3d-grafiikkaa tekemään. Tuli aika hyvä kun tein tosta joystickillä ohjattavan.
Wautsi wau!
Tuoshan tulee vaan kuva joka ei liiku mihinkää. Eikö tuota sais nopeutettua? Tämä kone on 366 mhz.
Siis hei, tämähän on aivan mahtava! Dude, kai muistat oikeat näppäimet (löytyvät Numpadista).
Hups en käyttänyt näppäimiä. hieno on.
Edit: Tein tuosta UGLlän avulla nopiamman version :).
Aihe on jo aika vanha, joten et voi enää vastata siihen.