From f14fcbba9fd8ffaf9fff19d0263274548b800293 Mon Sep 17 00:00:00 2001 From: gnembon Date: Wed, 3 Jun 2020 03:47:38 -0300 Subject: [PATCH] added spheres to draw_shape --- docs/scarpet/Full.md | 8 ++ docs/scarpet/api/Auxiliary.md | 8 ++ .../carpet/script/utils/ShapeDispatcher.java | 110 ++++++++++++++++++ .../carpet/script/utils/ShapesRenderer.java | 83 +++++++++++-- 4 files changed, 197 insertions(+), 12 deletions(-) diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index fc2725cf..a0bac5ea 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3170,6 +3170,14 @@ Available shapes: * Optional attributes: * `width` - mesh line thickness, defaults to 2.0pt * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere + * Required attributes: + * `center` - center of the sphere + * `radius` - radius of the sphere + * Optional attributes: + * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the + level of detail will be selected automatically based on radius. + * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index a668dfa3..90860cc9 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -76,6 +76,14 @@ Available shapes: * Optional attributes: * `width` - mesh line thickness, defaults to 2.0pt * `fill` - color for the box faces, defaults to no fill, use shared color attribute format + * `'sphere'` - draws a sphere + * Required attributes: + * `center` - center of the sphere + * `radius` - radius of the sphere + * Optional attributes: + * `level` - level of details, or grid size. The more the denser your sphere. Default level of 0, means that the + level of detail will be selected automatically based on radius. + * `width` - line thickness ### `create_marker(text, pos, rotation?, block?)` diff --git a/src/main/java/carpet/script/utils/ShapeDispatcher.java b/src/main/java/carpet/script/utils/ShapeDispatcher.java index a1d1f071..5202ddf7 100644 --- a/src/main/java/carpet/script/utils/ShapeDispatcher.java +++ b/src/main/java/carpet/script/utils/ShapeDispatcher.java @@ -28,6 +28,7 @@ import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.Registry; import net.minecraft.world.dimension.DimensionType; @@ -38,6 +39,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; +import java.util.Random; import java.util.Set; import java.util.function.Consumer; import java.util.function.Function; @@ -157,6 +159,7 @@ public class ShapeDispatcher public static final Map,ExpiringShape>> shapeProviders = new HashMap, ExpiringShape>>(){{ put("line", creator(Line::new)); put("box", creator(Box::new)); + put("sphere", creator(Sphere::new)); }}; private static Function,ExpiringShape> creator(Supplier shapeFactory) { @@ -387,6 +390,83 @@ public class ShapeDispatcher } } + public static class Sphere extends ExpiringShape + { + private final Set required = ImmutableSet.of("center", "radius"); + private final Map optional = ImmutableMap.of("width", new NumericValue(2.0), "level", Value.ZERO); + @Override + protected Set requiredParams() { return Sets.union(super.requiredParams(), required); } + @Override + protected Set optionalParams() { return Sets.union(super.optionalParams(), optional.keySet()); } + + private Sphere() + { + super(); + } + + float cx, cy, cz; + float radius; + int level; + int subdivisions; + float lineWidth; + + @Override + protected void init(Map options) + { + super.init(options); + List from = ((ListValue)options.get("center")).getItems(); + cx = NumericValue.asNumber(from.get(0)).getFloat(); + cy = NumericValue.asNumber(from.get(1)).getFloat(); + cz = NumericValue.asNumber(from.get(2)).getFloat(); + radius = NumericValue.asNumber(options.get("radius")).getFloat(); + level = NumericValue.asNumber(options.getOrDefault("level", optional.get("level"))).getInt(); + subdivisions = level; + if (subdivisions <= 0) + { + subdivisions = Math.max(10, (int)(10*Math.sqrt(radius))); + } + lineWidth = NumericValue.asNumber(options.getOrDefault("width", optional.get("width"))).getFloat(); + } + + @Override + public Consumer alternative() { return p -> + { + String particleName = String.format(Locale.ROOT , "dust %.1f %.1f %.1f 1.0", r, g, b); + ParticleEffect particle = getParticleData(particleName); + float pihalf = (float)(Math.PI / 180.0f); + int partno = Math.min(1000,20*subdivisions); + Random rand = p.world.getRandom(); + ServerWorld world = p.getServerWorld(); + for (int i=0; i> decoders = new HashMap>(){{ @@ -398,6 +478,9 @@ public class ShapeDispatcher put("to", Vec3Param::decode); put("width", ShapeDispatcher::decodeFloat); put("fill", ShapeDispatcher::decodeInt); + put("center", Vec3Param::decode); + put("radius", ShapeDispatcher::decodeFloat); + put("level", ShapeDispatcher::decodeInt); }}; Map coders = new HashMap(){{ put("player", new PlayerParam()); @@ -409,6 +492,9 @@ public class ShapeDispatcher put("to", new ToParam()); put("width", new WidthParam()); put("fill", new FillColorParam()); + put("center", new CenterParam()); + put("radius", new RadiusParam()); + put("level", new LevelParam()); }}; Tag toTag(Value value); //validates value, returning null if not necessary to keep it and serialize Value validate(CarpetContext cc, Value value); // makes sure the value is proper @@ -624,6 +710,30 @@ public class ShapeDispatcher public String identify() { return "to"; } } + public static class CenterParam extends Vec3Param + { + @Override + public boolean appliesTo(ExpiringShape shape) { return (shape instanceof Sphere); } + @Override + public boolean roundsUpForBlocks() { return false; } + @Override + public String identify() { return "center"; } + } + public static class RadiusParam extends PositiveFloatParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } + @Override + public String identify() { return "radius"; } + } + public static class LevelParam extends PositiveIntParam + { + @Override + public boolean appliesTo(ExpiringShape shape) { return shape instanceof Sphere; } + @Override + public String identify() { return "level"; } + } + private static boolean isStraight(Vec3d from, Vec3d to, double density) diff --git a/src/main/java/carpet/script/utils/ShapesRenderer.java b/src/main/java/carpet/script/utils/ShapesRenderer.java index 46ee549b..8552ca7a 100644 --- a/src/main/java/carpet/script/utils/ShapesRenderer.java +++ b/src/main/java/carpet/script/utils/ShapesRenderer.java @@ -12,6 +12,7 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.Entity; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Identifier; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.registry.Registry; import net.minecraft.world.IWorld; import net.minecraft.world.dimension.DimensionType; @@ -31,6 +32,7 @@ public class ShapesRenderer {{ put("line", RenderedLine::new); put("box", RenderedBox::new); + put("sphere", RenderedSphere::new); }}; public ShapesRenderer(MinecraftClient minecraftClient) @@ -159,8 +161,8 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { RenderSystem.lineWidth(shape.lineWidth); - bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - drawBoxWireGLLines(bufferBuilder, + + drawBoxWireGLLines(tessellator, bufferBuilder, shape.x1 - cx-renderEpsilon, shape.y1 - cy-renderEpsilon, shape.z1 - cz-renderEpsilon, shape.x2 - cx+renderEpsilon, shape.y2 - cy+renderEpsilon, shape.z2 - cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b @@ -172,13 +174,13 @@ public class ShapesRenderer { if (shape.fa == 0.0) return; RenderSystem.lineWidth(1.0F); - bufferBuilder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 - drawBox(bufferBuilder, + + drawBoxFaces(tessellator, bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.fr, shape.fg, shape.fb, shape.fa ); - tessellator.draw(); + } } @@ -192,25 +194,42 @@ public class ShapesRenderer public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) { RenderSystem.lineWidth(shape.lineWidth); - bufferBuilder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 - drawLine(bufferBuilder, + drawLine(tessellator, bufferBuilder, shape.x1-cx-renderEpsilon, shape.y1-cy-renderEpsilon, shape.z1-cz-renderEpsilon, shape.x2-cx+renderEpsilon, shape.y2-cy+renderEpsilon, shape.z2-cz+renderEpsilon, shape.r, shape.g, shape.b, shape.a ); - tessellator.draw(); + } + } + + public static class RenderedSphere extends RenderedShape + { + public RenderedSphere(MinecraftClient client, ShapeDispatcher.ExpiringShape shape) + { + super(client, (ShapeDispatcher.Sphere)shape); + } + @Override + public void render(Tessellator tessellator, BufferBuilder bufferBuilder, float cx, float cy, float cz) + { + RenderSystem.lineWidth(shape.lineWidth); + drawSphereWireframe(tessellator, bufferBuilder, + shape.cx-cx-renderEpsilon, shape.cy-cy-renderEpsilon, shape.cz-cz-renderEpsilon, + shape.radius, shape.subdivisions, + shape.r, shape.g, shape.b, shape.a); } } // some raw shit - public static void drawLine(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { - + public static void drawLine(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); } - public static void drawBoxWireGLLines(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + public static void drawBoxWireGLLines(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2) { + builder.begin(GL11.GL_LINES, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn2, blu2, alpha).next(); builder.vertex(x1, y1, z1).color(red2, grn1, blu2, alpha).next(); @@ -237,7 +256,8 @@ public class ShapesRenderer builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); } - public static void drawBox(BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + public static void drawBoxFaces(Tessellator tessellator, BufferBuilder builder, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha) { + builder.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR); // 3 builder.vertex(x1, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y1, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); @@ -267,5 +287,44 @@ public class ShapesRenderer builder.vertex(x2, y2, z1).color(red1, grn1, blu1, alpha).next(); builder.vertex(x2, y2, z2).color(red1, grn1, blu1, alpha).next(); builder.vertex(x1, y2, z2).color(red1, grn1, blu1, alpha).next(); + tessellator.draw(); + } + + public static void drawSphereWireframe(Tessellator tessellator, BufferBuilder builder, + float cx, float cy, float cz, + float r, int subd, + float red, float grn, float blu, float alpha) + { + float pihalf = (float)(Math.PI / 180.0f); + float step = 180f / (subd/2); + for (float i = 0f; i <= 360.0f; i+=step) + { + builder.begin(GL11.GL_LINE_STRIP, VertexFormats.POSITION_COLOR); + float theta = i * pihalf; + for (float j = 0f; j <= 180.0f; j+=step) { + float phi = j * pihalf; + float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); + float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); + float y = r * MathHelper.cos(phi); + builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + for (float j = 0f; j <= 180.0f; j+=step) + { + builder.begin(GL11.GL_LINE_LOOP, VertexFormats.POSITION_COLOR); + float phi = j * pihalf; + + for (float i = 0f; i <= 360.0f; i+=step) + { + float theta = i * pihalf; + float x = r * MathHelper.sin(phi) * MathHelper.cos(theta); + float z = r * MathHelper.sin(phi) * MathHelper.sin(theta); + float y = r * MathHelper.cos(phi); + builder.vertex(x+cx, y+cy, z+cz).color(red, grn, blu, alpha).next(); + } + tessellator.draw(); + } + } }