SDF materials

This commit is contained in:
paulevsGitch 2020-09-29 01:38:56 +03:00
parent 2e632bf245
commit 257307d93d
14 changed files with 107 additions and 15 deletions

View file

@ -6,15 +6,15 @@ import java.util.function.Function;
import com.google.common.collect.Sets;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.ServerWorldAccess;
import ru.betterend.util.BlocksHelper;
public interface ISDF {
public float getDistance(float x, float y, float z);
public void setBlock(ServerWorldAccess world, BlockPos pos);
default void fillRecursive(ServerWorldAccess world, BlockPos start, Function<BlockState, Boolean> canReplace, int dx, int dy, int dz) {
Set<BlockPos> blocks = Sets.newHashSet();
Set<BlockPos> ends = Sets.newHashSet();
@ -34,8 +34,10 @@ public interface ISDF {
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) < 0) {
BlocksHelper.setWithoutUpdate(world, wpos, Blocks.STONE);
add.add(pos);
setBlock(world, wpos);
if (Math.abs(pos.getX()) < dx && Math.abs(pos.getY()) < dy && Math.abs(pos.getZ()) < dz) {
add.add(pos);
}
}
}
}
@ -65,7 +67,7 @@ public interface ISDF {
if (!blocks.contains(pos) && canReplace.apply(world.getBlockState(wpos))) {
if (this.getDistance(pos.getX(), pos.getY(), pos.getZ()) <= 0) {
BlocksHelper.setWithoutUpdate(world, wpos, Blocks.STONE);
setBlock(world, wpos);
add.add(pos);
}
}

View file

@ -1,10 +1,13 @@
package ru.betterend.util.sdf.operator;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import ru.betterend.util.sdf.ISDF;
public abstract class SDFBinary implements ISDF {
protected ISDF sourceA;
protected ISDF sourceB;
protected boolean firstValue;
public SDFBinary setSourceA(ISDF sourceA) {
this.sourceA = sourceA;
@ -15,4 +18,17 @@ public abstract class SDFBinary implements ISDF {
this.sourceB = sourceB;
return this;
}
protected void selectValue(float a, float b) {
firstValue = a < b;
}
@Override
public void setBlock(ServerWorldAccess world, BlockPos pos) {
if (firstValue) {
sourceA.setBlock(world, pos);
} else {
sourceB.setBlock(world, pos);
}
}
}

View file

@ -7,6 +7,7 @@ public class SDFIntersection extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
return MHelper.max(a, b);
}
}

View file

@ -14,6 +14,7 @@ public class SDFSmoothIntersection extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
float h = MathHelper.clamp(0.5F - 0.5F * (b - a) / radius, 0F, 1F);
return MathHelper.lerp(h, b, a) + radius * h * (1F - h);
}

View file

@ -14,6 +14,7 @@ public class SDFSmoothSubtraction extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
float h = MathHelper.clamp(0.5F - 0.5F * (b + a) / radius, 0F, 1F);
return MathHelper.lerp(h, b, -a) + radius * h * (1F - h);
}

View file

@ -14,6 +14,7 @@ public class SDFSmoothUnion extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
float h = MathHelper.clamp(0.5F + 0.5F * (b - a) / radius, 0F, 1F);
return MathHelper.lerp(h, b, a) - radius * h * (1F - h);
}

View file

@ -7,6 +7,7 @@ public class SDFSubtraction extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
return MHelper.max(a, -b);
}
}

View file

@ -1,5 +1,7 @@
package ru.betterend.util.sdf.operator;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import ru.betterend.util.sdf.ISDF;
public abstract class SDFUnary implements ISDF {
@ -9,4 +11,9 @@ public abstract class SDFUnary implements ISDF {
this.source = source;
return this;
}
@Override
public void setBlock(ServerWorldAccess world, BlockPos pos) {
source.setBlock(world, pos);
}
}

View file

@ -7,6 +7,7 @@ public class SDFUnion extends SDFBinary {
public float getDistance(float x, float y, float z) {
float a = this.sourceA.getDistance(x, y, z);
float b = this.sourceB.getDistance(x, y, z);
this.selectValue(a, b);
return MHelper.min(a, b);
}
}

View file

@ -1,13 +1,24 @@
package ru.betterend.util.sdf.primitive;
import java.util.function.Function;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import ru.betterend.util.MHelper;
import ru.betterend.util.sdf.ISDF;
public class SDFCapsule implements ISDF {
public class SDFCapsule extends SDFPrimitive {
private float radius;
private float height;
public SDFCapsule(Function<BlockPos, BlockState> placerFunction) {
super(placerFunction);
}
public SDFCapsule(BlockState state) {
super(state);
}
public SDFCapsule setRadius(float radius) {
this.radius = radius;
return this;

View file

@ -1,10 +1,13 @@
package ru.betterend.util.sdf.primitive;
import java.util.function.Function;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import ru.betterend.util.MHelper;
import ru.betterend.util.sdf.ISDF;
public class SDFLine implements ISDF {
public class SDFLine extends SDFPrimitive {
private float radius;
private float x1;
private float y1;
@ -13,6 +16,14 @@ public class SDFLine implements ISDF {
private float y2;
private float z2;
public SDFLine(Function<BlockPos, BlockState> placerFunction) {
super(placerFunction);
}
public SDFLine(BlockState state) {
super(state);
}
public SDFLine setRadius(float radius) {
this.radius = radius;
return this;

View file

@ -0,0 +1,27 @@
package ru.betterend.util.sdf.primitive;
import java.util.function.Function;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ServerWorldAccess;
import ru.betterend.util.BlocksHelper;
import ru.betterend.util.sdf.ISDF;
public abstract class SDFPrimitive implements ISDF {
protected final Function<BlockPos, BlockState> placerFunction;
public SDFPrimitive(Function<BlockPos, BlockState> placerFunction) {
this.placerFunction = placerFunction;
}
public SDFPrimitive(BlockState state) {
this.placerFunction = (pos) -> {
return state;
};
}
public void setBlock(ServerWorldAccess world, BlockPos pos) {
BlocksHelper.setWithoutUpdate(world, pos, placerFunction.apply(pos));
}
}

View file

@ -1,11 +1,22 @@
package ru.betterend.util.sdf.primitive;
import ru.betterend.util.MHelper;
import ru.betterend.util.sdf.ISDF;
import java.util.function.Function;
public class SDFSphere implements ISDF {
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import ru.betterend.util.MHelper;
public class SDFSphere extends SDFPrimitive {
private float radius;
public SDFSphere(Function<BlockPos, BlockState> placerFunction) {
super(placerFunction);
}
public SDFSphere(BlockState state) {
super(state);
}
public SDFSphere setRadius(float radius) {
this.radius = radius;
return this;

View file

@ -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.util.math.BlockPos;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.chunk.ChunkGenerator;
@ -36,10 +37,10 @@ public class MossyGlowshroomFeature extends DefaultFeature {
}
static {
SDFLine stem = new SDFLine().setRadius(2F).setEnd(0, 15, 0);
SDFLine stem = new SDFLine(Blocks.GOLD_BLOCK.getDefaultState()).setRadius(2F).setEnd(0, 15, 0);
SDFSphere outerSphere = new SDFSphere().setRadius(10);
SDFSphere innerSphere = new SDFSphere().setRadius(10);
SDFSphere outerSphere = new SDFSphere(Blocks.REDSTONE_BLOCK.getDefaultState()).setRadius(10);
SDFSphere innerSphere = new SDFSphere(Blocks.DIAMOND_BLOCK.getDefaultState()).setRadius(10);
SDFTranslate sphereOffset = new SDFTranslate().setTranslate(0, -10F, 0);