Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: DirectX 9 - First person näkymä

Sivun loppuun

Tumpelo [08.06.2007 18:46:32]

#

Mulla meni nyt aivot totaalisen tukkoon enkä millään tahdo saada päähäni miten hoidin homman aikanaan OpenGL:llä. Googlekin ylikuumeni kun raiskasin sitä mutta mitään ei löytynyt. Ongelma ei varsinaisesti koske itse DirectX:ää, vaan yleisesti 3D:tä. Eli kun pitäisi matrixeja väännellä niin että hahmo liikkuu (ts. maailma liikkuu niin että näyttää kuin hahmo liikkuisi) ympäriinsä kuten tapana on. Siis se ongelma on missä järjestyksessä ja miten niitä matrixeja pitää muokata. Esim seuraava...

device.Transform.World = Matrix.Identity;
device.Transform.World = Matrix.RotationY(CameraAngle) * Matrix.Translation(-CameraPositionX, -CameraPositionY, -CameraPositionZ);

...toimii muuten oikein mutta maailma pyörii aina saman akselin ympäri eikä kuvitteellisen hahmon ympäri.

Toivottavasti joku nyt ymmärsi mitä haen takaa...

Metabolix [08.06.2007 19:25:12]

#

Entäpä jos vaihtaisi siirron ja pyörityksen toisin päin? Opettele matriisilaskentaa vähän, katso OpenGL-oppaista (ei ole vaikea) tai kokeile.

Tumpelo [08.06.2007 19:32:37]

#

Metabolix kirjoitti:

Entäpä jos vaihtaisi siirron ja pyörityksen toisin päin? Opettele matriisilaskentaa vähän, katso OpenGL-oppaista (ei ole vaikea) tai kokeile.

Ei toimi sen kummemmin, pyörii vain entistä erikoisemmin.

Tumpelo [09.06.2007 09:27:14]

#

No jaa eipä se ongelma ollut noissa matrixeissa vaan ihan muualla.. Pitäisi osata laskea suuntaa ja ties mitä. Löysin Metabolixin pari vuotta wanhan viestin:

Metabolix kirjoitti:

(13.04.2005 22:25:16) Paras tapa on luonnollisesti se, että säilytät jossakin tyypin koordinaatteja ja suuntakulmia, lasket sinin ja kosinin avulla normalisoidun liikesuunnan, ja liikut sen mukaan. Tässä tavassa on etuna se, että tyypin sijainti on jatkuvasti tiedossa, ja tätä on pakko käyttää, jos haluaa jonkinlaista peliä ja törmäystarkistusta tehdä.

Liikkuvan pisteen toteutukseen olen todennut hyväksi luokan, jonka varsinaiset ominaisuudet ovat suunnan muuttaminen ja määrättyyn suuntaan liikkuminen. Suunta on varmaankin kätevintä määrittää kahdella muuttujalla: kulma sivusuunnassa ja kulma vaakatasosta ylös/alas. Tämän perusteella kannattaa laskea valmiiksi vektori, jottei kallista prosessoritehoa kulu jatkivasti sinien ja kosinien vääntöön. Liikkumisfunktio sitten lisää kuhunkin koordinaattiin liikevektorin vastaavan arvon (kerrottuna liikkeen määrällä). Tällaisella vehkeellä pääsee yllättävän pitkälle, ja kun sen on kerran tehnyt, sitä voi aina käyttää.

Vielä kun ymmärtäisi jotain. Matikan numero ollut vitosta ensimmäiset neljä pitkän matikan kurssia. ^^ Et viittis vääntää rautalangasta mitä tässä nyt pitää tehdä?

Markus [09.06.2007 12:29:23]

#

Kokeilu lukea artikkelini "Matriisimatematiikkaa peliohjelmoijille":
http://www.suomipelit.com/files/artikkelit/56/MatriisimatematiikkaaPeliohjelmoijille.zip

Tumpelo [09.06.2007 18:59:03]

#

Oon saanut homman (luultavasti) toimimaan niin pitkälle että ainoa ongelma on enää että miten tiedän missä kulmassa kamera on pyörinyt. Tällä hetkellä ohjelmassa on RotationY muuttuja jota lisätään tai vähennetään hiiren liikkeiden mukaisesti ja sitten pyöritetään kenttää. Mutta pitäisi tietää asteina kulma verrattuna alkuperäiseen jotta voisi laskea kaikkea kivaa...

Tumpelo [11.06.2007 08:43:34]

#

Ää miten voi ihminen olla näin tyhmä... Tietenki minä tiedän sen kulman kun pyöritän kenttää aina tietyn asteluvun verran. >-<

Tumpelo [13.06.2007 16:59:28]

#

Ääh pentele. Siis, ongelma on nyt se että en osaa laskea paljonko pitää X ja Z akseleihin lisätä tai vähentää kun olen kääntyneenä johonkin suuntaan. Siis tiedetään että olen kääntyneenä X astetta vasemmalle, missä suhteessa kasvatan X- ja missä Y-akselia? Repäisin jostain OpenGL-tutoriaalista tällaisen kaavan:

xpos -= sin(heading*piover180) * 0.05f;
zpos -= cos(heading*piover180) * 0.05f;

Josta tuli minun koodissa:

CameraPositionX -= (float)Math.Sin(rotationY * (Math.PI / 180)) * 0.1f;
CameraPositionZ += (float)Math.Cos(rotationY * (Math.PI / 180)) * 0.1f;

(DirectX käyttää vasenkätistä koordinaatistoa, siitä etumerkin muutos toiseen)

Mutta ei toimi niin ei toimi. Voisiko joku koittaa auttaa... Olen kohta viikon päivät taistellut eikä näytä tulevan yhtään mitään. WTF LOL OMG suorastaan..

Metabolix [13.06.2007 23:18:12]

#

Jos nyt käsitin ongelman oikein, niin 3D-tapauksessa kaava menisi seuraavalla tavalla. Oletetaan siis vasenkätinen koordinaatisto, jossa X on oikealle, Y ylös ja Z katsojasta ruutuun päin, ja olkoon "eteen" Z-akselille. Kulmat ovat tietenkin radiaaneissa.

x -= cos(ylaviisto) * sin(vaakasuunta);
y += sin(ylaviisto);
z += cos(ylaviisto) * cos(vaakasuunta)

Muistetaanpa vielä, etten minä ole aivan varma noista vasenkätisistä hommista, kun itse käytän OGLia ja oikea matematiikka on yleensä tehty oikeakätisille. 2D-version saa tietenkin aikaan asettamalla ylaviisto-muuttujan nollaksi (jolloin sini on nolla ja kosini yksi ja sini nolla). Jos ei ole erityistä syytä pitää kulmaa tallessa asteina, suosittelisin radiaaneja ennemmin... Vaikka samapa tuo. Ehkä kannattaisi tehdä muunnosfunktiot (hm, osaankohan näin äkkiseltään C#:ta):

public static double DegToRad(double deg) {
    return deg / 180.0 * Math.PI;
}
public static double RadToDeg(double rad) {
    return rad * 180.0 / Math.PI;
}

Ai niin, ja luonnollisesti kertoimiin kannattaisi sisällyttää jotenkin se kulunut aika, muutenhan nopeus riippuu koneen nopeudesta (ts. FPS:stä).

T.M. [14.06.2007 02:37:42]

#

// Eteenpäin:
x -= sin(vaakasuunta) * sin(ylaviisto);
y -= cos(vaakasuunta) * sin(ylaviisto);
z -= cos(ylaviisto);

Tämän pitäisi toimia koordinaatistossa jossa x on vasemmalle/oikealle, y eteen/taakse, ja z ylös/alas, (itse käytän tuollaista koordinaatistoa).

Tumpelo [14.06.2007 09:32:36]

#

Metabolix kirjoitti:

x -= cos(ylaviisto) * sin(vaakasuunta);
y += sin(ylaviisto);
z += cos(ylaviisto) * cos(vaakasuunta)

Sehän toimii! Kiitoksia kovasti, pääsen viimeinkin tuskistani tämän asian suhteen. :)

lainaus:

Jos ei ole erityistä syytä pitää kulmaa tallessa asteina, suosittelisin radiaaneja ennemmin... Vaikka samapa tuo. Ehkä kannattaisi tehdä muunnosfunktiot (hm, osaankohan näin äkkiseltään C#:ta):

Itse asiassa ne on tallessa sekä radiaaneina että asteina. Tai no, alkuperältään ne on radiaaneja mistä muutan ne asteiksi koska tarvitsen asteitakin muutamaan kohtaan.

lainaus:

Ai niin, ja luonnollisesti kertoimiin kannattaisi sisällyttää jotenkin se kulunut aika, muutenhan nopeus riippuu koneen nopeudesta (ts. FPS:stä).

Juu tiedossa on ja toteutuskin onnistuu jopa minun matikkapäällä. :o


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta