@@ -33,7 +33,6 @@ public class Scene {
33
33
34
34
35
35
private static final int TILE_DRAW_DISTANCE = 75 ;
36
- public static boolean [][][][] TILE_VISIBILITY_MAPS = new boolean [8 ][32 ][(TILE_DRAW_DISTANCE * 2 ) + 1 ][(TILE_DRAW_DISTANCE * 2 ) + 1 ];
37
36
38
37
39
38
public static boolean lowMemory = true ;
@@ -110,107 +109,17 @@ public class Scene {
110
109
private int currentCameraTileX ;
111
110
private int currentCameraZ ;
112
111
112
+ private CameraTileVisibility tileVisibilityInfo ;
113
+
113
114
public Scene (int [][][] heightMap ) {
114
115
tileArray = new SceneTile [mapSizeZ ][mapSizeX ][mapSizeY ];
115
116
tileOcclusionCycles = new int [mapSizeZ ][mapSizeX + 1 ][mapSizeY + 1 ];
116
117
this .heightMap = heightMap ;
117
118
initToNull ();
118
119
}
119
120
120
- /**
121
- * Precomputes visibility information for the game world's tiles based on possible camera positions and orientations.
122
- *
123
- * This helps to quickly determine which tiles need to be rendered based on the camera's current position and orientation.
124
- *
125
- * It then interpolates this data, ensuring that the nearby tiles around visible tiles are also visible.
126
- * This interpolation helps to prevent sudden changes in tile visiblity as the camera moves or rotates.
127
- *
128
- * @param minHeight The minimum height to check for visibility.
129
- * @param maxHeight The maximum height to check for visibility.
130
- * @param width The width of the viewport.
131
- * @param height The height of the viewport.
132
- * @param arg0 An array containing height values for each camera pitch angle.
133
- */
134
- public void computeTileVisibilityMaps (int minHeight , int maxHeight , int width , int height , int [] arg0 ) {
135
- drawWidth = width ;
136
- drawHeight = height ;
137
- drawWidthMidpoint = width / 2 ;
138
- drawHeightMidpoint = height / 2 ;
139
-
140
- final int cameraAngles = 9 ;
141
- final int rotationsPerCircle = 32 ;
142
-
143
- boolean [][][][] visibilityMaps = new boolean [cameraAngles ][rotationsPerCircle ][(TILE_DRAW_DISTANCE * 2 ) + 3 ][(TILE_DRAW_DISTANCE * 2 ) + 3 ];
144
-
145
- // Iterating over different camera pitch angles (from 128 to 384)
146
- for (int pitch = 128 ; pitch <= 384 ; pitch += 32 ) {
147
- // Iterating over different camera yaw angles (from 0 to 2048)
148
- for (int yaw = 0 ; yaw < 2048 ; yaw += 64 ) {
149
- CameraRotation camera = new CameraRotation (yaw , pitch );
150
-
151
- int pitchIndex = (pitch - 128 ) / 32 ;
152
- int yawIndex = yaw / 64 ;
153
-
154
- // Iterating over different tile positions around the camera
155
- for (int tileX = -26 ; tileX <= 26 ; tileX ++) {
156
- for (int tileY = -26 ; tileY <= 26 ; tileY ++) {
157
- int absoluteTileX = tileX * 128 ;
158
- int absoluteTileY = tileY * 128 ;
159
- boolean isVisible = false ;
160
-
161
- // Checking visibility at different heights
162
- for (int h = -minHeight ; h <= maxHeight ; h += 128 ) {
163
- if (isPointVisibleOnScreen (absoluteTileX , arg0 [pitchIndex ] + h , absoluteTileY , camera )) {
164
- isVisible = true ;
165
- break ;
166
- }
167
- }
168
- visibilityMaps [pitchIndex ][yawIndex ][tileX + TILE_DRAW_DISTANCE + 1 ][tileY + TILE_DRAW_DISTANCE + 1 ] = isVisible ;
169
- }
170
- }
171
- }
172
- }
173
-
174
- // smooth out any gaps in the visibility maps by checking adjacent values
175
- final int maxPitchIndex = 8 ;
176
- final int maxYawIndex = 32 ;
177
-
178
- for (int pitchIndex = 0 ; pitchIndex < maxPitchIndex ; pitchIndex ++) {
179
- for (int yawIndex = 0 ; yawIndex < maxYawIndex ; yawIndex ++) {
180
- for (int tileX = -TILE_DRAW_DISTANCE ; tileX < TILE_DRAW_DISTANCE ; tileX ++) {
181
- for (int tileY = -TILE_DRAW_DISTANCE ; tileY < TILE_DRAW_DISTANCE ; tileY ++) {
182
- boolean isVisible = false ;
183
-
184
- checkVisibility :
185
- for (int xOffset = -1 ; xOffset <= 1 ; xOffset ++) {
186
- for (int yOffset = -1 ; yOffset <= 1 ; yOffset ++) {
187
- // Check visibility at the current pitch and yaw, adjusted by the offset
188
- if (visibilityMaps [pitchIndex ][yawIndex ][tileX + xOffset + TILE_DRAW_DISTANCE + 1 ][tileY + yOffset + TILE_DRAW_DISTANCE + 1 ]) {
189
- isVisible = true ;
190
- break checkVisibility ;
191
- }
192
- // Check visibility at the current pitch and next yaw, adjusted by the offset
193
- if (visibilityMaps [pitchIndex ][(yawIndex + 1 ) % 31 ][tileX + xOffset + TILE_DRAW_DISTANCE + 1 ][tileY + yOffset + TILE_DRAW_DISTANCE + 1 ]) {
194
- isVisible = true ;
195
- break checkVisibility ;
196
- }
197
- // Check visibility at the next pitch and current yaw, adjusted by the offset
198
- if (visibilityMaps [pitchIndex + 1 ][yawIndex ][tileX + xOffset + TILE_DRAW_DISTANCE + 1 ][tileY + yOffset + TILE_DRAW_DISTANCE + 1 ]) {
199
- isVisible = true ;
200
- break checkVisibility ;
201
- }
202
- // Check visibility at the next pitch and next yaw, adjusted by the offset
203
- if (visibilityMaps [pitchIndex + 1 ][(yawIndex + 1 ) % 31 ][tileX + xOffset + TILE_DRAW_DISTANCE + 1 ][tileY + yOffset + TILE_DRAW_DISTANCE + 1 ]) {
204
- isVisible = true ;
205
- break checkVisibility ;
206
- }
207
- }
208
- }
209
- TILE_VISIBILITY_MAPS [pitchIndex ][yawIndex ][tileX + TILE_DRAW_DISTANCE ][tileY + TILE_DRAW_DISTANCE ] = isVisible ;
210
- }
211
- }
212
- }
213
- }
121
+ public void precalculateTileVisibility (int viewportWidth , int viewportHeight , int minHeight , int maxHeight , int [] heightsForPitch ) {
122
+ tileVisibilityInfo = new CameraTileVisibility (viewportWidth , viewportHeight , TILE_DRAW_DISTANCE , minHeight , maxHeight , heightsForPitch );
214
123
}
215
124
216
125
public static int adjustLightness (int hsl , int lightness ) {
@@ -223,36 +132,6 @@ public static int adjustLightness(int hsl, int lightness) {
223
132
return (hsl & 0xff80 ) + lightness ;
224
133
}
225
134
226
- /**
227
- * Checks if a point in 3D space projects onto the screen, after rotation and perspective transformation.
228
- *
229
- * @param x The x-coordinate of the point in 3D space.
230
- * @param y The y-coordinate of the point in 3D space.
231
- * @param z The z-coordinate of the point in 3D space.
232
- * @return Returns true if the projected point falls within the screen boundaries; otherwise false.
233
- */
234
- public boolean isPointVisibleOnScreen (int x , int y , int z , CameraRotation cameraRotation ) {
235
- // Rotate around the X axis
236
- int rotatedX = z * cameraRotation .yawSine + x * cameraRotation .yawCosine >> 16 ;
237
- int rotatedZ = z * cameraRotation .yawCosine - x * cameraRotation .yawSine >> 16 ;
238
-
239
- // Rotate around the Y axis
240
- int rotatedY = y * cameraRotation .pitchSine + rotatedZ * cameraRotation .pitchCosine >> 16 ;
241
- int finalZ = y * cameraRotation .pitchCosine - rotatedZ * cameraRotation .pitchSine >> 16 ;
242
-
243
- // Check if the point is behind the near clipping plane (too close to the camera)
244
- if (rotatedY < 50 /* || rotatedY > 3500*/ ) {
245
- return false ;
246
- }
247
-
248
- // Apply perspective division and translate to screen space
249
- int screenX = drawWidthMidpoint + (rotatedX << 9 ) / rotatedY ;
250
- int screenY = drawHeightMidpoint + (finalZ << 9 ) / rotatedY ;
251
-
252
- // Check if the point is within the screen bounds
253
- return screenX >= 0 && screenX <= drawWidth && screenY >= 0 && screenY <= drawHeight ;
254
- }
255
-
256
135
257
136
public void createOccluder (int z , int searchMask , int lowestX , int highestX , int lowestY , int highestY , int highestZ , int lowestZ ) {
258
137
SceneCluster sceneCluster = new SceneCluster ();
@@ -422,7 +301,7 @@ public void render(Camera camera, int plane) {
422
301
currentPitchCosine = Model .COSINE [pitch ];
423
302
currentYawSine = Model .SINE [yaw ];
424
303
currentYawCosine = Model .COSINE [yaw ];
425
- currentTileVisibilityMap = TILE_VISIBILITY_MAPS [(pitch - 128 ) / 32 ][yaw / 64 ];
304
+ currentTileVisibilityMap = tileVisibilityInfo . visibilityInfo [(pitch - 128 ) / 32 ][yaw / 64 ];
426
305
currentCameraX = cameraPosX ;
427
306
currentCameraZ = cameraPosZ ;
428
307
currentCameraY = cameraPosY ;
0 commit comments