Developedia
Developedia
A derékszögű háromszög

A derékszögű háromszög

A játékfejlesztés vagy még általánosabban a számítógépes grafika bizonyos szempontból a geometria és a programozás találkozásánál helyezkedik el, ezért érdemes tisztában lennünk a legalapvetőbb geometriai összefüggésekkel.

Nézzük most át a derékszögű háromszögek matematikáját és felhasználásait a játékfejlesztésben!

Egy derékszögű háromszögöt a következő információk írnak le:

  1. Az a befogó hossza
  2. A b befogó hossza
  3. A c átfogó hossza
  4. Az a befogóval szembeni α (alfa) szög
  5. A b befogóval szembeni β (béta) szög

Ezen információkból, ha kettőt tudunk könnyedén kiszámolhatjuk a másik hármat a következő összefüggésekkel. (Kivétel ez alól, ha csak α és β szögeket ismerjük. Ekkor még legalább egy oldalhosszra szükségünk van a másik oldalak kiszámításához.)

A háromszög belső szögeinek összege: 180°

Ez nem csak a derékszögű, de minden egyéb háromszög esetén is igaz. A derékszögű háromszög ennek csak egy speciális esete, ahol a háromból ez egyik szög garantáltan 90°, így a maradék kettőre összesen jut a másik 90°.

α+β=90°α + β = 90°α+β=90°
β=90°−αβ = 90° - αβ=90°−α
α=90°−βα = 90° - βα=90°−β

Pitagorasz-tétel

Az egyik alapvető összefüggés, amit a derékszögű háromszögekkel kapcsolatban használunk, a Pitagorasz-tétel, amely a háromszög oldalainak hossza közti kapcsolatot mondja ki. A tétel szerint a derékszögű háromszög átfogójának négyzete egyenlő a két befogó négyzetének összegével.

c2=a2+b2c^2=a^2+b^2c2=a2+b2

Az egyenlet átalakítható úgy, hogy bármelyik oldalt meg tudjuk kapni a két másik alapján.

c=a2+b2c = \sqrt{a^2+b^2}c=a2+b2​
a=c2−b2a = \sqrt{c^2-b^2}a=c2−b2​
b=c2−b2b = \sqrt{c^2-b^2}b=c2−b2​

Emlékezzünk, hogy Unity-ben a négyzetgyök-vonást a Mathf.Sqrt függvénnyel tudjuk megtenni szóval a fentiek a következőképp néznek ki C#-ban:

float c = Mathf.Sqrt(a*a + b*b);
float a = Mathf.Sqrt(c*c - b*b);
float b = Mathf.Sqrt(c*c - a*a);

Annak ellenére, hogy létezik hatványozó függvény Unity-ben, javaslom, hogy ilyen egyszerű esetben használjuk az szimplaszorzást. Olvashatóbb és optimálisabb is lesz a kód.

Trigonometriai függvények

6 trigonometriai függvény érdekel most minket: a szinusz, a koszinusz és a tangens valamint ezek inverz függvényei, az arkuszszinusz, az arkuszkoszinusz és az arkusztangens.

Szögfüggvény
Definíció
Mathf függvény
Szinusz
Egy szög szinusza = szöggel szemben lévő befogó / átfogó
Mathf.Sin( )
Koszinusz
Egy szög koszinusza = szög melletti lévő befogó / átfogó
Mathf.Cos( )
Tangens
Egy szög tangense = szöggel szemben lévő bef. / szög melletti bef.
Mathf.Tan( )

A fenti definíciók alapján felírhatók:

a/c=sin(α)a/c = sin(α)a/c=sin(α)

b/c=sin(β)b/c = sin(β)b/c=sin(β)

b/c=cos(α)b/c = cos(α)b/c=cos(α)

a/c=cos(β)a/c = cos(β)a/c=cos(β)

a/b=tg(α)a/b = tg(α)a/b=tg(α)

b/a=tg(β)b/a = tg(β)b/a=tg(β)

Tehát a fenti 3 trigonometriai függvény akkor hasznos nekünk, ha egy fokot és egy oldal ismerünk. Ezek alapján kiszámolható a másik két oldal hossza:

a befogó hossza:

a=sin(α)⋅ca = sin(α) · ca=sin(α)⋅c

a=cos(β)⋅ca = cos(β) · ca=cos(β)⋅c

a=tg(α)⋅ba = tg(α)·ba=tg(α)⋅b

a=b/tg(β)a = b/tg(β)a=b/tg(β)

b befogó hossza:

a=sin(β)⋅ca = sin(β) · ca=sin(β)⋅c

b=cos(α)⋅cb = cos(α) · cb=cos(α)⋅c

b=a/tg(α)b = a/tg(α)b=a/tg(α)

b=tg(β)⋅ab = tg(β) · ab=tg(β)⋅a

c átfogó hossza:

c=a/sin(α)c = a / sin(α)c=a/sin(α)

c=b/sin(β)c = b/sin(β)c=b/sin(β)

c=a/cos(β)c = a/cos(β)c=a/cos(β)

c=b/cos(α)c = b/cos(α)c=b/cos(α)

// Például az alábbi kóddal "alpha" szög és a "c" átfogó alapján kiszámolhatók a befogók
float a = Mathf.Sin(alphaInRad) * c;  // a oldal
float b = Mathf.Cos(alphaInRad) * c;  // b oldal
⚠️
Fontos!

A Unity trigonometriai függvényei radiánban várják a paramétert, nem fokban!

Tehát ha fokban ismertjük az alfa vagy a béta szöget először át kell váltani azt radiánba. Ehhez a Mathf.Deg2Rad szorzókonstans használhatjuk.

float a = Mathf.Sin(alphaInDeg * Mathf.Deg2Rad) * c;  // a oldal
float b = Mathf.Cos(alphaInDeg * Mathf.Deg2Rad) * c;  // b oldal
A szinusz függvény vizualizálva

Inverz trigonometriai függvények

Ahogy korábban láttuk, ha két oldalhosszt ismerünk, akkor a Pitagorasz-tétel segítségével kiszámolható a harmadik. Mit tehetünk akkor, ha viszont minket nem a harmadik oldal hossza érdekel, hanem a szögek? A korábban megismert szögfüggvények leírták már az összefüggést a szögek és oldalak közt, ám ez önmagában nem elég akkor, ha pont egy szög érdekel minket:

Pl.: Ismerjük a-t és c-t és ismerjük a kettő közti összefüggést: a/c=sin(α)a/c = sin(α)a/c=sin(α). Ez alapján ki tudjuk számolni α szinuszát, de nem α- magát. Ekkor kellenek az arkusz függvények, amikor egy szög szinusza, koszinusza vagy tangense alapján meg akarjuk kapni a fokot magát.

Szögfüggvény
Definíció
Mathf függvény
Arkuszszinusz
Egy szög szinuszának arkuszszinusza = A szög maga
Mathf.Asin( )
Arkuszkoszinusz
Egy szög koszinuszának arkuszkoszinusza = A szög maga
Mathf.Acos( )
Arkusztangens
Egy szög tangensének arkusztangense = A szög maga
Mathf.Atan( )

Tehát α és β szögek megkaphatók az oldalak alapján a következőképpen:

α=arcsin(a/c)α = arcsin(a/c)α=arcsin(a/c)

α=arccos(b/c)α = arccos(b/c)α=arccos(b/c)

α=tg(a/b)α = tg(a/b)α=tg(a/b)

β=arcsin(b/c)β = arcsin(b/c)β=arcsin(b/c)

β=arccos(a/c)β = arccos(a/c)β=arccos(a/c)

β=tg(b/a)β = tg(b/a)β=tg(b/a)

// Például az alábbi kóddal "alpha" és "béta" szögek az "a" és "c" oldalak alapján
float alphaInRad = Mathf.Asin(a/c);
float betaInRad = Mathf.Acos(a/c);

⚠️ Ne feledjük ⚠️ A Mathf könyvtár arkusz függvényei az eredményeket szintén radiánban adják. Ha a szögeket fokban szeretnénk megkapni, át kell váltanunk a Mathf.Rad2Deg szorzó segítségével.

float alphaInDeg = Mathf.Asin(a/c) * Mathf.Rad2Deg;
float betaInDeg = Mathf.Acos(a/c) * Mathf.Rad2Deg;

A derékszögű háromszög jelentősége a játékfejlesztésben

A 2 és 3D-ben történő programozás alapjait a vektorok képezik. A 2D vektor-ra viszont úgy is tekinthetünk, mint egy derékszögű háromszögre:

x és y komponensek a befogók, a vektor hossza az átfogó és a vízszintessel valamint a függőlegessel bezárt szögei a háromszög belső szögeivel egyeznek meg.

A fentiek alapján tehát sok esetben kiszámolhatunk egy szükséges vektort korlátolt információk alapján. Egy példa:

A következő fejezetekben egyéb valós példákat is megismerünk: Pl.: A virtuális kamera látótereA virtuális kamera látótere

Ha feljebb lépünk a harmadik dimenzióba, akkor is felbontható egy vektor derékszögű háromszögekre a következőképpen:

image

Vegyük V vektort, amit az (x, y és z) értékek írnek le descartes koordináta rendszerben.

Vh = V vektor vízszintes komponense (Vetítése a vízszintes síkra)

|V| = V vektor hossza

Ekkor Vh és y, mint befogók és |V|, mint átfogó leír egy derékszögű háromszöget. (illusztráción sárga)

Emellett x, és z, mint befogók és Vh, mint átfogó szintén leír egy derékszögű háromszöget. (illusztráción lila)

Példa a felhasználásra: Célpontkövető kameraCélpontkövető kamera

Logo

Főoldal

Blog

Elmélet

3D Studio

Adatvédelmi nyilatkozat

GY.I.K.

Házirend

Szerző: Marosi Csaba / marosi.csaba@3d-studio.hu

DiscordGitHubLinkedIn
// Egy lövedék kezdő sebesség-vektora, az ágyú dőlésszöge és a kezdő sebesség alapján

float startSpeed = 10f;   // Derékszögű háromszög "c" átfogója
float gunAngle = 45f;     // A vízszintessel bezárt "alfa" szög

float x = Mathf.Sin(Mathf.Deg2Rad * gunAngle) * c; // alfával szmközti "a" oldal hossza
float y = Mathf.Cos(Mathf.Deg2Rad * gunAngle) * c; // alfa melletti "b" oldal hossza

Vector3 velocity = new Vector2(x,y);  // Kész is a vektpor