Hei!
Olen jo 39 vuotias, eikä minulla ole tietokone aloista koulutusta.
Kuitenkin on mukavana harrastuksena ollut kaikki vuodet, vuodesta -83 niin pieni
muotoinen peli ohjelmointi.
Minulla on kaikenlaista peliä tullut rakenneltua, myöskin 3D puolella, mistä nyt hieman kyselen.
Tällä kertaa en aio käyttää valmiita 3D kirjastoja lainkaan, minulla on tarkoitus
Java Graphics2D:n avulla rakentaa simppeli 3D engine.
Minulla on rakentelu sujunnut googlen avulla ihan kivasti aina tähän asti
kun nyt tämä 3D "silmä" pitäisi sijoittaa avaruuteeni,
taikka ei nyt avaruuteen mutta tähän alla olevan linkin shakkilautaan.
http://88.192.212.114
Ongelmana on 3 akselia joita rotatoida, minä en tällä hetkellä osaa laskea tarkan
rotaten kuin yhdellä vapaasti valittavalla akselilla.
Kun yritän rakentaa AWT.lookAt ( Point3D p1, Point3D p2 ); metodia itselleni,
niin, kääntely tuottaa vain hassuja ja virheellisiä katse suuntia.
Olen yrittänä lukea, siis googlen tutoriaaleista eri tapoja, mutta englanti ja
matematiikka on lyhyestä lukiosta jota kävin vuosia sitten kovin heikentynyt.
Tahtoisin hieman neuvoja sellaisilta jotka ovat vastaavaa 3D avaruus silmää
joskus rakentana siis ILMAN virallisia kehittyneitä 3D engineitä, kuten OpenGL ja Direct3D.
//----
Kiitos,,
Jos kyseessä on monikulmioihin ja viivoihin perustuva 3D-vehje, niin suosittelisin lämpimästi harkitsemaan tarkemmin OpenGL:ää, joka ei ole perusidealtaan mikään avaimet-käteen-3D-engine, vaan aika minimalistinen systeemi, joka tekee juurikin tuollaisiin käskyihin liittyvät laskut ja alkeelliset piirto-operaatiot puolestasi. "Matalan tason" kolmiulotteista hahmotusta ja pähkäilyä saa sen kanssa tehdä ihan riittävästi.
Toinen olennainen pointti OpenGL:n (tai Direct3D:n) käytössä on tietenkin se, että CPU:lla raskaat piirto-operaatiot suoritetaan GPU:lla. Tätä piirtonopeuden kannalta erittäin kriittistä ominaisuutta et käytännössä edes pysty koodaamaan itse.
Vaikka haluaisit koodata kaiken itse, niin suosittelisin silti ottamaan mallia OpenGL:n toimintaperiaatteista - etenkin siitä, miten GL:n kameran ja kappaleiden liikutus toimii. Tässä muutamia aiheeseen (ja myös alkuperäiseen kysymykseen) liittyviä linkkejä:
http://www.glprogramming.com/red/chapter03.html
http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
http://en.wikipedia.org/wiki/
http://en.wikipedia.org/wiki/3D_projection
3D-systeemissä katsesuunnan ilmaisemiseen tarvitaan myös tieto, missä on "ylös". Ymmärrät asian, kun istut paikallasi, katsot jotain ja kääntelet päätäsi kallelleen: vaikka pään ja kohteen sijainnit pysyvät vakioina, näkymä muuttuu. Voit käyttää laskuissa jotain oletusarvoa tai lisätä uuden parametrin.
Tämä on jo neljäs moottoriasi koskeva ketju, mikä kertoo tilanteesta aika paljon. Ei pidä tehdä projekteja, joihin ei itse kykene alkuunkaan hankkimaan tietoa. Kannattaisi sen sijaan aloittaa jostain paljon yksinkertaisemmasta ja opetella matematiikkaa oikein urakalla. Tämänkin voi nimittäin helposti laskea aivan tavallisilla vektorilaskuilla, kun vain hahmottaa tilanteen ja todella ymmärtää ne peruslaskutoimitukset (kuten pistetulon ja ristitulon), joista tarvittavat lausekkeet muodostetaan. Jos me muut väännämme rautalangasta kaikki laskut puolestasi, onko moottori enää sinun tekemäsi?
Tässä on kuitenkin matemaattinen apu esittämääsi ongelmaan:
Olkoon todellisessa koordinaatistossa S silmän sijainti, T kohteen sijainti ja P muun (piirrettävän) pisteen sijainti. Olkoon piirrettävässä koordinaatistossa S' = 0 ja T' = -|T-S|k, missä k on z-akselin suuntainen yksikkövektori. Oletetaan lisäksi, että "ylös" on mahdollisuuksien mukaan y-akselin suuntaan ja että T-S ≠ ±j, missä j on y-akselin suuntainen kantavektori.
Lasketaan ensiksi piirrettävän koordinaatiston kantavektorien i, j ja k vastineet i0, j0 ja k0 alkuperäisessä koordinaatistossa. Ensimmäinen seuraa suoraan edellisistä määritelmistä (S' ja T'), seuraavaan vaaditaan lisäksi yläsuunta (j), ja viimeinen saadaan näiden ristitulosta.
k0 = -(T - S) / |T - S|
i0 = (j × k0) / |j × k0|
j0 = k0 × i0
P' saadaan näiden avulla laskemalla P - S ja vaihtamalla kantavektorit uusiksi. Matemaattisesti se onnistuu pistetulolla.
P' = ((P - S) · i0) · i + ((P - S) · j0) · j + ((P - S) · k0) · k
En tarkistanut tulosta mitenkään, vaan laskin sen suoraan tässä muodossa tähän, mutta uskoisin, että se on oikein.
Jotta keskustelu olisi mukavampaa, suosittelen lisäksi seuraavia asioita:
3DLaskuja!
Heh, minulla todellakin on vain puolikas aikuis lukiota suoritettuna 11 vuotta sitten ja olen myöskin
vain muutaman viikon suorittanut tietojenkäsittelyn perustutkintoa amiedussa,
jotenka myös Java on hieman oppineita heikompaa.
Minulla on siis Java käytössäni, Herra Metabolix kuinkas tuo teidän esimerkki, niin kuinka se tulisi kääntää Java muotoon.
Tässä on alla minun tämän hetkinen koodini 3D pisteen muuttamiseen 2D muotoon,
toivottavasti siintä on apua jollekkin, itse tarvitsen siis tuon 3D silmän katsomaan haluttuun pisteeseen 3D avaruudessa.
public Point2D rotateWorld3DPointTo2DPoint ( Point3D fp3d ) { double sx = sini [ (int)(rotatex*128) ]; double cx = cosi [ (int)(rotatex*128) ]; double sy = sini [ (int)((360-rotatey)*128) ]; double cy = cosi [ (int)((360-rotatey)*128) ]; double sz = sini [ (int)(rotatez*128) ]; double cz = cosi [ (int)(rotatez*128) ]; double x,y,z, xy,xz, yx,yz, zx,zy, scaleFactor; x = fp3d.x- world_xpos; y = fp3d.y- world_ypos; z = fp3d.z- world_zpos; // rotation around x xy = cx*y - sx*z; xz = sx*y + cx*z; // rotation around y yz = cy*xz - sy*x; yx = sy*xz + cy*x; // rotation around z zx = cz*yx - sz*xy; zy = sz*yx + cz*xy; z = yz+viewport_zz; scaleFactor = viewport_zz/(viewport_zz-z); x = (zx)*scaleFactor; y = (zy)*scaleFactor; return new Point2D ( x,y,z,scaleFactor ); };
En aio käyttää alustavasti OpenGL Direct3D kirjastoja lainkaan, koska haluan
että Java sovellukseni käynnistyvät ilman ikäviä Java varmenteita, eli Java2D käytössäni.
//----
Kiitos,,
kpzpt kirjoitti:
Herra Metabolix kuinkas tuo teidän esimerkki, niin kuinka se tulisi kääntää Java muotoon.
Se on varmaankin se osa tästä hommasta, joka sinun pitäisi itse tehdä, jotta voisit sanoa edes koodanneesi tämän itse, vaikket laskenutkaan. Ei todellakaan pitäisi olla vaikeaa, jos edes vaivaudut Wikipediasta lukemaan ristitulon ja pistetulon. Kaavatkin annetaan tuolla suoraan.
Vinkkinä koodiisi: Olet käyttänyt tolkuttoman isoa hakutaulua (128 * 360) sineille ja kosineille. Tuhlaat muistia. Nykykoneella kyseiset laskutoimitukset ovat niin nopeita, että saattaa olla jopa nopeampaa laskea ne tuossa suoraan.
Metabolix kirjoitti:
Se on varmaankin se osa tästä hommasta, joka sinun pitäisi itse tehdä, jotta voisit sanoa edes koodanneesi tämän itse, vaikket laskenutkaan.
Vinkkinä koodiisi: Olet käyttänyt tolkuttoman isoa hakutaulua (128 * 360) sineille ja kosineille. Tuhlaat muistia. Nykykoneella kyseiset laskutoimitukset ovat niin nopeita, että saattaa olla jopa nopeampaa laskea ne tuossa suoraan.
3DLaskuja!
Ok, minulla ei valitettavasti ole vielä tällä hetkellä vaadittavaa matematiittista taitoa,
En ole tässä koko elämäni aikana laskena ristituloa taikka pistetuloa, tämä koko 3D matematiikka on minulle ihan uusi harrastus.
Tämä itse tekeminen on hieman huvittava lause minusta, en tahdo mitään riitelyä tässä, mutta aika harva ihminen itse 3D matematiikan, oli sitten kyse koodista taikka laskuista, niin itse rakentaa, se eri ihmisille sijoittuu erillaisiin elämän vaiheisiin ja jotkut eivät koskaan opi 3D matikkaa, ymmärtäisin että sinä olet oman oppinut koulussa taikka oppilaitoksissa, itse opiskelen täällä ohjelmointiputkassa ja googlessa, mutta, minulta puuttuu vielä liian monta termiä ja rakentavaa lausetta, jotta ihan itse tietäisin kuinka toimia. Täytyy tässä jutella vielä jonkun sukulaisen taikka ystävän kanssa koneen ääressä ja kirjoittaa pari testi Java demoa.
Valitettavasti en näitten vinkkien avulla jotka tässä ketjussa vastaanotin, niin, en osaa rakentaa Java koodia 3D silmälle.
Tulen sitten takaisin parin viikon kuluttua, kun on hieman enemmän opiskellut matikkaa, vektoreita ja sini ja cosi järjestyksiä.
Nuo sini ja cosi taulukot todellakin olivat hieman suuria, mutta en ole myöskään sellaisia aikaisemmin 3D:n kanssa käyttänä, jotenka niissä on vähän varmuuden vuoksi lisää mukana, jonka voin sitten tietenkin myöhemmin poistaa.
//----
Kiitos,,
Mod. korjasi viestin rivityksen. Älä rivitä viestejä käsin!
kpzpt kirjoitti:
Nuo sini ja cosi taulukot todellakin olivat hieman suuria, mutta en ole myöskään sellaisia aikaisemmin 3D:n kanssa käyttänä, jotenka niissä on vähän varmuuden vuoksi lisää mukana, jonka voin sitten tietenkin myöhemmin poistaa.
Alä käytä nytkään. Ne ovat ennenaikaista optimointia (a.k.a. kaiken pahan alku ja juuri), joka monimutkaistaa kodiasti turhaan ja niiden nopeuttava vaikutus on ylipäänsä hyvin kyseenalainen. Korvaa ne siis funktioilla Math.sin
ja Math.cos
.
Suosittelisin myös käyttämään enemmän aikaa ohjelman suunnitteluun. Onko 3D-moottorisi perustoimintaperiaate selvillä? Mitä toimintoja moottorin on ainakin tarkoitus tukea? Mitä asioita moottorissa tapahtuu, kun piirrät näytölle vaikkapa kuution? Jos et vielä pysty vastaamaan näihin kysymyksiin, niin kannattaa keskeyttää koodaaminen ja palata suunnittelupöydälle (ja lukemaan teoriaa).
Hyvä vaihtoehto voisi olla koodata välitavoitteena yksinkertaisempia ohjelmia. Esimerkiksi sellainen, jonka ainoa tavoite on piirtää näytölle hiirellä pyöritettävä varjostamaton kuutio. Tämän jälkeen sinulla olisi huomattavasti paremmat eväät lähteä kehittämään laajempaa 3D-moottoria.
os kirjoitti:
Alä käytä nytkään. Ne ovat ennenaikaista optimointia (a.k.a. kaiken pahan alku ja juuri), joka monimutkaistaa kodiasti turhaan ja niiden nopeuttava vaikutus on ylipäänsä hyvin kyseenalainen. Korvaa ne siis funktioilla
Math.sin
jaMath.cos
.Suosittelisin myös käyttämään enemmän aikaa ohjelman suunnitteluun. Onko 3D-moottorisi perustoimintaperiaate selvillä? Mitä toimintoja moottorin on ainakin tarkoitus tukea? Mitä asioita moottorissa tapahtuu, kun piirrät näytölle vaikkapa kuution? Jos et vielä pysty vastaamaan näihin kysymyksiin, niin kannattaa keskeyttää koodaaminen ja palata suunnittelupöydälle (ja lukemaan teoriaa).
Hyvä vaihtoehto voisi olla koodata välitavoitteena yksinkertaisempia ohjelmia. Esimerkiksi sellainen, jonka ainoa tavoite on piirtää näytölle hiirellä pyöritettävä varjostamaton kuutio. Tämän jälkeen sinulla olisi huomattavasti paremmat eväät lähteä kehittämään laajempaa 3D-moottoria.
3DEngine!
Minulla on aika vanha tietokone, ostin sen 2003 ja se oli silloin jo pari vuotta ollut kaupan valikoimissa, minulla on iso tehon lisäys kun lasken for loopissa 3D pointteja 2D pointteihin tällä tavalla sin ja cos arraylla verrattuna Math.sin ja Math.cos ja Math.toRadians funktioihin.
----
Minun suunnitelma oli ensin rakentaa Graphics2D:n line käskyillä pyörivä kuutio, kun tämä oli valmis niin rakensin sitten täytetyn shakkilaudan ja tein skaalaavat spritet sille, nyt olen sitten lisännyt kameran liikkumisen ja engine alkaa olla muuten valmis pelisivustoni käyttöön, mutta, siis nämä kaksi, kauempien objektien tummennus ja avaruus silma, joka osaisi katsella valittuun koordinaattiin.
Moottorin toiminnat ovat siis seuraavat -> 3DSpritet ja 3DPolygonit ja 3DObjektit.
Nuo 3DSpritet ovat BufferedImageja, 3DPolygonit ovat tavallisia Polygoneja ja 3DObjektit ovat Blenderissä ja muissa joissa on tuki Directx fileelle, niin, piirrettyjä väritettyjä 3D mesh objekti kokonaisuuksia.
Minulla on tässä tämä minun tämän hetkinen engine toiminnassa -> http://88.192.212.114
Engine on muuten valmis, mutta, siintä puuttuu vielä kauempien alueitten tummentaminen ja tuo lookAt(..) silmä.
Minun ohjelmointi tapani on vielä aika kokeellinen tämän minun pelisivustoni kohdalla, rakentelen erillaisia vaihtoehtoja joilla voin sivustoni pelit toteuttaa, valikoin sitten tämän vuoden kuluessa ne kehittämäni metodit mitä sitten koen tarvitsevani sivustoni rakentelussa, tämä 3D tuki jossa tämä 3D silmä on kyllä ehdoton löytää funktio listaltani, täytyy tässä hieman opiskella matikkaa.
Jos jotakuta sattuu kiinnostamaan mitä Suomen Java-Peli rintamalla tapahtuu minun ostaltani, niin.
Pelisivustoni rakentuu tässä -> http://temp4321.dy.fi Tervetuloa..
//----
Kiitos,,
LookAt!
Tässä on minun tämän hetkinen koodini, se on vain osittain riittävä rakentamaan minulle tämä AWT.lookAt ( Point3D, Point3D ); funktio.
if ( JC.keys[KeyEvent.VK_L]) { double xk = JMath.palautaKulma ( new Point ( (int)AWT.silmä_ypos, (int)AWT.silmä_zpos), new Point(0,0) ); double yk = JMath.palautaKulma ( new Point ( (int)AWT.silmä_xpos, (int)AWT.silmä_zpos), new Point(0,0) ); //double zk = JMath.palautaKulma ( new Point ( (int)AWT.silmä_xpos, (int)AWT.silmä_ypos), new Point(0,0) ); AWT.rotate3DTo ( xk , yk , 180 ); }
En ole ihan vielä rakentana varsinaista funktiota lookAtille, tällä hetkellä siis tämä "L" kirjain toimittaa tehtävää.
Minulla on oma aika alkeellinen JMath luokka, matemaattisia funktioitani varten, sieltä vastaanotan arvon palautaKulmasta kahden 2D pointin välille.
Mitä minä olen ymmärtänyt väärin tuossa koodissa ??
En ole vielä opiskellut Vektoreita enkä Piste- taikka Ristituloja vaikka ne tuossa aiemmin jo mainittiinkin, ajattelin vain varmistaa taitavammilta matematiikan käyttäjiltä, että, onko tämä tapa mahdollista rakentaa valmiiksi, mitä minä olen siis tuossa yllä jo aloittanut.
Tässä vielä linkki siihen samaan 3D shakkilautaani johonka rakentelen tätä 3D silmää -> http://88.192.212.114
Onko lähestymis tapani propleemaani totaalisen epä-matemaattinen ??
//----
Kiitos,,
En tiedä, missä määrin seuraava teoria (EDIT: melko samaa kuin Metabolixin aiemmassa viestissä) on sinulle jo selvää. Toivottavasti tämä kuitenkin auttaa hahmottamaan tilannetta.
3D-piirtoa voi selkeyttää tiettyjen koordinaatistojen avulla. Tärkeimpiä koordinaatistoja ovat maailma-, kamera- ja näyttökoordinaatisto. Pisteen maailmakoordinaatit kuvaavat sen paikkaa 3D-maailmassa. Nämä eivät muutu mihinkään jos kameraa siirretään. Pisteen kamerakoordinaatit kertovat, kuinka paljon kamerasta lähtien pitää liikkua "eteen", "ylös" ja "oikealle" (näiden merkitys riippuu kameran asennosta), jotta päästään pisteeseen. Kamerakoordinaatisto ja näinollen myös 3D-maailmassa paikallaan pysyvien pisteiden kamerakoordinaatit muuttuvat, kun kameraa siirretään tai käännetään. [/i]Näyttökoordinaatit[/i] kertovat, mihin kohtaan piste piiretään näytöllä. Ne lasketaan kamerakoordinaateista ja luonnollisesti muuttuvat, kun kameraa siirretään.
Kun haluat tietää jonkin pisteen paikan näytöllä, niin silloin teoriassa kuvaat maailmakoordinaatit näyttökoordinaateiksi. Tämä kannattaa tehdä kuvaamalla piste ensin kamerakoordinaatistoon.
Kamerakoordinaatiston voi esittää seuraavien vektoreiden avulla: kameran paikka c ja yksikkövektorit u (oikealle) v (ylös), w (eteenpäin). Pisteen p = (x,y,z), (maailmakoordinaatit) esitys (xk, yk, zk) kamerakoordinaatistossa on
xk = (p-c).u
yk = (p-c).v
zk = (p-c).w
missä . tarkoitta pistetuloa, (a,b,c).(d,e,f) = a*d + b*e + c*f.
Kuvakoordinaatit (xn, yn) saadaan käytännössä (yksinkertaisin tapa) kamerakoordinaateista jakamalla näiden z-komponentilla ja skaalaamalla & siirtämällä näytölle sopivasti (ja piirtämällä ainoastaan ne pisteet, jotka ovat kameran etupuolella, zk > 0)
xn = (xk/zk + x0) * a
yn = (yk/zk + y0) * a
Kamerakoordinaatiston kantavektorit u, v, w voit laskea Metabolixin näyttämällä tavalla (vastaavat vektoreita i0, j0, k0). Tämä koordinaatisto muodostetaan kerran per frame tai aina, kun kameraa siirretään. Idea on siis se, että kaikki muunnokset kamera- ja näyttökoordinaatistoon (kuten koodisi rotateWorld3DPointTo2DPoint
) tehdään valmiiksi laskettujen kamerakoordinaatiston vektorien u, v, w ja c avulla.
EDIT: Ilmeisesti nyt kameran tila esitetään koodissasi muuttujien rotatex
, -y
ja z
(ns. Eulerin kulmat) ja vektoria c vastaavien (world_xpos
, -ypos
, -zpos
) avulla. Kulmien lisäksi kannattaa tallentaa vektorit u, v ja w, jotta niitä ei tarvitse laskea näistä kulmista uudelleen joka pisteelle. Näin pääset eroon myös sini- ja kosinitaulukoistasi.
lookAt!
Kiitos kaikille vastanneille täytyy vielä myöhemmin opiskella näitä pistetuloja ja ristituloja, en ihan tässä vielä edes tiedä mitä kaikkea tuollaisilla voi laskea, minulla kuitenkin on nyt toimiva lookAt ( Point3D , Point3D ); funktio Java 3D kirjastossani.
Lopullinen neuvo tuli JavaGaming forumilta, eli, kiitosta myös sinne.
Tämä ketju saa päättyä minun osaltani tähän, aloitan uuden ketjun, aiheena on sitten tuolla kertaa liikkuminen 3D avaruudessa aluksen kärjen osoittamaan suuntaan ja myöskin aluksen liikkuminen luonnollisesti 3D mallin sisällä.
Hienoa kuitenkin että tämä lookAt nyt vihdoin toimii !! Tästä jatketaan !!
//----
Kiitos,,
Aihe on jo aika vanha, joten et voi enää vastata siihen.