Implement the 3D image engine from scratch: (6) vector function library

Source: Internet
Author: User
Tags cos

1. Mathematical Analysis

1) basic definition:

A vector consists of multiple components. A 2D or 3D vector represents a directed line segment. The following UX And Uy are two components.

Vector u = <UX, Uy>. If Point P1 (x1, Y1) points to point P2 (X2, Y2), then:

U = P2-p1 = (x2-x1, y2-y1) = <UX, Uy>

After a vector is defined, it is always relative to the origin. Therefore, a point can be used to represent the vector pointing from the origin to the point.

 

2) Vector norm)

The norm is the vector length, which is the distance from the origin point to the end point. | U |, so:

| U | = SQRT (ux2 + uy2)

| U | = SQRT (ux2 + uy2 + uz2)

 

3) unit vector and Normalization

Sometimes, we only care about the vector direction but not its length, so we can normalize the vector so that its direction remains unchanged, and the length is scaled to 1 to facilitate computation. N.

Normalization formula:

N' = N/| n |

 

4) scalar and vector multiplication

For a scalar K, the formula for multiplying a scalar and a vector is:
K * u = K * <UX, Uy> = <K * UX, K * Uy>

Ry of scalar and vector multiplication: scales a vector. You can also multiply by-1 to reverse the vector.

 

5) add vectors and add each component.

U + V = <UX, Uy> + <VX, Vy >=< UX + VX, Uy + Vy>

The geometric meaning of vector addition: the starting point of the translation V to the end point of the U, the result is the line segment from the starting point of the u to the end point of the V after the translation. For example:

 

6) subtraction of vectors and subtraction of components

U-V = <UX, Uy>-<VX, Vy >=< Ux-VX, UY-Vy>

Ry: the end point of a subtrahend pointing to the end line of the subtrahend, for example:

 

7) Point product

Because directly multiplying the components of two vectors has no practical geometric significance, it is generally useless. The dot product is very useful. Definition:

U. V = UX * VX + Uy * Vy

The dot product operation is to multiply the components of two vectors and then add them together. The result is a scalar.

The geometric meaning of Point product is embodied in the dot product formula:

U. V = | u | * | v | * Cos (theta)

That is, the dot product is equal to the length product of two vectors and multiplied by the cosine of the angle between them. So we can calculate the angle:

Theta = arccos (U. V/(| u | * | v | ))

This formula is the basis of many 3D graphics algorithms, and if u and v are both units vectors, then | u | = | v | = 1, then:

Theta = arccos (U. V)

Below are four vertices that are very important:

1. if u is perpendicular to V, U. V = 0

2. If the angle is acute, U. V> 0

3. If the angle is blunt, then u. v <0

4. If U and V are equal, U. V = | u | = | v |

 

Based on these properties of the dot product, we can find a major purpose brought about by the dot product-to calculate the projection vector of the vector in the given direction.

First look:

In fact, the idea is very simple. Since it is to find the projection vector of U on the V component, we can know the direction, so the unit vector of the projection vector is equal to the unit vector of v, so we can obtain the unit vector of the projection vector: P (unit) = V/| v |

Now, the length is reduced. You can know | p | = | u | * Cos (theta). After combining them, you can obtain:

P = (V/| v |) * (| u | * Cos (theta ))

Do you still remember the dot-product formula? U. V = | u | * | v | * Cos (theta)

Therefore, we can simplify the above derivation:

P = (U. V * V)/(| v | * | v |)

 

In addition, the dot product satisfies the following multiplication Law, which is a good proof. It is omitted here:

U. V = V. u

U. (V + W) = (U. V + U. W)

K * (U. V) = (k * u). V = U. (K * V)

 

8) Cross Product

First, define the output cross product:

U × V = | u | * | v | * sin (theta) * n

N is the unit normal vector perpendicular to u and v.

 

How to calculate n? We need to create a matrix:

| I j k |

| UX Uy uz |

| VX Vy VZ |

Where I, j, and K are the unit vectors parallel to X, Y, and Z axes.

N is a linear combination of three scalar values multiplied by X, Y, and Z axis unit vectors:

N = (Uy * VZ-Vy * Uz) * I-(UX * VZ-VX * Uz) * j + (UX * Vy-VX * uy) * k

So n = <Uy * VZ-Vy * Uz,-UX * VZ + VX * Uz, UX * Vy-VX * Uy>

N obtained in this way is not necessarily a unit vector, so normalization is required before use.

 

In fact, the subsequent definition of N non-cross product is more important, because if the angle is required, the dot product can be directly calculated, so the cross product is generally used to obtain the normal vector.

 

Multiplication law of cross product:

U × V =-(v × U)

U x (V + W) = u x V + u x W

(U + V) x w = u x W + V X W

K * (U × V) = (k * u) × V = u * (K * V)

 

9) Displacement Vector

First look at the figure:

P1 is the vector from the origin to P1, VD is the vector from the Point P1 to P2, V is the unit vector of VD, and P is the vector from the origin to P2.

Do you still remember vector addition? We introduced a parameter t to represent the proportion of the sum, then:

P = p1 + T * V' where the value of T is [0, | VD |]

Or

P = p1 + T * vd where the value of T ranges from 0 to 1.

This concept is very important, because it is very useful in tracking straight lines, line segments, curves in the game.

 

 

2. Code Implementation

Void _ cppyin_math: vectoradd (vector2d_ptr va, vector2d_ptr VB, vector2d_ptr vsum) <br/>{< br/> vsum-> X = va-> X + VB-> X; <br/> vsum-> Y = va-> Y + VB-> Y; <br/>}</P> <p> void _ cppyin_math :: vectoradd (vector3d_ptr va, vector3d_ptr VB, vector3d_ptr vsum) <br/>{< br/> vsum-> X = va-> X + VB-> X; <br/> vsum-> Y = va-> Y + VB-> Y; <br/> vsum-> Z = va-> Z + VB-> Z; <br/>}</P> <p> void _ cppyin_math: vectoradd (vector4d_ptr va, vector4d_ptr VB, vector4d_ptr vsum) <br/>{< br/> vsum-> X = va-> X + VB-> X; <br/> vsum-> Y = va-> Y + VB-> Y; <br/> vsum-> Z = va-> Z + VB-> Z; <br/> vsum-> W = 1; <br/>}</P> <p> void _ cppyin_math: vectorsub (vector2d_ptr va, vector2d_ptr VB, vector2d_ptr vsum) <br/>{< br/> vsum-> X = va-> X-Vb-> X; <br/> vsum-> Y = va-> Y-Vb-> Y; <br/>}</P> <p> void _ cppyin_math :: vectorsub (vector3d_ptr va, vector3d_ptr VB, vector3d_ptr vsum) <br/>{< br/> vsum-> X = va-> X-Vb-> X; <br/> vsum-> Y = va-> Y-Vb-> Y; <br/> vsum-> Z = va-> Z-Vb-> Z; <br/>}</P> <p> void _ cppyin_math: vectorsub (vector4d_ptr va, vector4d_ptr VB, vector4d_ptr vsum) <br/>{< br/> vsum-> X = va-> X-Vb-> X; <br/> vsum-> Y = va-> Y-Vb-> Y; <br/> vsum-> Z = va-> Z-Vb-> Z; <br/> vsum-> W = 1; <br/>}</P> <p> void _ cppyin_math: vectorscale (Double K, vector2d_ptr va, vector2d_ptr vscaled) <br/>{< br/> vscaled-> X = K * va-> X; <br/> vscaled-> Y = K * va-> Y; <br/>}</P> <p> void _ cppyin_math: vectorscale (Double K, vector3d_ptr va, vector3d_ptr vscaled) <br/>{< br/> vscaled-> X = K * va-> X; <br/> vscaled-> Y = K * va-> Y; <br/> vscaled-> Z = K * va-> Z; <br/>}</P> <p> void _ cppyin_math: vectorscale (Double K, vector4d_ptr va, vector4d_ptr vscaled) <br/>{< br/> vscaled-> X = K * va-> X; <br/> vscaled-> Y = K * va-> Y; <br/> vscaled-> Z = K * va-> Z; <br/> vscaled-> W = 1; <br/>}</P> <p> double _ cppyin_math: vectordot (vector2d_ptr va, vector2d_ptr VB) <br/>{< br/> return (va-> X * Vb-> x) + (va-> y * Vb-> Y ); <br/>}</P> <p> double _ cppyin_math: vectordot (vector3d_ptr va, vector3d_ptr VB) <br/>{< br/> return (va-> X * Vb-> x) + (va-> y * Vb-> Y) + (va-> Z * va-> Z); <br/>}</P> <p> double _ cppyin_math: vectordot (vector4d_ptr va, vector4d_ptr VB) <br/>{< br/> return (va-> X * Vb-> x) + (va-> y * Vb-> Y) + (va-> Z * va-> Z); <br/>}</P> <p> void _ cppyin_math: vectorcross (vector3d_ptr va, vector3d_ptr VB, vector3d_ptr VN) <br/>{< br/> VN-> X = (va-> y * Vb-> Z) -(va-> Z * Vb-> Y); <br/> VN-> Y =-(va-> X * Vb-> Z) -(va-> Z * Vb-> X); <br/> VN-> Z = (va-> X * Vb-> Y) -(va-> y * Vb-> X); <br/>}</P> <p> void _ cppyin_math: vectorcross (vector4d_ptr va, vector4d_ptr VB, vector4d_ptr VN) <br/>{< br/> VN-> X = (va-> y * Vb-> Z) -(va-> Z * Vb-> Y); <br/> VN-> Y =-(va-> X * Vb-> Z) -(va-> Z * Vb-> X); <br/> VN-> Z = (va-> X * Vb-> Y) -(va-> y * Vb-> X); <br/> VN-> W = 1; <br/>}</P> <p> double _ cppyin_math: vectorlength (vector2d_ptr VA) <br/>{< br/> return SQRT (va-> X * va-> X + va-> y * va-> Y ); <br/>}</P> <p> double _ cppyin_math: vectorlength (vector3d_ptr VA) <br/> {<br/> return SQRT (va-> X * va-> X + va-> y * va-> Y + va-> Z * va-> z ); <br/>}</P> <p> double _ cppyin_math: vectorlength (vector4d_ptr VA) <br/> {<br/> return SQRT (va-> X * va-> X + va-> y * va-> Y + va-> Z * va-> z ); <br/>}</P> <p> void _ cppyin_math: vectornormalize (vector2d_ptr va, vector2d_ptr VN) <br/>{< br/> VN-> x = 0; <br/> VN-> Y = 0; <br/> double length = vectorlength (VA ); </P> <p> If (length <epsilon) <br/>{< br/> return; <br/>}< br/> else <br/>{< br/> double lengthdao = 1/length; <br/> VN-> X = va-> X * lengthdao; <br/> VN-> Y = va-> y * lengthdao; <br/>}</P> <p> void _ cppyin_math: vectornormalize (vector3d_ptr va, vector3d_ptr VN) <br/>{< br/> VN-> x = 0; <br/> VN-> Y = 0; <br/> VN-> Z = 0; <br/> double length = vectorlength (VA); </P> <p> If (length <epsilon) <br/>{< br/> return; <br/>}< br/> else <br/>{< br/> double lengthdao = 1/length; <br/> VN-> X = va-> X * lengthdao; <br/> VN-> Y = va-> y * lengthdao; <br/> VN-> Z = va-> Z * lengthdao; <br/>}</P> <p> void _ cppyin_math :: vectornormalize (vector4d_ptr va, vector4d_ptr VN) <br/>{< br/> VN-> x = 0; <br/> VN-> Y = 0; <br/> VN-> Z = 0; <br/> VN-> W = 0; <br/> double length = vectorlength (VA ); </P> <p> If (length <epsilon) <br/>{< br/> return; <br/>}< br/> else <br/>{< br/> double lengthdao = 1/length; <br/> VN-> X = va-> X * lengthdao; <br/> VN-> Y = va-> y * lengthdao; <br/> VN-> Z = va-> Z * lengthdao; <br/> VN-> W = 1; <br/>}</P> <p> double _ cppyin_math: vectorcos (vector2d_ptr va, vector2d_ptr VB) <br/>{< br/> return vectordot (va, VB)/(vectorlength (VA) * vectorlength (VB )); <br/>}</P> <p> double _ cppyin_math: vectorcos (vector3d_ptr va, vector3d_ptr VB) <br/>{< br/> return vectordot (va, VB)/(vectorlength (VA) * vectorlength (VB); <br/>}</P> <p> double _ cppyin_math: vectorcos (vector4d_ptr va, vector4d_ptr VB) <br/>{< br/> return vectordot (va, VB)/(vectorlength (VA) * vectorlength (VB); <br/>}

Needless to say, it is implemented directly according to the formula derived from the above mathematics.

 

 

3. Download Code

Download complete project source code:> click to enter the download page <

Previously, I forgot to change the resource score to 1 by default. From this time on, I changed it to 0.

 

 

4. Additional content

1) for the question of Vector norm, in fact, this implementation method is not very efficient, and now we use the form of the hook operator to implement, but actually we can use the Taylor series to calculate the approximate value, although there is a little error, however, the computing speed is greatly improved.

2) You can find that when we perform vector normalization, we first obtain lengthdao = 1/length and then multiply with the three components, instead of dividing them by length. In fact, it is also the cause of efficiency. The Division speed of computers is far slower than multiplication. Therefore, we only perform one division, but perform three multiplication. The effect of such simple optimization is very obvious.

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.