3D image engine implementation from scratch: (8) parameterized linear and 3D plane function library

Source: Internet
Author: User

1. Mathematical Analysis

1) parameterized line

Do you still remember the displacement vectors we introduced when learning vectors? The principle of parameterized straight lines is the same as that of parameterized straight lines. In fact, the so-called parameterized line is to use a parameter t to represent a line segment on a straight line. When T is 0, it takes the endpoint of one end of the line segment. When T is set to 1, to the endpoint of the other end.

The core principle is the geometric meaning of vector addition. VD is the addition. If T (from 0 to 1) is used to multiply this VD, the vector p can be described, the coordinate value of P at a certain T is the coordinate value of the line segment from Point P1 to point P2 at T. Note that we use P = p1 + T * vd in the figure, so that the value of T is 0 to 1. If it is P = p1 + T * V ', the value of T is 0 to | VD |, which must be calculated first | VD |. It is not necessary to do so, and 0 and 1 are special numbers for easy operation.

Therefore, the parameterized equation is p (x, y, z) = P0 + V * t.

 

Why do we use parameterization to represent a line segment? Because when we calculate the intersection of two line segments, we only need a system of equations composed of two parameter equations and obtain T1 and T2, as long as they are between 0 and 1, we can know that they have a point of intersection. For example:

Line Segment 1:

X = 1 + 2 * T1;

Y = 3 + 4 * T1;

Line Segment 2:

X = 5 + 6 * t2;

Y = 7 + 8 * t2;

Four equations, four unknowns, can be obtained T1 and T2. If they are all between 0 and 1, then they intersect.

How can I find it? Do you forget the inverse matrix mentioned in the previous chapter? First, calculate the deciding factor, and then...

 

Note: We have not considered many cases, such:

1. Two straight lines are parallel, with no point of intersection

2. The two line segments are on the same line but do not overlap each other

3. Two Line Segments overlap on the same line.

4. The two lines are in the same line, with only one point overlapping

In my implementation functions, I regard these four special cases as non-intersecting or meaningless, and return the return code 0 when they are parallel or collocated. At this time, the calculated T1, T2, and intersection are meaningless.

 

2) 3D plane

How do we define a 3D plane? See:

If you look at the picture carefully, you don't need to talk about it. If there is a point P0, and the normal vector N in the plane, you can determine a plane.

Definition: For any point in space P, if the line segment p-> P0 is perpendicular to the normal vector N, the point P is on the plane.

 

Do you still remember the dot product of the vector? Its most important property is its geometric meaning: The angle between two vectors can be determined. When the dot product of two vectors is 0, the two vectors are perpendicular to each other.

So: n. (p-> P0) = 0

Expand: <a, B, c>. <x-x0, y-y0> = 0

Finally, we can get the point-normal representation of the plane in the form of a * (x-x0) + B * (y-y0) + C (z-z0) = 0

 

We can also d = (-A * x0-B * y0-C * z0)

The preceding format can be:

A * x + B * Y + C * z + D = 0

This is the general form of 3D plane. It is very convenient to calculate the intersection between two planes in general form.

 

Expand the thinking, you can know, for any point <x, y, z>, A * (x-x0) + B * (y-y0) + C (z-z0) the relationship between the value and 0 determines which side of the plane the point is located on. This is very important. I plan to give an example before giving an answer.

Or reference, this is a special plane, is the X-Z plane, so the normal vector N is <0, 1, 0>, a point on the plane, we choose the origin <0, 0, 0>, so now let's take any point, such as (5, 5, 5), then put the data into a * (x-x0) + B * (y-y0) + C (z-z0 ), d:

1 * (5-0) = 5> 0, so the point (5, 5, 5) is in the square direction of the plane.

Then take the vertex (5,-5, 5), then 1 * (-5-0) =-5 <0, so the vertex (5,-5, 5) in the negative direction of the plane.

 

Because this concept is often used, I want to prove it through theory after giving an example. Please refer:

This figure is a plane version. In fact, the relationship between any 3D point and the plane can be viewed from this angle. Here the X axis is the line of the horizontal angle of the X-Z plane, the Y axis is the normal vector of the plane, the picture on the left prompted everyone, U. V = | u | * | v | * Cos (theta ). In the lower left corner, the result of COS (theta) is determined based on the method of the Vector norm to determine whether U. V is greater than 0. The four color points on the graph indicate any point that may be near the plane. Do you still remember the cosine function line? Not much. By now, we have proved that, at a certain point of any 3D limit, we can calculate u with a 3D plane. v> 0 is in the positive direction of the plane, U. v <0 is in the negative direction.

 

3) intersection of parameterized straight lines and 3D planes

Actually, it is to solve the equations and put the linear equation and the 3D plane equation together for simplification.

Parameterized line:

X = x0 + VX * t

Y = y0 + Vy * t

Z = z0 + VZ * t

X0, y0, and z0 are the points that have been on the parameterized straight line.

 

3D plane:

A * x + B * Y + C * z + D = 0

A = NX

B = ny

C = NZ

D =-NX * x0'-ny * y0'-NZ * z0'

X0', y0', and z0' are known points on the 3D plane, so they are added to distinguish known points on the straight line.

 

The expression form of t can be obtained after these equations are substituted into the transformation:

T =-(A * x0 + B * y0 + C * z0 + d)/(A * VX + B * Vy + C * VZ)

Through this T, we can know whether the line segment and the plane have the intersection point. Don't let me talk about it. Check whether T is between 0 and 1.

 

These equations can also represent the coordinates of the intersection points x, y, and z:

X = x0 + VX * t

Y = y0 + Vy * t

Z = z0 + VZ * t

Haha, isn't t the form of the original line segment...

 

 

2. Code Implementation

1) Structure Definition

First, we define the structure that represents parameterized straight lines and 3D planes:

Typedef struct paramline2d_type // parameterized 2D line <br/>{< br/> point2d P0; <br/> point2d P1; <br/> vector2d V; <br/>} paramline2d, * paramline2d_ptr; </P> <p> typedef struct paramline3d_type // parameterized 3D straight line <br/>{< br/> point3d P0; <br/> point3d P1; <br/> vector3d V; <br/>} paramline3d, * paramline3d_ptr; </P> <p> typedef struct plane3d_type // 3D plane <br/>{< br/> point3d P0; <br/> vector3d N; <br/>} plane3d, * plane3d_ptr;

 

2) implementation of common functions

 Void _ cppyin_math: paramlinecreate (point2d_ptr P0, point2d_ptr P1, paramline2d_ptr p) <br/>{< br/> P-> Paix = P0-> X; <br/> P-> 1_y = P0-> Y; <br/> P-> p1.x = p1-> X; <br/> P-> p1.y = p1-> Y; <br/> P-> v. X = p1-> X-P0-> X; <br/> P-> v. y = p1-> Y-P0-> Y; <br/>}</P> <p> void _ cppyin_math: paramlinecreate (point3d_ptr P0, point3d_ptr P1, paramline3d_ptr P) <br/>{< br/> P-> running X = P0-> X; <br/> P-> running y = P0-> Y; <br/> P-> 1_z = P0-> Z; <br/> P-> p1.x = p1-> X; <br/> P-> p1.y = p1-> Y; <br/> P-> p1.z = p1-> Z; <br/> P-> v. X = p1-> X-P0-> X; <br/> P-> v. y = p1-> Y-P0-> Y; <br/> P-> v. z = p1-> Z-P0-> Z; <br/>}</P> <p> void _ cppyin_math: paramlinegetpoint (paramline2d_ptr P, double T, point2d_ptr pt) <br/>{< br/> Pt-> X = p-> limit x + P-> v. x * t; <br/> Pt-> Y = p-> 1_y + P-> v. y * t; <br/>}</P> <p> void _ cppyin_math: paramlinegetpoint (paramline3d_ptr P, double T, point3d_ptr pt) <br/>{< br/> Pt-> X = p-> limit x + P-> v. x * t; <br/> Pt-> Y = p-> 1_y + P-> v. y * t; <br/> Pt-> Z = p-> limit Z + P-> v. z * t; <br/>}</P> <p> int _ cppyin_math: paramlineintersect (paramline2d_ptr P1, paramline2d_ptr P2, double * T1, double * t2) // 0 parallel or coline1 line segment intersection 2 line segments do not intersection <br/>{< br/> double det_p1p2 = p1-> v. x * P2-> v. y-P1-> v. y * P2-> v. x; <br/> If (ABS (det_p1p2) <= epsilon) <br/> return 0; </P> <p> * T1 = (P2-> v. x * (P1-> 1_y-P2-> 1_y)-P2-> v. y * (P1-> 1_x-P2-> 1_x)/det_p1p2; <br/> * t2 = (P1-> v. x * (P1-> 1_y-P2-> 1_y)-P1-> v. y * (P1-> 1_x-P2-> 1_x)/det_p1p2; </P> <p> If (* T1> = 0) & (* t1 <= 1) & (* T2> = 0) & (* t2 <= 1) <br/> return 1; <br/> else <br/> return 2; <br/>}</P> <p> int _ cppyin_math: paramlineintersect (paramline2d_ptr P1, paramline2d_ptr P2, point2d_ptr pt) // 0 parallel or collinearity 1 line segment intersection 2 line segments do not intersection <br/>{< br/> double T1, T2, det_p1p2 = (P1-> v. x * P2-> v. y-P1-> v. y * P2-> v. x); </P> <p> If (ABS (det_p1p2) <= epsilon) <br/> return 0; </P> <p> T1 = (P2-> v. x * (P1-> 1_y-P2-> 1_y)-P2-> v. y * (P1-> 1_x-P2-> 1_x)/det_p1p2; <br/> T2 = (P1-> v. x * (P1-> 1_y-P2-> 1_y)-P1-> v. y * (P1-> 1_x-P2-> 1_x)/det_p1p2; </P> <p> Pt-> X = p1-> 1_x + p1-> v. x * T1; <br/> Pt-> Y = p1-> 1_y + p1-> v. y * T1; </P> <p> If (T1> = 0) & (t1 <= 1) & (T2> = 0) & (t2 <= 1) <br/> return 1; <br/> else <br/> return 2; <br/>}</P> <p> void _ cppyin_math: planecreate (plane3d_ptr plane, point3d_ptr P0, vector3d_ptr normal, int normalize) <br/>{< br/> plane-> running X = P0-> X; <br/> plane-> running y = P0-> Y; <br/> plane-> normalized z = P0-> Z; </P> <p> If (normalize) <br/>{< br/> vector3d N; <br/> vectornormalize (normal, & N); <br/> plane-> N. X = n. x; <br/> plane-> N. y = n. y; <br/> plane-> N. z = n. z; <br/>}< br/> else <br/>{< br/> plane-> N. X = normal-> X; <br/> plane-> N. y = normal-> Y; <br/> plane-> N. z = normal-> Z; <br/>}</P> <p> double _ cppyin_math: planewithpoint (point3d_ptr PT, plane3d_ptr plane) <br/>{< br/> double HS = plane-> N. x * (Pt-> X-plane-> limit x) + <br/> plane-> N. y * (Pt-> Y-plane-> p0.y) + <br/> plane-> N. z * (Pt-> Z-plane-> p0.z); </P> <p> return HS; <br/>}</P> <p> int _ cppyin_math:: planeparamlineinterset (paramline3d_ptr pline, plane3d_ptr plane, double * t, point3d_ptr pt) // 0 not intersection 1 2 intersection on the Extension Line 3 line segments on the plane <br/>{< br/> // calculate the Point product of the straight line and the plane normal vector <br/> double plane_dot_line = vectordot (& pline-> V, & plane-> N); </P> <p> If (ABS (plane_dot_line) <= epsilon) // The Point product is 0, and the line is perpendicular to the face normal, either parallel to the plane, or on the plane, use a straight line below to test <br/>{< br/> If (ABS (planewithpoint (& pline-> P0, plane) <= epsilon) <br/> return 3; <br/> else <br/> return 0; <br/>}</P> <p> // evaluate t <br/> * t =-(plane-> N. x * pline-> limit x + <br/> plane-> N. y * pline-> p0.y + <br/> plane-> N. z * pline-> p0.z-<br/> plane-> N. x * plane-> parallel X-<br/> plane-> N. y * plane-> Policy-<br/> plane-> N. z * plane-> partition Z)/(plane_dot_line); </P> <p> Pt-> X = pline-> partition x + pline-> v. x * (* t); <br/> Pt-> Y = pline-> p0.y + pline-> v. y * (* t); <br/> Pt-> Z = pline-> p0.z + pline-> v. z * (* t); </P> <p> If (* T> = 0.0 & * t <= 1.0) <br/> return 1; <br/> else <br/> return 2; <br/>}

 

 

 

3. Download Code

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

 

 

 

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.