diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index a573c2fc..7beb22c0 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -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 diff --git a/src/main/java/electrosphere/server/macro/town/TownLayout.java b/src/main/java/electrosphere/server/macro/town/TownLayout.java index aef18aa2..1a2d41bf 100644 --- a/src/main/java/electrosphere/server/macro/town/TownLayout.java +++ b/src/main/java/electrosphere/server/macro/town/TownLayout.java @@ -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; + } + } diff --git a/src/main/java/electrosphere/util/math/VoronoiUtils.java b/src/main/java/electrosphere/util/math/VoronoiUtils.java index 0e8aa33a..9146c794 100644 --- a/src/main/java/electrosphere/util/math/VoronoiUtils.java +++ b/src/main/java/electrosphere/util/math/VoronoiUtils.java @@ -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); } }