diff --git a/src/main/java/ru/betterend/util/sdf/operator/SDFInvert.java b/src/main/java/ru/betterend/util/sdf/operator/SDFInvert.java new file mode 100644 index 00000000..455635e7 --- /dev/null +++ b/src/main/java/ru/betterend/util/sdf/operator/SDFInvert.java @@ -0,0 +1,8 @@ +package ru.betterend.util.sdf.operator; + +public class SDFInvert extends SDFUnary { + @Override + public float getDistance(float x, float y, float z) { + return -this.source.getDistance(x, y, z); + } +} diff --git a/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java b/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java index c168abe0..2ea8e206 100644 --- a/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java +++ b/src/main/java/ru/betterend/world/features/terrain/GeyserFeature.java @@ -4,6 +4,7 @@ import java.util.Random; import java.util.function.Function; import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; import net.minecraft.block.LeavesBlock; import net.minecraft.block.Material; import net.minecraft.client.util.math.Vector3f; @@ -12,21 +13,20 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.world.StructureWorldAccess; import net.minecraft.world.gen.chunk.ChunkGenerator; import net.minecraft.world.gen.feature.DefaultFeatureConfig; +import ru.betterend.noise.OpenSimplexNoise; import ru.betterend.registry.EndBlocks; import ru.betterend.registry.EndTags; import ru.betterend.util.MHelper; import ru.betterend.util.sdf.SDF; -import ru.betterend.util.sdf.operator.SDFIntersection; +import ru.betterend.util.sdf.operator.SDFCoordModify; +import ru.betterend.util.sdf.operator.SDFDisplacement; +import ru.betterend.util.sdf.operator.SDFInvert; import ru.betterend.util.sdf.operator.SDFRotation; -import ru.betterend.util.sdf.operator.SDFScale; -import ru.betterend.util.sdf.operator.SDFScale3D; -import ru.betterend.util.sdf.operator.SDFSmoothUnion; import ru.betterend.util.sdf.operator.SDFSubtraction; import ru.betterend.util.sdf.operator.SDFTranslate; import ru.betterend.util.sdf.operator.SDFUnion; import ru.betterend.util.sdf.primitive.SDFCapedCone; import ru.betterend.util.sdf.primitive.SDFFlatland; -import ru.betterend.util.sdf.primitive.SDFSphere; import ru.betterend.world.features.DefaultFeature; public class GeyserFeature extends DefaultFeature { @@ -43,23 +43,56 @@ public class GeyserFeature extends DefaultFeature { SDF sdf = new SDFCapedCone().setHeight(halfHeight).setRadius1(radius1).setRadius2(radius2).setBlock(EndBlocks.SULFURIC_ROCK.stone); sdf = new SDFTranslate().setTranslate(0, halfHeight - 3, 0).setSource(sdf); - SDF bowl = new SDFSphere().setRadius(10).setBlock(EndBlocks.SULFURIC_ROCK.stone); - bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(new SDFScale().setScale(0.7F).setSource(bowl)); - bowl = new SDFIntersection().setSourceA(bowl).setSourceB(new SDFFlatland().setBlock(EndBlocks.SULFURIC_ROCK.stone)); - bowl = new SDFScale3D().setScale(1, 0.4F, 1).setSource(bowl); - bowl = new SDFTranslate().setTranslate(5, 0, 0).setSource(bowl); - int count = halfHeight >> 1; + int count = halfHeight; for (int i = 0; i < count; i++) { - int py = i << 2; + int py = i << 1; float delta = (float) i / (float) (count - 1); - float offset = MathHelper.lerp(delta, radius1, radius2); - float scale = (1 - delta * 0.5F) * halfHeight / 20F; + float radius = MathHelper.lerp(delta, radius1, radius2) * 1.3F; - SDF bowlPositioned = new SDFScale().setScale(scale).setSource(bowl); - bowlPositioned = new SDFTranslate().setTranslate(offset, py, 0).setSource(bowlPositioned); - bowlPositioned = new SDFRotation().setRotation(Vector3f.POSITIVE_Y, i * 1.5F).setSource(bowlPositioned); - sdf = new SDFSmoothUnion().setRadius(10).setSourceA(bowlPositioned).setSourceB(sdf); - //sdf = new SDFUnion().setSourceA(sdf).setSourceB(bowlPositioned); + /*SDF bowl = new SDFCapedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(EndBlocks.SULFURIC_ROCK.stone); + SDF cut = new SDFTranslate().setTranslate(0, 2, 0).setSource(bowl); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(cut); + + SDF inner = new SDFCapedCone().setHeight(radius - 2).setRadius1(0).setRadius2(radius - 1).setBlock(EndBlocks.BRIMSTONE); + cut = new SDFTranslate().setTranslate(0, 4, 0).setSource(inner); + inner = new SDFSubtraction().setSourceA(inner).setSourceB(cut); + inner = new SDFTranslate().setTranslate(0, 1.99F, 0).setSource(inner); + bowl = new SDFUnion().setSourceA(inner).setSourceB(bowl); + + SDF water = new SDFCapedCone().setHeight(radius - 4).setRadius1(0).setRadius2(radius - 3).setBlock(Blocks.WATER); + bowl = new SDFUnion().setSourceA(water).setSourceB(bowl);*/ + + SDF bowl = new SDFCapedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(EndBlocks.SULFURIC_ROCK.stone); + + SDF brimstone = new SDFCapedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(EndBlocks.BRIMSTONE); + brimstone = new SDFTranslate().setTranslate(0, 2F, 0).setSource(brimstone); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(brimstone); + bowl = new SDFUnion().setSourceA(brimstone).setSourceB(bowl); + + SDF water = new SDFCapedCone().setHeight(radius).setRadius1(0).setRadius2(radius).setBlock(Blocks.WATER); + water = new SDFTranslate().setTranslate(0, 4, 0).setSource(water); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(water); + bowl = new SDFUnion().setSourceA(water).setSourceB(bowl); + + final OpenSimplexNoise noise1 = new OpenSimplexNoise(random.nextLong()); + final OpenSimplexNoise noise2 = new OpenSimplexNoise(random.nextLong()); + /*bowl = new SDFDisplacement().setFunction((vec) -> { + return (float) noise.eval(vec.getX() * 0.1, vec.getY() * 0.1, vec.getZ() * 0.1); + }).setSource(bowl);*/ + bowl = new SDFCoordModify().setFunction((vec) -> { + float dx = (float) noise1.eval(vec.getX() * 0.1, vec.getY() * 0.1, vec.getZ() * 0.1); + float dz = (float) noise2.eval(vec.getX() * 0.1, vec.getY() * 0.1, vec.getZ() * 0.1); + vec.add(dx, 0, dz); + }).setSource(bowl); + + SDF cut = new SDFFlatland().setBlock(Blocks.AIR); + cut = new SDFInvert().setSource(cut); + cut = new SDFTranslate().setTranslate(0, radius - 2, 0).setSource(cut); + bowl = new SDFSubtraction().setSourceA(bowl).setSourceB(cut); + + bowl = new SDFTranslate().setTranslate(radius, py - radius, 0).setSource(bowl); + bowl = new SDFRotation().setRotation(Vector3f.POSITIVE_Y, i * 4F).setSource(bowl); + sdf = /*new SDFSmoothUnion()*/new SDFUnion()/*.setRadius(3)*/.setSourceA(sdf).setSourceB(bowl); } sdf.setReplaceFunction(REPLACE).fillRecursive(world, pos);