Passed
Push — main ( 6b9c84...d238e2 )
by Etienne
01:40
created

renderBeam(MatrixStack,VertexConsumerProvider,Identifier,float,long,Vec3d,float[],float,float)   A

Complexity

Conditions 1

Size

Total Lines 37
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 36
c 1
b 0
f 0
dl 0
loc 37
rs 9.016
cc 1
1
package de.kleiner3.lasertag.entity.render;
2
3
import de.kleiner3.lasertag.entity.LaserRayEntity;
4
import net.minecraft.client.render.LightmapTextureManager;
5
import net.minecraft.client.render.OverlayTexture;
6
import net.minecraft.client.render.RenderLayer;
7
import net.minecraft.client.render.VertexConsumer;
8
import net.minecraft.client.render.VertexConsumerProvider;
9
import net.minecraft.client.render.entity.EntityRenderer;
10
import net.minecraft.client.render.entity.EntityRendererFactory.Context;
11
import net.minecraft.client.util.math.MatrixStack;
12
import net.minecraft.util.Identifier;
13
import net.minecraft.util.math.MathHelper;
14
import net.minecraft.util.math.Matrix3f;
15
import net.minecraft.util.math.Matrix4f;
16
import net.minecraft.util.math.Quaternion;
17
import net.minecraft.util.math.Vec3d;
18
19
/**
20
 * A custom renderer to render the laser ray entity as a smaller beacon beam
21
 *
22
 * @author Étienne Muser
23
 */
24
public class LaserRayEntityRenderer extends EntityRenderer<LaserRayEntity> {
25
    // TODO: Laser ray gets culled when origin is off screen or too far away
26
27
    public static final Identifier BEAM_TEXTURE = new Identifier("textures/entity/beacon_beam.png");
28
29
    public LaserRayEntityRenderer(Context ctx) {
30
        super(ctx);
31
    }
32
33
    @Override
34
    public Identifier getTexture(LaserRayEntity var1) {
35
        return BEAM_TEXTURE;
36
    }
37
38
    /**
39
     * Renders the entity
40
     */
41
    @Override
42
    public void render(LaserRayEntity laserRayEntity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) {
43
        long worldTime = laserRayEntity.getWorld().getTime();
44
        int color = laserRayEntity.getColor();
45
        float[] colorArr = new float[] {
46
                ((color >> 16) & 0xFF) / 255.0F,
47
                ((color >> 8) & 0xFF) / 255.0F,
48
                ((color) & 0xFF) / 255.0F
49
        };
50
        Vec3d end = laserRayEntity.getEnd().subtract(laserRayEntity.getPos());
51
        renderBeam(matrices, vertexConsumers, tickDelta, worldTime, colorArr, end);
52
    }
53
54
    /**
55
     * Render a beacon beam
56
     *
57
     * @param matrices The matrix stack
58
     * @param vertexConsumers The vertex consumer provider
59
     * @param color the color float array
60
     * @param end The end position of the ray relative to its start position
61
     */
62
    private static void renderBeam(MatrixStack matrices, VertexConsumerProvider vertexConsumers, float tickDelta, long worldTime, float[] color, Vec3d end) {
63
        renderBeam(matrices, vertexConsumers, BEAM_TEXTURE, tickDelta, worldTime, end, color, 0.0125f, 0.015625f);
64
    }
65
66
    /**
67
     * Render a beacon beam
68
     *
69
     * @param matrices The matrix stack
70
     * @param vertexConsumers The vertex consumer provider
71
     */
72
    public static void renderBeam(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Identifier textureId, float tickDelta, long worldTime, Vec3d end, float[] color, float innerRadius, float outerRadius) {
73
        double length = end.length();
74
        Quaternion rot = getRot(end);
75
        matrices.push();
76
77
        float beamSpinProgress = (float) Math.floorMod(worldTime, 40) + tickDelta;
78
        float h = MathHelper.fractionalPart(beamSpinProgress * 0.2f - (float) MathHelper.floor(beamSpinProgress * 0.1f));
79
        float colorR = color[0];
80
        float colorG = color[1];
81
        float colorB = color[2];
82
        matrices.push();
83
        matrices.multiply(rot);
84
        float m;
85
        float n = innerRadius;
86
        float o = innerRadius;
87
        float p;
88
        float q = -innerRadius;
89
        float r;
90
        float s;
91
        float t = -innerRadius;
92
        float w = -1.0f + h;
93
        float x = (float) length * (0.5f / innerRadius) + w;
94
        renderBeamLayer(matrices, vertexConsumers.getBuffer(RenderLayer.getBeaconBeam(textureId, false)), colorR, colorG, colorB, 1.0f, length, 0.0f, n, o, 0.0f, q, 0.0f, 0.0f, t, x, w);
95
        matrices.pop();
96
        matrices.multiply(rot);
97
        m = -outerRadius;
98
        n = -outerRadius;
99
        o = outerRadius;
100
        p = -outerRadius;
101
        q = -outerRadius;
102
        r = outerRadius;
103
        s = outerRadius;
104
        t = outerRadius;
105
        w = -1.0f + h;
106
        x = (float) length + w;
107
        renderBeamLayer(matrices, vertexConsumers.getBuffer(RenderLayer.getBeaconBeam(textureId, true)), colorR, colorG, colorB, 0.125f, length, m, n, o, p, q, r, s, t, x, w);
108
        matrices.pop();
109
    }
110
111
    /**
112
     * Renders a single layer of a beacon
113
     */
114
    private static void renderBeamLayer(MatrixStack matrices, VertexConsumer vertices, float red, float green, float blue, float alpha, double length, float x1, float z1, float x2, float z2, float x3, float z3, float x4, float z4, float v1, float v2) {
115
        MatrixStack.Entry entry = matrices.peek();
116
        Matrix4f matrix4f = entry.getPositionMatrix();
117
        Matrix3f matrix3f = entry.getNormalMatrix();
118
        renderBeamFace(matrix4f, matrix3f, vertices, red, green, blue, alpha, length, x1, z1, x2, z2, v1, v2);
119
        renderBeamFace(matrix4f, matrix3f, vertices, red, green, blue, alpha, length, x4, z4, x3, z3, v1, v2);
120
        renderBeamFace(matrix4f, matrix3f, vertices, red, green, blue, alpha, length, x2, z2, x4, z4, v1, v2);
121
        renderBeamFace(matrix4f, matrix3f, vertices, red, green, blue, alpha, length, x3, z3, x1, z1, v1, v2);
122
    }
123
124
    private static void renderBeamFace(Matrix4f positionMatrix, Matrix3f normalMatrix, VertexConsumer vertices, float red, float green, float blue, float alpha, double length, float x1, float z1, float x2, float z2, float v1, float v2) {
125
        renderBeamVertex(positionMatrix, normalMatrix, vertices, red, green, blue, alpha, length, x1, z1, (float) 1.0, v1);
126
        renderBeamVertex(positionMatrix, normalMatrix, vertices, red, green, blue, alpha, 0, x1, z1, (float) 1.0, v2);
127
        renderBeamVertex(positionMatrix, normalMatrix, vertices, red, green, blue, alpha, 0, x2, z2, (float) 0.0, v2);
128
        renderBeamVertex(positionMatrix, normalMatrix, vertices, red, green, blue, alpha, length, x2, z2, (float) 0.0, v1);
129
    }
130
131
    /**
132
     * @param v the top-most coordinate of the texture region
133
     * @param u the left-most coordinate of the texture region
134
     */
135
    private static void renderBeamVertex(Matrix4f positionMatrix, Matrix3f normalMatrix, VertexConsumer vertices, float red, float green, float blue, float alpha, double y, float x, float z, float u, float v) {
136
        vertices.vertex(positionMatrix, x, (float) y, z).color(red, green, blue, alpha).texture(u, v).overlay(OverlayTexture.DEFAULT_UV).light(LightmapTextureManager.MAX_LIGHT_COORDINATE).normal(normalMatrix, 0.0f, 1.0f, 0.0f).next();
137
    }
138
139
    /**
140
     * Helper method to get the rotation quaternion to rotate the up-vector to the direction vector
141
     *
142
     * @param direction The direction vector
143
     * @return The rotation quaternion
144
     */
145
    private static Quaternion getRot(Vec3d direction) {
146
        Vec3d up = new Vec3d(0, 1, 0);
147
148
        Vec3d cross = up.crossProduct(direction);
149
        double dot = up.dotProduct(direction);
150
151
        Quaternion q;
152
        if (direction.y < 0 && Math.abs(direction.x) < 0.001F && Math.abs(direction.z) < 0.001F) {
153
            q = new Quaternion(1.0F, 0.0F, 0.0F, (float) Math.cos(0.5 * Math.PI));
154
        } else {
155
            q = new Quaternion((float) cross.x, (float) cross.y, (float) cross.z,
156
                    (float) direction.length() + (float) dot);
157
        }
158
159
        q.normalize();
160
        return q;
161
    }
162
}
163