Matematik i 3D programmering - vektorer

Tags:    diverse
Skrevet af Bruger #2730 @ 22.04.2004

Matematik for 3D udviklere - vektorer


Inden folk begynder at hagle denne artikel ned samt mine matematiske færdigheder, vil jeg sige at jeg ikke har beskæftiget mig med denne type matematik tidligere. Jeg har indset at skal jeg lave noget fornuftigt 3D programmering i enten DirectX eller OpenGL så er jeg nødt til at kende lidt til matematik. Min Højere Handelseksamen med Matematik på B niveau rækker desværre ikke så langt som til at have gennemgået vektorer. Jeg håber denne artikel kan give lidt lys over det matematik jeg gennemgår. De helt store matematiske genier må bære over med mig ved at trække på smilebåndet over min manglende viden. Jeg ved at jeg nu har forståelse for dette område, og det hjælper mig meget i min daglige udvikling.

Hvad kan man bruge det til


Vektorregning er særdeles nyttigt når man arbejder med geometri eller trigonometri. Eksempelvis til at regne på forskellige lilniestykker i et koordinatsystem, men måske vigtigst af alt så bruges det hele tiden når man arbejder med 3D og spiludvikling.

Vektorer


En vektor kan meget simplistisk forklares som en linie i et koordinatsystem. Det der gør en linie til en vektor er at den har en længde og en retning. En vektors egenskaber består således at to ting, en længde og en retning. Mere er der egentligt ikke i vektorer. Dette er meget simpelt og ikke særligt svært.



Det betyder intet for en vektor om man taler om et almindeligt 2D miljø eller om et 3D miljø eller sågar et 4D miljø, en vektor består stadig kun af en længde og en retning. En vektors udgangspunkt (koordinater fra hvor den starter) betyder ikke noget for dens egenskaber, dette betyder med andre ord at alle vektorer der har ens længde og retning (det vil sige at de er parallelle) er lig med hinanden.



På billedet er vist 5 frit definerede vektorer.

Når en vektor befinder sig med dens "hale" i centrum af et koordinatsystem (dvs. 0,0) så siger man at den befinder sig i "Standard position". Det vil sige at har man en vektor der befinder sig i standard posistion så kan den beskrives ved at angive dens "hoved". Disse to koordinater kaldes for en vektors komponenteer, eller mere simplet for dens start og slut koordinater.



Som det kan ses har vi de to vektorer u og v lig med hinanden, dette skyldes at de har samme længde og retning, hvilket netop var forudsætningen for at man kunne sætte dem lig med hinanden. Da man kan definere en vektor, der er i standard position (dvs. har "hale" i centrum) blot ved at angive dens "hoved" kan man nemt forveksle punkter og vektorer. Punkter er kun et punkt i et koordinatsystem mens en vektor er længde og retning. Normalt angiver man en vektor med små bogstaver som der også tidligere er vist, men man kan også bruge store bogstaver. Her er nogle eksempler på 2, 3 og 4 dimensionelle vektorer:

implementeringer af vectorer:

C# eksempel

Fold kodeboks ind/udKode 


Delphi eksempel

Fold kodeboks ind/udKode 


C++ eksempel
Fold kodeboks ind/udKode 





Det bogstav der står til venstre for ligheds tegnet er navnet på vektoren. De bogstaver der står inden i paranteserne er punkterne for denne vektor i de forskellige dimensioner. Det vil sige at de steder der står ux (læs det x som sænket i forhold til u) er vektorens koordinat på x aksen og så fremdeles med de andre punkter på deres respektive akser. Det vil også sige at når man angiver en vektor så skriver man et tal på pladsen i vektorens beskrivelse i stedet for eks. ux. Dette er et eksempel på en vektor der går igennem 1 på x-aksen, 2 på y-aksen og 3 på z aksen (dvs. en tredimensionel vektor).



Fire typer vektorer


Der introduceres nu fire typer vektorer, den første er en nul-vektor. Denne vektor har nul som alle punkter i dens definition:



De tre sidste typer kaldes for basis vektorer for de løber langs deres respektive akser (x,y,z) og har en længde på 1:



dette vil rent grafisk faktisk danne et tredimensionelt koordinatsystem, som det nedenstående:



Rent geometrisk siger man at to vektorer er ens hvis deres retning og længde er ens. Rent algebraisk siger man at to vektorer er ens hvis deres længde er ens og deres tilsvarede komponenter er ens (dvs. x i den ene skal være lig med x i den anden):



Typisk når man programmerer vælger man at repræsentere en punkt i et koordinatsystem med en floating point værdi (float/kommatal). Derfor kan man godt risikere at man sammenligner to tal der burde være forskellige, men på grund af afrundinger ikke er det. For at kunne sammenligne disse definerer man en "buffer" værdi kaldes EPSILON. Denne værdi er meget lille og skal egentligt bare udjævne de små forskelle vi løber ind i ved afrundinger og andet Det vil

sige at skal vi teste om to vektorer er ens så trækker vi deres koordinater (indenfor hver dimension/akse) fra hinanden og er restværdien mindre end EPSILON, så er de ens.

C++ eksempel
Fold kodeboks ind/udKode 


C# eksempel
Fold kodeboks ind/udKode 


Delphi eksempel
Fold kodeboks ind/udKode 


Længden på en vektor


Rent matematisk kan man beregne længden på en vektor ved at benytte nedenstående formel:



Linierne omkring u'et betyder "længden af", og i dette tilfælde u.

Eksempel:
Find længden af nedenstående vectorer:

u = (1, 2, 3)
v = (1, 2)

Ved hjælp af ovenstående formel kan vi nu beregne længden af hver vektor. Vi starter med vektor u:



og herefter vektor v:



Normalisering af vektorer


Ved at normalisere en vektor forstås at man transformerer den således at dens længde bliver til 1. Dette kaldes også for en enhedsvektor. Denne normalisering ka beregnes ved at dividere længden på vektoren op i hvert enkelt element således:



Et bogstav med en hat ^ over betyder normalisering. Nu er det så bare at indsætte tal i formlen og derefter er vektoren normaliseret.

Vektor addering


Man kan lægge to vektorer sammen ved at addere deres respektive korrodinater sammen, det vil sige at alle fra x dimensionen lægges sammen, det samme gør sig gældende for alle elementer fra y dimensionen og så videre.

Eksempel:



Når man lægger to vektorer sammen kan det se ud som dette. Det der er sket er at man "forlænger" den ene vector med den anden (symboliseret med den grå linie, det er reelt vektoren v der er langt i enden på vektoren u).



Subtraktion af vektorer


Ganske som ved addering trækker man to vectorer fra hinanden ved at trække deres respektive koordinater/punkter fra hinanden, formelen er ikke meget anderledes end ved addering, der står blot minus - i stedet for plus +.



Ved at trække to vektorer fra hinanden får vi som resultat en vektor der peger fra spidsen af v til spidsen af u. Dette bruges tit i computer spil til at beregne en retning fra et punkt til et andet.

Multiplikation af vektorer


Ved at gange to vektorer sammen bevares retningen men længden forøges i henhold til den faktor der ganges med. Hvis der ganges med en negativ faktor så flippes vektoren.

Eksempel:



Prik produkter


Prikprodukter er et af to produkter der er defineret i vektor algebra, det bliver beregnet på følgende måde:



Denne formel giver ingen umiddelbar geometrisk mening, men ved at bruge cosinus' lov kan vi finde en sammenhæng



Denne regel siger at prikproduktet mellem to vektorer er lig cosinus til vinklen mellem dem, skaleret med vektorernes længder. Det vil sige at hvis begge vektorer er unit vektorer (dvs med en længde på 1) så er u gange v lig med cosinus til vinklen mellem dem. Nogle nyttige tips til dette forhold er disse:

Hvis U * v = 0 så er u retvinklet på v.
Hvis U * v > 0 så er vinklen mellem de to vektorer større end 90 grader
Hvis u * v < 0 så er vinklen mellem de to vektorer større end 90 grader.

Krydsprodukter


Den anden form for multiplicering er krydsprodukter. Ulig prikproduktet der giver en længde forøgelse giver krydsproduktet derimod en ny vektor ud fra de eksisterende vektorer. Denne nye vektor er vinkelret på både vektoren u samt vektoren v. Det vil med at dre ord sige at krydsproduktet af vektorerne u og v giver en anden vektor p, der er vinkelret på begge vektorer. Krydsproduktet bliver beregnet således:



I komponentform vil dette se således ud:



Rent geometrisk ville det blive afbildet således:



Et eksempel på dette kunne for eksempel være at man skal finde krydsproduktet af to vektorer k og i og bagefter verificere at den nye vektor j rent faktisk står vinkelret på dem begge:



Dette bliver læst på følgende måde (de ekstra paranteser er for ikke at forvirre når man ganger sammen)



Dette betyder at den nye vektor j ser således ud:



Og som der tidligere er blevet gennemgået så kan vi nu kontrollere at den nye vektor rent faktisk er vinkelret på de andre to vektorer, dette kunne vi teste ved at gange dem sammen og hvis resultatet var nul så var de vinkelrette på hinanden. Det vil sige at j*k=0 og j*i=0. Dette giver os det endelige bevis.

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (19)

User
Bruger #5097 @ 23.04.04 16:46
Hmmm.
Du fortæller da noget godt.
Fin artikel, selvom jeg selv ikke laver 3D spil og andet. Men den er stadig god.
(Læste lidt rundt omkring)

:) :P :D Ti fire
User
Bruger #5377 @ 24.04.04 12:07
vektorregning uden matrcier? Næh nej, den går ikke!
User
Bruger #3530 @ 24.04.04 17:51
En lille træls ting er at udviklermenuen i venstre side blokerer for noget af udsynet til teksten, så jeg kan ikke læse det hele :/
User
Bruger #4503 @ 25.04.04 11:48
Bare læs den som printervenlig version så...
http://www.udvikleren.dk/article_pf.php?id=206
User
Bruger #5358 @ 26.04.04 21:03
hej....

da jeg så overskriften tænkte jeg på SVG........
(w3c modspil til vml (fra MS)) har angiver man kordinator til kontrol punkter for en linie.....
man kan også for vist disse kontrol punkter hvis man tegner en streg i flash...........

er der nogen der kender udregningen bag disse kontrol punkter????????
User
Bruger #2654 @ 27.04.04 16:35
hej...
Jeg vil lige tilføje lift matematik. Når man skriver en vektor, fx vektr-u vil man normalt - i hvert fald i min matbag - skrive u med fed, så vektor-u: u kan kendes fra punktet u. En anden vigtig ting ved vektorer: hvis u har vinklen v med x-aksen er u = |u|*(cos(v), sin(v)). Krydsproduktet kan, udover den måde du angiver, regnes som a X b = |a|*|b|*sin(v), hvor v er vinklen mellem a og b.

adam
User
Bruger #2654 @ 27.04.04 16:41
ups... det jeg skrev blev vist lidt sort, jeg lavede nogen tyrk fejl, men mest af alt akn jeg vist ikke skrive med fed. Nå... uden den fed skrift er humlen:
u = |u|*(cos(v), sin(v))
hvor v er vinklen mellem u og x-aksen
a X b = |a|*|b|*sin(w)
hvor w er vinklen mellem a og b

adam
User
Bruger #4868 @ 28.04.04 16:23
God artikel.

Heh ikke for at hagle ned på din matematik, men så vidt jeg ved så er a^ ikke en enhedsvektor men derimod en tværvektor (hatvektor). Det er en vektor som står vinkelret på vektor a. hvis vektor a's koordinater er (x,y), så er vektor a^'s koordinater (-y,x)... Er det mig der galt på den ? :)
User
Bruger #2654 @ 28.04.04 18:11
Jeg er med blablabla... en hat vektor er en vektor der står vinkel ret på den oprindelige vektor... men det er lidt lige meget

adam
User
Bruger #1151 @ 02.05.04 16:38
Øøøøh er der ikke en regnefejl her? Der hvor du regner længden af vektor |v|. Der får du 2^2 til 1, men ovenfor får du det til 4:s Eller er det bare mig som ikke helt er med?
User
Bruger #1151 @ 02.05.04 16:51
Øøøøh er der ikke en regnefejl her? Der hvor du regner længden af vektor |v|. Der får du 2^2 til 1, men ovenfor får du det til 4:s Eller er det bare mig som ikke helt er med?
User
Bruger #2730 @ 02.05.04 22:12
wooops tyrk fejl..... det skal selvfølgelig være 2^2 = 4...... jeg vil gerne bilde mig self at det var en bevidst indlagt fejl for at se om i var skarpe (P.S. er der nogle der kender nogle gode programmer til at tegne formler i, andre end LaTeX ?, og som her photoshop)
User
Bruger #285 @ 02.05.04 23:45
Hvis du kører Windows, er MathType er godt valg, der dog ikke er gratis. Hvis du har Word inde, ligger der noget i det, det hedder Eqution Editor, der er ok. Det, der er i OpenOffice er også ok!
User
Bruger #2841 @ 03.05.04 19:20
Jeg bruger LyX (også noget Latex fidus, men mere visuelt)
User
Bruger #5800 @ 27.11.04 00:15
nah, mathcad (ja, det koster røv mange penge) owner alt matematik udrening på Win32

Ellers fin artikel.
User
Bruger #6559 @ 26.04.06 20:45
Det var faktisk ikke så ringe, det kan varmt anbefales at læse, og skal man være elektrikker, er det noget man vil møde før eller senere i sin AC teori.
User
Bruger #1445 @ 22.05.06 22:41
Hej Brian Hvarregaard !!!
sqrt((1)^2+(2)^2) bliver til sqrt(5). Du har nok set fejlen. Hvis man skal lave 3D grafik vil jeg også hælde til man bruger Matrix regning og det er jo super nemt. Man bruger bare en rotations matrix for at rotere sine koordinater.

Der findes en relativ nem bog om emnet der hedder
Fundamentals of Robotics ISBN : 0-13-344433-3

Men det er en fin artikel du har skrevet her.
Med Venlig Hilsen
Janus S. Andersen
User
Bruger #2695 @ 25.01.08 12:13
Faktisk bør man bruge quarternioner når der skal roteres og den slags da de løser mange af de problemer, der er ved brugen af matricer...f.eks. rækkefølgen af rotationerne.

Og nej, det er ikke ligemeget om en hatvektor betyder normalisering eller vinkelret. Hvordan vil du læse en matematisk funktion korrekt, hvis du ikke ved hvad hatten betyder ?
User
Bruger #6559 @ 16.04.08 22:05
Jeg har nu haft et mindre forløb om vektorer, og jeg synes man burde skrive, at når man skriver a som en vektor, så plejer man at have en pil over "bogstavet" for at fortælle det er en vektor. Og når "|" står ved f.eks. a, så betyder det numerisk værdi og hvis det er vektor-a betyder det længden af vektoren. Men stadigvæk en god artikel :)
Du skal være logget ind for at skrive en kommentar.
t