Point Algorithm vector calculation

Source: Internet
Author: User

 

In OpenGL programming, the calculation of the 3D model vertex method vector is very important, and it directly affects the display effect. I am not familiar with OpenGL for a long time, for a long time, I have been confused about the problem of normal vector computing. After careful research and finding some information, I basically realized the algorithm of normal vector computing. The following is a summary, hope to help beginners.
We all know that in OpenGL, the reflection of the vertex-triangle model on illumination depends on the settings of the vertex method vector. If the method vector calculation is correct, the displayed model is smooth and shiny, otherwise, the image is blurred or hard to see. The following assumes that the model data is derived from the file in the DXF format of AutoCAD. Because the data stored in the DXF file is the vertex coordinate and the sequence of the triangle vertex, and there is no vertex vector information, you need to calculate it yourself; from the knowledge of three-dimensional ry, we can see that the normal vector of a point is equal to the sum of the normal vectors of all triangles whose points are vertex. Therefore, we only need to calculate the normal vector of each triangle, add this normal vector to the normal vector of the three vertices of the triangle. The following are some key code and comments for program implementation:
Void centity: computenormalvector ()
{
Int I, J;
// Retrieve the structure of each vertex
Vertexlist * PVL = new vertexlist [m_nvertexnum + 1];
Vertexlist * pvltemp = (vertexlist *) m_vl.pnext;
For (I = 1; I <m_nvertexnum + 1; I ++)
{
* (PVL + I) = * (pvltemp );
Pvltemp = (vertexlist *) pvltemp-> pnext;
}
// Retrieve the sequence structure of each triangle Vertex
Sequencelist * PSL = new sequencelist [m_nsequencenum];
Sequencelist * psltemp = (sequencelist *) m_sl.pnext;
For (I = 0; I <m_nsequencenum; I ++)
{
* (Psl + I) = * (psltemp );
Psltemp = (sequencelist *) psltemp-> pnext;
}
// Calculate the normal vector of each triangle
Vertex V1, V2, V3;
Vertex temp_v1, temp_v2, V;
For (I = 0; I <m_nsequencenum; I ++)
{
V1 = (PVL + (Psl + I)-> sequence. A)-> vertex;
V2 = (PVL + (Psl + I)-> sequence. B)-> vertex;
V3 = (PVL + (Psl + I)-> sequence. c)-> vertex; // retrieves Three-Point Coordinates
  
Temp_v1 = vector2v (V1, V2); // subtract two-point coordinates to find the vector composed of two points
Temp_v2 = vector2v (V2, V3); // obtain the two vectors of the triangle.
V = normalizevertex (crossvertex (temp_v2, temp_v1); // two vector cross multiplication, Normalization
(Psl + I)-> normalvertex = V; // save
}
Vertex vnormal = vertex (0, 0 );
// Traverse each triangle and add the current triangle normal vector to the three vertex normal vectors respectively
For (j = 0; j <m_nsequencenum; j ++)
{
// Retrieve the current triangle Normal Vector
Vnormal = (Psl + J)-> normalvertex;
// Add the current triangle normal vector to the three vertex normal vectors
(PVL + (Psl + J)-> sequence. a)-> normalvertex =: addvertex (PVL + (Psl + J)-> sequence. a)-> normalvertex, vnormal );
(PVL + (Psl + J)-> sequence. b)-> normalvertex =: addvertex (PVL + (Psl + J)-> sequence. b)-> normalvertex, vnormal );
(PVL + (Psl + J)-> sequence. c)-> normalvertex =: addvertex (PVL + (Psl + J)-> sequence. c)-> normalvertex, vnormal );
  
}
  
// Traverse each vertex and save the calculated normal vector to the vertexlist linked list.
Pvltemp = (vertexlist *) m_vl.pnext;
For (I = 1; I <m_nvertexnum + 1; I ++)
{
Pvltemp-> normalvertex = (PVL + I)-> normalvertex;
Pvltemp = (vertexlist *) pvltemp-> pnext;
}
Delete [] PVL;
Delete [] PSL; // release the buffer
}
The two structures are as follows:
Typedef struct {
Void * PPRE;
Vertex vertex;
Vertex normalvertex; // vertex Normal Vector
Void * pnext;
} Vertexlist; // vertex linked list
Typedef struct {
Void * PPRE;
Sequence sequence;
Vertex normalvertex; // triangle Normal Vector
Void * pnext;
} Sequencelist; // The Sequence List of triangles.
At this point, the vertex normal vector calculation is complete, and then the display list is created:
Id = glgenlists (1 );
Glnewlist (ID, gl_compile );
Glbegin (gl_triangles );
For (I = 0; I <nsnum; I ++) // traverse each triangle
{
V1 = (pvertex + PSL-> sequence. A)-> vertex; // vertex coordinates
V = (pvertex + PSL-> sequence. A)-> normalvertex; // vertex method Vector
Glnormal3f (V. X, V. Y, V. z); // sets the normal vector.
Glvertex3f (v1.x, v1.y, v1.z); // image point
V2 = (pvertex + PSL-> sequence. B)-> vertex;
V = (pvertex + PSL-> sequence. B)-> normalvertex;
Glnormal3f (V. X, V. Y, V. z );
Glvertex3f (v2.x, v2.y, v2.z );
V3 = (pvertex + PSL-> sequence. c)-> vertex;
V = (pvertex + PSL-> sequence. c)-> normalvertex;
Glnormal3f (V. X, V. Y, V. z );
Glvertex3f (v3.x, v3.y, v3.z );
Psl = (sequencelist *) PSL-> pnext;
}
Glend ();
In addition, setting the light and material correctly is the decisive factor affecting the OpenGL display effect. I will not go into details here, but only list the materials and lighting models I have set:
Glshademodel (gl_smooth );
// Set the material and illumination.
Glfloat mat_ambient [] = {0.6, 0.6, 0.6, 1.0}; // ambient light component strength
Glfloat mat_diffuse [] = {0.2, 0.2, 0.2, 1.0}; // diffuse reflection light component strength
Glfloat mat_specular [] = {0.0, 0.0, 0.0, 1.0}; // mirror reflection
Glfloat mat_shininess [] ={ 10.0 };
Glfloat lightmap ambient [] = {0.6, 0.6, 0.6, 1.0 };
Glfloat light=diffuse [] = {0.2, 0.2, 0.2, 1.0 };
Glfloat lightdeskspecular [] = {0.0, 0.0, 0.0, 0.0 };
Glfloat lightfill position [] = {-400.0,-400.0, 200, 1.0 };

 

Wait... an article about how to calculate vertex normals for a mesh? This is very easy right? Yes, but let's say you want high quality normals at faster speed than usual implementatins. Let's say that you want the rutine to be small too. OK, then this very
Short is the articles for you. I assume you know what a mesh is, what a vertex normal is, and that you know what a cross product is. Yes? OK, let's start.

Getting rid of the divissions
Most mesh normalization implementations out there use the typical normal averaging of face normals to calculate the vertex normal. for that, one iterates all the faces on which the current vertex is contained, accumulate the normals and then divide by the amount
Of faces used in the accumulation. now think what this division is doing to the normal. it does not change it's ction for sure, since a division by a scalar only affects the length of the normal. actually we do not care about this length at all, since
We will most probably normalize it to unit length. this means that riyun after the face normal accumulation, we are done, we don't need any divission. thus we can skip not only this operation by also all the code to keep track of the amount of faces that affect
Each vertex.

Getting rid of the normalizations (square roots and divisions)
Now think again what we are really doing When accumulating the face normals into vertex normals. We are making a linear combination of normals, with equal importance or weight for all of them. Is this good? Well, one wowould think that polygons with bigger area
Shocould probably contribute more to the final result. This indeed gives better quality vertex normals. So, let's try to calculate the area of each polygon... Hey, but wait! Open your primary school math book. Have a look to the definition of cross product,
Specially to the length of the cross product. cheeses, the length of a cross product is proportional to the area of the paralepiped created by the two vectors involved in the product. and is not our triangle normal calculated actually as the Cross Product
Of two of its edges? Basically the cross product of these two edges will then give as a face normal with length proportional to the area of the triangle. For free! OK, this means we must not normalice the face normals, and just accumulate them on the vertices
So that we do a high quallity vertex normal calculation. We just skiped one vector normalization per face (meaning, one square root and a division, or an inverse-square root )!

Looping only once
Some implementations make two passes on the mesh to normalize it, one on the faces to calc face normals and vertex-to-normal connectivity, and a second one where this information is used to do the actual normal accumulation for each vertex. this is unnecessary,
We can make the Code a lot smaller and faster, and use less memory by doing it all in one pass. for each face on the mesh, Calc the face normal (without normalization, as just explained), and directly accumulate this normal in each vertex belonging to
Face. After you are done with the faces, each vertex will have recieved all the face normals It Was Supposed To recieve. That simple.

The Code
To finish, let's put all together in a small piece of code:
Void mesh_normalize (mesh * myself) {vert * vert = myself-> Vert; triangle * Face = myself-> face; For (INT I = 0; I <myself-> mnumverts; I ++) vert [I]. normal = vec3 (0.0f); For (INT I = 0; I <myself-> mnumfaces; I ++) {const int IA = face [I]. V [0]; const int
IB = face [I]. V [1]; const int Ic = face [I]. V [2]; const vec3 e1 = vert [Ia]. pos-Vert [IB]. pos; const vec3 e2 = vert [IC]. pos-Vert [IB]. pos; const vec3 NO = cross (E1, E2); vert [Ia]. normal + = no; vert [IB]. normal + = no; vert [IC]. normal + = no;} for (I = 0; I <
Myself-> mnumverts; I ++) Verts [I]. Normal = normalize (Verts [I]. Normal );}
This is quite fast, fast enough to do lot of mesh normalizations per frame. on top of it, if you are using Vertex Shaders You Can Be interested on skipping the last vertex normalization and do it on the shader (last line on the code above ). also in some cases,
Like 64 or even 4 kilobyte demos, It's usual to have all allocated buffers automatically initialized to zero. in that case, if this is the first and only normalization for a given mesh, you may skip the first loop on the function too of course.

From: http://hi.baidu.com/%B0%EB%F5%FC%B9%E2%C4%EA/blog/item/7e96061b269fc1e2ae513378.html

 

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.