diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFHeightmap.java b/src/main/java/ru/betterend/util/sdf/operator/SDFHeightmap.java new file mode 100644 index 00000000..82ba749a --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFHeightmap.java @@ -0,0 +1,59 @@ +package ru.betterend.util.sdf.operator; + +import net.minecraft.client.texture.NativeImage; +import net.minecraft.util.math.MathHelper; + +public class SDFHeightmap extends SDFDisplacement { + private float intensity = 1F; + private NativeImage map; + private float offsetX; + private float offsetZ; + private float angle; + private float scale; + + public SDFHeightmap() { + setFunction((pos) -> { + if (map == null) { + return 0F; + } + float dx = MathHelper.clamp(pos.getX() * scale + offsetX, 0, map.getWidth() - 2); + float dz = MathHelper.clamp(pos.getZ() * scale + offsetZ, 0, map.getHeight() - 2); + int x1 = MathHelper.floor(dx); + int z1 = MathHelper.floor(dz); + int x2 = x1 + 1; + int z2 = z1 + 1; + dx = dx - x1; + dz = dz - z1; + float a = (map.getPixelColor(x1, z1) & 255) / 255F; + float b = (map.getPixelColor(x2, z1) & 255) / 255F; + float c = (map.getPixelColor(x1, z2) & 255) / 255F; + float d = (map.getPixelColor(x2, z2) & 255) / 255F; + a = MathHelper.lerp(dx, a, b); + b = MathHelper.lerp(dx, c, d); + return -MathHelper.lerp(dz, a, b) * intensity; + }); + } + + public SDFHeightmap setMap(NativeImage map) { + this.map = map; + offsetX = map.getWidth() * 0.5F; + offsetZ = map.getHeight() * 0.5F; + scale = map.getWidth(); + return this; + } + + public SDFHeightmap setAngle(float angle) { + this.angle = angle; + return this; + } + + public SDFHeightmap setScale(float scale) { + this.scale = map.getWidth() * scale; + return this; + } + + public SDFHeightmap setIntensity(float intensity) { + this.intensity = intensity; + return this; + } +} diff --git a/src/main/java/ru/betterend/world/generator/IslandLayer.java b/src/main/java/ru/betterend/world/generator/IslandLayer.java index a5fff6e2..bd08ff1c 100644 --- a/src/main/java/ru/betterend/world/generator/IslandLayer.java +++ b/src/main/java/ru/betterend/world/generator/IslandLayer.java @@ -1,5 +1,7 @@ package ru.betterend.world.generator; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -8,10 +10,13 @@ import java.util.Random; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import net.minecraft.client.texture.NativeImage; import net.minecraft.util.math.BlockPos; +import ru.betterend.BetterEnd; import ru.betterend.noise.OpenSimplexNoise; import ru.betterend.util.MHelper; import ru.betterend.util.sdf.SDF; +import ru.betterend.util.sdf.operator.SDFHeightmap; import ru.betterend.util.sdf.operator.SDFScale; import ru.betterend.util.sdf.operator.SDFSmoothUnion; import ru.betterend.util.sdf.operator.SDFTranslate; @@ -19,7 +24,7 @@ import ru.betterend.util.sdf.primitive.SDFCappedCone; public class IslandLayer { private static final Random RANDOM = new Random(); - private static final SDF ISLAND; + private static final SDF[] ISLAND; private final List positions = new ArrayList(9); private final Map islands = Maps.newHashMap(); @@ -86,11 +91,11 @@ public class IslandLayer { SDF island = islands.get(pos); if (island == null) { if (pos.getX() == 0 && pos.getZ() == 0) { - island = new SDFScale().setScale(1.3F).setSource(ISLAND); + island = new SDFScale().setScale(1.3F).setSource(ISLAND[0]); } else { RANDOM.setSeed(getSeed(pos.getX(), pos.getZ())); - island = new SDFScale().setScale(RANDOM.nextFloat() + 0.5F).setSource(ISLAND); + island = new SDFScale().setScale(RANDOM.nextFloat() + 0.5F).setSource(ISLAND[0]); } islands.put(pos, island); } @@ -130,7 +135,24 @@ public class IslandLayer { return new SDFTranslate().setTranslate(0, minY + hh, 0).setSource(sdf); } + private static NativeImage loadMap(String path) { + InputStream stream = IslandLayer.class.getResourceAsStream(path); + if (stream != null) { + try { + NativeImage map = NativeImage.read(stream); + stream.close(); + return map; + } + catch (IOException e) { + BetterEnd.LOGGER.warning(e.getMessage()); + } + } + return null; + } + static { + NativeImage map = loadMap("/assets/" + BetterEnd.MOD_ID + "/textures/heightmaps/mountain_1.png"); + SDF cone1 = makeCone(0, 0.4F, 0.2F, -0.3F); SDF cone2 = makeCone(0.4F, 0.5F, 0.1F, -0.1F); SDF cone3 = makeCone(0.5F, 0.45F, 0.03F, 0.0F); @@ -139,6 +161,11 @@ public class IslandLayer { SDF coneBottom = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone1).setSourceB(cone2); SDF coneTop = new SDFSmoothUnion().setRadius(0.02F).setSourceA(cone3).setSourceB(cone4); - ISLAND = new SDFSmoothUnion().setRadius(0.01F).setSourceA(coneTop).setSourceB(coneBottom); + SDF map1 = new SDFHeightmap().setMap(map).setIntensity(0.3F).setSource(coneTop); + + ISLAND = new SDF[] { + new SDFSmoothUnion().setRadius(0.01F).setSourceA(coneTop).setSourceB(coneBottom), + new SDFSmoothUnion().setRadius(0.01F).setSourceA(map1).setSourceB(coneBottom) + }; } } diff --git a/src/main/resources/assets/betterend/textures/heightmaps/mountain_1.png b/src/main/resources/assets/betterend/textures/heightmaps/mountain_1.png new file mode 100644 index 00000000..020f8daa Binary files /dev/null and b/src/main/resources/assets/betterend/textures/heightmaps/mountain_1.png differ