diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 373df375..75875815 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -1880,6 +1880,8 @@ Server utility to move entities scans to see if it needs to create macro data if Road macro data generation Macro data is injected into voxel chunk generators Close macro objects injected into voxel chunk gen instead of all data +Fix spline3d mat storing calculations when getting positions +Roads applied to terrain voxel gen diff --git a/src/main/java/electrosphere/server/macro/MacroData.java b/src/main/java/electrosphere/server/macro/MacroData.java index 663981db..4f443b55 100644 --- a/src/main/java/electrosphere/server/macro/MacroData.java +++ b/src/main/java/electrosphere/server/macro/MacroData.java @@ -301,6 +301,7 @@ public class MacroData { */ public List getNearbyObjects(Vector3d position){ List rVal = new LinkedList(); + rVal.addAll(this.roads); return rVal; } diff --git a/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java b/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java index 43e8c73c..14ea4a44 100644 --- a/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java +++ b/src/main/java/electrosphere/server/macro/civilization/CivilizationGenerator.java @@ -37,9 +37,10 @@ public class CivilizationGenerator { Town startingTown = macroData.addTown(spawnPoint, INITIAL_TOWN_RADIUS, newCiv.getId()); newCiv.addTown(startingTown); Road.createRoad(macroData, Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(spawnPoint).add(-20,0,0), new Vector3d(spawnPoint).add(-10,0,0), - new Vector3d(spawnPoint), new Vector3d(spawnPoint).add( 10,0,0), + new Vector3d(spawnPoint).add( 20,0,0), })); } } diff --git a/src/main/java/electrosphere/server/physics/terrain/generation/ProceduralChunkGenerator.java b/src/main/java/electrosphere/server/physics/terrain/generation/ProceduralChunkGenerator.java index c7198671..4d5dae0f 100644 --- a/src/main/java/electrosphere/server/physics/terrain/generation/ProceduralChunkGenerator.java +++ b/src/main/java/electrosphere/server/physics/terrain/generation/ProceduralChunkGenerator.java @@ -4,6 +4,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.joml.Vector3d; + import electrosphere.client.terrain.cache.ChunkData; import electrosphere.data.biome.BiomeData; import electrosphere.data.biome.BiomeSurfaceGenerationParams; @@ -28,6 +30,7 @@ import electrosphere.server.physics.terrain.generation.voxelphase.NoiseVoxelGen; import electrosphere.server.physics.terrain.generation.voxelphase.VoxelGenerator; import electrosphere.server.physics.terrain.manager.ServerTerrainChunk; import electrosphere.server.physics.terrain.models.TerrainModel; +import electrosphere.util.math.GeomUtils; import electrosphere.util.noise.OpenSimplex2S; import io.github.studiorailgun.MathUtils; @@ -264,18 +267,25 @@ public class ProceduralChunkGenerator implements ChunkGenerator { double realX, double realY, double realZ, GeneratedVoxel voxel ){ + boolean rVal = false; + Vector3d realPt = new Vector3d(realX, realY, realZ); for(MacroObject object : objects){ if(object instanceof Road){ Road road = (Road)object; //broad phase intersection if(road.getAABB().testPoint(realX, realY, realZ)){ - + if(GeomUtils.pointIntersectsSpline(realPt, road.getSpline(), road.getRadius())){ + if(voxel.type != ServerTerrainChunk.VOXEL_TYPE_AIR){ + voxel.type = 1; + rVal = true; + } + } } } else { throw new Error("Unsupported object type " + object); } } - return false; + return rVal; } /** diff --git a/src/main/java/electrosphere/util/ds/Spline3d.java b/src/main/java/electrosphere/util/ds/Spline3d.java index dc4a8a9c..4a2a8b17 100644 --- a/src/main/java/electrosphere/util/ds/Spline3d.java +++ b/src/main/java/electrosphere/util/ds/Spline3d.java @@ -149,7 +149,7 @@ public class Spline3d { // //Perform calculation Matrix4d pointMat = new Matrix4d(p1,p2,p3,p4).transpose(); - Matrix4d matResult = characteristicMatrix.mul(pointMat); + Matrix4d matResult = characteristicMatrix.mul(pointMat, new Matrix4d()); Vector4d rawResult = timeVec.mul(matResult.transpose()); Vector4d normalizedResult = rawResult; if(rawResult.w != 0 && Double.isFinite(rawResult.w)){ diff --git a/src/main/java/electrosphere/util/math/GeomUtils.java b/src/main/java/electrosphere/util/math/GeomUtils.java index 4b6813fe..690272e0 100644 --- a/src/main/java/electrosphere/util/math/GeomUtils.java +++ b/src/main/java/electrosphere/util/math/GeomUtils.java @@ -3,6 +3,8 @@ package electrosphere.util.math; import org.joml.Vector3d; import org.joml.Vector3i; +import electrosphere.util.ds.Spline3d; + /** * Utilities for dealing with geometry */ @@ -18,6 +20,11 @@ public class GeomUtils { */ public static final int SIMPLIFICATION_CUTOFF = 100000; + /** + * Amount to sample splines by + */ + public static final int SPLINE_SAMPLE_RATE = 10; + /** * Gets the minimum distance from a point to an axis aligned cube * @param pos the position to check against @@ -570,5 +577,77 @@ public class GeomUtils { } return true; } + + /** + * Gets the squared distance between a spline and a point + * @param point The point + * @param spline The tube's spline + * @param samplesPerSegment The samples per segment + * @return the distance squared + */ + public static double getPointSplineDist(Vector3d point, Spline3d spline, int samplesPerSegment) { + double closestDist = Double.POSITIVE_INFINITY; + float incrementAmount = 1/(float)samplesPerSegment; + + for(double t = 1; t < spline.getPoints().size() - 1; t=t+incrementAmount){ + Vector3d splinePoint = spline.getPos(t); + double dist = splinePoint.distance(point); + + if(dist < closestDist){ + closestDist = dist; + } + } + + return closestDist; + } + + /** + * Gets the squared distance between a spline and a point + * @param point The point + * @param spline The tube's spline + * @return the distance squared + */ + public static double getPointSplineDist(Vector3d point, Spline3d spline) { + return GeomUtils.getPointSplineDist(point, spline, SPLINE_SAMPLE_RATE); + } + + /** + * Checks whether a point intersects a tube defined by a spline + * @param point The point + * @param spline The tube's spline + * @param radius The radius of the tube around the spline + * @param samplesPerSegment The samples per segment + * @return true if they intersect, false otherwise + */ + public static boolean pointIntersectsSpline(Vector3d point, Spline3d spline, double radius, int samplesPerSegment) { + double closestDistSquared = Double.POSITIVE_INFINITY; + float incrementAmount = 1/(float)samplesPerSegment; + + for(double t = 1; t < spline.getPoints().size() - 1; t=t+incrementAmount){ + Vector3d splinePoint = spline.getPos(t); + double distSquared = splinePoint.distance(point); + if(distSquared < radius){ + return true; // early exit + } + + if(distSquared < closestDistSquared){ + closestDistSquared = distSquared; + } + } + + return false; + } + + /** + * Checks whether a point intersects a tube defined by a spline + * @param point The point + * @param spline The tube's spline + * @param radius The radius of the tube around the spline + * @param samplesPerSegment The samples per segment + * @return true if they intersect, false otherwise + */ + public static boolean pointIntersectsSpline(Vector3d point, Spline3d spline, double radius) { + return GeomUtils.pointIntersectsSpline(point, spline, radius, SPLINE_SAMPLE_RATE); + } } diff --git a/src/test/java/electrosphere/util/math/GeomUtilsTests.java b/src/test/java/electrosphere/util/math/GeomUtilsTests.java index 0f4a9dd6..8d052952 100644 --- a/src/test/java/electrosphere/util/math/GeomUtilsTests.java +++ b/src/test/java/electrosphere/util/math/GeomUtilsTests.java @@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.*; import org.joml.Vector3d; import electrosphere.test.annotations.UnitTest; +import electrosphere.util.ds.Spline3d; /** * Tests for geometry utils @@ -41,4 +42,74 @@ public class GeomUtilsTests { assertEquals(Math.sqrt(3), GeomUtils.getMinDistanceAABB(new Vector3d(3,3,3), new Vector3d(0,0,0), new Vector3d(2,2,2))); } + @UnitTest + public void test_getPointSplineDist_1(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(0,5,5), + new Vector3d(10,5,5), + new Vector3d(20,5,5), + new Vector3d(30,5,5) + }); + assertTrue(GeomUtils.getPointSplineDist(new Vector3d(10,3,5), testSpline) < 3); + assertTrue(GeomUtils.getPointSplineDist(new Vector3d(10,3,5), testSpline) > 0); + } + + @UnitTest + public void test_getPointSplineDist_2(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(500000,10,500000), + new Vector3d(500010,10,500000), + new Vector3d(500020,10,500000), + new Vector3d(500030,10,500000) + }); + assertTrue(GeomUtils.getPointSplineDist(new Vector3d(500010,11,500000), testSpline) < 3); + assertTrue(GeomUtils.getPointSplineDist(new Vector3d(500010,11,500000), testSpline) > 0); + } + + @UnitTest + public void test_getPointSplineDist_3(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(524268,10,524288), + new Vector3d(524278,10,524288), + new Vector3d(524298,10,524288), + new Vector3d(524308,10,524288) + }); + double dist = GeomUtils.getPointSplineDist(new Vector3d(524298,10,524288), testSpline); + assertTrue(dist < 3, dist + ""); + assertTrue(dist > 0, dist + ""); + } + + @UnitTest + public void test_pointIntersectsSpline_1(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(500000,10,500000), + new Vector3d(500010,10,500000), + new Vector3d(500020,10,500000), + new Vector3d(500030,10,500000) + }); + assertTrue(GeomUtils.pointIntersectsSpline(new Vector3d(500010,8,500000), testSpline, 3)); + } + + @UnitTest + public void test_pointIntersectsSpline_2(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(500000,10,500000), + new Vector3d(500010,10,500000), + new Vector3d(500020,10,500000), + new Vector3d(500030,10,500000) + }); + assertFalse(GeomUtils.pointIntersectsSpline(new Vector3d(500010,20,500000), testSpline, 3)); + } + + @UnitTest + public void test_pointIntersectsSpline_3(){ + Spline3d testSpline = Spline3d.createCatmullRom(new Vector3d[]{ + new Vector3d(524268,10,524288), + new Vector3d(524278,10,524288), + new Vector3d(524298,10,524288), + new Vector3d(524308,10,524288) + }); + assertTrue(GeomUtils.pointIntersectsSpline(new Vector3d(524298.0,10,524288.0), testSpline, 3)); + } + }