]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/renderers/AbstractRenderer.java
98e8a919938f9ad4c8a2feac336fbf56c885fbff
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / renderers / AbstractRenderer.java
1 package com.irtimaled.bbor.client.renderers;
2
3 import com.irtimaled.bbor.client.Camera;
4 import com.irtimaled.bbor.client.RenderCulling;
5 import com.irtimaled.bbor.client.config.ConfigManager;
6 import com.irtimaled.bbor.client.models.Point;
7 import com.irtimaled.bbor.common.MathHelper;
8 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
9 import com.mojang.blaze3d.systems.RenderSystem;
10 import net.minecraft.client.MinecraftClient;
11 import net.minecraft.client.font.TextRenderer;
12 import net.minecraft.client.gl.VertexBuffer;
13 import net.minecraft.client.render.BufferBuilder;
14 import net.minecraft.client.render.BufferRenderer;
15 import net.minecraft.client.render.GameRenderer;
16 import net.minecraft.client.render.Shader;
17 import net.minecraft.client.render.Tessellator;
18 import net.minecraft.client.render.VertexFormat;
19 import net.minecraft.client.render.VertexFormats;
20 import net.minecraft.client.util.math.MatrixStack;
21 import net.minecraft.util.math.BlockPos;
22 import net.minecraft.util.math.Box;
23 import net.minecraft.util.math.Matrix4f;
24 import org.lwjgl.opengl.GL11;
25
26 import java.awt.*;
27
28 public abstract class AbstractRenderer<T extends AbstractBoundingBox> {
29     private static final double TAU = 6.283185307179586D;
30     public static final double PHI_SEGMENT = TAU / 90D;
31     private static final double PI = TAU / 2D;
32     public static final double THETA_SEGMENT = PHI_SEGMENT / 2D;
33
34     private final VertexBuffer solidBox = new VertexBuffer();
35     private final VertexBuffer outlinedBox = new VertexBuffer();
36
37     {
38         final Box box = new Box(BlockPos.ORIGIN);
39         RenderHelper.drawSolidBox(box, solidBox);
40         RenderHelper.drawOutlinedBox(box, outlinedBox);
41     }
42
43     public abstract void render(MatrixStack matrixStack, T boundingBox);
44
45     void renderCuboid(MatrixStack matrixStack, OffsetBox bb, Color color, boolean fillOnly) {
46         OffsetBox nudge = bb.nudge();
47
48         GL11.glEnable(GL11.GL_LINE_SMOOTH);
49         GL11.glEnable(GL11.GL_CULL_FACE);
50         RenderHelper.polygonModeFill();
51         matrixStack.push();
52
53         RenderHelper.applyRegionalRenderOffset(matrixStack);
54         renderCuboid0(matrixStack, nudge, color, fillOnly);
55
56         matrixStack.pop();
57         GL11.glDisable(GL11.GL_LINE_SMOOTH);
58         RenderSystem.setShaderColor(1, 1, 1, 1);
59     }
60
61     private void renderCuboid0(MatrixStack stack, OffsetBox nudge, Color color, boolean fillOnly) {
62         if (!RenderCulling.isVisibleCulling(nudge.toBox())) return;
63         if (ConfigManager.invertBoxColorPlayerInside.get() &&
64                 playerInsideBoundingBox(nudge)) {
65             color = new Color(255 - color.getRed(), 255 - color.getGreen(), 255 - color.getBlue());
66         }
67         stack.push();
68         int regionX = (((int) Camera.getX()) >> 9) << 9;
69         int regionZ = (((int) Camera.getZ()) >> 9) << 9;
70         RenderSystem.setShader(GameRenderer::getPositionShader);
71         stack.translate(nudge.getMin().getX() - regionX, nudge.getMin().getY(), nudge.getMin().getZ() - regionZ);
72         stack.scale((float) (nudge.getMax().getX() - nudge.getMin().getX()),
73                 (float) (nudge.getMax().getY() - nudge.getMin().getY()),
74                 (float) (nudge.getMax().getZ() - nudge.getMin().getZ()));
75
76         Matrix4f viewMatrix = stack.peek().getModel();
77         Matrix4f projMatrix = RenderSystem.getProjectionMatrix();
78         Shader shader = RenderSystem.getShader();
79         if (fillOnly || ConfigManager.fill.get()) {
80             RenderSystem.setShaderColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 30 / 255F);
81             solidBox.setShader(viewMatrix, projMatrix, shader);
82         }
83         if (!fillOnly) {
84             RenderSystem.setShaderColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 1F);
85             outlinedBox.setShader(viewMatrix, projMatrix, shader);
86         }
87
88         stack.pop();
89     }
90
91     private boolean playerInsideBoundingBox(OffsetBox nudge) {
92         return nudge.getMin().getX() < 0 && nudge.getMax().getX() > 0 &&
93                 nudge.getMin().getY() < 0 && nudge.getMax().getY() > 0 &&
94                 nudge.getMin().getZ() < 0 && nudge.getMax().getZ() > 0;
95     }
96
97     void renderLine(MatrixStack matrixStack, OffsetPoint startPoint, OffsetPoint endPoint, Color color) {
98         if (!RenderCulling.isVisibleCulling(new OffsetBox(startPoint, endPoint).toBox())) return; // TODO better culling
99         matrixStack.push();
100
101         RenderHelper.applyRegionalRenderOffset(matrixStack);
102         RenderSystem.setShader(GameRenderer::getPositionShader);
103         RenderSystem.setShaderColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 0.55f);
104         int regionX = (((int) Camera.getX()) >> 9) * 512;
105         int regionZ = (((int) Camera.getZ()) >> 9) * 512;
106
107         BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
108         bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINES,
109                 VertexFormats.POSITION);
110         bufferBuilder
111                 .vertex(matrixStack.peek().getModel(),
112                         (float) startPoint.getX() - regionX,
113                         (float) startPoint.getY(),
114                         (float) startPoint.getZ() - regionZ)
115                 .next();
116         bufferBuilder
117                 .vertex(matrixStack.peek().getModel(),
118                         (float) endPoint.getX() - regionX,
119                         (float) endPoint.getY(),
120                         (float) endPoint.getZ() - regionZ)
121                 .next();
122         bufferBuilder.end();
123         BufferRenderer.draw(bufferBuilder);
124
125         matrixStack.pop();
126     }
127
128     void renderText(MatrixStack matrixStack, OffsetPoint offsetPoint, String... texts) {
129         TextRenderer fontRenderer = MinecraftClient.getInstance().textRenderer;
130         RenderHelper.beforeRenderFont(matrixStack, offsetPoint);
131         float top = -(fontRenderer.fontHeight * texts.length) / 2f;
132         for (String text : texts) {
133             float left = fontRenderer.getWidth(text) / 2f;
134             fontRenderer.draw(new MatrixStack(), text, -left, top, -1);
135             top += fontRenderer.fontHeight;
136         }
137         RenderHelper.afterRenderFont(matrixStack);
138     }
139
140     void renderSphere(MatrixStack matrixStack, Point center, double radius, Color color) {
141         if (ConfigManager.renderSphereAsDots.get()) {
142             renderDotSphere(matrixStack, center, radius, color);
143         } else {
144             renderLineSphere(matrixStack, center, radius, color);
145         }
146     }
147
148     private void renderLineSphere(MatrixStack matrixStack, Point center, double radius, Color color) {
149         if (!RenderCulling.isVisibleCulling(new Box(new BlockPos(center.getX(), center.getY(), center.getZ())).expand(radius))) return;
150         RenderHelper.lineWidth2();
151
152         double offset = ((radius - (int) radius) == 0) ? center.getY() - (int) center.getY() : 0;
153         int dyStep = radius < 64 ? 1 : MathHelper.floor(radius / 32);
154         for (double dy = offset - radius; dy <= radius + 1; dy += dyStep) {
155             double circleRadius = Math.sqrt((radius * radius) - (dy * dy));
156             if (circleRadius == 0) circleRadius = Math.sqrt(2) / 2;
157             renderCircle(matrixStack, center, circleRadius, color, dy + 0.001F);
158         }
159     }
160
161     private void renderCircle(MatrixStack matrixStack, Point center, double radius, Color color, double dy) {
162         matrixStack.push();
163
164         RenderHelper.applyRegionalRenderOffset(matrixStack);
165         RenderSystem.setShader(GameRenderer::getPositionShader);
166         RenderSystem.setShaderColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 0.55f);
167         int regionX = (((int) Camera.getX()) >> 9) * 512;
168         int regionZ = (((int) Camera.getZ()) >> 9) * 512;
169
170         BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
171         bufferBuilder.begin(VertexFormat.DrawMode.DEBUG_LINE_STRIP,
172                 VertexFormats.POSITION);
173
174         Point firstPoint = null;
175
176         for (double phi = 0.0D; phi < TAU; phi += PHI_SEGMENT) {
177             final Point point = center.offset(Math.cos(phi) * radius, dy, Math.sin(phi) * radius);
178             if (firstPoint == null) firstPoint = point;
179             bufferBuilder.vertex(matrixStack.peek().getModel(),
180                     (float) point.getX() - regionX,
181                     (float) point.getY(),
182                     (float) point.getZ() - regionZ)
183                     .next();
184         }
185
186         bufferBuilder.vertex(matrixStack.peek().getModel(),
187                 (float) firstPoint.getX() - regionX,
188                 (float) firstPoint.getY(),
189                 (float) firstPoint.getZ() - regionZ)
190                 .next();
191
192         bufferBuilder.end();
193         BufferRenderer.draw(bufferBuilder);
194         matrixStack.pop();
195     }
196
197     private void renderDotSphere(MatrixStack matrixStack, Point center, double radius, Color color) {
198         if (!RenderCulling.isVisibleCulling(new Box(new BlockPos(center.getX(), center.getY(), center.getZ())).expand(radius))) return;
199         matrixStack.push();
200         RenderHelper.applyRegionalRenderOffset(matrixStack);
201         RenderSystem.setShader(GameRenderer::getPositionShader);
202         RenderSystem.setShaderColor(color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 0.55f);
203         int regionX = (((int) Camera.getX()) >> 9) * 512;
204         int regionZ = (((int) Camera.getZ()) >> 9) * 512;
205
206         BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer();
207         bufferBuilder.begin(VertexFormat.DrawMode.QUADS,
208                 VertexFormats.POSITION);
209
210         for (double phi = 0.0D; phi < TAU; phi += PHI_SEGMENT) {
211             double dy = radius * Math.cos(phi);
212             double radiusBySinPhi = radius * Math.sin(phi);
213             for (double theta = 0.0D; theta < PI; theta += THETA_SEGMENT) {
214                 double dx = radiusBySinPhi * Math.cos(theta);
215                 double dz = radiusBySinPhi * Math.sin(theta);
216
217                 final Point point = center.offset(dx, dy, dz);
218                 bufferBuilder
219                         .vertex(matrixStack.peek().getModel(),
220                                 (float) point.getX() - regionX,
221                                 (float) point.getY(),
222                                 (float) point.getZ() - regionZ)
223                         .next();
224             }
225         }
226         bufferBuilder.end();
227         BufferRenderer.draw(bufferBuilder);
228         matrixStack.pop();
229     }
230 }