Files
fabric-carpet/src/main/java/carpet/script/utils/ShapesRenderer.java
T
2025-07-31 01:57:08 +02:00

1455 lines
64 KiB
Java

package carpet.script.utils;
import carpet.script.CarpetScriptServer;
import carpet.script.external.Carpet;
import carpet.script.utils.shapes.ShapeDirection;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.Tesselator;
//import com.mojang.blaze3d.vertex.VertexBuffer;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat.Mode;
import com.mojang.math.Axis;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiFunction;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.components.debug.DebugScreenEntries;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.util.Mth;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.EntityBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.TagValueInput;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
import org.joml.Matrix4fStack;
public class ShapesRenderer
{
private final Map<ResourceKey<Level>, Long2ObjectOpenHashMap<RenderedShape<? extends ShapeDispatcher.ExpiringShape>>> shapes;
private final Map<ResourceKey<Level>, Long2ObjectOpenHashMap<RenderedShape<? extends ShapeDispatcher.ExpiringShape>>> labels;
private final Minecraft client;
private final Map<String, BiFunction<Minecraft, ShapeDispatcher.ExpiringShape, RenderedShape<? extends ShapeDispatcher.ExpiringShape>>> renderedShapes
= new HashMap<>()
{{
put("line", RenderedLine::new);
put("box", RenderedBox::new);
put("sphere", RenderedSphere::new);
put("cylinder", RenderedCylinder::new);
put("label", RenderedText::new);
put("polygon", RenderedPolyface::new);
put("block", (c, s) -> new RenderedSprite(c, s, false));
put("item", (c, s) -> new RenderedSprite(c, s, true));
}};
public static void rotatePoseStackByShapeDirection(PoseStack poseStack, ShapeDirection shapeDirection, Camera camera, Vec3 objectPos)
{
switch (shapeDirection)
{
case NORTH -> {}
case SOUTH -> poseStack.mulPose(Axis.YP.rotationDegrees(180));
case EAST -> poseStack.mulPose(Axis.YP.rotationDegrees(270));
case WEST -> poseStack.mulPose(Axis.YP.rotationDegrees(90));
case UP -> poseStack.mulPose(Axis.XP.rotationDegrees(90));
case DOWN -> poseStack.mulPose(Axis.XP.rotationDegrees(-90));
case CAMERA -> poseStack.mulPose(camera.rotation());
case PLAYER -> {
Vec3 vector = objectPos.subtract(camera.getPosition());
double x = vector.x;
double y = vector.y;
double z = vector.z;
double d = Math.sqrt(x * x + z * z);
float rotX = (float) (Math.atan2(x, z));
float rotY = (float) (Math.atan2(y, d));
// that should work somehow but it doesn't for some reason
//matrices.mulPose(new Quaternion( -rotY, rotX, 0, false));
poseStack.mulPose(Axis.YP.rotation(rotX));
poseStack.mulPose(Axis.XP.rotation(-rotY));
}
}
}
public ShapesRenderer(Minecraft minecraftClient)
{
this.client = minecraftClient;
shapes = new HashMap<>();
labels = new HashMap<>();
}
public void render(Matrix4f modelViewMatrix, Camera camera, float partialTick)
{
Runnable token = Carpet.startProfilerSection("Scarpet client");
// posestack is not needed anymore - left as TODO to cleanup later
PoseStack matrices = new PoseStack();
//Camera camera = this.client.gameRenderer.getCamera();
ClientLevel iWorld = this.client.level;
ResourceKey<Level> dimensionType = iWorld.dimension();
if ((shapes.get(dimensionType) == null || shapes.get(dimensionType).isEmpty()) &&
(labels.get(dimensionType) == null || labels.get(dimensionType).isEmpty()))
{
return;
}
long currentTime = client.level.getGameTime();
////RenderSystem.enableDepthTest();
//RenderSystem.setShader(CoreShaders.POSITION_COLOR);
////RenderSystem.depthFunc(515);
////RenderSystem.enableBlend();
////RenderSystem.defaultBlendFunc();
// too bright
//RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ZERO);
// meh
//RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA);
////RenderSystem.disableCull();
////RenderSystem.depthMask(false);
//RenderSystem.polygonOffset(-3f, -3f);
//RenderSystem.enablePolygonOffset();
Tesselator tesselator = Tesselator.getInstance();
// render
double cameraX = camera.getPosition().x;
double cameraY = camera.getPosition().y;
double cameraZ = camera.getPosition().z;
boolean entityBoxes = client.debugEntries.isCurrentlyEnabled(DebugScreenEntries.ENTITY_HITBOXES);
if (!shapes.isEmpty())
{
shapes.get(dimensionType).long2ObjectEntrySet().removeIf(
entry -> entry.getValue().isExpired(currentTime)
);
Matrix4fStack matrixStack = RenderSystem.getModelViewStack();
matrixStack.pushMatrix();
matrixStack.mul(matrices.last().pose());
// lines
RenderSystem.lineWidth(0.5F);
shapes.get(dimensionType).values().forEach(s -> {
if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType))
{
s.renderLines(matrices, tesselator, cameraX, cameraY, cameraZ, partialTick);
}
});
// faces
RenderSystem.lineWidth(0.1F);
shapes.get(dimensionType).values().forEach(s -> {
if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType))
{
s.renderFaces(tesselator, cameraX, cameraY, cameraZ, partialTick);
}
});
RenderSystem.lineWidth(1.0F);
matrixStack.popMatrix();
}
if (!labels.isEmpty())
{
labels.get(dimensionType).long2ObjectEntrySet().removeIf(
entry -> entry.getValue().isExpired(currentTime)
);
labels.get(dimensionType).values().forEach(s -> {
if ((!s.shape.debug || entityBoxes) && s.shouldRender(dimensionType))
{
s.renderLines(matrices, tesselator, cameraX, cameraY, cameraZ, partialTick);
}
});
}
////RenderSystem.enableCull();
////RenderSystem.depthMask(true);
////RenderSystem.enableBlend();
////RenderSystem.defaultBlendFunc();
token.run();
}
public void addShapes(ListTag tag)
{
Runnable token = Carpet.startProfilerSection("Scarpet client");
for (int i = 0, count = tag.size(); i < count; i++)
{
addShape(tag.getCompound(i).orElseThrow());
}
token.run();
}
public void addShape(CompoundTag tag)
{
ShapeDispatcher.ExpiringShape shape = ShapeDispatcher.fromTag(tag, client.level);
if (shape == null)
{
return;
}
BiFunction<Minecraft, ShapeDispatcher.ExpiringShape, RenderedShape<? extends ShapeDispatcher.ExpiringShape>> shapeFactory;
shapeFactory = renderedShapes.get(tag.getString("shape").orElseThrow());
if (shapeFactory == null)
{
CarpetScriptServer.LOG.info("Unrecognized shape: " + tag.getString("shape"));
}
else
{
RenderedShape<?> rshape = shapeFactory.apply(client, shape);
ResourceKey<Level> dim = shape.shapeDimension;
long key = rshape.key();
Map<ResourceKey<Level>, Long2ObjectOpenHashMap<RenderedShape<? extends ShapeDispatcher.ExpiringShape>>> container =
rshape.stageDeux() ? labels : shapes;
RenderedShape<?> existing = container.computeIfAbsent(dim, d -> new Long2ObjectOpenHashMap<>()).get(key);
if (existing != null)
{ // promoting previous shape
existing.promoteWith(rshape);
}
else
{
container.get(dim).put(key, rshape);
}
}
}
public void reset()
{
shapes.values().forEach(Long2ObjectOpenHashMap::clear);
labels.values().forEach(Long2ObjectOpenHashMap::clear);
}
public void renewShapes()
{
Runnable token = Carpet.startProfilerSection("Scarpet client");
shapes.values().forEach(el -> el.values().forEach(shape -> shape.expiryTick++));
labels.values().forEach(el -> el.values().forEach(shape -> shape.expiryTick++));
token.run();
}
public abstract static class RenderedShape<T extends ShapeDispatcher.ExpiringShape>
{
protected T shape;
protected Minecraft client;
long expiryTick;
double renderEpsilon;
public abstract void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick);
public void renderFaces(Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
}
protected RenderedShape(Minecraft client, T shape)
{
this.shape = shape;
this.client = client;
expiryTick = client.level.getGameTime() + shape.getExpiry();
renderEpsilon = (3 + ((double) key()) / Long.MAX_VALUE) / 1000;
}
public boolean isExpired(long currentTick)
{
return expiryTick < currentTick;
}
public long key()
{
return shape.key(client.level.registryAccess());
}
public boolean shouldRender(ResourceKey<Level> dim)
{
if (shape.followEntity <= 0)
{
return true;
}
if (client.level == null)
{
return false;
}
if (client.level.dimension() != dim)
{
return false;
}
return client.level.getEntity(shape.followEntity) != null;
}
public boolean stageDeux()
{
return false;
}
public void promoteWith(RenderedShape<?> rshape)
{
expiryTick = rshape.expiryTick;
}
}
public static class RenderedSprite extends RenderedShape<ShapeDispatcher.DisplayedSprite>
{
private final boolean isitem;
private ItemDisplayContext transformType = ItemDisplayContext.NONE;
private BlockPos blockPos;
private BlockState blockState;
private BlockEntity BlockEntity = null;
protected RenderedSprite(Minecraft client, ShapeDispatcher.ExpiringShape shape, boolean isitem)
{
super(client, (ShapeDispatcher.DisplayedSprite) shape);
this.isitem = isitem;
if (isitem)
{
this.transformType = ItemDisplayContext.valueOf(((ShapeDispatcher.DisplayedSprite) shape).itemTransformType.toUpperCase(Locale.ROOT));
}
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy,
double cz, float partialTick)
{
if (shape.a == 0.0)
{
return;
}
Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick);
Camera camera1 = client.gameRenderer.getMainCamera();
matrices.pushPose();
if (!isitem)// blocks should use its center as the origin
{
matrices.translate(0.5, 0.5, 0.5);
}
matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz);
rotatePoseStackByShapeDirection(matrices, shape.facing, camera1, isitem ? v1 : v1.add(0.5, 0.5, 0.5));
if (shape.tilt != 0.0f)
{
matrices.mulPose(Axis.ZP.rotationDegrees(-shape.tilt));
}
if (shape.lean != 0.0f)
{
matrices.mulPose(Axis.XP.rotationDegrees(-shape.lean));
}
if (shape.turn != 0.0f)
{
matrices.mulPose(Axis.YP.rotationDegrees(shape.turn));
}
matrices.scale(shape.scaleX, shape.scaleY, shape.scaleZ);
if (!isitem)
{
// blocks should use its center as the origin
matrices.translate(-0.5, -0.5, -0.5);
}
else
{
// items seems to be flipped by default
matrices.mulPose(Axis.YP.rotationDegrees(180));
}
////RenderSystem.depthMask(true);
////RenderSystem.enableCull();
////RenderSystem.enableDepthTest();
blockPos = BlockPos.containing(v1);
int light = 0;
if (client.level != null)
{
light = LightTexture.pack(
shape.blockLight < 0 ? client.level.getBrightness(LightLayer.BLOCK, blockPos) : shape.blockLight,
shape.skyLight < 0 ? client.level.getBrightness(LightLayer.SKY, blockPos) : shape.skyLight
);
}
blockState = shape.blockState;
MultiBufferSource.BufferSource immediate = client.renderBuffers().bufferSource();
if (!isitem)
{
// draw the block itself
if (blockState.getRenderShape() == RenderShape.MODEL)
{
var bakedModel = client.getBlockRenderer().getBlockModel(blockState);
int color = client.getBlockColors().getColor(blockState, client.level, blockPos, 0);
//dont know why there is a 0.
//see https://github.com/senseiwells/EssentialClient/blob/4db1f291936f502304791ee323f369c206b3021d/src/main/java/me/senseiwells/essentialclient/utils/render/RenderHelper.java#L464
float red = (color >> 16 & 0xFF) / 255.0F;
float green = (color >> 8 & 0xFF) / 255.0F;
float blue = (color & 0xFF) / 255.0F;
RenderType type;
if (blockState.getBlock() instanceof LeavesBlock && !Minecraft.useFancyGraphics()) {
type = RenderType.solid();
} else {
type = ItemBlockRenderTypes.getRenderType(blockState);
}
client.getBlockRenderer().getModelRenderer().renderModel(matrices.last(), immediate.getBuffer(type), bakedModel, red, green, blue, light, OverlayTexture.NO_OVERLAY);
}
// draw the block`s entity part
if (BlockEntity == null)
{
if (blockState.getBlock() instanceof EntityBlock eb)
{
BlockEntity = eb.newBlockEntity(blockPos, blockState);
if (BlockEntity != null)
{
BlockEntity.setLevel(client.level);
if (shape.blockEntity != null)
{
try (final ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(BlockEntity.problemPath(), CarpetScriptServer.LOG)) {
BlockEntity.loadWithComponents(TagValueInput.create(reporter, client.level.registryAccess(), shape.blockEntity));
}
}
}
}
}
if (BlockEntity != null)
{
BlockEntityRenderer<BlockEntity> blockEntityRenderer = client.getBlockEntityRenderDispatcher().getRenderer(BlockEntity);
if (blockEntityRenderer != null)
{
blockEntityRenderer.render(BlockEntity, partialTick,
matrices, immediate, light, OverlayTexture.NO_OVERLAY, camera1.getPosition());
}
}
}
else
{
if (shape.item != null)
{
// draw the item
client.getItemRenderer().renderStatic(shape.item, transformType, light,
OverlayTexture.NO_OVERLAY, matrices, immediate, client.level, (int) shape.key(client.level.registryAccess()));
}
}
matrices.popPose();
immediate.endBatch();
////RenderSystem.disableCull();
////RenderSystem.disableDepthTest();
////RenderSystem.depthMask(false);
}
@Override
public boolean stageDeux()
{
return true;
}
}
public static class RenderedText extends RenderedShape<ShapeDispatcher.DisplayedText>
{
protected RenderedText(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.DisplayedText) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.a == 0.0)
{
return;
}
Vec3 v1 = shape.relativiseRender(client.level, shape.pos, partialTick);
Camera camera1 = client.gameRenderer.getMainCamera();
Font textRenderer = client.font;
if (shape.doublesided)
{
//// RenderSystem.disableCull(); TODO culling
}
else
{
//// RenderSystem.enableCull();
}
matrices.pushPose();
matrices.translate(v1.x - cx, v1.y - cy, v1.z - cz);
rotatePoseStackByShapeDirection(matrices, shape.facing, camera1, v1);
matrices.scale(shape.size * 0.0025f, -shape.size * 0.0025f, shape.size * 0.0025f);
//RenderSystem.scalef(shape.size* 0.0025f, -shape.size*0.0025f, shape.size*0.0025f);
if (shape.tilt != 0.0f)
{
matrices.mulPose(Axis.ZP.rotationDegrees(shape.tilt));
}
if (shape.lean != 0.0f)
{
matrices.mulPose(Axis.XP.rotationDegrees(shape.lean));
}
if (shape.turn != 0.0f)
{
matrices.mulPose(Axis.YP.rotationDegrees(shape.turn));
}
matrices.translate(-10 * shape.indent, -10 * shape.height - 9, (-10 * renderEpsilon) - 10 * shape.raise);
//if (visibleThroughWalls) RenderSystem.disableDepthTest();
matrices.scale(-1, 1, 1);
//RenderSystem.applyModelViewMatrix(); // passed matrix directly to textRenderer.draw, not AffineTransformation.identity().getMatrix(),
float text_x = 0;
if (shape.align == 0)
{
text_x = (float) (-textRenderer.width(shape.value.getString())) / 2.0F;
}
else if (shape.align == 1)
{
text_x = (float) (-textRenderer.width(shape.value.getString()));
}
MultiBufferSource.BufferSource immediate = MultiBufferSource.immediate(new ByteBufferBuilder(RenderType.TRANSIENT_BUFFER_SIZE));
// text doesn't appear if backgroud is set
///script run draw_shape('label', 100, 'pos', [200, 100, 200], 'text', 'Hewwo World!', 'color', 0xffffffff, 'fill', 0x33333333)
textRenderer.drawInBatch(shape.value, text_x, 0.0F, shape.textcolor, false, matrices.last().pose(), immediate, Font.DisplayMode.SEE_THROUGH, shape.textbck, 15728880);
immediate.endBatch();
matrices.popPose();
////RenderSystem.enableCull();
}
@Override
public boolean stageDeux()
{
return true;
}
@Override
public void promoteWith(RenderedShape<?> rshape)
{
super.promoteWith(rshape);
try
{
this.shape.value = ((ShapeDispatcher.DisplayedText) rshape.shape).value;
}
catch (ClassCastException ignored)
{
CarpetScriptServer.LOG.error("shape " + rshape.shape.getClass() + " cannot cast to a Label");
}
}
}
public static class RenderedBox extends RenderedShape<ShapeDispatcher.Box>
{
private RenderedBox(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Box) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.a == 0.0)
{
return;
}
Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick);
Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick);
drawBoxWireGLLines(tesselator,
(float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon),
(float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon),
v1.x != v2.x, v1.y != v2.y, v1.z != v2.z,
shape.r, shape.g, shape.b, shape.a, shape.r, shape.g, shape.b
);
}
@Override
public void renderFaces(Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.fa == 0.0)
{
return;
}
Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick);
Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick);
// consider using built-ins
//DebugRenderer.drawBox(new Box(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z), 0.5f, 0.5f, 0.5f, 0.5f);//shape.r, shape.g, shape.b, shape.a);
drawBoxFaces(tesselator,
(float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon),
(float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon),
v1.x != v2.x, v1.y != v2.y, v1.z != v2.z,
shape.fr, shape.fg, shape.fb, shape.fa
);
}
}
public static class RenderedLine extends RenderedShape<ShapeDispatcher.Line>
{
public RenderedLine(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Line) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
Vec3 v1 = shape.relativiseRender(client.level, shape.from, partialTick);
Vec3 v2 = shape.relativiseRender(client.level, shape.to, partialTick);
drawLine(tesselator,
(float) (v1.x - cx - renderEpsilon), (float) (v1.y - cy - renderEpsilon), (float) (v1.z - cz - renderEpsilon),
(float) (v2.x - cx + renderEpsilon), (float) (v2.y - cy + renderEpsilon), (float) (v2.z - cz + renderEpsilon),
shape.r, shape.g, shape.b, shape.a
);
}
}
private static void drawWithShader(MeshData mesh, RenderType type) {
type.draw(mesh);
//VertexBuffer buffre = mesh.drawState().format().getImmediateDrawVertexBuffer();
//buffre.bind();
//buffre.upload(mesh);
//buffre.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderType. RenderSystem.getShader());
}
public static class RenderedPolyface extends RenderedShape<ShapeDispatcher.Polyface>
{
// mode now can only be 4, 5, or 6
private static final VertexFormat.Mode[] faceIndices = new VertexFormat.Mode[]{
Mode.LINES, Mode.LINE_STRIP, Mode.DEBUG_LINES, Mode.DEBUG_LINE_STRIP, Mode.TRIANGLES, Mode.TRIANGLE_STRIP, Mode.TRIANGLE_FAN, Mode.QUADS};
private static final RenderType [] renderTypes = new RenderType[] {
RenderType.debugLineStrip(1),
RenderType.debugLineStrip(1),
RenderType.debugLineStrip(1),
RenderType.debugLineStrip(1),
RenderType.debugTriangleFan(), // TODO wrong
RenderType.debugTriangleFan(), // TODO wrong
RenderType.debugTriangleFan(),
RenderType.debugQuads()
};
public RenderedPolyface(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Polyface) shape);
}
@Override
public void renderFaces(Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.fa == 0)
{
return;
}
if (shape.doublesided)
{
////RenderSystem.disableCull(); // todo culling
}
else
{
////RenderSystem.enableCull();
}
BufferBuilder builder = tesselator.begin(faceIndices[shape.mode], DefaultVertexFormat.POSITION_COLOR);
for (int i = 0; i < shape.vertexList.size(); i++)
{
Vec3 vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.fr, shape.fg, shape.fb, shape.fa);
}
drawWithShader(builder.buildOrThrow(), renderTypes[shape.mode]);
////RenderSystem.disableCull();
////RenderSystem.depthMask(false);
//RenderSystem.enableDepthTest();
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy,
double cz, float partialTick)
{
if (shape.a == 0)
{
return;
}
if (shape.mode == 6)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
Vec3 vec0 = null;
for (int i = 0; i < shape.vertexList.size(); i++)
{
Vec3 vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
if (i == 0)
{
vec0 = vec;
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
}
builder.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
if (shape.inneredges)
{
BufferBuilder builderr = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
for (int i = 1; i < shape.vertexList.size() - 1; i++)
{
Vec3 vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builderr.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
builderr.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
builderr.addVertex((float) (vec0.x() - cx), (float) (vec0.y() - cy), (float) (vec0.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
}
drawWithShader(builderr.buildOrThrow(), RenderType.debugLineStrip(1));
}
return;
}
if (shape.mode == 5)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
Vec3 vec = shape.vertexList.get(1);
if (shape.relative.get(1))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
int i;
for (i = 0; i < shape.vertexList.size(); i += 2)
{
vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
}
i = shape.vertexList.size() - 1;
for (i -= 1 - i % 2; i > 0; i -= 2)
{
vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
}
if (shape.inneredges)
{
for (i = 2; i < shape.vertexList.size() - 1; i++)
{
vec = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vec = shape.relativiseRender(client.level, vec, partialTick);
}
builder.addVertex((float) (vec.x() - cx), (float) (vec.y() - cy), (float) (vec.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
}
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
return;
}
if (shape.mode == 4)
{
//
for (int i = 0; i < shape.vertexList.size(); i++)
{
BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
Vec3 vecA = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vecA = shape.relativiseRender(client.level, vecA, partialTick);
}
i++;
Vec3 vecB = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vecB = shape.relativiseRender(client.level, vecB, partialTick);
}
i++;
Vec3 vecC = shape.vertexList.get(i);
if (shape.relative.get(i))
{
vecC = shape.relativiseRender(client.level, vecC, partialTick);
}
builder.addVertex((float) (vecA.x() - cx), (float) (vecA.y() - cy), (float) (vecA.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
builder.addVertex((float) (vecB.x() - cx), (float) (vecB.y() - cy), (float) (vecB.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
//builder.addVertex((float) (vecB.x() - cx), (float) (vecB.y() - cy), (float) (vecB.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
builder.addVertex((float) (vecC.x() - cx), (float) (vecC.y() - cy), (float) (vecC.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
//builder.addVertex((float) (vecC.x() - cx), (float) (vecC.y() - cy), (float) (vecC.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
builder.addVertex((float) (vecA.x() - cx), (float) (vecA.y() - cy), (float) (vecA.z() - cz)).setColor(shape.r, shape.g, shape.b, shape.a);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
//drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
}
}
public static class RenderedSphere extends RenderedShape<ShapeDispatcher.Sphere>
{
public RenderedSphere(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Sphere) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.a == 0.0)
{
return;
}
Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick);
drawSphereWireframe(tesselator,
(float) (vc.x - cx), (float) (vc.y - cy), (float) (vc.z - cz),
(float) (shape.radius + renderEpsilon), shape.subdivisions,
shape.r, shape.g, shape.b, shape.a);
}
@Override
public void renderFaces(Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.fa == 0.0)
{
return;
}
Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick);
drawSphereFaces(tesselator,
(float) (vc.x - cx), (float) (vc.y - cy), (float) (vc.z - cz),
(float) (shape.radius + renderEpsilon), shape.subdivisions,
shape.fr, shape.fg, shape.fb, shape.fa);
}
}
public static class RenderedCylinder extends RenderedShape<ShapeDispatcher.Cylinder>
{
public RenderedCylinder(Minecraft client, ShapeDispatcher.ExpiringShape shape)
{
super(client, (ShapeDispatcher.Cylinder) shape);
}
@Override
public void renderLines(PoseStack matrices, Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.a == 0.0)
{
return;
}
Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick);
double dir = Mth.sign(shape.height);
drawCylinderWireframe(tesselator,
(float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon),
(float) (shape.radius + renderEpsilon), (float) (shape.height + 2 * dir * renderEpsilon), shape.axis,
shape.subdivisions, shape.height == 0,
shape.r, shape.g, shape.b, shape.a);
}
@Override
public void renderFaces(Tesselator tesselator, double cx, double cy, double cz, float partialTick)
{
if (shape.fa == 0.0)
{
return;
}
Vec3 vc = shape.relativiseRender(client.level, shape.center, partialTick);
double dir = Mth.sign(shape.height);
drawCylinderFaces(tesselator,
(float) (vc.x - cx - dir * renderEpsilon), (float) (vc.y - cy - dir * renderEpsilon), (float) (vc.z - cz - dir * renderEpsilon),
(float) (shape.radius + renderEpsilon), (float) (shape.height + 2 * dir * renderEpsilon), shape.axis,
shape.subdivisions, shape.radius == 0,
shape.fr, shape.fg, shape.fb, shape.fa);
}
}
// some raw shit
public static void drawLine(Tesselator tesselator, float x1, float y1, float z1, float x2, float y2, float z2, float red1, float grn1, float blu1, float alpha)
{
BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
builder.addVertex(x1, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
public static void drawBoxWireGLLines(
Tesselator tesselator,
float x1, float y1, float z1,
float x2, float y2, float z2,
boolean xthick, boolean ythick, boolean zthick,
float red1, float grn1, float blu1, float alpha, float red2, float grn2, float blu2)
{
BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
/* old lines not using strip
if (xthick)
{
builder.addVertex(x1, y1, z1).setColor(red1, grn2, blu2, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn2, blu2, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
}
if (ythick)
{
builder.addVertex(x1, y1, z1).setColor(red2, grn1, blu2, alpha);
builder.addVertex(x1, y2, z1).setColor(red2, grn1, blu2, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
}
if (zthick)
{
builder.addVertex(x1, y1, z1).setColor(red2, grn2, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red2, grn2, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
}
*/
if (xthick)
{
builder.addVertex(x1, y1, z1).setColor(red1, grn2, blu2, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn2, blu2, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
}
if (ythick)
{
builder.addVertex(x1, y1, z1).setColor(red2, grn1, blu2, alpha);
builder.addVertex(x1, y2, z1).setColor(red2, grn1, blu2, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
}
if (zthick)
{
builder.addVertex(x1, y1, z1).setColor(red2, grn2, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red2, grn2, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
public static void drawBoxFaces(
Tesselator tesselator,
float x1, float y1, float z1,
float x2, float y2, float z2,
boolean xthick, boolean ythick, boolean zthick,
float red1, float grn1, float blu1, float alpha)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
if (xthick && ythick)
{
builder.addVertex(x1, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
if (zthick)
{
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
}
}
if (zthick && ythick)
{
builder.addVertex(x1, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
if (xthick)
{
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
}
}
// now at least drawing one
if (zthick && xthick)
{
builder.addVertex(x1, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y1, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y1, z2).setColor(red1, grn1, blu1, alpha);
if (ythick)
{
builder.addVertex(x1, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z1).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x2, y2, z2).setColor(red1, grn1, blu1, alpha);
builder.addVertex(x1, y2, z2).setColor(red1, grn1, blu1, alpha);
}
}
drawWithShader(builder.buildOrThrow(), RenderType.debugQuads());
}
public static void drawCylinderWireframe(Tesselator tesselator,
float cx, float cy, float cz,
float r, float h, Direction.Axis axis, int subd, boolean isFlat,
float red, float grn, float blu, float alpha)
{
float step = (float) Math.PI / (subd / 2);
int num_steps180 = (int) (Math.PI / step) + 1;
int num_steps360 = (int) (2 * Math.PI / step);
int hsteps = 1;
float hstep = 1.0f;
if (!isFlat)
{
hsteps = (int) Math.ceil(Mth.abs(h) / (step * r)) + 1;
hstep = h / (hsteps - 1);
}// draw base
if (axis == Direction.Axis.Y)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh * hstep;
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
for (int i = 0; i <= num_steps360 + 1; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = hh;
float z = r * Mth.sin(theta);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
if (!isFlat)
{
for (int i = 0; i <= num_steps180; i++)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(cx - x, cy + 0, cz + z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + x, cy + 0, cz - z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + x, cy + h, cz - z).setColor(red, grn, blu, alpha);
builder.addVertex(cx - x, cy + h, cz + z).setColor(red, grn, blu, alpha);
builder.addVertex(cx - x, cy + 0, cz + z).setColor(red, grn, blu, alpha);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
}
/* else
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR);
for (int i = 0; i <= num_steps180; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(cx - x, cy, cz + z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + x, cy, cz - z).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}*/
}
else if (axis == Direction.Axis.X)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh * hstep;
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float z = r * Mth.cos(theta);
float x = hh;
float y = r * Mth.sin(theta);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
if (!isFlat)
{
for (int i = 0; i <= num_steps180; i++)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(cx + 0, cy - y, cz + z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + 0, cy + y, cz - z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + h, cy + y, cz - z).setColor(red, grn, blu, alpha);
builder.addVertex(cx + h, cy - y, cz + z).setColor(red, grn, blu, alpha);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
}
/*else
{
BufferBuilder builder = tesselator.begin(Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
for (int i = 0; i <= num_steps360+1; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(cx, cy + y, cz + z).setColor(red, grn, blu, alpha);
//builder.addVertex(cx, cy + y, cz - z).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}*/
}
else if (axis == Direction.Axis.Z)
{
for (int dh = 0; dh < hsteps; dh++)
{
float hh = dh * hstep;
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = hh;
float x = r * Mth.sin(theta);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
if (!isFlat)
{
for (int i = 0; i <= num_steps180; i++)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
builder.addVertex(cx + x, cy - y, cz + 0).setColor(red, grn, blu, alpha);
builder.addVertex(cx - x, cy + y, cz + 0).setColor(red, grn, blu, alpha);
builder.addVertex(cx - x, cy + y, cz + h).setColor(red, grn, blu, alpha);
builder.addVertex(cx + x, cy - y, cz + h).setColor(red, grn, blu, alpha);
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
}
/*else
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINES, DefaultVertexFormat.POSITION_COLOR);
for (int i = 0; i <= num_steps180; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
builder.addVertex(cx + x, cy - y, cz).setColor(red, grn, blu, alpha);
builder.addVertex(cx - x, cy + y, cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}*/
}
}
public static void drawCylinderFaces(Tesselator tesselator,
float cx, float cy, float cz,
float r, float h, Direction.Axis axis, int subd, boolean isFlat,
float red, float grn, float blu, float alpha)
{
float step = (float) Math.PI / (subd / 2);
//final int num_steps180 = (int) (Math.PI / step) + 1;
int num_steps360 = (int) (2 * Math.PI / step) + 1;
if (axis == Direction.Axis.Y)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builder.addVertex(cx, cy, cz).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(x + cx, cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan());
if (!isFlat)
{
BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builderr.addVertex(cx, cy + h, cz).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builderr.addVertex(x + cx, cy + h, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan());
BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads
float xp = r * 1;
float zp = r * 0;
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builderrr.addVertex(cx + xp, cy + 0, cz + zp).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + xp, cy + h, cz + zp).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + x, cy + h, cz + z).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + x, cy + 0, cz + z).setColor(red, grn, blu, alpha);
xp = x;
zp = z;
}
drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads());
}
}
else if (axis == Direction.Axis.X)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builder.addVertex(cx, cy, cz).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builder.addVertex(cx, cy + y, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan());
if (!isFlat)
{
BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builderr.addVertex(cx + h, cy, cz).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builderr.addVertex(cx + h, cy + y, cz + z).setColor(red, grn, blu, alpha);
}
drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan());
BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads
float yp = r * 1;
float zp = r * 0;
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float y = r * Mth.cos(theta);
float z = r * Mth.sin(theta);
builderrr.addVertex(cx + 0, cy + yp, cz + zp).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + h, cy + yp, cz + zp).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + h, cy + y, cz + z).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + 0, cy + y, cz + z).setColor(red, grn, blu, alpha);
yp = y;
zp = z;
}
drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads());
}
}
else if (axis == Direction.Axis.Z)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builder.addVertex(cx, cy, cz).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
builder.addVertex(x + cx, cy + y, cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugTriangleFan());
if (!isFlat)
{
BufferBuilder builderr = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
builderr.addVertex(cx, cy, cz + h).setColor(red, grn, blu, alpha);
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
builderr.addVertex(x + cx, cy + y, cz + h).setColor(red, grn, blu, alpha);
}
drawWithShader(builderr.buildOrThrow(), RenderType.debugTriangleFan());
BufferBuilder builderrr = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads
float xp = r;
float yp = 0;
for (int i = 1; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.cos(theta);
float y = r * Mth.sin(theta);
builderrr.addVertex(cx + xp, cy + yp, cz + 0).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + xp, cy + yp, cz + h).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + x, cy + y, cz + h).setColor(red, grn, blu, alpha);
builderrr.addVertex(cx + x, cy + y, cz + 0).setColor(red, grn, blu, alpha);
xp = x;
yp = y;
}
drawWithShader(builderrr.buildOrThrow(), RenderType.debugQuads());
}
}
}
public static void drawSphereWireframe(Tesselator tesselator,
float cx, float cy, float cz,
float r, int subd,
float red, float grn, float blu, float alpha)
{
float step = (float) Math.PI / (subd / 2);
int num_steps180 = (int) (Math.PI / step) + 1;
int num_steps360 = (int) (2 * Math.PI / step) + 1;
for (int i = 0; i <= num_steps360; i++)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR);
float theta = step * i;
for (int j = 0; j <= num_steps180; j++)
{
float phi = step * j;
float x = r * Mth.sin(phi) * Mth.cos(theta);
float z = r * Mth.sin(phi) * Mth.sin(theta);
float y = r * Mth.cos(phi);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
for (int j = 0; j <= num_steps180; j++)
{
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.DEBUG_LINE_STRIP, DefaultVertexFormat.POSITION_COLOR); // line loop to line strip
float phi = step * j;
for (int i = 0; i <= num_steps360; i++)
{
float theta = step * i;
float x = r * Mth.sin(phi) * Mth.cos(theta);
float z = r * Mth.sin(phi) * Mth.sin(theta);
float y = r * Mth.cos(phi);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
}
drawWithShader(builder.buildOrThrow(), RenderType.debugLineStrip(1));
}
}
public static void drawSphereFaces(Tesselator tesselator,
float cx, float cy, float cz,
float r, int subd,
float red, float grn, float blu, float alpha)
{
float step = (float) Math.PI / (subd / 2);
int num_steps180 = (int) (Math.PI / step) + 1;
int num_steps360 = (int) (2 * Math.PI / step);
for (int i = 0; i <= num_steps360; i++)
{
float theta = i * step;
float thetaprime = theta + step;
BufferBuilder builder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); // quad strip to quads
float xb = 0;
float zb = 0;
float xbp = 0;
float zbp = 0;
float yp = r;
for (int j = 0; j <= num_steps180; j++)
{
float phi = j * step;
float x = r * Mth.sin(phi) * Mth.cos(theta);
float z = r * Mth.sin(phi) * Mth.sin(theta);
float y = r * Mth.cos(phi);
float xp = r * Mth.sin(phi) * Mth.cos(thetaprime);
float zp = r * Mth.sin(phi) * Mth.sin(thetaprime);
builder.addVertex(xb + cx, yp + cy, zb + cz).setColor(red, grn, blu, alpha);
builder.addVertex(xbp + cx, yp + cy, zbp + cz).setColor(red, grn, blu, alpha);
builder.addVertex(xp + cx, y + cy, zp + cz).setColor(red, grn, blu, alpha);
builder.addVertex(x + cx, y + cy, z + cz).setColor(red, grn, blu, alpha);
xb = x;
zb = z;
xbp = xp;
zbp = zp;
yp = y;
}
drawWithShader(builder.buildOrThrow(), RenderType.debugQuads());
}
}
}