Trocha matematiky pro 3D

6. díl - Trocha matematiky pro 3D

Tomáš Herceg       11.07.2008       VB.NET, XNA, Algoritmy       24392 zobrazení

V tomto díle si stručně rozebereme goniometrické funkce a práci s vektory, což budeme potřebovat v dalších dílech (a už jsme potřebovali i v dílech minulých).

Nechci si hrát na experta na matematiku ani na experta na její didaktiku, na to jsou tu povolanější. Ale 3D grafika se nedá dělat bez trochy teorie z matematiky a geometrie. Nebudu zabíhat do nějakých šíleně formálních definic, protože je stejně neumím a nadělal bych tam spoustu chyb, a navíc by nikomu nic neřekly. Pokusím se jednoduše a prakticky vysvětlit, co jsou a jak se používají goniometrické funkce, a jak se pracuje s vektory v 3D prostoru. Hodně věcí budu zjednodušovat, aby se to vešlo do tohoto článku, ale nemělo by to být na úkor srozumitelnosti. Určitě v zájmu zjednodušení nezmíním různé krajní případy a dopustím se mnoha nepřesností, prosím znalé matematiky, aby mi prominuli. Cílem tohoto článku je vysvětlit začátečníkům, kteří ještě potřebné matematické znalosti nemají, alespoň základy této problematiky, minimální množinu věcí, které budeme potřebovat.

Goniometrické funkce anebo trocha teorie na začátek

Jistě je ze školních lavic dobře znáte, jedná se o funkce sinus, kosinus a tangens (ještě byly nějaké další, ale nám budou stačit tyto). Na základních školách se s těmito funkcemi pracuje ve stupních, ale daleko praktičtější je pracovat v radiánech, pojďme se na ně podívat.

Stupňová a oblouková míra

Všichni víme, že pravý úhel je 90 stupňů, plný úhel je pak 360 stupňů. Kromě stupňové míry máme také míru obloukovou, neboli úhel můžeme určit v radiánech. Máme-li kruhovou výseč (část koláče), kde poloměr má stejnou délku jako oblouk na kraji, pak má úhel u středu velikost právě 1 radián. Pro lepší představu máme obrázek:

1 radián 

l je délka oblouku, r je poloměr. Pokud je úhel 1 radián, pak l = r. Ze školy si určitě pamatujete vzorec pro obvod kružnice, platí, že o = 2.π.r. Když jako kruhovou výseč vezmeme celou kružnici, pak oblouk je 2π krát delší než poloměr, takže plný úhel 360 stupňů = 2π radiánů. Předpokládám, že všichni víte, co je to π; pro jistotu, kdyby tady byl někdo mladší, kdo ho ještě ve škole neměl - π (pí) je Ludolfovo číslo a má hodnotu přibližně 3,14159. Je to poměr mezi obvodem kružnice a jejím průměrem.

Jak tedy převádět stupně a radiány mezi sebou? Je to jednoduchá trojčlenka (zkusíme převést 1 radián na stupně):

Převod radiánů na stupně

V XNA máme pro převádění stupňů a radiánů nachystané metody MathHelper.ToDegrees a MathHelper.ToRadians, které převádí radiány na stupně, resp. stupně na radiány.

Sinus

Nyní se podíváme na funkci sinus. Tato funkce má periodu 2π, základní interval je [0, 2π]. Její graf jistě všichni znáte, vypadá takto:

Funkce sinus

V bodě π/2 má funkce hodnotu 1, v bodě 3π/2 má hodnotu -1. Od 2π dále se její základní interval neustále opakuje-

Kosinus

Kosinus je mírně posunutý sinus, opět je 2π periodický a základní interval je [0, 2π]. Graf této funkce vypadá takto:

Funkce kosinus

V bodě 0 má funkce hodnotu 1, v bodě π má funkce hodnotu -1. Od 2π dále se její základní interval také neustále opakuje.

Jednotková kružnice

Hodnoty funkcí sin a cos se dají najít také na tzv. jednotkové kružnici. Dejme tomu, že chceme zjistit hodnoty funkcí sin a cos v bodě π/6 (30 stupňů). Nakreslíme si tedy kružnici o poloměru 1 a naneseme si na ní požadovaný úhel. Hodnoty funkce sin a cos budou vzdálenosti průsečíku polopřímky a kružnice od vodorovné, resp. svislé osy procházející středem kružnice:

 Jednotková kružnice

Poloměr kružnice musí být 1, aby hodnoty funkcí sin a cos vyšly. Úhel se nanáší od vodorovné osy ve směru šipky. Všimněte si, že pokud nanesete úhel 0, hodnota funkce sin bude 0 a funkce cos jakoby 1, červená tečka se nám posune po kružnici na osu X doprava. Vzdálenost od vodorovné osy bude 0 a vzdálenost od svislé 1. Takže vidíme, že to vychází. Když bude tečka pod vodorovnou osou, resp. vlevo od svislé osy, musíme vzít vzdálenost záporně, aby to vyšlo.

Tangens

Funkci tangens vezmu jen tak, aby se neřeklo. Ve skutečnosti platí tan(x) = sin(x) / cos(x), tam, kde je cos(x) = 0 funkce tangens není definována. Funkce tangens má periodu π, její základní interval je [-π/2, π/2]. Vypadá takto:

Funkce tangens

V bodech -π/2 a π/2 jdou hodnoty funkce k ∞ zleva a k -∞ zprava. Od π/2 se stále opakuje základní interval funkce.

Pravoúhlý trojúhelník

Máme-li pravoúhlý trojúhelník, pomocí goniometrických funkcí můžeme vyjádřit vztahy mezi délkami stran a velikostmi úhlů:

Vztahy goniometrických funkcí, délek stran a úhlů v pravoúhlém trojúhelníku

Tím bychom mohli s goniometrickými funkcemi skončit. Předpokládám, že jste je všichni znali, ale pro připomenutí se to hodí. Zvlášť uvědomit si jednotkovou kružnici je velice důležité, budeme ji potřebovat a vlastně jsme ji již v minulých dílech použili, akorát jsem se o tom nezmiňoval.

Trocha 3D geometrie ještě nikoho nezabila

V některém z minulých dílů jsme si už povídali o vektorech a souřadnicích. Nyní si zde jen v rychlosti projdeme základní operace s vektory. Pak si řekneme něco o reprezentaci ploch v 3D prostoru, protože se nám to určitě někdy příště bude hodit.

Vektor

Vektor ve 3D prostoru

Vektor nám ve 3D prostoru určuje vzdálenost a směr. S vektorem můžeme provádět několik operací:

Vynásobení vektoru číslem

Nechť v je vektor a a je číslo, pak vektor a.v má stejný směr, změní se pouze jeho délka. Pokud je a záporné, směr vektoru se přeci jen změní, bude ukazovat přesně na druhou stranu. Pokud v = (x, y, z), pak a.v = (a.x, a.y, a.z). Každá složka vektoru se vynásobí číslem a.

 Vynásobení vektoru číslem

Na tomto obrázu (ve 2D, ale to je jedno), vidíme vektor v=(2,1) a vektor 2.v, jehož souřadnice jsou vynásobené dvěmi, tzn. 2.v=(4,2). Je snadné nahlédnout, že délka vektoru se také zdvojnásobila.

Vynásobíme-li vektor dvěma, zvětší se i jeho délka dvakrát

Dá se to samozřejmě vyjádřit i obecně, aby bylo jasné, že to platí pro každé velikosti souřadnic vektorů, dvojka na druhou se ve druhém výrazu pod odmocninou vytkne, a pak se odmocní. Pro výpočet délky vektoru jsme použili známou Pythagorovu větu. Pro trojsložkové vektory to bude to samé, akorát že pod odmocninou budou všechny tři souřadnice:

Délka vektoru ve 3D    a, b, c jsou jednotlivé souřadnice vektoru

Pokud vektor vynásobíme číslem záporným, obrátí se jeho směr. Opačný vektor k v je -v, má souřadnice (-2,-1).

Dva vektory v a w jsou rovnoběžné, pokud existuje číslo k tak, že v = k . w, jinak řečeno pokud  jeden vektor je násobkem vektoru druhého.

Součet vektorů

Nechť v a w jsou dva vektory a v = (a, b) a w = (c, d). Pak v + w = (a+c, b+d) a vypadá to takto:

Součet vektorů

Pokud vektor w posuneme tak, aby začínal tam, kde vektor v končí, získáme jednu polovinu rovnoběžníka. Úhlopříčkou tohoto rovnoběžníka je pak vektor v+w. Z obrázku je vidět, že souřadnice zeleného vektoru opravdu vychází jako součty souřadnic x a y vektorů v a w.

Nemá smysl zvlášť rozebírat odčítání vektorů, je to to samé, jako sčítání vektoru v s vektorem -w, který už umíme sestrojit. Opět vyjde nějaký rovnoběžník a součet (rozdíl) vektorů bude úhlopříčka na něm. Samozřejmě to funguje i ve 3D prostoru, akorát už nemáme rovnoběžník, ale jakýsi "rovnoběžnostěn".

Skalární součin vektorů

Nechť v a w jsou opět dva vektory, pak skalárním součinem je číslo z, které vznikne vynásobením souřadnic po složkách a jejich sečtením. Nechť v=(a, b, c) a w=(d, e, f), pak z = <v | w> = a . d + b . e + c . f. Výraz <v | w> čteme jako skalární součin vektorů v a w.

Skalární součin vektorů můžeme použít k vypočítání mnoha užitečných informací, například pomocí něj můžeme zjistit, jaký mezi sebou vektory svírají úhel. Pokud jsou vektory u a v normalizované (mají délku 1), pak cos a = <u | v>, kde a je úhel, který mezi sebou tyto vektory svírají.

Pokud se skalární součin dvou vektorů rovná nule, jsou na sebe vektory kolmé. Opět platí jak v rovině, tak i ve 3D prostoru.

Vektorový součin

Nechť v a w jsou opět dva vektory (nerovnoběžné), pak vektorový součin v × w je vektor, který je kolmý jak na vektor v, tak i na vektor w. Tady už jasně vyplývá, že tohle funguje pouze ve 3D prostoru, protože jeden vektor nemůže být v rovině kolmý na dva různoběžné vektory. V prostoru je to naproti tomu velmi užitečné.

 Vektorový součin

Jak se součin počítá? Souřadnice vektorů v a w si zapíšeme do tabulky, zopakujeme je postupně dvakrát za sebe, čili v každém řádku máme x y z x y z. Pak po směru šipek počítáme jednotlivé souřadnice. Modrá šipka značí, že součin čísel přičítáme, červená znamená, že součin odčítáme. První kříž je první souřadnice, druhý kříž je druhá a třetí kříž je třetí souřadnice.

První souřadnici součinu tedy získáme ze součinů 2 . 2 (modrá šipka) a 3 . 0 (červená šipka). První součin přičteme, druhý odečteme, takže první souřadnice je + 2 . 2 - 3 . 0, tedy 4. Obdobně vypočítáme další dvě souřadnice.

Na obrázku jsem nakreslil vektory v a w (červený a modrý). Vektor v×w je dlouhý zelený vektor. Obrázek není úplně přesný, 3D prostor je zkreslený použitou projekcí, takže úhly také nemůžeme měřit úhloměrem, nemají skutečné velikosti. Pokud ale máte trochu prostorové představivosti, vidíte, že zelený vektor je kolmý jak na vektor červený, tak na vektor modrý.

Je nutno podotknout, že v×w není to samé co w×v, na pořadí vektorů v tomto součinu záleží. Pokud bychom vzali vektorový součin w×v, dostaneme jako výsledek vektor opačný, tzn. zelený vektor by měl stejnou délku, ale vedl by na opačnou stranu. Vyplývá to ze způsobu, jak vektorový součin počítáme, když prohodíme řádky tabulky, tak dvojice, které se přičítaly, se budou odčítat, a naopak. Dostaneme tedy opačné souřadnice.

Přímka v prostoru

Přímka obecně je určena jedním bodem a jedním vektorem. Vektor udává pouze směr, nikoliv už pozici, kde se nachátí. Proto potřebujeme nějaký bod, aby bylo jasné, kudy přímka prochází, a směr už určí vektor. To platí jak v rovině, tak i v prostoru.

Přímku v prostoru i v rovině můžeme vyjádřit parametricky:

Parametrické vyjádření přímky Přímka zadaná bodem a vektorem

Přímka na obrázku je zadána modrým bodem se souřadnicemi a,b,c a zeleným vektorem se souřadnicemi u,v,w. Parametrické vyjádření přímky jsou tři rovnice vedle obrázku. Pokud za a,b,c a u,v,w dosadíme, pak pro každé číslo, které dosadíme za t nám vyjdou x,y,z souřadnice nějakého bodu, který leží na přímce. Proč? Protože číslem t násobíme vektor, čímž měníme pouze jeho délku, nikoliv směr. Pomocí čísla t jsme tedy schopni "ukázat vektorem" na každý bod přímky, včetně toho modrého (za t dosadíme nulu) i bodů, které jsou na opačné straně (t dosadíme záporné).

A naopak pokud nám někdo zadá bod a chceme zjistit, jestli leží na naší přímce, zkusíme k němu najít číslo t. Známe modrý bod i vektor a souřadnice bodu x,y,z, o kterém zjišťujeme, jestli na přímce je, máme tedy 3 rovnice s jednou neznámou, což není problém spočítat. Pokud nám ve všech řádcích vyjde stejné t, pak bod na přímce leží. V opačném případě je bod x,y,z mimo přímku, protože nemůžeme zelený vektor natáhnout po přímce tak, aby dosáhl na bod x,y,z. Museli bychom změnit jeho směr, což už ale nejde, protože ho můžeme jen vynásobit číslem.

Rovina v prostoru

S rovinou je to velmi podobné jako s přímkou, je zadána jedním bodem a dvěma vektory, které nesmí být rovnoběžné (protože tím by nám rovina nevznikla, oba vektory musí začínat v daném bodě, jinak to nemá smysl; pozor - vektor není přímka!).

Rovinu můžeme také vyjádřit parametricky:

Parametrické vyjádření roviny Rovina zadaná bodem a dvěma vektory

Opět pomocí kombinace čísel t a s můžeme "ukázat" na libovolný bod roviny a pokud chceme zjistit, jestli bod x,y,z v rovině leží, dosadíme do rovnic a řešíme soustavu. V případě, že najdeme právě jedno řešení, tzn. všechny rovnice budou platit pro jedno konkrétní t a jedno konkrétní s, pak bod x,y,z v rovině leží.

Rovina se dá také zadat pomocí bodu a normálového vektoru. O normále jsme se již bavili v některém z minulých dílů, normála je přímka, která je kolmá na nějakou rovinu. Normálový vektor bude tedy vektor kolmý na tuto rovinu:

Rovina zadaná bodem a normálovým vektorem

Na těchto ilustracích je rovina omezena přímkami, ve skutečnosti je každá rovina, stejně jako přímka nekonečná, stejně jako máme nekonečně mnoho možností pro volbu t, resp. t a s. Tady, aby bylo něco vidět, máme rovinu ohraničenou a bledě modře znázorněnou její část.

V praxi se místo modrého bodu používá konstanta c, což je vzdálenost roviny od počátku vzhledem k délce normálového vektoru. Pokud rovina prochází počátkem, je c nula. Vzhledem k tomu, že jako vzdálenost bodu a roviny se bere vzdálenost nejkratší možná, která vede po kolmici, je to vlastně délka měřená ve směru normálového vektoru, kde jednotkou je délka tohoto normálového vektoru. Tomto vyjádření se říká obecný tvar roviny v prostoru, nám ale pro účely 3D grafiky bude stačit určení roviny bodem a vektorem.

Závěrem

Jsem si vědom toho, že tento teoretický díl plný potřebných znalostí, měl být na začátku seriálu, ale je to proti mé zásadě "nejdřív nadchnout a pak až rozumět". Pro začátečníky je důležité, aby hned ze začátku něco bylo vidět, což se u 3D tutoriálů dělá poměrně těžko bez znalostí práce s vektory. Pokud vám tedy v minulých dílech nebylo něco jasné, po přečtení tohoto dílu by už být mělo. Příště si ukážeme praktické použití toho, co jsme se dnes teoreticky naučili.

Pokud jste vše, co jsem zde složitě popisoval, už znali dříve, je to jen dobře. Doufám ale, že tento díl pomohl těm, kteří potřebné znalosti nemají nebo si je potřebují oprášit.

 

hodnocení článku

3 bodů / 3 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Všechny díly tohoto seriálu

6. Trocha matematiky pro 3D 11.07.2008
5. Klávesnice a myš v XNA 30.03.2008
4. Textury a světla v XNA 24.02.2008
3. Generování terénu 20.02.2008
2. Vykreslujeme 3D model v XNA 17.02.2008
1. Seznámení s XNA frameworkem 14.02.2008

 

Mohlo by vás také zajímat

Windows Presentation Foundation (WPF) - díl 7.: Grid

Grid je jedna z nejdůležitější a nejpoužívanějších pozicovacích komponent ve WPF. Ulehčuje návrh formulářů a své uplatnění nachází v řadě scénářů.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 1.: Úvod do časových pásem a letního času

Ve článku se snažím popsat úskalí, která přináší konverze času přes více časových pásem a pravidel pro počítání letního času.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 3.: DateTimeOffset v .NET Frameworku

DateTimeOffset je méně využívanou alternativou struktury DateTime v .NET Frameworku. Navíc dovoluje ukládat časové pásmo a pohodlně s ním pracovat.

 

 

Nový příspěvek

 

Mr.

1'

csharp|

xml|

css|


'

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

To co pravíte o vektrovém součinu

Tak si uvědomte, že vektorvý součin může být v jakémkoliv n rozměrném prostru. Takže je nesmysl se domnívat, že vektorový součin je realizace požadavku, vytvořit formuli, jež vyrobí jeden vektor kolmý na dva jen a pouze v E2 a nikdy jinak To je opravdu pošetilostt. Ve skutečnosti máte N-rozměrný prostor v něm N-1 LNZ vektorů a chcete jednou formulí zařídit vektor kolmý na těch n-1. A to jde pochopitelně i v desetirozměrném protoru. Pravda, souřadnice vektrou kolmého na těch 9 budou minory (subdeterminanty 9. stupně s přísl. poloh. znaménkem). Takže vektorový součin přísně vzato jde udělat i v E2 a sice takto Máte N-1 tedy 2-1 LNZ vektorů a chcete vyrobit 1 kolmý na n1. To jde přesně stejně, jako v E3, kde ale n-1=2. Takže v E2 obdržíte jako souřadnice toho vektrového součinu minory, ovšem 1. stupně, opatřené polohovým znaménkem.Takhle to totiž vypadá, že se snad chcete domnívat, že vektrový součin je jen v E3 a nikde jine.Starou belu.

V E3 učiníte toto

a1 a2 a3 (zapíšeme znovu jeden z LNZ) do 1. ř.

det a1 a2 a3 = a1* (-1)^1+1 * minor a2 a3 + a2*(-1)^1+2 * minor a1 a3 + a3*(-1)^1+3 * minor a1 a2

b1 b2 b3 b2 b3 b1 b3 b1 b2

a máte souřadnioce vektrou kolmého na N-1 = 3-1 dané LNZ. Totž podobně by bylo v E4, tam byste měl dány 3 LNZ (o č souřadnicích) a postup zcela stejný, ovšem minory stuopně 3

A podobně v E2

čili dán N-1 LNZ tedy

a1 a2 (zapíšeme znovu jeden LNZ do 1. ř)

det a1 a2 = a1 * (-1)^1+1 * minor a2 + a2 * (-1)^1+2 * minor a1

Čili vektorem kolmým na N-1 tedy na ten jediný možný v E2 je právě vektro n = (a2,-1*a1), což je výsledek vektrového součinu v E2. A jak vidno skalární součin daného (a1,a2) spolu s výsledkem vektrového součinu, tedy (n(n1,n2) = (a2,-1*a1) = NULA, což značí, že postup je správný.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

S desetirozměrnými prostory ať si hrají na matfyzu, to přeci není předmětem článku.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Kdy bude pokračování?

čekám na další díl. Nebo je nějáké odúvodnění proč nepokračují další díly?

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Další díl

Mohu se zeptat jestli to bude mít nějáké pokračování?

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

aj ja som hladal nieco taketo aj ked este by bodlo viac z toho XNA game studia 4.0 ..strasne ma to zaujima a samozrejme vsetky knizky len po engl. tutoriali som uz asi spravil secky co su na nete po cesky aa tak

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

bude?

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

Přeji dobrý večer.

Po letech jsem se začetl do jednoho z Vašich starších článků (něco jsem hledal) a přestože se jedná o záležitost skutečně prvohorní (z pohledu životního cyklu Vašeho webu), nelze zcela vyloučit, že občas i v těchto článcích bude k nalezení něco sdělného pro mladé začínající programátory, proto bych se chtěl jenom tak trochu laicky pozeptat, jestli skutečně na MatFyzu je výsledkem skalárního součinu vektor. Ptám se jenom proto, že na školách, které jsem prodělal já, byl výsledkem vždy skalár - nutno však přiznat, že to byly školy ještě za hlubokého socializmu a jak jsem záhy mohl zjistit, ne ve všem nás vždy vyučovaly pravdě. A také se ptám proto, abych moc nehuboval svého syna příjde-li mi s takovýmito vědomostmi (zítra totiž nastupuje právě k Vám na MatFyz ;-)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

No, jak tak na to teď koukám, tak to mám špatně. Na druhou stranu vzato do důsledků, i skalár je vektor (jednorozměrný).

Každopádně díky za připomínku, opravím to.

nahlásit spamnahlásit spam 1 / 3 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

zdravim, vidim ze publikujete jine clanky.. a na tohle uz kaslete? :)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

Můžeme očekvat pokračování tohoto seriálu?

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Ano, taky sem si říkal. Kdy bude pokračování?

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Diskuse: Trocha matematiky pro 3D

Trocha matematiky pro 3D

diky tohle jsem hledal

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback