summaryrefslogtreecommitdiffstats
path: root/src/main/java/dev/figboot/cuberender/state/Mesh.java
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2024-06-14 20:29:43 -0500
committerLibravatar bigfoot547 <[email protected]>2024-06-14 20:29:43 -0500
commit2113ae54df2da867f553df3a9ee457c0a3856a33 (patch)
tree7d76e281893c155918e9bbf368509155bb4dfd9a /src/main/java/dev/figboot/cuberender/state/Mesh.java
initial commit
Diffstat (limited to 'src/main/java/dev/figboot/cuberender/state/Mesh.java')
-rw-r--r--src/main/java/dev/figboot/cuberender/state/Mesh.java159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/main/java/dev/figboot/cuberender/state/Mesh.java b/src/main/java/dev/figboot/cuberender/state/Mesh.java
new file mode 100644
index 0000000..2f28c16
--- /dev/null
+++ b/src/main/java/dev/figboot/cuberender/state/Mesh.java
@@ -0,0 +1,159 @@
+package dev.figboot.cuberender.state;
+
+import dev.figboot.cuberender.math.MathUtil;
+import dev.figboot.cuberender.math.Vector2f;
+import dev.figboot.cuberender.math.Vector3f;
+import dev.figboot.cuberender.math.Vector4f;
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+
+import java.util.*;
+
+@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
+public abstract class Mesh<T> implements Sampleable<T> {
+ final Vector3f[] vertices;
+ final Vector3f[] normals;
+ final int[] indices;
+
+ final Map<AttachmentType, Object> attachments;
+
+ protected void applyLighting(Vector4f color, Vector3f normal) {
+ Float lightFact = (Float)attachments.get(AttachmentType.LIGHT_FACTOR);
+
+ if (lightFact == null) {
+ return;
+ }
+
+ float fact = 1 - (normal.dot((Vector3f)attachments.get(AttachmentType.LIGHT_VECTOR)) + 1) / 2;
+ fact *= lightFact; // lightFact should kinda set the "black level"
+ fact = 1 - fact;
+
+ fact = MathUtil.clamp(fact, 0, 1);
+
+ color.x *= fact;
+ color.y *= fact;
+ color.z *= fact;
+ }
+
+ public static class Builder {
+ private final List<Vector3f> vertices = new ArrayList<>();
+ private final List<Vector3f> normals = new ArrayList<>();
+ private final List<Integer> indices = new ArrayList<>();
+ private final List<Vector2f> texCoords = new ArrayList<>();
+ private int color;
+ private Texture texture;
+
+ private final Map<AttachmentType, Object> attachments = new EnumMap<>(AttachmentType.class);
+
+ public Builder() {
+ color = 0xFF000000;
+ texture = null;
+ }
+
+ public Builder color(int color) {
+ this.color = color;
+ return this;
+ }
+
+ public Builder texture(Texture t) {
+ this.texture = t;
+ return this;
+ }
+
+ public Builder texCoords(Vector2f... tex) {
+ texCoords.addAll(Arrays.asList(tex));
+ return this;
+ }
+
+ public Builder vertex(Vector3f... vert) {
+ vertices.addAll(Arrays.asList(vert));
+ return this;
+ }
+
+ public Builder normals(Vector3f... norm) {
+ normals.addAll(Arrays.asList(norm));
+ return this;
+ }
+
+ public Builder indices(int... indices) {
+ for (int idx : indices) {
+ this.indices.add(idx);
+ }
+ return this;
+ }
+
+ public Builder attach(AttachmentType type, Object o) {
+ attachments.put(type, o);
+ return this;
+ }
+
+ public Mesh<?> build() {
+ int[] idxArr;
+ if (indices.isEmpty()) {
+ idxArr = null;
+ } else {
+ idxArr = new int[indices.size()];
+ for (int i = 0, max = indices.size(); i < max; ++i) {
+ idxArr[i] = indices.get(i);
+ }
+ }
+
+ if (texture == null) {
+ return new ColorMesh(vertices.toArray(new Vector3f[0]), normals.toArray(new Vector3f[0]), idxArr, attachments, color);
+ } else {
+ return new TextureMesh(vertices.toArray(new Vector3f[0]), normals.toArray(new Vector3f[0]), idxArr, attachments, texture, texCoords.toArray(new Vector2f[0]));
+ }
+ }
+ }
+
+ private static class ColorMesh extends Mesh<Void> {
+ int color;
+
+ ColorMesh(Vector3f[] vertices, Vector3f[] normals, int[] indices, Map<AttachmentType, Object> attachments, int color) {
+ super(vertices, normals, indices, attachments);
+ this.color = color;
+ }
+
+ @Override
+ public Void extra(int idx) {
+ return null;
+ }
+
+ @Override
+ public void sample(float b0, float b1, float b2, Vector3f normal, Void u1, Void u2, Void u3, Vector4f outColor) {
+ applyLighting(outColor.fromARGB(color), normal);
+ }
+ }
+
+ private static class TextureMesh extends Mesh<Vector2f> {
+ Texture texture;
+ Vector2f[] texCoords;
+
+ TextureMesh(Vector3f[] vertices, Vector3f[] normals, int[] indices, Map<AttachmentType, Object> attachments, Texture tex, Vector2f[] texCoords) {
+ super(vertices, normals, indices, attachments);
+ this.texture = tex;
+ this.texCoords = texCoords;
+ }
+
+ @Override
+ public Vector2f extra(int idx) {
+ return texCoords[idx];
+ }
+
+ @Override
+ public void sample(float b0, float b1, float b2, Vector3f normal, Vector2f tc1, Vector2f tc2, Vector2f tc3, Vector4f color) {
+ float texX = b0 * tc1.x + b1 * tc2.x + b2 * tc3.x;
+ float texY = b0 * tc1.y + b1 * tc2.y + b2 * tc3.y;
+
+ int texiX = (int)Math.min(texture.width-1, Math.max(0, Math.floor(texX * texture.width)));
+ int texiY = (int)Math.min(texture.height-1, Math.max(0, Math.floor((1f - texY) * texture.height)));
+
+ applyLighting(color.fromARGB(texture.image.getRGB(texiX, texiY)), normal);
+ }
+ }
+
+ public enum AttachmentType {
+ LIGHT_FACTOR, // float
+ LIGHT_VECTOR // Vector3f
+ }
+}