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
|
|
|
|