September 28, 2021, 17:29:51

### Author Topic: [bb] CalculateNormals by sswift [ 1+ years ago ]  (Read 1466 times)

#### BlitzBot

• Jr. Member
•  • Posts: 1 ##### [bb] CalculateNormals by sswift [ 1+ years ago ]
« on: June 29, 2017, 00:28:43 »
Title : CalculateNormals
Author : sswift
Posted : 1+ years ago

Description : This function calculates both the face and vertex normals for a mesh using a method which does NOT smooth across vertcies that sit at the same location in space.  If two faces do not share a vertex, no smoothing will take place.  This allows you to more easily build levels which have sharp corners.  For exmaple, if you make a cube which has six seperate sides, with no vertcies shared between sides, this function will smooth it properly, whereas the built in function will not.

Code :
Code: BlitzBasic
1. Dim Face_NX#(32768)
2. Dim Face_NY#(32768)
3. Dim Face_NZ#(32768)
4.
5. Dim Vertex_ConnectedTris(32768)
6. Dim Vertex_TriList(32768, 32)
7.
8.
9. ; -------------------------------------------------------------------------------------------------------------------
10. ; This function calculates and sets the normals for a mesh.
11. ;
12. ; Should probably update this so that it can recursively loop through all of an entities children as well.
13. ; -------------------------------------------------------------------------------------------------------------------
14. Function Calculate_Normals(ThisMesh)
15.
16.         ; Loop through all surfaces of the mesh.
17.         Surfaces = CountSurfaces(ThisMesh)
18.         For LOOP_Surface = 1 To Surfaces
19.
20.                 Surface_Handle = GetSurface(ThisMesh, LOOP_Surface)
21.
22.                 ; Reset the number of connected polygons for each vertex.
23.                 For LoopV = 0 To 32767
24.                         Vertex_ConnectedTris(LoopV) = 0
25.                 Next
26.
27.                 ; Loop through all triangles in this surface of the mesh.
28.                 Tris = CountTriangles(Surface_Handle)
29.                 For LOOP_Tris = 0 To Tris-1
30.
31.                         ; Get the vertices that make up this triangle.
32.                                 Vertex_0 = TriangleVertex(Surface_Handle, LOOP_Tris, 0)
33.                                 Vertex_1 = TriangleVertex(Surface_Handle, LOOP_Tris, 1)
34.                                 Vertex_2 = TriangleVertex(Surface_Handle, LOOP_Tris, 2)
35.
36.                         ; Adjust the number of triangles each vertex is connected to and
37.                         ; store this triangle in each vertex's list of triangles it is connected to.
38.                                 ConnectedTris = Vertex_ConnectedTris(Vertex_0)
39.                                 Vertex_TriList(Vertex_0, ConnectedTris) = LOOP_Tris
40.                                 Vertex_ConnectedTris(Vertex_0) = ConnectedTris + 1
41.
42.                                 ConnectedTris = Vertex_ConnectedTris(Vertex_1)
43.                                 Vertex_TriList(Vertex_1, ConnectedTris) = LOOP_Tris
44.                                 Vertex_ConnectedTris(Vertex_1) = ConnectedTris + 1
45.
46.                                 ConnectedTris = Vertex_ConnectedTris(Vertex_2)
47.                                 Vertex_TriList(Vertex_2, ConnectedTris) = LOOP_Tris
48.                                 Vertex_ConnectedTris(Vertex_2) = ConnectedTris + 1
49.
50.                         ; Calculate the normal for this face.
51.
52.                                 ; Get the corners of this face:
53.                                 Ax# = VertexX#(Surface_Handle, Vertex_0)
54.                                 Ay# = VertexY#(Surface_Handle, Vertex_0)
55.                                 Az# = VertexZ#(Surface_Handle, Vertex_0)
56.
57.                                 Bx# = VertexX#(Surface_Handle, Vertex_1)
58.                                 By# = VertexY#(Surface_Handle, Vertex_1)
59.                                 Bz# = VertexZ#(Surface_Handle, Vertex_1)
60.
61.                                 Cx# = VertexX#(Surface_Handle, Vertex_2)
62.                                 Cy# = VertexY#(Surface_Handle, Vertex_2)
63.                                 Cz# = VertexZ#(Surface_Handle, Vertex_2)
64.
65.                                 ; Triangle 1
66.                                 ; Get the vectors for two edges of the triangle.
67.                                 Px# = Ax#-Bx#
68.                                 Py# = Ay#-By#
69.                                 Pz# = Az#-Bz#
70.
71.                                 Qx# = Bx#-Cx#
72.                                 Qy# = By#-Cy#
73.                                 Qz# = Bz#-Cz#
74.
75.                                 ; Compute their cross product.
76.                                 Nx# = Py#*Qz# - Pz#*Qy#
77.                                 Ny# = Pz#*Qx# - Px#*Qz#
78.                                 Nz# = Px#*Qy# - Py#*Qx#
79.
80.                                 ; Store the face normal.
81.                                 Face_NX#(LOOP_Tris) = Nx#
82.                                 Face_NY#(LOOP_Tris) = Ny#
83.                                 Face_NZ#(LOOP_Tris) = Nz#
84.
85.                 Next
86.
87.                 ; Now that all the face normals for this surface have been calculated, calculate the vertex normals.
88.                 Vertices = CountVertices(Surface_Handle)
89.                 For LOOP_Vertices = 0 To Vertices-1
90.
91.                         ; Reset this normal.
92.                         Nx# = 0
93.                         Ny# = 0
94.                         Nz# = 0
95.
96.                         ; Add the normals of all polygons which are connected to this vertex.
97.                         Polys = Vertex_ConnectedTris(LOOP_Vertices)
98.
99.                         For LOOP_Polys = 0 To Polys-1
100.
101.                                 ThisPoly = Vertex_TriList(LOOP_Vertices, LOOP_Polys)
102.
103.                                 Nx# = Nx# + Face_NX#(ThisPoly)
104.                                 Ny# = Ny# + Face_NY#(ThisPoly)
105.                                 Nz# = Nz# + Face_NZ#(ThisPoly)
106.
107.                         Next
108.
109.                         ; Normalize the new vertex normal.
110.                         ; (Normalizing is scaling the vertex normal down so that it's length = 1)
111.
112.                                 Nl# = Sqr(Nx#^2 + Ny#^2 + Nz#^2)
113.
114.                                 ; Avoid a divide by zero error if by some freak accident, the vectors add up to 0.
115.                                 ; If Nl# = 0 Then Nl# = 0.1
116.
117.                                 Nx# = Nx# / Nl#
118.                                 Ny# = Ny# / Nl#
119.                                 Nz# = Nz# / Nl#
120.
121.                         ; Set the vertex normal.
122.
123.                                 VertexNormal Surface_Handle, LOOP_Vertices, Nx#, Ny#, Nz#
124.                                 ;VertexColor Surface_Handle, LOOP_Vertices, polys*127, polys*127, polys*127
125.
126.                 Next
127.
128.         Next
129.
130. End Function

Swift... this code saved my terrain (build in normals in b3d has some buggs then using several alpha surface)