better chunk position hashing algo
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-03-30 17:10:53 -04:00
parent 9c6333108d
commit 67212d6003
9 changed files with 42 additions and 14 deletions

View File

@ -1394,6 +1394,7 @@ Vector pooling
Simplify WorldOctTree to reduce lag with large node counts
Increase memory allowance, mostly fixed latency while walking around
AssetManager streaming budget
Better chunk position hashing algo

View File

@ -6,9 +6,10 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import electrosphere.util.math.HashUtils;
/**
* Caches chunk data on the server
*/
@ -158,7 +159,7 @@ public class BlockChunkCache {
* @return The key
*/
public long getKey(int worldX, int worldY, int worldZ){
return Objects.hash(worldX, worldY, worldZ);
return HashUtils.hashIVec(worldX, worldY, worldZ);
}
/**

View File

@ -7,7 +7,6 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import org.joml.Vector3i;
@ -22,6 +21,7 @@ import electrosphere.net.parser.net.message.TerrainMessage;
import electrosphere.renderer.meshgen.BlockMeshgen.BlockMeshData;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.math.HashUtils;
/**
@ -296,6 +296,6 @@ public class ClientBlockManager {
* @return The key
*/
private Long getRequestKey(int worldX, int worldY, int worldZ, int stride){
return (long)Objects.hash(worldY, worldZ, worldZ);
return (long)HashUtils.hashIVec(worldY, worldZ, worldZ);
}
}

View File

@ -5,11 +5,12 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import org.joml.Vector3i;
import electrosphere.util.math.HashUtils;
/**
@ -151,7 +152,7 @@ public class ClientTerrainCache {
* @return The cache key
*/
public long getKey(int worldX, int worldY, int worldZ){
return Objects.hash(worldX, worldY, worldZ);
return HashUtils.hashIVec(worldX, worldY, worldZ);
}
/**

View File

@ -9,7 +9,6 @@ import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Semaphore;
@ -33,6 +32,7 @@ import electrosphere.renderer.meshgen.TransvoxelModelGeneration;
import electrosphere.renderer.model.Model;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.util.math.HashUtils;
/**
* Manages terrain storage and access on the client
@ -389,7 +389,7 @@ public class ClientTerrainManager {
* @return The key
*/
private Long getRequestKey(int worldX, int worldY, int worldZ, int stride){
return (long)Objects.hash(worldY, worldZ, worldZ);
return (long)HashUtils.hashIVec(worldY, worldZ, worldZ);
}
}

View File

@ -6,7 +6,6 @@ import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;
@ -16,6 +15,7 @@ import electrosphere.engine.Globals;
import electrosphere.logger.LoggerInterface;
import electrosphere.util.FileUtils;
import electrosphere.util.annotation.Exclude;
import electrosphere.util.math.HashUtils;
/**
* An interface for accessing the disk map of chunk information
@ -48,7 +48,7 @@ public class ServerBlockChunkDiskMap {
* @return The key
*/
private static long getBlockChunkKey(int worldX, int worldY, int worldZ){
return Objects.hash(worldX, worldY, worldZ);
return HashUtils.hashIVec(worldX, worldY, worldZ);
}
/**

View File

@ -1,7 +1,6 @@
package electrosphere.server.content;
import java.util.Collection;
import java.util.Objects;
import org.joml.Vector3i;
@ -12,6 +11,7 @@ import electrosphere.server.datacell.Realm;
import electrosphere.server.datacell.ServerDataCell;
import electrosphere.server.saves.SaveUtils;
import electrosphere.util.FileUtils;
import electrosphere.util.math.HashUtils;
public class ServerContentManager {
@ -50,7 +50,7 @@ public class ServerContentManager {
contentRaw.hydrateRawContent(realm,cell);
} else {
//else create from scratch
ServerContentGenerator.generateContent(realm, cell, worldPos, Objects.hash(worldPos.x, worldPos.y, worldPos.z));
ServerContentGenerator.generateContent(realm, cell, worldPos, HashUtils.hashIVec(worldPos.x, worldPos.y, worldPos.z));
}
} else {
//just because content wasn't generated doesn't mean there isn't data saved under that key

View File

@ -7,7 +7,6 @@ import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -42,6 +41,7 @@ import electrosphere.server.fluid.manager.ServerFluidChunk;
import electrosphere.server.fluid.manager.ServerFluidManager;
import electrosphere.server.terrain.manager.ServerTerrainManager;
import electrosphere.server.terrain.models.TerrainModel;
import electrosphere.util.math.HashUtils;
import electrosphere.server.terrain.manager.ServerTerrainChunk;
/**
@ -729,7 +729,7 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
* @return The server data cell if it exists, otherwise null
*/
private Long getServerDataCellKey(Vector3i worldPos){
return (long)Objects.hash(worldPos.x, worldPos.y, worldPos.z);
return (long)HashUtils.hashIVec(worldPos.x, worldPos.y, worldPos.z);
}
/**

View File

@ -0,0 +1,25 @@
package electrosphere.util.math;
/**
* Utilities for hashing things
*/
public class HashUtils {
private static final int SHIFT_Y = 16; // 16 bits per value
private static final int SHIFT_Z = 32; // 2 * 16 bits
/**
* Hashes an integer vector. Must be within the range [0,65536]
* @param x The x component
* @param y The y component
* @param z The z component
* @return The hashed value
*/
public static long hashIVec(int x, int y, int z){
if (x < 0 || x > 65536 || y < 0 || y > 65536 || z < 0 || z > 65536) {
throw new IllegalArgumentException("Values must be in range [0, 65536]");
}
return ((long) x) | ((long) y << SHIFT_Y) | ((long) z << SHIFT_Z);
}
}