Browse Source

Fix normals computation, now computing per vertex normals. Directional light is then ok.

Phyks (Lucas Verney) 4 years ago
parent
commit
f2fd11ab76
3 changed files with 78 additions and 22 deletions
  1. 12
    12
      res/config.json
  2. 1
    0
      src/core/Terrain.cc
  3. 65
    10
      src/framework/Heightmap.cc

+ 12
- 12
res/config.json View File

@@ -28,16 +28,16 @@
28 28
     ],
29 29
 
30 30
     "HEIGHTMAP_METADATA":
31
-{
32
-    "CELLHEIGHT": 75.0,
33
-    "CELLWIDTH": 75.0,
34
-    "MAX_ALTITUDE": 2735.06,
35
-    "MEAN_ALTITUDE": 1897.3,
36
-    "N_COLS": 31,
37
-    "N_ROWS": 446,
38
-    "X_MAX": 989362.5,
39
-    "X_MIN": 987112.5,
40
-    "Y_MAX": 6362362.5,
41
-    "Y_MIN": 6328987.5
42
-}
31
+    {
32
+        "CELLHEIGHT": 75.0,
33
+        "CELLWIDTH": 75.0,
34
+        "MAX_ALTITUDE": 2735.06,
35
+        "MEAN_ALTITUDE": 1897.3,
36
+        "N_COLS": 31,
37
+        "N_ROWS": 446,
38
+        "X_MAX": 989362.5,
39
+        "X_MIN": 987112.5,
40
+        "Y_MAX": 6362362.5,
41
+        "Y_MIN": 6328987.5
42
+    }
43 43
 }

+ 1
- 0
src/core/Terrain.cc View File

@@ -8,6 +8,7 @@
8 8
 #include "Config.h"
9 9
 #include "Buffer.h"
10 10
 
11
+
11 12
 TerrainProgram::TerrainProgram(
12 13
         const std::string vertex_shader_filename,
13 14
         const std::string fragment_shader_filename)

+ 65
- 10
src/framework/Heightmap.cc View File

@@ -23,6 +23,9 @@ Heightmap::Heightmap(const heightmap::metadata_t metadata, const char* filename)
23 23
 std::vector<float> Heightmap::get_as_linear_buffer(void) const {
24 24
     std::vector<float> buffer;
25 25
 
26
+    // Resize buffer to prevent reallocation
27
+    buffer.reserve(3 * metadata_.n_rows * metadata_.n_cols);
28
+
26 29
     // Store the current position in variables
27 30
     // Start from the NW corner
28 31
     float x = metadata_.x_min;
@@ -49,8 +52,16 @@ std::vector<float> Heightmap::get_as_linear_buffer(void) const {
49 52
 
50 53
 
51 54
 std::vector<float> Heightmap::compute_vertex_normals(void) const {
52
-    // TODO: This does not compute per vertex normals, but per face normals
53
-    std::vector<float> normals;
55
+    // Step 1 : Compute a list of the normals associated to each vertex.
56
+
57
+    // Store the normals for each vertex
58
+    // Each first index is a vertex. It contains a list of normals stored as
59
+    // X1, Y1, Z1, X2, Y2, Z2 …
60
+    // Vertices are ordered from NW to SE.
61
+    std::vector< std::vector<float> > vertex_normals;
62
+
63
+    // Resize vector to prevent reallocation
64
+    vertex_normals.resize(metadata_.n_rows * metadata_.n_cols);
54 65
 
55 66
     // Iterate over all the rows and consider them by pair
56 67
     // (hence the nrows - 1)
@@ -63,6 +74,7 @@ std::vector<float> Heightmap::compute_vertex_normals(void) const {
63 74
             // 1   3   …
64 75
             // | / | /
65 76
             // 2   4
77
+            // (Indices in the previous diagram are indices from IBO)
66 78
 
67 79
             // Compute two vectors in the first face
68 80
             const vec3 v12 = {
@@ -76,14 +88,27 @@ std::vector<float> Heightmap::compute_vertex_normals(void) const {
76 88
                 data_[i][j+1] - data_[i+1][j]
77 89
             };  // Second vector, between point number 2 and 3
78 90
 
91
+            // Iterator to the first point in the diagram above
92
+            // Do not keep it as iterators are invalidated when adding
93
+            // elements.
94
+            std::vector< std::vector<float> >::iterator current_first = vertex_normals.begin() + i * metadata_.n_cols + j;
95
+
79 96
             // Compute normal for the first triangle face
80 97
             vec3 normal = {};
81 98
             vec3_mul_cross(normal, v12, v23);
82 99
             vec3_norm(normal, normal);
83
-            // Push normal coordinates
84
-            normals.push_back(normal[0]);
85
-            normals.push_back(normal[1]);
86
-            normals.push_back(normal[2]);
100
+            // Push normal coordinates for point 1
101
+            current_first->push_back(normal[0]);
102
+            current_first->push_back(normal[1]);
103
+            current_first->push_back(normal[2]);
104
+            // Push normal coordinates for point 2
105
+            (current_first + metadata_.n_cols)->push_back(normal[0]);
106
+            (current_first + metadata_.n_cols)->push_back(normal[1]);
107
+            (current_first + metadata_.n_cols)->push_back(normal[2]);
108
+            // Push normal coordinates for point 3
109
+            (current_first + 1)->push_back(normal[0]);
110
+            (current_first + 1)->push_back(normal[1]);
111
+            (current_first + 1)->push_back(normal[2]);
87 112
 
88 113
             // Same thing for second face
89 114
             vec3 v34 = {
@@ -94,13 +119,43 @@ std::vector<float> Heightmap::compute_vertex_normals(void) const {
94 119
             // Compute normal for the second triangle face
95 120
             vec3_mul_cross(normal, v34, v23);  // Mind the order of the vectors to have a positive normal
96 121
             vec3_norm(normal, normal);
97
-            // Push normal coordinates
98
-            normals.push_back(normal[0]);
99
-            normals.push_back(normal[1]);
100
-            normals.push_back(normal[2]);
122
+            // Push normal coordinates for point 2
123
+            (current_first + metadata_.n_cols)->push_back(normal[0]);
124
+            (current_first + metadata_.n_cols)->push_back(normal[1]);
125
+            (current_first + metadata_.n_cols)->push_back(normal[2]);
126
+            // Push normal coordinates for point 3
127
+            (current_first + 1)->push_back(normal[0]);
128
+            (current_first + 1)->push_back(normal[1]);
129
+            (current_first + 1)->push_back(normal[2]);
130
+            // Push normal coordinates for point 4
131
+            (current_first + metadata_.n_cols + 1)->push_back(normal[0]);
132
+            (current_first + metadata_.n_cols + 1)->push_back(normal[1]);
133
+            (current_first + metadata_.n_cols + 1)->push_back(normal[2]);
101 134
         }
102 135
     }
103 136
 
137
+    // Store the normals computed averaged per vertex
138
+    std::vector<float> normals;
139
+
140
+    // Resize vector to prevent reallocation
141
+    normals.resize(3 * metadata_.n_rows * metadata_.n_cols);
142
+
143
+    int n_vertex = 0;
144
+    for (auto& vertex: vertex_normals) {
145
+        vec3 mean_normal = {};
146
+        for (int i = 0; i < vertex.size(); i += 3) {
147
+            vec3 normal = {vertex.at(i), vertex.at(i + 1), vertex.at(i + 2)};
148
+            vec3_add(mean_normal, mean_normal, normal);
149
+        }
150
+        vec3_norm(mean_normal, mean_normal);
151
+
152
+        normals.at(n_vertex) = mean_normal[0];
153
+        normals.at(n_vertex + 1) = mean_normal[1];
154
+        normals.at(n_vertex + 2) = mean_normal[2];
155
+
156
+        n_vertex += 3;
157
+    }
158
+
104 159
     return normals;
105 160
 }
106 161