Implement 3D image engine from scratch: (15) triangular grating

Source: Internet
Author: User

1. Why raster a triangle?

We cannot always display wireframes in our engines. To support solid colors, lighting, and texture pasters, We need to raster a triangle.

 

 

2. triangle type

To facilitate grating, triangles are generally divided into the following four types:

 

 

 

3. Flat-bottom triangle Grating

First:

The principle of raster a flat triangle is very simple, that is, draw a horizontal line from top down. In the histogram, we take any raster line. The X value on the left side of the line is XL, And the XR on the right side. The Y value does not need to be considered, because these lines are drawn from top down, so y is always ++ from y0 until Y1 or Y2.

 

So the algorithm is very simple, that is, every time we add a Y, We need to calculate the XL and XR, and then call the raster linear function we wrote a long time ago to draw this line.

How can we find XL and XR?

Straight lines can be expressed in many forms. Because we know the coordinates of vertices, the most intuitive form is the two-point formula:

Two points (x1, Y1) and (X2, Y2) on a known straight line are:

(Y-y1)/(y2-y1) = (x-x1)/(x2-x1)

Given that Y is known, let's change the formula to the value of X:

X = (y-y1) * (x2-x1)/(y2-y1)

 

According to the above, we only need to substitute P0 and P1 to obtain XL. Then, we can substitute P0 and P2 to obtain XR. If you don't talk about it much, you can directly provide the implementation code:

Void _ cppyin_3dlib: drawtriangle1 (INT X1, int Y1, int X2, int Y2, int X3, int Y3, DWORD color) // draw a solid flat triangle <br/>{< br/> for (INT y = Y1; y <= Y2; ++ y) <br/> {<br/> int XS, Xe; <br/> xs = (Y-Y1) * (x2-X1)/(Y2-Y1) + X1 + 0.5; <br/> Xe = (Y-Y1) * (X3-X1)/(Y3-Y1) + X1 + 0.5; <br/> drawline (XS, Y, XE, Y, color); <br/>}< br/>}

 

 

 

4. Rasterization of flat triangle

Needless to say, the principle is the same as above and the code is directly pasted.

Void _ cppyin_3dlib: drawtriangle2 (INT X1, int Y1, int X2, int Y2, int X3, int Y3, DWORD color) // draw a solid flat triangle <br/>{< br/> for (INT y = Y1; y <= Y3; ++ y) <br/> {<br/> int XS, Xe; <br/> xs = (Y-Y1) * (X3-X1)/(Y3-Y1) + X1 + 0.5; <br/> Xe = (Y-Y2) * (X3-X2)/(Y3-Y2) + X2 + 0.5; <br/> drawline (XS, Y, XE, Y, color); <br/>}< br/>}

 

 

 

5. grating of any triangle

In fact, after reading this figure, we should find it very simple. We can find a special point (xlongside, ymiddle), draw a flat triangle, and then draw a flat triangle.

The following code implements this function and provides some help:

1. Given the Y value of three vertices, you can determine whether it is flat or flat. If one of them is satisfied, you can directly draw the image.

2. the three vertices of the input function are out of order, so we need to identify several situations based on the Y value. In my implementation, we have exhausted several cases of the Y value, then assign values to the three vertices.

3. Draw them one by one. below is the code.

Void _ cppyin_3dlib: drawtriangle (INT X1, int Y1, int X2, int Y2, int X3, int Y3, DWORD color) // draw any solid triangle <br/>{< br/> If (Y1 = Y2) <br/>{< br/> If (Y3 <= Y1) // flat bottom <br/>{< br/> drawtriangle1 (X3, Y3, X1, Y1, X2, Y2, color ); <br/>}< br/> else // flat top <br/>{< br/> drawtriangle2 (x1, Y1, X2, Y2, X3, Y3, color ); <br/>}< br/> else if (Y1 = Y3) <br/>{< br/> If (Y2 <= Y1) // flat bottom <br/>{< br/> drawtriangle1 (X2, Y2, X1, Y1, X3, Y3, color ); <br/>}< br/> else // flat top <br/>{< br/> drawtriangle2 (x1, Y1, X3, Y3, X2, Y2, color ); <br/>}< br/> else if (y2 = Y3) <br/>{< br/> If (Y1 <= Y2) // flat bottom <br/>{< br/> drawtriangle1 (x1, Y1, X2, Y2, X3, Y3, color ); <br/>}< br/> else // flat top <br/>{< br/> drawtriangle2 (X2, Y2, X3, Y3, X1, Y1, color ); <br/>}< br/> else <br/> {<br/> double xtop, ytop, xmiddle, ymiddle, xbottom, and ybottom; <br/> If (Y1 <Y2 & Y2 <Y3) // Y1 Y2 Y3 <br/>{< br/> xtop = x1; <br/> ytop = Y1; <br/> xmiddle = x2; <br/> ymiddle = Y2; <br/> xbottom = X3; <br/> ybottom = Y3; <br/>}< br/> else if (Y1 <Y3 & Y3 <Y2) // Y1 Y3 Y2 <br/>{< br/> xtop = x1; <br/> ytop = Y1; <br/> xmiddle = X3; <br/> ymiddle = Y3; <br/> xbottom = x2; <br/> ybottom = Y2; <br/>}< br/> else if (Y2 <Y1 & Y1 <Y3) // Y2 Y1 Y3 <br/>{< br/> xtop = x2; <br/> ytop = Y2; <br/> xmiddle = x1; <br/> ymiddle = Y1; <br/> xbottom = X3; <br/> ybottom = Y3; <br/>}< br/> else if (Y2 <Y3 & Y3 <Y1) // Y2 Y3 Y1 <br/>{< br/> xtop = x2; <br/> ytop = Y2; <br/> xmiddle = X3; <br/> ymiddle = Y3; <br/> xbottom = x1; <br/> ybottom = Y1; <br/>}< br/> else if (Y3 <Y1 & Y1 <Y2) // Y3 Y1 Y2 <br/>{< br/> xtop = X3; <br/> ytop = Y3; <br/> xmiddle = x1; <br/> ymiddle = Y1; <br/> xbottom = x2; <br/> ybottom = Y2; <br/>}< br/> else if (Y3 <Y2 & Y2 <Y1) // Y3 Y2 Y1 <br/>{< br/> xtop = X3; <br/> ytop = Y3; <br/> xmiddle = x2; <br/> ymiddle = Y2; <br/> xbottom = x1; <br/> ybottom = Y1; <br/>}< br/> int XL; // X for long edges in ymiddle, to determine whether the long side is on the left or right <br/> XL = (ymiddle-ytop) * (xbottom-xtop)/(ybottom-ytop) + xtop + 0.5; </P> <p> If (XL <= xmiddle) // Left triangle <br/> {<br/> // draw a flat bottom <br/> drawtriangle1 (xtop, ytop, XL, ymiddle, xmiddle, ymiddle, color); </P> <p> // painting flat top <br/> drawtriangle2 (XL, ymiddle, xmiddle, ymiddle, xbottom, ybottom, color); <br/>}< br/> else // right triangle <br/>{< br/> // draw a flat bottom <br/> drawtriangle1 (xtop, ytop, xmiddle, ymiddle, XL, ymiddle, color); </P> <p> // painting flat top <br/> drawtriangle2 (xmiddle, ymiddle, XL, ymiddle, xbottom, ybottom, color); <br/>}< br/>}

 

 

 

6. implement solid rendering of Objects

Previously, we had only one rendering mode, that is, wireframes. With the above triangle raster function, we can do solid rendering. below is the rendering code, which is very simple.

It's just traversing every triangle of an object and then calling the above function, hey.

Void _ cppyin_3dlib: objectdrawsolid (object_ptr OBJ) // draw the solid polygon of an object <br/>{< br/> for (INT I = 0; I <obj-> polycount; ++ I) <br/>{< br/> point4d_ptr p0 = & (obj-> vertexlisttrans [obj-> polylist [I]. vertexindexs [0]); <br/> point4d_ptr p1 = & (obj-> vertexlisttrans [obj-> polylist [I]. vertexindexs [1]); <br/> point4d_ptr P2 = & (obj-> vertexlisttrans [obj-> polylist [I]. vertexindexs [2]); </P> <p> // draw only the front <br/> If (obj-> polylist [I]. state = poly_state_active) <br/>{< br/> drawtriangle (P0-> X, P0-> Y, P1-> X, P1-> y, p2-> X, P2-> Y, obj-> polylist [I]. color); <br/>}< br/>}

 

 

 

7.

This is the demo of solid rendering.

 

 

 

8. Download Code

Complete Project source code:> click to enter the download page <

 

 

 

9. Special Instructions

I have recently started working on C ++ in order to find a job. I am working on an online game client, so I haven't updated this graphics library yet. I am free to continue updating it. I found that I am still not familiar with C ++, and may update more C ++ stuff.

 

 

 

 

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.