properly layout roads

This commit is contained in:
austin 2025-05-20 13:24:56 -04:00
parent f8e919f599
commit d3d37bb763
3 changed files with 76 additions and 24 deletions

View File

@ -1919,6 +1919,7 @@ Unify functions to fetch/generate chunks on server
Macro data blocks terrain and block generation until it is ready
Content generation blocks for macro data generation
Roads block content generation
Properly layout roads along town points in TownLayout

View File

@ -5,6 +5,7 @@ import java.util.List;
import java.util.stream.Collectors;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.data.struct.StructureData;
import electrosphere.engine.Globals;
@ -24,12 +25,12 @@ public class TownLayout {
/**
* Scaler for town layout nodes
*/
public static final double TOWN_LAYOUT_SCALER = 16;
public static final double TOWN_LAYOUT_SCALER = 64;
/**
* Relaxation factor for regularizing placement of town center nodes
*/
public static final double VORONOI_RELAXATION_FACTOR = 0.5;
public static final double VORONOI_RELAXATION_FACTOR = 0.4;
/**
* Lays out structures for a town
@ -63,42 +64,76 @@ public class TownLayout {
//
//find the nodes to connect
Vector3d townCenter = town.getPos();
Vector3d scanPoint = new Vector3d();
//get center loc
Vector3d centerNodeLoc = VoronoiUtils.solveClosestVoronoiNode(
townCenter.x / TOWN_LAYOUT_SCALER,
0,
townCenter.z / TOWN_LAYOUT_SCALER,
VORONOI_RELAXATION_FACTOR
).mul(TOWN_LAYOUT_SCALER,1,TOWN_LAYOUT_SCALER);
centerNodeLoc.y = realm.getServerWorldData().getServerTerrainManager().getElevation(centerNodeLoc);
scanPoint.set(townCenter);
Vector3d centerNodeLoc = TownLayout.getTownCenter(realm, scanPoint);
//get north node
Vector3d upNodeLoc = VoronoiUtils.solveClosestVoronoiNode(
townCenter.x / TOWN_LAYOUT_SCALER,
0,
townCenter.z / TOWN_LAYOUT_SCALER + TOWN_LAYOUT_SCALER,
VORONOI_RELAXATION_FACTOR).mul(TOWN_LAYOUT_SCALER,1,TOWN_LAYOUT_SCALER);
upNodeLoc.y = realm.getServerWorldData().getServerTerrainManager().getElevation(upNodeLoc);
scanPoint.set(townCenter).add(0,0,TOWN_LAYOUT_SCALER);
Vector3d upNodeLoc = TownLayout.getTownCenter(realm, scanPoint);
//get left node
Vector3d leftNodeLoc = VoronoiUtils.solveClosestVoronoiNode(
townCenter.x / TOWN_LAYOUT_SCALER - TOWN_LAYOUT_SCALER,
0,
townCenter.z / TOWN_LAYOUT_SCALER,
VORONOI_RELAXATION_FACTOR
).mul(TOWN_LAYOUT_SCALER,1,TOWN_LAYOUT_SCALER);
leftNodeLoc.y = realm.getServerWorldData().getServerTerrainManager().getElevation(leftNodeLoc);
scanPoint.set(townCenter).add(-TOWN_LAYOUT_SCALER,0,0);
Vector3d leftNodeLoc = TownLayout.getTownCenter(realm, scanPoint);
//get right node
scanPoint.set(townCenter).add(TOWN_LAYOUT_SCALER,0,0);
Vector3d rightNodeLoc = TownLayout.getTownCenter(realm, scanPoint);
//get south node
scanPoint.set(townCenter).add(0,0,-TOWN_LAYOUT_SCALER);
Vector3d downNodeLoc = TownLayout.getTownCenter(realm, scanPoint);
System.out.println("Center: " + centerNodeLoc.x + " " + centerNodeLoc.y + " " + centerNodeLoc.z);
System.out.println("Up: " + upNodeLoc.x + " " + upNodeLoc.y + " " + upNodeLoc.z);
System.out.println("Right: " + rightNodeLoc.x + " " + rightNodeLoc.y + " " + rightNodeLoc.z);
System.out.println("Left: " + leftNodeLoc.x + " " + leftNodeLoc.y + " " + leftNodeLoc.z);
System.out.println("Down: " + downNodeLoc.x + " " + downNodeLoc.y + " " + downNodeLoc.z);
//up-facing road
Road.createRoad(macroData, upNodeLoc, centerNodeLoc);
//up-facing road
//right-facing road
Road.createRoad(macroData, rightNodeLoc, centerNodeLoc);
//left-facing road
Road.createRoad(macroData, leftNodeLoc, centerNodeLoc);
//down-facing road
Road.createRoad(macroData, downNodeLoc, centerNodeLoc);
town.setResolution(Town.TOWN_RES_MAX);
}
/**
* Clamps the scan point to the closest town center point
* @param realm The realm
* @param scanPoint The scan point
* @return The closest town center point
*/
private static Vector3d getTownCenter(Realm realm, Vector3d scanPoint){
Vector3d solved = VoronoiUtils.solveClosestVoronoiNode(
scanPoint.x / TOWN_LAYOUT_SCALER,
0,
scanPoint.z / TOWN_LAYOUT_SCALER,
VORONOI_RELAXATION_FACTOR
);
solved.mul(TOWN_LAYOUT_SCALER,0,TOWN_LAYOUT_SCALER);
Vector3i cell = VoronoiUtils.solveVoronoiCell(
scanPoint.x / TOWN_LAYOUT_SCALER,
0,
scanPoint.z / TOWN_LAYOUT_SCALER
);
solved.add(
cell.x * TOWN_LAYOUT_SCALER,
0,
cell.z * TOWN_LAYOUT_SCALER
);
solved.y = realm.getServerWorldData().getServerTerrainManager().getElevation(solved);
return solved;
}
}

View File

@ -1,6 +1,7 @@
package electrosphere.util.math;
import org.joml.Vector3d;
import org.joml.Vector3i;
import io.github.studiorailgun.RandUtils;
@ -54,6 +55,21 @@ public class VoronoiUtils {
-1, -1, -1,
};
/**
* Calculates The voronoi cell that the point falls within
* @param x The x coordinate
* @param y The y coordinate
* @param z The z coordinate
* @return The voronoi cell
*/
public static Vector3i solveVoronoiCell(double x, double y, double z){
//integer of the point coordinates
int x_i = (int)Math.floor(x);
int y_i = (int)Math.floor(y);
int z_i = (int)Math.floor(z);
return new Vector3i(x_i,y_i,z_i);
}
/**
* Calculates voronoi noise within a cube
* @param x The x coordinate
@ -78,7 +94,7 @@ public class VoronoiUtils {
double y_relaxed = p_y * (1.0 - relaxationFactor) + (relaxationFactor / 2.0);
double z_relaxed = p_z * (1.0 - relaxationFactor) + (relaxationFactor / 2.0);
return new Vector3d(x_i + x_relaxed,y_i + y_relaxed,z_i + z_relaxed);
return new Vector3d(x_relaxed,y_relaxed,z_relaxed);
}
}