This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/binaries/data/mods/public/maps/random/rmgen/painter/SmoothElevationPainter.js

Last change on this file was 28036, checked in by marder, 11 months ago

rmgen: var -> let -> const

One should always use the variable declaration with the least possible scope.
This patch cleans up many (but not all) of the var in rmgen and replaces them with let or const.
The same is done for let -> const.

comments by: @sera @Stan

Differential revision: https://code.wildfiregames.com/D5214

  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
1/**
2 * Absolute height change.
3 */
4const ELEVATION_SET = 0;
5
6/**
7 * Relative height change.
8 */
9const ELEVATION_MODIFY = 1;
10
11/**
12 * Sets the elevation of the Area in dependence to the given blendRadius and
13 * interpolates it with the existing elevation.
14 *
15 * @param type - ELEVATION_MODIFY or ELEVATION_SET.
16 * @param elevation - target height.
17 * @param blendRadius - How steep the elevation change is.
18 * @param randomElevation - maximum random elevation difference added to each vertex.
19 */
20function SmoothElevationPainter(type, elevation, blendRadius, randomElevation = 0)
21{
22 this.type = type;
23 this.elevation = elevation;
24 this.blendRadius = blendRadius;
25 this.randomElevation = randomElevation;
26
27 if (type != ELEVATION_SET && type != ELEVATION_MODIFY)
28 throw new Error("SmoothElevationPainter: invalid type '" + type + "'");
29}
30
31SmoothElevationPainter.prototype.paint = function(area)
32{
33 // The heightmap grid has one more vertex per side than the tile grid
34 const heightmapSize = g_Map.height.length;
35
36 // Remember height inside the area before changing it
37 const gotHeightPt = [];
38 const newHeight = [];
39 for (let i = 0; i < heightmapSize; ++i)
40 {
41 gotHeightPt[i] = new Uint8Array(heightmapSize);
42 newHeight[i] = new Float32Array(heightmapSize);
43 }
44
45 // Get heightmap grid vertices within or adjacent to the area
46 const brushSize = 2;
47 const heightPoints = [];
48 for (const point of area.getPoints())
49 for (let dx = -1; dx < 1 + brushSize; ++dx)
50 {
51 const nx = point.x + dx;
52 for (let dz = -1; dz < 1 + brushSize; ++dz)
53 {
54 const nz = point.y + dz;
55 const position = new Vector2D(nx, nz);
56
57 if (g_Map.validHeight(position) && !gotHeightPt[nx][nz])
58 {
59 newHeight[nx][nz] = g_Map.getHeight(position);
60 gotHeightPt[nx][nz] = 1;
61 heightPoints.push(position);
62 }
63 }
64 }
65
66 const withinArea = (area, position) => g_TileVertices.some(vertexPos => area.contains(Vector2D.sub(position, vertexPos)));
67
68 // Change height inside the area depending on the distance to the border
69 breadthFirstSearchPaint({
70 "area": area,
71 "brushSize": brushSize,
72 "gridSize": heightmapSize,
73 "withinArea": withinArea,
74 "paintTile": (point, distance) => {
75 let a = 1;
76 if (distance <= this.blendRadius)
77 a = (distance - 1) / this.blendRadius;
78
79 if (this.type == ELEVATION_SET)
80 newHeight[point.x][point.y] = (1 - a) * g_Map.getHeight(point);
81
82 newHeight[point.x][point.y] += a * this.elevation + randFloat(-0.5, 0.5) * this.randomElevation;
83 }
84 });
85
86 // Smooth everything out
87 for (const point of heightPoints)
88 {
89 if (!withinArea(area, point))
90 continue;
91
92 let count = 0;
93 let sum = 0;
94
95 for (let dx = -1; dx <= 1; ++dx)
96 {
97 const nx = point.x + dx;
98
99 for (let dz = -1; dz <= 1; ++dz)
100 {
101 const nz = point.y + dz;
102
103 if (g_Map.validHeight(new Vector2D(nx, nz)))
104 {
105 sum += newHeight[nx][nz];
106 ++count;
107 }
108 }
109 }
110
111 g_Map.setHeight(point, (newHeight[point.x][point.y] + sum / count) / 2);
112 }
113};
114
115/**
116 * Calls the given paintTile function on all points within the given Area,
117 * providing the distance to the border of the area (1 for points on the border).
118 * This function can traverse any grid, for instance the tile grid or the larger heightmap grid.
119 *
120 * @property area - An Area storing the set of points on the tile grid.
121 * @property gridSize - The size of the grid to be traversed.
122 * @property brushSize - Number of points per axis on the grid that are considered a point on the tilemap.
123 * @property withinArea - Whether a point of the grid is considered part of the Area.
124 * @property paintTile - Called for each point of the Area of the tile grid.
125 */
126function breadthFirstSearchPaint(args)
127{
128 // These variables save which points were visited already and the shortest distance to the area
129 const saw = [];
130 const dist = [];
131 for (let i = 0; i < args.gridSize; ++i)
132 {
133 saw[i] = new Uint8Array(args.gridSize);
134 dist[i] = new Uint16Array(args.gridSize);
135 }
136
137 const withinGrid = (x, z) => Math.min(x, z) >= 0 && Math.max(x, z) < args.gridSize;
138
139 // Find all points outside of the area, mark them as seen and set zero distance
140 const pointQueue = [];
141 for (const point of args.area.getPoints())
142 // The brushSize is added because the entire brushSize is by definition part of the area
143 for (let dx = -1; dx < 1 + args.brushSize; ++dx)
144 {
145 const nx = point.x + dx;
146 for (let dz = -1; dz < 1 + args.brushSize; ++dz)
147 {
148 const nz = point.y + dz;
149 const position = new Vector2D(nx, nz);
150
151 if (!withinGrid(nx, nz) || args.withinArea(args.area, position) || saw[nx][nz])
152 continue;
153
154 saw[nx][nz] = 1;
155 dist[nx][nz] = 0;
156 pointQueue.push(position);
157 }
158 }
159
160 // Visit these points, then direct neighbors of them, then their neighbors recursively.
161 // Call the paintTile method for each point within the area, with distance == 1 for the border.
162 while (pointQueue.length)
163 {
164 const point = pointQueue.shift();
165 const distance = dist[point.x][point.y];
166
167 if (args.withinArea(args.area, point))
168 args.paintTile(point, distance);
169
170 // Enqueue neighboring points
171 for (let dx = -1; dx <= 1; ++dx)
172 {
173 const nx = point.x + dx;
174 for (let dz = -1; dz <= 1; ++dz)
175 {
176 const nz = point.y + dz;
177 const position = new Vector2D(nx, nz);
178
179 if (!withinGrid(nx, nz) || !args.withinArea(args.area, position) || saw[nx][nz])
180 continue;
181
182 saw[nx][nz] = 1;
183 dist[nx][nz] = distance + 1;
184 pointQueue.push(position);
185 }
186 }
187 }
188}
Note: See TracBrowser for help on using the repository browser.