diff --git a/build.gradle b/build.gradle
index 84a7fd4..025aaff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,13 +17,20 @@ repositories {
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
mavenCentral()
+ maven {
+ name = 'ParchmentMC'
+ url = 'https://maven.parchmentmc.org'
+ }
//----for test---
}
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
- mappings loom.officialMojangMappings()
+ mappings loom.layered() {
+ officialMojangMappings()
+ parchment("org.parchmentmc.data:parchment-1.20.2:2023.10.08@zip")
+ }
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
@@ -78,4 +85,7 @@ publishing {
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
+}
+loom {
+ accessWidenerPath = file("src/main/resources/ryansRenderingKit.accesswidener")
}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5e50ffa
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,93 @@
+
+ 4.0.0
+
+
+ io.github.hotpad100c
+ ryansrenderingkit
+ 1.0.0
+ Ryan's Rendering Kit
+ A Fabric-based rendering toolkit for Minecraft
+ https://github.com/hotpad100c/ryansrenderingkit
+
+
+
+ 21
+ 21
+ UTF-8
+
+
+ true
+
+
+
+
+
+ github
+ GitHub Packages
+ https://maven.pkg.github.com/hotpad100c/ryansrenderingkit
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.3.0
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.6.0
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ 21
+
+
+
+
+
+
+
diff --git a/src/main/java/mypals/ml/Helpers.java b/src/main/java/mypals/ml/Helpers.java
index 2cf88ed..e2c799f 100644
--- a/src/main/java/mypals/ml/Helpers.java
+++ b/src/main/java/mypals/ml/Helpers.java
@@ -1,7 +1,22 @@
package mypals.ml;
+import java.util.Arrays;
+import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
+
+import com.mojang.blaze3d.vertex.*;
+import com.mojang.math.Axis;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.ShapeRenderer;
+import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.level.block.entity.SignText;
+import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+import org.joml.Quaternionf;
+import org.joml.Vector3f;
+import org.joml.Vector4f;
import static mypals.ml.RyansRenderingKit.MOD_ID;
@@ -11,4 +26,115 @@ public static ResourceLocation generateUniqueId(String prefix) {
int randomNum = ThreadLocalRandom.current().nextInt(10000);
return ResourceLocation.fromNamespaceAndPath(MOD_ID,prefix.toLowerCase() +"_"+ timestamp + "_" + randomNum);
}
+ public static Vec3 max(Vec3 a, Vec3 b) {
+ return new Vec3(
+ Math.max(a.x, b.x),
+ Math.max(a.y, b.y),
+ Math.max(a.z, b.z)
+ );
+ }
+
+ public static Vec3 min(Vec3 a, Vec3 b) {
+ return new Vec3(
+ Math.min(a.x, b.x),
+ Math.min(a.y, b.y),
+ Math.min(a.z, b.z)
+ );
+ }
+ public static Vec3 calculateCentroid(List vertices) {
+ double sumX = 0, sumY = 0, sumZ = 0;
+ for (Vec3 v : vertices) {
+ sumX += v.x;
+ sumY += v.y;
+ sumZ += v.z;
+ }
+ double n = vertices.size();
+ return new Vec3(sumX / n, sumY / n, sumZ / n);
+ }
+ public static Matrix4f createViewMatrix(Camera camera) {
+ Matrix4f view = new Matrix4f();
+
+ Quaternionf camRot = camera.rotation();
+ Quaternionf camRotInv = new Quaternionf(camRot).conjugate();
+ view.rotation(camRotInv);
+
+ Vec3 camPos = camera.getPosition();
+ view.translate(new Vector3f(
+ (float) -camPos.x,
+ (float) -camPos.y,
+ (float) -camPos.z
+ ));
+
+ return view;
+ }
+ public static boolean isVertexInFrustum(Vec3 v, Matrix4f mvp) {
+ Vector4f clip = new Vector4f((float)v.x, (float)v.y, (float)v.z, 1f);
+ clip.mul(mvp);
+ if (clip.w <= 0) return false;
+ float ndcX = clip.x / clip.w;
+ float ndcY = clip.y / clip.w;
+ float ndcZ = clip.z / clip.w;
+
+ return ndcX >= -1 && ndcX <= 1 &&
+ ndcY >= -1 && ndcY <= 1 &&
+ ndcZ >= -1 && ndcZ <= 1;
+ }
+ public static int multiplyRGB(int color, float shade) {
+ int alpha = color >>> 24 & 255;
+ int red = (int)((float)(color >>> 16 & 255) * shade);
+ int green = (int)((float)(color >>> 8 & 255) * shade);
+ int blue = (int)((float)(color & 255) * shade);
+ return alpha << 24 | red << 16 | green << 8 | blue;
+ }
+ public static void renderLineBox(PoseStack poseStack, VertexConsumer consumer,
+ Vec3 center, float size,
+ float red, float green, float blue, float alpha) {
+
+ double half = size / 2.0;
+
+ ShapeRenderer.renderLineBox(
+ poseStack, consumer,
+ center.x - half, center.y - half, center.z - half,
+ center.x + half, center.y + half, center.z + half,
+ red, green, blue,
+ alpha, red, green,
+ blue
+ );
+ }
+ public static void renderBillboardFrame(
+ PoseStack poseStack,
+ VertexConsumer vc,
+ Vec3 vec3,
+ float size,
+ float r, float g, float b, float a
+ ) {
+ poseStack.pushPose();
+ poseStack.translate(vec3);
+
+ Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
+
+ poseStack.mulPose(Axis.YP.rotationDegrees(-camera.getYRot()));
+ poseStack.mulPose(Axis.XP.rotationDegrees(camera.getXRot()));
+
+ PoseStack.Pose pose = poseStack.last();
+
+ float s = size / 2f;
+
+ Vec3 v1 = new Vec3(-s, -s, 0);
+ Vec3 v2 = new Vec3(s, -s, 0);
+ Vec3 v3 = new Vec3(s, s, 0);
+ Vec3 v4 = new Vec3(-s, s, 0);
+
+ Vec3 n = new Vec3(0, 0, -1);
+
+ addLine(pose, vc, v1, v2, r, g, b, a, n);
+ addLine(pose, vc, v2, v3, r, g, b, a, n);
+ addLine(pose, vc, v3, v4, r, g, b, a, n);
+ addLine(pose, vc, v4, v1, r, g, b, a, n);
+ poseStack.popPose();
+ }
+ private static void addLine(PoseStack.Pose pose, VertexConsumer vc, Vec3 a, Vec3 b, float r, float g, float b2, float a2, Vec3 normal) {
+ vc.addVertex(pose, (float)a.x, (float)a.y, (float)a.z).setColor(r, g, b2, a2).setNormal(pose, (float)normal.x, (float)normal.y, (float)normal.z);
+ vc.addVertex(pose, (float)b.x, (float)b.y, (float)b.z).setColor(r, g, b2, a2).setNormal(pose, (float)normal.x, (float)normal.y, (float)normal.z);
+ }
}
diff --git a/src/main/java/mypals/ml/RyansRenderingKit.java b/src/main/java/mypals/ml/RyansRenderingKit.java
index a84c7bd..4eadfa3 100644
--- a/src/main/java/mypals/ml/RyansRenderingKit.java
+++ b/src/main/java/mypals/ml/RyansRenderingKit.java
@@ -7,43 +7,33 @@
import mypals.ml.test.Tester;
import net.fabricmc.api.ModInitializer;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static mypals.ml.test.Tester.registerDebugCommands;
+
public class RyansRenderingKit implements ModInitializer {
public static final String MOD_ID = "ryansrenderingkit";
- // This logger is used to write text to the console and the log file.
- // It is considered best practice to use your mod id as the logger's name.
- // That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override
public void onInitialize() {
- // This code runs as soon as Minecraft is in a mod-load-ready state.
- // However, some things (like resources) may still be uninitialized.
- // Proceed with mild caution.
BuilderManagers.init();
ShapeManagers.init();
VertexBuilderGetter.init();
- WorldRenderEvents.AFTER_TRANSLUCENT.register(this::handleRenderFabulous);
WorldRenderEvents.LAST.register(this::handleRenderLast);
ClientTickEvents.END_WORLD_TICK.register(c-> ShapeManagers.syncShapeTransform());
-
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> {
+ registerDebugCommands(dispatcher);
+ });
Tester.init();
-
- LOGGER.info("Hello Fabric world!");
}
- private void handleRenderFabulous(WorldRenderContext ctx) {
- //if (!ctx.advancedTranslucency()) return;
- //InformationRender.render(ctx.matrixStack(), ctx.camera(),ctx.tickCounter().getGameTimeDeltaPartialTick(true));
- }
-
private void handleRenderLast(WorldRenderContext ctx) {
- //if (ctx.advancedTranslucency()) return;
InformationRender.render(ctx.matrixStack(), ctx.camera(),ctx.tickCounter().getGameTimeDeltaPartialTick(true));
}
}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/builderManager/BuilderManager.java b/src/main/java/mypals/ml/builderManager/BuilderManager.java
index 2148be9..82ae8af 100644
--- a/src/main/java/mypals/ml/builderManager/BuilderManager.java
+++ b/src/main/java/mypals/ml/builderManager/BuilderManager.java
@@ -1,5 +1,6 @@
package mypals.ml.builderManager;
+import com.mojang.blaze3d.vertex.PoseStack;
import mypals.ml.builders.vertexBuilders.BatchVertexBuilder;
import mypals.ml.builders.vertexBuilders.BufferedVertexBuilder;
import mypals.ml.builders.vertexBuilders.ImmediateVertexBuilder;
@@ -38,7 +39,7 @@ public BuilderGroup(Matrix4f matrix,boolean seeThrough,RenderMethod renderMethod
public void drawBatch(Consumer builder, RenderMethod renderMethod){
batchVertexBuilder.beginBatch(renderMethod);
builder.accept(batchVertexBuilder);
- batchVertexBuilder.drawBatch();
+ batchVertexBuilder.drawBatch(renderMethod);
}
public void drawImmediate(Shape shape, Consumer builder, RenderMethod renderMethod){
immediateShapeBuilder.draw(shape,builder,renderMethod);
@@ -73,7 +74,7 @@ public void rebuildVBO(Collection shapeList, boolean seeThrough){
sortedShapes.sort(SHAPE_ORDER_COMPARATOR);
for(Shape shape: sortedShapes){
- shape.draw(builder);
+ shape.draw(false, builder,new PoseStack(),1);
}
});
else normalBuilderGroup.bufferedVertexBuilder.rebuild(renderMethod, builder->{
@@ -82,7 +83,7 @@ public void rebuildVBO(Collection shapeList, boolean seeThrough){
sortedShapes.sort(SHAPE_ORDER_COMPARATOR);
for(Shape shape: sortedShapes){
- shape.draw(builder);
+ shape.draw(false, builder,new PoseStack(),1);
}
});
}
diff --git a/src/main/java/mypals/ml/builderManager/BuilderManagers.java b/src/main/java/mypals/ml/builderManager/BuilderManagers.java
index 6f16485..6f2fdfb 100644
--- a/src/main/java/mypals/ml/builderManager/BuilderManagers.java
+++ b/src/main/java/mypals/ml/builderManager/BuilderManagers.java
@@ -1,5 +1,4 @@
package mypals.ml.builderManager;
-
import mypals.ml.render.RenderMethod;
import org.joml.Matrix4f;
@@ -7,32 +6,36 @@
import java.util.List;
public class BuilderManagers {
- public static BuilderManager QUADS_BUILDER_MANAGER = null;
public static BuilderManager LINES_BUILDER_MANAGER = null;
public static BuilderManager LINE_STRIP_BUILDER_MANAGER = null;
public static BuilderManager TRIANGLES_BUILDER_MANAGER = null;
- public static BuilderManager TRIANGLES_STRIP_BUILDER_MANAGER = null;
- public static BuilderManager TRIANGLES_FAN_BUILDER_MANAGER = null;
- public static BuilderManager TEXT = null;
+ public static EmptyBuilderManager NON_SHAPE_OBJECTS = null;
public static List builders = new ArrayList<>();
+ public static List emptyBuilders = new ArrayList<>();
public static void init() {
Matrix4f matrix4f = new Matrix4f();
- QUADS_BUILDER_MANAGER = register(matrix4f,RenderMethod.QUADS,"quads_builder_manager");
LINES_BUILDER_MANAGER = register(matrix4f, RenderMethod.LINES,"lines_builder_manager");
LINE_STRIP_BUILDER_MANAGER = register(matrix4f,RenderMethod.LINE_STRIP,"line_strip_builder_manager");
TRIANGLES_BUILDER_MANAGER = register(matrix4f,RenderMethod.TRIANGLES,"triangles_builder_manager");
- TRIANGLES_STRIP_BUILDER_MANAGER = register(matrix4f,RenderMethod.TRIANGLES_STRIP,"triangles_strip_builder_manager");
- TRIANGLES_FAN_BUILDER_MANAGER = register(matrix4f,RenderMethod.TRIANGLES_FAN,"triangles_fan_builder_manager");
- TEXT = register(matrix4f,RenderMethod.TEXT,"text_manager");
+ NON_SHAPE_OBJECTS = registerEmpty(matrix4f,"empty");
}
public static void updateMatrix(Matrix4f matrix4f){
for(BuilderManager builderManager : builders){
builderManager.updateMatrix(matrix4f);
}
+ for(EmptyBuilderManager builderManager : emptyBuilders){
+ builderManager.updateMatrix(matrix4f);
+ }
}
+
public static BuilderManager register(Matrix4f matrix4f, RenderMethod renderMethod,String id){
BuilderManager builderManager = new BuilderManager(matrix4f,renderMethod,id);
builders.add(builderManager);
return builderManager;
}
+ public static EmptyBuilderManager registerEmpty(Matrix4f matrix4f, String id){
+ EmptyBuilderManager builderManager = new EmptyBuilderManager(matrix4f,id);
+ emptyBuilders.add(builderManager);
+ return builderManager;
+ }
}
diff --git a/src/main/java/mypals/ml/builderManager/EmptyBuilderManager.java b/src/main/java/mypals/ml/builderManager/EmptyBuilderManager.java
new file mode 100644
index 0000000..94852e3
--- /dev/null
+++ b/src/main/java/mypals/ml/builderManager/EmptyBuilderManager.java
@@ -0,0 +1,33 @@
+package mypals.ml.builderManager;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import mypals.ml.builders.vertexBuilders.*;
+import mypals.ml.render.RenderMethod;
+import mypals.ml.shape.Shape;
+import net.minecraft.client.Camera;
+import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static mypals.ml.shapeManagers.ShapeManager.SHAPE_ORDER_COMPARATOR;
+
+public class EmptyBuilderManager{
+ public String id;
+ public EmptyVertexBuilder emptyVertexBuilder;;
+ public EmptyBuilderManager(Matrix4f matrix4f, String id){
+ this.id = id;
+ emptyVertexBuilder = new EmptyVertexBuilder(matrix4f);
+ }
+
+ public void draw(Consumer builder){
+ emptyVertexBuilder.draw(builder);
+ }
+ public void updateMatrix(Matrix4f modelViewMatrix){
+ emptyVertexBuilder.setPositionMatrix(modelViewMatrix);
+ }
+}
+
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/BaseBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/BaseBuilder.java
index 3dc9f56..5de562f 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/BaseBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/BaseBuilder.java
@@ -5,6 +5,7 @@
import java.awt.*;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public abstract class BaseBuilder, R> implements ShapeBuilder {
@@ -12,7 +13,7 @@ public abstract class BaseBuilder, R> implements Sha
protected Color color = Color.WHITE;
protected boolean seeThrough = false;
- private TransformerSupplier transformerSupplier = () -> (t, s) -> {};
+ private TransformerSupplier transformerSupplier = () ->(t)-> {};
@SuppressWarnings("unchecked")
protected T self() {
@@ -24,7 +25,7 @@ protected T self() {
public T color(int color) {return this.color(new Color(color)); }
@Override public T seeThrough(boolean seeThrough) { this.seeThrough = seeThrough; return self(); }
- public T transform(BiConsumer transformer) {
+ public T transform(Consumer transformer) {
this.transformerSupplier = () -> transformer;
return self();
}
@@ -34,7 +35,7 @@ public T transform(TransformerSupplier supplier) {
return self();
}
- protected BiConsumer getTransformer() {
+ protected Consumer getTransformer() {
return transformerSupplier.get();
}
@@ -42,6 +43,6 @@ protected BiConsumer getTransformer() {
@FunctionalInterface
public interface TransformerSupplier {
- BiConsumer get();
+ Consumer get();
}
}
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/BoxFaceBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/BoxFaceBuilder.java
index 800198e..09baf69 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/BoxFaceBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/BoxFaceBuilder.java
@@ -21,7 +21,7 @@ public class BoxFaceBuilder extends BaseBuilder {
+public class ObjModelBuilder extends BaseBuilder {
private ResourceLocation resourceLocation;
public ObjModelBuilder model(ResourceLocation resourceLocation) {
@@ -15,7 +16,7 @@ public ObjModelBuilder model(ResourceLocation resourceLocation) {
}
@Override
- public Shape build(Shape.RenderingType type) {
+ public ObjModelShape build(Shape.RenderingType type) {
@SuppressWarnings("unchecked")
var t = getTransformer();
return new ObjModelShape(type, t, resourceLocation, center, color, seeThrough);
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/ObjModelOutlineBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/ObjModelOutlineBuilder.java
index c6f7600..2677d86 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/ObjModelOutlineBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/ObjModelOutlineBuilder.java
@@ -5,9 +5,7 @@
import mypals.ml.shape.model.ObjModelShapeOutline;
import net.minecraft.resources.ResourceLocation;
-import java.util.function.BiConsumer;
-
-public class ObjModelOutlineBuilder extends BaseBuilder {
+public class ObjModelOutlineBuilder extends BaseBuilder {
private ResourceLocation resourceLocation;
private float lineWidth = 1.0f;
@@ -21,7 +19,7 @@ public ObjModelOutlineBuilder lineWidth(float lineWidth) {
}
@Override
- public Shape build(Shape.RenderingType type) {
+ public ObjModelShapeOutline build(Shape.RenderingType type) {
@SuppressWarnings("unchecked")
var t = getTransformer();
return new ObjModelShapeOutline(type, t, resourceLocation, center, lineWidth, color, seeThrough);
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/ShapeGenerator.java b/src/main/java/mypals/ml/builders/shapeBuilders/ShapeGenerator.java
index 49ee337..0c7db32 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/ShapeGenerator.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/ShapeGenerator.java
@@ -3,6 +3,9 @@
public final class ShapeGenerator {
private ShapeGenerator() {}
+ public static TextBuilder generateText() {
+ return new TextBuilder();
+ }
public static FaceCircleBuilder generateFaceCircle() {
return new FaceCircleBuilder();
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/SphereBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/SphereBuilder.java
index d78edde..ca8c166 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/SphereBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/SphereBuilder.java
@@ -1,23 +1,22 @@
package mypals.ml.builders.shapeBuilders;
import mypals.ml.shape.Shape;
+import mypals.ml.shape.round.FaceCircleShape;
import mypals.ml.shape.round.SphereShape;
import java.util.function.BiConsumer;
-public class SphereBuilder extends BaseBuilder {
- private SphereShape.SphereMode mode = SphereShape.SphereMode.UV;
+public class SphereBuilder extends BaseBuilder {
private int segments = 32;
private float radius = 1.0f;
- public SphereBuilder mode(SphereShape.SphereMode mode) { this.mode = mode; return this; }
public SphereBuilder segments(int segments) { this.segments = segments; return this; }
public SphereBuilder radius(float radius) { this.radius = radius; return this; }
@Override
- public Shape build(Shape.RenderingType type) {
+ public SphereShape build(Shape.RenderingType type) {
@SuppressWarnings("unchecked")
var t = getTransformer();
- return new SphereShape(type, t, mode, center, segments, radius, color, seeThrough);
+ return new SphereShape(type, t, center, segments, radius, color, seeThrough);
}
}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/StripLineBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/StripLineBuilder.java
index f051de7..b748eba 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/StripLineBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/StripLineBuilder.java
@@ -8,9 +8,8 @@
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.BiConsumer;
-public class StripLineBuilder extends BaseBuilder {
+public class StripLineBuilder extends BaseBuilder {
private final List vertexes = new ArrayList<>();
private final List colors = new ArrayList<>();
private float lineWidth = 1.0f;
@@ -21,7 +20,7 @@ public class StripLineBuilder extends BaseBuilder {
+
+ private Shape.RenderingType type = Shape.RenderingType.IMMEDIATE;
+ private List texts = new ArrayList<>();
+ private List textColors = new ArrayList<>();
+ private TextShape.BillBoardMode billBoardMode = TextShape.BillBoardMode.FIXED;
+ private boolean shadow = true;
+ private boolean outline = false;
+
+
+ public TextBuilder type(Shape.RenderingType type) {
+ this.type = type;
+ return this;
+ }
+
+ public TextBuilder texts(List texts) {
+ this.texts = new ArrayList<>(texts);
+ return this;
+ }
+
+ public TextBuilder texts(String... texts) {
+ this.texts = Arrays.asList(texts);
+ return this;
+ }
+
+ public TextBuilder addText(String text) {
+ this.texts.add(text);
+ return this;
+ }
+
+ public TextBuilder addText(String text, Color color) {
+ this.texts.add(text);
+ this.textColors.add(color);
+ return this;
+ }
+
+ public TextBuilder textColors(List colors) {
+ this.textColors = new ArrayList<>(colors);
+ return this;
+ }
+
+ public TextBuilder textColors(Color... colors) {
+ this.textColors = Arrays.asList(colors);
+ return this;
+ }
+
+ public TextBuilder billBoardMode(TextShape.BillBoardMode mode) {
+ this.billBoardMode = mode != null ? mode : TextShape.BillBoardMode.FIXED;
+ return this;
+ }
+
+ public TextBuilder shadow(boolean shadow) {
+ this.shadow = shadow;
+ return this;
+ }
+
+ public TextBuilder outline(boolean outline) {
+ this.outline = outline;
+ return this;
+ }
+
+ @Override
+ public TextShape build(Shape.RenderingType type) {
+ this.type = type;
+ if (textColors.isEmpty() || textColors.size() < texts.size()) {
+ List colors = new ArrayList<>(texts.size());
+ colors.addAll(textColors);
+ while (colors.size() < texts.size()) {
+ colors.add(Color.WHITE);
+ }
+ textColors = colors;
+ }
+
+ return new TextShape(
+ this.type,
+ getTransformer(),
+ center,
+ Collections.unmodifiableList(texts),
+ Collections.unmodifiableList(textColors),
+ billBoardMode,
+ seeThrough,
+ shadow,
+ outline
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/builders/shapeBuilders/WireframedBoxBuilder.java b/src/main/java/mypals/ml/builders/shapeBuilders/WireframedBoxBuilder.java
index 0ff73fc..3934a4b 100644
--- a/src/main/java/mypals/ml/builders/shapeBuilders/WireframedBoxBuilder.java
+++ b/src/main/java/mypals/ml/builders/shapeBuilders/WireframedBoxBuilder.java
@@ -31,7 +31,7 @@ public class WireframedBoxBuilder extends BaseBuilder builder) {
public void draw(Shape shape, Consumer builder, RenderMethod renderMethod) {
beginBatch(renderMethod);
push(builder);
- drawBatch();
+ drawBatch(renderMethod);
}
- public void drawBatch() {
- if (!isBuilding) {
+ public void drawBatch(RenderMethod renderMethod) {
+ if (!isBuilding || this.getBufferBuilder().vertices == 0) {
return;
}
+ //flushTransparent();
- setUpRendererSystem(null);
-
- MeshData builtBuffer = this.getBufferBuilder().buildOrThrow();
- BufferUploader.drawWithShader(builtBuffer);
+ MeshData builtBuffer = this.getBufferBuilder().build();
+ if(builtBuffer!=null){
+ ByteBufferBuilder byteBufferBuilder = null;
+ if(renderMethod.mode() == VertexFormat.Mode.TRIANGLES){
+ int vertexCount = builtBuffer.drawState().vertexCount();
+ int bufferSize = vertexCount * Integer.BYTES;
+ byteBufferBuilder = new ByteBufferBuilder(bufferSize);
+ ((MeshDataExt)builtBuffer).ryansrenderingkit$sortTriangles(byteBufferBuilder, RenderSystem.getProjectionType().vertexSorting());
+ }
+ setUpRendererSystem(null);
+ BufferUploader.drawWithShader(builtBuffer);
+ if(byteBufferBuilder != null){
+ byteBufferBuilder.close();
+ }
+ builtBuffer.close();
+ restoreRendererSystem();
+ }
- restoreRendererSystem();
isBuilding = false;
}
diff --git a/src/main/java/mypals/ml/builders/vertexBuilders/BufferedVertexBuilder.java b/src/main/java/mypals/ml/builders/vertexBuilders/BufferedVertexBuilder.java
index 6ffab61..71444fc 100644
--- a/src/main/java/mypals/ml/builders/vertexBuilders/BufferedVertexBuilder.java
+++ b/src/main/java/mypals/ml/builders/vertexBuilders/BufferedVertexBuilder.java
@@ -2,8 +2,11 @@
import com.mojang.blaze3d.buffers.BufferUsage;
import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.MeshData;
import com.mojang.blaze3d.vertex.VertexBuffer;
+import com.mojang.blaze3d.vertex.VertexFormat;
+import mypals.ml.interfaces.MeshDataExt;
import mypals.ml.render.RenderMethod;
import net.minecraft.world.phys.Vec3;
import org.joml.Matrix4f;
@@ -24,7 +27,8 @@ public BufferedVertexBuilder(Matrix4f modelViewMatrix, boolean seeThrough, Rende
public void rebuild(RenderMethod renderMethod, Consumer builder) {
start(renderMethod);
push(builder);
- end();
+ //flushTransparent();
+ end(renderMethod);
}
public void start(RenderMethod renderMethod) {
@@ -43,8 +47,8 @@ public void push(Consumer builder) {
}
}
- public void end() {
- if (!isBuilding) {
+ public void end(RenderMethod renderMethod) {
+ if (!isBuilding || this.getBufferBuilder().vertices == 0) {
return;
}
@@ -55,8 +59,18 @@ public void end() {
isBuilding = false;
return;
}
-
+ ByteBufferBuilder byteBufferBuilder = null;
+ if(renderMethod.mode() == VertexFormat.Mode.TRIANGLES){
+ int vertexCount = builtBuffer.drawState().vertexCount();
+ int bufferSize = vertexCount * Integer.BYTES;
+ byteBufferBuilder = new ByteBufferBuilder(bufferSize);
+ ((MeshDataExt)builtBuffer).ryansrenderingkit$sortTriangles(byteBufferBuilder,RenderSystem.getProjectionType().vertexSorting());
+ }
this.vertexBuffer.upload(builtBuffer);
+ if(byteBufferBuilder != null){
+ byteBufferBuilder.close();
+ }
+ builtBuffer.close();
VertexBuffer.unbind();
isBuilding = false;
}
diff --git a/src/main/java/mypals/ml/builders/vertexBuilders/EmptyVertexBuilder.java b/src/main/java/mypals/ml/builders/vertexBuilders/EmptyVertexBuilder.java
new file mode 100644
index 0000000..b4458c8
--- /dev/null
+++ b/src/main/java/mypals/ml/builders/vertexBuilders/EmptyVertexBuilder.java
@@ -0,0 +1,13 @@
+package mypals.ml.builders.vertexBuilders;
+import org.joml.Matrix4f;
+import java.util.function.Consumer;
+
+public class EmptyVertexBuilder extends VertexBuilder {
+
+ public EmptyVertexBuilder(Matrix4f modelViewMatrix) {
+ super(modelViewMatrix, false);
+ }
+ public void draw(Consumer vertexBuilderConsumer) {
+ vertexBuilderConsumer.accept(this);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/builders/vertexBuilders/ImmediateVertexBuilder.java b/src/main/java/mypals/ml/builders/vertexBuilders/ImmediateVertexBuilder.java
index 261a8e8..421881a 100644
--- a/src/main/java/mypals/ml/builders/vertexBuilders/ImmediateVertexBuilder.java
+++ b/src/main/java/mypals/ml/builders/vertexBuilders/ImmediateVertexBuilder.java
@@ -2,7 +2,10 @@
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferUploader;
+import com.mojang.blaze3d.vertex.ByteBufferBuilder;
import com.mojang.blaze3d.vertex.MeshData;
+import com.mojang.blaze3d.vertex.VertexFormat;
+import mypals.ml.interfaces.MeshDataExt;
import mypals.ml.render.RenderMethod;
import mypals.ml.shape.Shape;
import org.joml.Matrix4f;
@@ -15,16 +18,33 @@ public ImmediateVertexBuilder(Matrix4f modelViewMatrix, boolean seeThrough) {
super(modelViewMatrix, seeThrough);
}
- public void draw(Shape shape, Consumer builder, RenderMethod renderMethod) {
+ public void draw(Shape shape, Consumer vertexBuilderConsumer, RenderMethod renderMethod) {
begin(renderMethod);
RenderSystem.setShader(renderMethod.shader());
- builder.accept(this);
-
- setUpRendererSystem(shape);
-
- MeshData builtBuffer = this.getBufferBuilder().buildOrThrow();
- BufferUploader.drawWithShader(builtBuffer);
-
- restoreRendererSystem();
+ vertexBuilderConsumer.accept(this);
+
+ if(this.getBufferBuilder().vertices == 0){
+ return;
+ }
+ MeshData meshData = this.getBufferBuilder().build();
+
+ if(meshData!=null){
+ ByteBufferBuilder byteBufferBuilder = null;
+
+ if(shape.baseColor.getAlpha() < 255 && renderMethod.mode() == VertexFormat.Mode.TRIANGLES){
+ int vertexCount = meshData.drawState().vertexCount();
+ int bufferSize = vertexCount * Integer.BYTES;
+ byteBufferBuilder = new ByteBufferBuilder(bufferSize);
+
+ ((MeshDataExt)meshData).ryansrenderingkit$sortTriangles(byteBufferBuilder,RenderSystem.getProjectionType().vertexSorting());
+ }
+ setUpRendererSystem(shape);
+ BufferUploader.drawWithShader(meshData);
+ if(byteBufferBuilder != null){
+ byteBufferBuilder.close();
+ }
+ meshData.close();
+ restoreRendererSystem();
+ }
}
}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/builders/vertexBuilders/VertexBuilder.java b/src/main/java/mypals/ml/builders/vertexBuilders/VertexBuilder.java
index 6240d45..dbea40e 100644
--- a/src/main/java/mypals/ml/builders/vertexBuilders/VertexBuilder.java
+++ b/src/main/java/mypals/ml/builders/vertexBuilders/VertexBuilder.java
@@ -64,11 +64,6 @@ public float[] toARGB(Color color) {
colors[3] = (argb & 0xFF) / 255f;
return colors;
}
-
- protected boolean shouldApplyNormal(RenderMethod renderMethod) {
- return renderMethod == RenderMethod.LINES || renderMethod == RenderMethod.LINE_STRIP;
- }
-
public void putVertex(Vector3f v, float r, float g, float b, float a) {
this.bufferBuilder.addVertex(positionMatrix, v.x, v.y, v.z).setColor(r, g, b, a);
}
diff --git a/src/main/java/mypals/ml/collision/RayModelIntersection.java b/src/main/java/mypals/ml/collision/RayModelIntersection.java
new file mode 100644
index 0000000..bb85e5e
--- /dev/null
+++ b/src/main/java/mypals/ml/collision/RayModelIntersection.java
@@ -0,0 +1,104 @@
+package mypals.ml.collision;
+
+import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public class RayModelIntersection {
+ private static final double EPSILON = 1e-6;
+
+
+ public static class Ray {
+ public Vec3 origin;
+ public Vec3 direction;
+
+ public Ray(Vec3 origin, Vec3 direction) {
+ this.origin = origin;
+ this.direction = direction.normalize();
+ }
+ }
+ public static class HitResult {
+ public boolean hit;
+ @Nullable
+ public Vec3 pos;
+ public double distance;
+
+ public HitResult(boolean hit, @Nullable Vec3 pos, double distance) {
+ this.hit = hit;
+ this.pos = pos;
+ this.distance = distance;
+ }
+ }
+
+ public static boolean intersectTriangle(Ray ray, Vec3 v0, Vec3 v1, Vec3 v2, double[] outT) {
+
+
+ Vec3 e1 = v1.subtract(v0);
+ Vec3 e2 = v2.subtract(v0);
+ Vec3 P = ray.direction.cross(e2);
+ double det = e1.dot(P);
+
+ if (Math.abs(det) < EPSILON) return false;
+
+ double invDet = 1.0 / det;
+ Vec3 T = ray.origin.subtract(v0);
+
+ double u = T.dot(P) * invDet;
+ if (u < 0.0 || u > 1.0) return false;
+
+ Vec3 Q = T.cross(e1);
+ double v = ray.direction.dot(Q) * invDet;
+ if (v < 0.0 || u + v > 1.0) return false;
+
+ double t = e2.dot(Q) * invDet;
+ if (t < EPSILON) return false;
+
+ if (outT != null) outT[0] = t;
+ return true;
+ }
+
+ public static HitResult rayIntersectsModel(
+ Ray ray,
+ List modelVertexes,
+ int[] indexBuffer) {
+
+ double closestT = Double.POSITIVE_INFINITY;
+ Vec3 closestHitVec3d = null;
+ boolean hit = false;
+
+ for (int i = 0; i < indexBuffer.length; i += 3) {
+ int i0 = indexBuffer[i];
+ int i1 = indexBuffer[i + 1];
+ int i2 = indexBuffer[i + 2];
+ if (i0 >= modelVertexes.size() || i1 >= modelVertexes.size() || i2 >= modelVertexes.size()) {
+ continue;
+ }
+
+ Vec3 v0 = modelVertexes.get(i0);
+ Vec3 v1 = modelVertexes.get(i1);
+ Vec3 v2 = modelVertexes.get(i2);
+
+ double[] tOut = new double[1];
+ if (intersectTriangle(ray, v0, v1, v2, tOut)) {
+ double t = tOut[0];
+ if (t < closestT) {
+ closestT = t;
+ closestHitVec3d = ray.origin.add(ray.direction.scale(t));
+ hit = true;
+ }
+ }
+ }
+
+ if (!hit) {
+ return new HitResult(hit,null, -1);
+ }
+
+ Vec3 hitPoint = new Vec3(
+ (float) closestHitVec3d.x,
+ (float) closestHitVec3d.y,
+ (float) closestHitVec3d.z
+ );
+ return new HitResult(hit,hitPoint, closestT);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/interfaces/MeshDataExt.java b/src/main/java/mypals/ml/interfaces/MeshDataExt.java
new file mode 100644
index 0000000..98cb0f6
--- /dev/null
+++ b/src/main/java/mypals/ml/interfaces/MeshDataExt.java
@@ -0,0 +1,12 @@
+package mypals.ml.interfaces;
+
+import com.mojang.blaze3d.vertex.ByteBufferBuilder;
+import com.mojang.blaze3d.vertex.MeshData;
+import com.mojang.blaze3d.vertex.VertexSorting;
+
+public interface MeshDataExt {
+ void ryansrenderingkit$sortTriangles(ByteBufferBuilder byteBufferBuilder, VertexSorting vertexSorting);
+ interface MeshDataSortableExt {
+ ByteBufferBuilder.Result ryansrenderingkit$buildSortedIndexBufferTriangles(ByteBufferBuilder byteBufferBuilder, VertexSorting vertexSorting);
+ }
+}
diff --git a/src/main/java/mypals/ml/mixin/KeyBoardMixin.java b/src/main/java/mypals/ml/mixin/KeyBoardMixin.java
new file mode 100644
index 0000000..142a0c1
--- /dev/null
+++ b/src/main/java/mypals/ml/mixin/KeyBoardMixin.java
@@ -0,0 +1,4 @@
+package mypals.ml.mixin;
+
+public class KeyBoardMixin {
+}
diff --git a/src/main/java/mypals/ml/mixin/MeshDataMixin.java b/src/main/java/mypals/ml/mixin/MeshDataMixin.java
new file mode 100644
index 0000000..530200f
--- /dev/null
+++ b/src/main/java/mypals/ml/mixin/MeshDataMixin.java
@@ -0,0 +1,92 @@
+package mypals.ml.mixin;
+
+import com.mojang.blaze3d.vertex.*;
+import mypals.ml.interfaces.MeshDataExt;
+import org.jetbrains.annotations.Nullable;
+import org.joml.Vector3f;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.Unique;
+
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.util.function.IntConsumer;
+
+@Mixin(MeshData.class)
+public abstract class MeshDataMixin implements MeshDataExt {
+ @Shadow @Nullable private ByteBufferBuilder.Result indexBuffer;
+
+ @Shadow @Final private ByteBufferBuilder.Result vertexBuffer;
+
+ @Shadow @Final private MeshData.DrawState drawState;
+
+ @Unique
+ private static Vector3f[] unpackTriangleCentroids(ByteBuffer byteBuffer, int vertexCount, VertexFormat vertexFormat) {
+ int posOffset = vertexFormat.getOffset(VertexFormatElement.POSITION);
+ if (posOffset == -1) {
+ throw new IllegalArgumentException("Cannot identify triangle centers with no position element");
+ }
+
+ FloatBuffer fb = byteBuffer.asFloatBuffer();
+ int floatsPerVertex = vertexFormat.getVertexSize() / 4;
+ int triangles = vertexCount / 3;
+ Vector3f[] centroids = new Vector3f[triangles];
+
+ for (int t = 0; t < triangles; t++) {
+ int base = t * floatsPerVertex * 3 + posOffset;
+ float x0 = fb.get(base);
+ float y0 = fb.get(base + 1);
+ float z0 = fb.get(base + 2);
+
+ int b1 = base + floatsPerVertex;
+ float x1 = fb.get(b1);
+ float y1 = fb.get(b1 + 1);
+ float z1 = fb.get(b1 + 2);
+
+ int b2 = base + floatsPerVertex * 2;
+ float x2 = fb.get(b2);
+ float y2 = fb.get(b2 + 1);
+ float z2 = fb.get(b2 + 2);
+
+ centroids[t] = new Vector3f((x0 + x1 + x2) / 3f, (y0 + y1 + y2) / 3f, (z0 + z1 + z2) / 3f);
+ }
+
+ return centroids;
+ }
+
+
+ @Unique
+ public void ryansrenderingkit$sortTriangles(ByteBufferBuilder byteBufferBuilder,VertexSorting vertexSorting) {
+
+ Vector3f[] compactVectorArray = unpackTriangleCentroids(this.vertexBuffer.byteBuffer(), this.drawState.vertexCount(), this.drawState.format());
+ MeshData.SortState sortState = new MeshData.SortState(compactVectorArray, this.drawState.indexType());
+ this.indexBuffer = ((MeshDataSortableExt)(Object)sortState).ryansrenderingkit$buildSortedIndexBufferTriangles(byteBufferBuilder, vertexSorting);
+ }
+ @Mixin(MeshData.SortState.class)
+ public static abstract class SortStateMixin implements MeshDataSortableExt{
+ @Shadow protected abstract it.unimi.dsi.fastutil.ints.IntConsumer indexWriter(long l, VertexFormat.IndexType indexType);
+
+ @Shadow @Final private VertexFormat.IndexType indexType;
+
+ @Shadow @Final private Vector3f[] centroids;
+
+ @Unique
+ public ByteBufferBuilder.Result ryansrenderingkit$buildSortedIndexBufferTriangles(ByteBufferBuilder byteBufferBuilder, VertexSorting vertexSorting) {
+ int[] sortedTriangleIndices = vertexSorting.sort(this.centroids);
+
+ long offset = byteBufferBuilder.reserve(sortedTriangleIndices.length * 3 * this.indexType.bytes);
+ IntConsumer intConsumer = this.indexWriter(offset, this.indexType);
+
+ for (int i : sortedTriangleIndices) {
+ int baseVertex = i * 3;
+ intConsumer.accept(baseVertex);
+ intConsumer.accept(baseVertex + 1);
+ intConsumer.accept(baseVertex + 2);
+ }
+
+ return byteBufferBuilder.build();
+ }
+
+ }
+}
diff --git a/src/main/java/mypals/ml/render/InformationRender.java b/src/main/java/mypals/ml/render/InformationRender.java
index 8fe65a8..73135a1 100644
--- a/src/main/java/mypals/ml/render/InformationRender.java
+++ b/src/main/java/mypals/ml/render/InformationRender.java
@@ -16,17 +16,16 @@ public static void render(PoseStack matrixStack, Camera camera, float tickDelta)
matrixStack.pushPose();
matrixStack.translate(-camera.getPosition().x, -camera.getPosition().y, -camera.getPosition().z);
- RenderSystem.depthMask(false);
RenderSystem.enableBlend();
+ RenderSystem.defaultBlendFunc();
Matrix4f pose = matrixStack.last().pose();
BuilderManagers.updateMatrix(pose);
- Tester.renderTick(matrixStack);//------
+ Tester.renderTick(matrixStack);
ShapeManagers.renderAll(matrixStack, tickDelta);
- RenderSystem.depthMask(true);
RenderSystem.disableBlend();
matrixStack.popPose();
diff --git a/src/main/java/mypals/ml/render/RenderMethod.java b/src/main/java/mypals/ml/render/RenderMethod.java
index 9b80a9d..e846755 100644
--- a/src/main/java/mypals/ml/render/RenderMethod.java
+++ b/src/main/java/mypals/ml/render/RenderMethod.java
@@ -13,13 +13,6 @@ public record RenderMethod(
@NotNull VertexFormat format,
boolean cullFace
) {
- public static final RenderMethod QUADS = new RenderMethod(
- CoreShaders.POSITION_COLOR,
- VertexFormat.Mode.QUADS,
- DefaultVertexFormat.POSITION_COLOR,
- true
- );
-
public static final RenderMethod LINES = new RenderMethod(
CoreShaders.RENDERTYPE_LINES,
VertexFormat.Mode.LINES,
@@ -40,22 +33,4 @@ public record RenderMethod(
DefaultVertexFormat.POSITION_COLOR,
true
);
- public static final RenderMethod TRIANGLES_STRIP = new RenderMethod(
- CoreShaders.POSITION_COLOR,
- VertexFormat.Mode.TRIANGLE_STRIP,
- DefaultVertexFormat.POSITION_COLOR,
- true
- );
- public static final RenderMethod TRIANGLES_FAN = new RenderMethod(
- CoreShaders.POSITION_COLOR,
- VertexFormat.Mode.TRIANGLE_FAN,
- DefaultVertexFormat.POSITION_COLOR,
- true
- );
- public static final RenderMethod TEXT = new RenderMethod(
- CoreShaders.RENDERTYPE_TEXT,
- VertexFormat.Mode.QUADS,
- DefaultVertexFormat.POSITION_TEX_LIGHTMAP_COLOR,
- true
- );
}
diff --git a/src/main/java/mypals/ml/shape/Shape.java b/src/main/java/mypals/ml/shape/Shape.java
index 7baf691..9d362fc 100644
--- a/src/main/java/mypals/ml/shape/Shape.java
+++ b/src/main/java/mypals/ml/shape/Shape.java
@@ -1,146 +1,317 @@
package mypals.ml.shape;
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.VertexConsumer;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
-import mypals.ml.shape.basics.tags.ExtractableShape;
+import mypals.ml.collision.RayModelIntersection;
import mypals.ml.shapeManagers.ShapeManagers;
-import mypals.ml.transform.Vec3dTransformer;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
+import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
-import mypals.ml.transform.QuaternionTransformer;
-import org.joml.Quaternionf;
-import org.joml.Vector3f;
+import org.joml.Matrix4f;
import com.mojang.blaze3d.vertex.PoseStack;
-import java.util.function.BiConsumer;
+import org.joml.Vector3f;
+import org.joml.Vector4f;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.*;
+import static mypals.ml.test.Tester.ENABLE_DEBUG;
public abstract class Shape {
- public enum RenderingType {
- IMMEDIATE, // Immediately rendered
- BATCH, // Stored in bufferBuilder, batch uploads every frame
- BUFFERED // Stored in VBO
- }
+ public enum RenderingType { IMMEDIATE, BATCH, BUFFERED }
+
public ResourceLocation id;
public final RenderingType type;
- public BiConsumer transformFunction;
public DefaultTransformer transformer;
+ public Consumer transformFunction;
+
+ public Shape parent;
+ public List children = new ArrayList<>();
+
+ public boolean visible = true;
+ public Color baseColor;
public boolean seeThrough;
- public Vec3 centerPoint = Vec3.ZERO;
- protected Shape(RenderingType type,BiConsumer super DefaultTransformer, Shape> transform) {
- this(type);
- this.transformFunction = (transformer, shape) -> transform.accept(this.transformer,shape);
- }
- protected Shape(RenderingType type) {
- this(type,false);
+ public List model_vertexes = new ArrayList<>();//This is the original model of our model.
+ public int[] indexBuffer = new int[0];
+ public Map customData = new HashMap<>();
+
+ protected Shape(RenderingType type, Consumer transform,Color color, Vec3 center, boolean seeThrough) {
+ this(type,color,seeThrough);
+ this.transformer = new DefaultTransformer(this,center);
+ this.transformFunction = transform;
}
- protected Shape(RenderingType type,boolean seeThrough) {
+ protected Shape(RenderingType type,Color color, boolean seeThrough) {
this.type = type;
this.seeThrough = seeThrough;
+ this.baseColor = color;
}
- protected Shape(RenderingType type,BiConsumer super DefaultTransformer, Shape> transform,boolean seeThrough) {
- this(type,seeThrough);
- this.transformFunction = (transformer, shape) -> transform.accept(this.transformer,shape);
+ public List getChildren(){
+ return this.children;
}
- public DefaultTransformer getTransformer() {
- return transformer;
+ public void addChild(Shape shape){
+ shape.setParent(this);
+ children.add(shape);
}
- public void setId(ResourceLocation identifier){
- this.id = identifier;
- }
- public void draw(VertexBuilder builder, PoseStack matrixStack, float deltaTime) {
- matrixStack.pushPose();
- beforeDraw(matrixStack,deltaTime);
- builder.setPositionMatrix(matrixStack.last().pose());
- draw(builder);
- matrixStack.popPose();
- }
- public void discard(){
- ShapeManagers.removeShape(this.id);
+ public void setParent(Shape parent){
+ if(this.parent != null){
+ this.parent.children.remove(this);
+ }
+ this.parent = parent;
}
- public void draw(VertexBuilder builder) {
- if(this instanceof ExtractableShape) throw new UnsupportedOperationException("This shape cant be rendered directly, use addGroup to extract it.");
+ public void setLocalPosition(Vec3 pos) { this.transformer.setShapeLocalPivot(pos); }
+ public void setLocalRotation(Vector3f rot) { this.transformer.setShapeLocalRotationDegrees(rot.x,rot.y,rot.z); }
+ public void setLocalScale(Vec3 scale) { this.transformer.setShapeLocalScale(scale); }
+
+ public void setWorldPosition(Vec3 pos) {this.transformer.setShapeWorldPivot(pos);}
+
+ public void setWorldRotation(Vector3f rot) {this.transformer.setShapeWorldRotationDegrees(rot.x, rot.y, rot.z);}
+
+ public void setWorldScale(Vec3 scale) {this.transformer.setShapeWorldScale(scale);}
+
+ public void setRenderPivot(Vec3 pos) {this.transformer.setShapeMatrixPivot(pos);}
+
+ public void setRenderRotation(Vector3f rot) {this.transformer.setShapeMatrixRotationDegrees(rot.x, rot.y, rot.z);}
+
+ public void setRenderScale(Vec3 scale) {this.transformer.setShapeMatrixScale(scale);}
+
+ public void forceSetLocalPosition(Vec3 pos) {
+ setLocalPosition(pos);
+ this.transformer.local.position.syncLastToTarget();
}
- public void beforeDraw(PoseStack matrixStack,float deltaTime){
- transformer.updateTickDelta(deltaTime);
- transformFunction.accept(transformer,this);
- transformer.applyTransformations(matrixStack);
+
+ public void forceSetLocalRotation(Vector3f rot) {
+ setLocalRotation(rot);
+ this.transformer.local.rotation.syncLastToTarget();
}
- public void setMatrixScale(Vector3f scale, PoseStack matrixStack){
- matrixStack.scale(scale.x,scale.y,scale.z);
+
+ public void forceSetLocalScale(Vec3 scale) {
+ setLocalScale(scale);
+ this.transformer.local.scale.syncLastToTarget();
}
- public void setMatrixRotation(Quaternionf rotation, PoseStack matrixStack){
- matrixStack.mulPose(rotation);
+
+ public void forceSetWorldPosition(Vec3 pos) {
+ setWorldPosition(pos);
+ this.transformer.world.position.syncLastToTarget();
}
- public void setMatrixCenterPos(Vec3 pos, PoseStack matrixStack){
- matrixStack.translate(pos.x, pos.y, pos.z);
+
+ public void forceSetWorldRotation(Vector3f rot) {
+ setWorldRotation(rot);
+ this.transformer.world.rotation.syncLastToTarget();
}
- public Vec3 calculateShapeCenterPos(){
- return this.centerPoint;
+
+ public void forceSetWorldScale(Vec3 scale) {
+ setWorldScale(scale);
+ this.transformer.world.scale.syncLastToTarget();
}
- public Vec3 getShapeCenterPos(){
- return this.centerPoint;
+
+ public void forceSetRenderPivot(Vec3 pos) {
+ setRenderPivot(pos);
+ this.transformer.matrix.position.syncLastToTarget();
}
- public void setShapeCenterPos(Vec3 pos){
- this.centerPoint = pos;
+
+ public void forceSetRenderRotation(Vector3f rot) {
+ setRenderRotation(rot);
+ this.transformer.matrix.rotation.syncLastToTarget();
}
- public void syncLastToTarget(){
- this.transformer.syncLastToTarget();
+
+ public void forceSetRenderScale(Vec3 scale) {
+ setRenderScale(scale);
+ this.transformer.matrix.scale.syncLastToTarget();
}
- public static class DefaultTransformer{
- public float delta = 0;
- public Shape managedShape;
- public Vec3dTransformer shapeCenterTransformer = new Vec3dTransformer();
- public Vec3dTransformer matrixCenterTransformer = new Vec3dTransformer();
- public QuaternionTransformer matrixRotationTransformer = new QuaternionTransformer();
- public Vec3dTransformer matrixScaleTransformer = new Vec3dTransformer(Vec3.ZERO.add(1));
- public DefaultTransformer(Shape managerShape){
- this.managedShape = managerShape;
+
+
+ protected abstract void generateRawGeometry(boolean lerp);
+
+
+ public List getModel(boolean applyMatrixTransformer) {
+ if (this.transformer.asyncModelInfo()) {
+ model_vertexes.clear();
+ generateRawGeometry(false);
}
- public float getTickDelta(){
- return this.delta;
+
+ PoseStack poseStack = new PoseStack();
+
+
+ List hierarchy = new ArrayList<>();
+ Shape current = this;
+ while (current != null) {
+ hierarchy.add(current);
+ current = current.parent;
}
- public void updateTickDelta(float delta){
- this.delta = delta;
+ for (int i = hierarchy.size() - 1; i >= 0; i--) {
+ Shape n = hierarchy.get(i);
+ if(applyMatrixTransformer){
+ n.transformer.applyTransformations(poseStack, true);
+ }else{
+ n.transformer.applyModelTransformations(poseStack, true);
+ }
}
- public void applyTransformations(PoseStack matrixStack) {
- float deltaTime = getTickDelta();
- shapeCenterTransformer.updateVector(pos -> managedShape.setShapeCenterPos(pos), deltaTime);
- matrixCenterTransformer.updateVector(pos -> managedShape.setMatrixCenterPos(pos, matrixStack), deltaTime);
- Vec3 matrixCenter = matrixCenterTransformer.getCurrentVector().add(shapeCenterTransformer.getCurrentVector());
+ Matrix4f matrix = poseStack.last().pose();
- matrixStack.translate(matrixCenter.x, matrixCenter.y, matrixCenter.z);
- matrixRotationTransformer.updateRotation(rot -> managedShape.setMatrixRotation(rot, matrixStack), deltaTime);
- matrixScaleTransformer.updateVector(scl -> managedShape.setMatrixScale(scl.toVector3f(), matrixStack), deltaTime);
- matrixStack.translate(-matrixCenter.x, -matrixCenter.y, -matrixCenter.z);
+ List transformed = new ArrayList<>(model_vertexes.size());
+ for (Vec3 local : model_vertexes) {
+ Vector3f vec = new Vector3f((float) local.x, (float) local.y, (float) local.z);
+ vec.mulPosition(matrix);
+ transformed.add(new Vec3(vec.x(), vec.y(), vec.z()));
}
- public void setShapeCenterPos(Vec3 pos){
- shapeCenterTransformer.setTargetVector(pos);
+
+ return transformed;
+ }
+
+ public void beforeDraw(PoseStack matrixStack, float deltaTime) {
+
+ transformer.updateTickDelta(deltaTime);
+ transformFunction.accept(transformer);
+ if (this.transformer.asyncModelInfo()) {
+ model_vertexes.clear();
+ generateRawGeometry(true);
}
- public void setMatrixCenterPos(Vec3 pos){
- matrixCenterTransformer.setTargetVector(pos);
+
+ List hierarchy = new ArrayList<>();
+ Shape current = this;
+ while (current != null) {
+ hierarchy.add(current);
+ current = current.parent;
}
- public void setMatrixCenterPos(Vector3f pos){
- matrixCenterTransformer.setTargetVector(new Vec3(pos.x,pos.y,pos.z));
+ for (int i = hierarchy.size() - 1; i >= 0; i--) {
+ Shape n = hierarchy.get(i);
+ n.transformer.applyTransformations(matrixStack, true);
}
- public void setMatrixRotation(Quaternionf rotation){
- matrixRotationTransformer.setTargetRotation(rotation);
+ //We'll apply all transformations to the matrix stack before drawing(With lerp!).
+ }
+ public void drawShapeDebugInfo(PoseStack matrixStack, float deltaTime){
+ VertexConsumer vertexConsumer = Minecraft.getInstance()
+ .renderBuffers().bufferSource().getBuffer(RenderType.LINES);
+
+ Vec3 localCenter = this.transformer.getShapeWorldPivot(true).add(this.transformer.getShapeLocalPivot(true));
+ Vec3 worldCenter = this.transformer.getShapeWorldPivot(true);
+ Vec3 visualCenter = this.transformer.getShapeMatrixPivot(true).add(worldCenter);
+ renderLineBox(matrixStack,vertexConsumer,localCenter,0.15f,1,0,0,1);
+
+ renderLineBox(matrixStack,vertexConsumer,worldCenter,0.1f,0,1,0,1);
+
+ renderLineBox(matrixStack,vertexConsumer,visualCenter,0.05f,0,0,1,1);
+
+ RenderSystem.depthMask(false);
+ for(Vec3 v : getModel(false)){
+ double distanceTo = v.distanceToSqr(Minecraft.getInstance().cameraEntity.position());
+ if(distanceTo < 50)
+ renderBillboardFrame(matrixStack,vertexConsumer,v, (float) (distanceTo * 0.01),1,0,1,1);
}
- public void setMatrixRotation(Vec3 rotation){
- matrixRotationTransformer.setTargetRotation(new Quaternionf().rotationXYZ(
- (float)Math.toRadians(rotation.x),
- (float)Math.toRadians(rotation.y),
- (float)Math.toRadians(rotation.z)
- ));
+ RenderSystem.depthMask(true);
+ }
+
+
+ public RayModelIntersection.HitResult isPlayerLookingAt(){
+ Minecraft minecraft = Minecraft.getInstance();
+ Player p = minecraft.player;
+ if(p == null) return new RayModelIntersection.HitResult(false,null, -1);;
+ Camera camera = minecraft.gameRenderer.getMainCamera();
+ RayModelIntersection.Ray r = new RayModelIntersection.Ray(camera.getPosition(), p.getForward());
+
+ return RayModelIntersection.rayIntersectsModel(
+ r,
+ this.getModel(false),
+ this.indexBuffer
+ );
+ }
+ public void draw(boolean frustumCull, VertexBuilder builder, PoseStack matrixStack, float deltaTime) {
+ boolean shouldDraw = shouldDraw();
+ Minecraft mc = Minecraft.getInstance();
+ if(mc.getEntityRenderDispatcher().shouldRenderHitBoxes() && ENABLE_DEBUG){
+ drawShapeDebugInfo(matrixStack,deltaTime);
}
- public void setMatrixScale(Vec3 scale) {
- matrixScaleTransformer.setTargetVector(scale);
+ if(!visible) return;
+ matrixStack.pushPose();
+ beforeDraw(matrixStack, deltaTime);
+ builder.setPositionMatrix(matrixStack.last().pose());
+ if(!frustumCull || shouldDraw){
+ drawInternal(builder);
}
- public void syncLastToTarget(){
- this.shapeCenterTransformer.syncLastToTarget();
- this.matrixCenterTransformer.syncLastToTarget();
- this.matrixRotationTransformer.syncLastToTarget();
- this.matrixScaleTransformer.syncLastToTarget();
+ matrixStack.popPose();
+ }
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
+
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
+
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
}
+ return false;
}
-}
+ public static boolean isVertexInFrustum(Vec3 v, Matrix4f mvp) {
+ Vector4f clip = new Vector4f((float)v.x, (float)v.y, (float)v.z, 1f);
+ clip.mul(mvp);
+
+ if (clip.w <= 0) return false;
+
+ float ndcX = clip.x / clip.w;
+ float ndcY = clip.y / clip.w;
+ float ndcZ = clip.z / clip.w;
+
+ return ndcX >= -1 && ndcX <= 1
+ && ndcY >= -1 && ndcY <= 1
+ && ndcZ >= -1 && ndcZ <= 1;
+ }
+ protected void drawInternal(VertexBuilder builder) {
+ builder.putColor(baseColor);
+ for (int i : indexBuffer) {
+ builder.putVertex(model_vertexes.get(i));
+ }
+ }
+ public void setBaseColor(Color color){
+ this.baseColor = color;
+ }
+ public void setId(ResourceLocation id) { this.id = id; }
+ public void discard() {
+ children.forEach(Shape::discard);
+ ShapeManagers.removeShape(this.id); }
+ public void syncLastToTarget() { transformer.syncLastToTarget(); }
+
+ private Map data() {
+ if (customData == null) customData = new HashMap<>(1);
+ return customData;
+ }
+
+ public void putCustomData(String key, T value) {
+ data().put(key , value);
+ }
+
+ @SuppressWarnings("unchecked")
+ public T getCustomData(String key, T def) {
+ return (T) customData.getOrDefault(key, def);
+ }
+ @SuppressWarnings("unchecked")
+ public void removeCustomData(String key) {
+ customData.remove(key);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/shape/basics/BoxLikeShape.java b/src/main/java/mypals/ml/shape/basics/BoxLikeShape.java
index aa13eb4..698ef6e 100644
--- a/src/main/java/mypals/ml/shape/basics/BoxLikeShape.java
+++ b/src/main/java/mypals/ml/shape/basics/BoxLikeShape.java
@@ -1,8 +1,8 @@
package mypals.ml.shape.basics;
-import com.mojang.blaze3d.vertex.PoseStack;
-import mypals.ml.shape.Shape;
-import mypals.ml.transform.Vec3dTransformer;
+import mypals.ml.shape.box.BoxShape;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.BoxModelInfo;
import net.minecraft.world.phys.Vec3;
public interface BoxLikeShape {
@@ -10,33 +10,39 @@ public interface BoxLikeShape {
Vec3 getMax();
void setMin(Vec3 min);
void setMax(Vec3 max);
- void setDimensions(Vec3 dimensions);
+ void setDimension(Vec3 dimensions);
default Vec3 getShapeCenterPos() {
double centerX = (getMin().x + getMax().x) / 2.0;
double centerY = (getMin().y + getMax().y) / 2.0;
double centerZ = (getMin().z + getMax().z) / 2.0;
return new Vec3(centerX, centerY, centerZ);
}
- class BoxTransformer extends Shape.DefaultTransformer {
- public BoxTransformer(Shape managedShape) {
- super(managedShape);
+ class BoxTransformer extends DefaultTransformer {
+
+ public BoxModelInfo boxModelInfo;
+ public BoxTransformer(BoxShape managedShape,Vec3 dim,Vec3 center) {
+ super(managedShape,center);
+ boxModelInfo = new BoxModelInfo(dim);
}
- public Vec3dTransformer dimensionTransformer = new Vec3dTransformer();
public void setDimension(Vec3 dimension) {
- this.dimensionTransformer.setTargetVector(dimension);
- }
- @Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof BoxLikeShape boxLikeShape) {
- dimensionTransformer.updateVector(boxLikeShape::setDimensions, deltaTime);
- }
+ this.boxModelInfo.setDimension(dimension);
}
+
public void syncLastToTarget(){
- this.dimensionTransformer.syncLastToTarget();
+ this.boxModelInfo.syncLastToTarget();
super.syncLastToTarget();
}
+ public Vec3 getDimension(boolean lerp){
+ return boxModelInfo.getDimension(lerp);
+ }
+ public boolean asyncModelInfo(){
+ return boxModelInfo.async();
+ }
+ @Override
+ public void updateTickDelta(float delta){
+ this.boxModelInfo.update(delta);
+ super.updateTickDelta(delta);
+ }
}
default void normalizeBounds() {
diff --git a/src/main/java/mypals/ml/shape/basics/CircleLikeShape.java b/src/main/java/mypals/ml/shape/basics/CircleLikeShape.java
index 627e37b..1f73d9f 100644
--- a/src/main/java/mypals/ml/shape/basics/CircleLikeShape.java
+++ b/src/main/java/mypals/ml/shape/basics/CircleLikeShape.java
@@ -3,8 +3,8 @@
public interface CircleLikeShape {
void setRadius(float radius);
void setSegments(int segments);
- float getRadius();
- int getSegments();
+ float getRadius(boolean lerp);
+ int getSegments(boolean lerp);
enum CircleAxis{
X,
Y,
diff --git a/src/main/java/mypals/ml/shape/basics/core/LineLikeShape.java b/src/main/java/mypals/ml/shape/basics/core/LineLikeShape.java
index f0429a5..586d9c2 100644
--- a/src/main/java/mypals/ml/shape/basics/core/LineLikeShape.java
+++ b/src/main/java/mypals/ml/shape/basics/core/LineLikeShape.java
@@ -1,14 +1,24 @@
package mypals.ml.shape.basics.core;
-import com.mojang.blaze3d.vertex.PoseStack;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.tags.DrawableLine;
-import mypals.ml.transform.FloatValueTransformer;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.LineModelInfo;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+import org.joml.Vector4f;
+
+import java.util.List;
+
+import static mypals.ml.Helpers.createViewMatrix;
public interface LineLikeShape extends DrawableLine {
void setLineWidth(float width);
+ float getLineWidth(boolean lerp);
default void addLineSegment(VertexBuilder vertexBuilder, Vec3 start, Vec3 end) {
double dx = end.x() - start.x();
double dy = end.y() - start.y();
@@ -20,27 +30,61 @@ default void addLineSegment(VertexBuilder vertexBuilder, Vec3 start, Vec3 end) {
vertexBuilder.putVertex(start, normal);
vertexBuilder.putVertex(end, normal);
}
-
- class DefaultLineTransformer extends Shape.DefaultTransformer{
- public FloatValueTransformer widthTransformer = new FloatValueTransformer();
- public DefaultLineTransformer(Shape managerShape) {
- super(managerShape);
+ class SimpleLineTransformer extends DefaultTransformer {
+ public LineModelInfo lineModelInfo;
+ public SimpleLineTransformer(Shape s, float width, Vec3 center) {
+ super(s, center);
+ lineModelInfo = new LineModelInfo(width);
+ }
+ public void setWidth(float width){
+ lineModelInfo.setWidth(width);
+ }
+ public float getWidth(boolean lerp){
+ return lineModelInfo.getWidth(lerp);
}
public void syncLastToTarget(){
- this.widthTransformer.syncLastToTarget();
+ lineModelInfo.syncLastToTarget();
super.syncLastToTarget();
}
- public void setWidth(float width){
- this.widthTransformer.setTargetValue(width);
+ public boolean asyncModelInfo(){
+ return lineModelInfo.async();
}
@Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof LineLikeShape lineLikeShape) {
- this.widthTransformer.updateValue(lineLikeShape::setLineWidth,deltaTime);
- }
+ public void updateTickDelta(float delta){
+ this.lineModelInfo.update(delta);
+ super.updateTickDelta(delta);
}
}
+
+ public static boolean isSegmentInFrustum(Vec3 a, Vec3 b, Matrix4f mvp) {
+ Vector4f ca = new Vector4f((float)a.x, (float)a.y, (float)a.z, 1f);
+ Vector4f cb = new Vector4f((float)b.x, (float)b.y, (float)b.z, 1f);
+
+ ca.mul(mvp);
+ cb.mul(mvp);
+
+ if (ca.w <= 0 && cb.w <= 0) return false;
+
+ int codeA = computeOutCode(ca);
+ int codeB = computeOutCode(cb);
+
+ if ((codeA & codeB) != 0) return false;
+
+ return true;
+ }
+
+ private static int computeOutCode(Vector4f c) {
+ int code = 0;
+ float x = c.x, y = c.y, z = c.z, w = c.w;
+
+ if (x < -w) code |= 1;
+ if (x > w) code |= 2;
+ if (y < -w) code |= 4;
+ if (y > w) code |= 8;
+ if (z < -w) code |= 16;
+ if (z > w) code |= 32;
+
+ return code;
+ }
}
diff --git a/src/main/java/mypals/ml/shape/basics/core/TwoPointsLineShape.java b/src/main/java/mypals/ml/shape/basics/core/TwoPointsLineShape.java
index 0840381..94c7240 100644
--- a/src/main/java/mypals/ml/shape/basics/core/TwoPointsLineShape.java
+++ b/src/main/java/mypals/ml/shape/basics/core/TwoPointsLineShape.java
@@ -1,45 +1,56 @@
package mypals.ml.shape.basics.core;
-
-import com.mojang.blaze3d.vertex.PoseStack;
-import mypals.ml.shape.Shape;
-import mypals.ml.transform.Vec3dTransformer;
+import mypals.ml.shape.line.LineShape;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.LineModelInfo;
import net.minecraft.world.phys.Vec3;
public interface TwoPointsLineShape extends LineLikeShape{
void setStart(Vec3 start);
void setEnd(Vec3 end);
- Vec3 getStart();
- Vec3 getEnd();
- class TwoPointsLineTransformer extends DefaultLineTransformer {
- public TwoPointsLineTransformer(Shape managedShape) {
- super(managedShape);
- }
- public Vec3dTransformer startPosTransformer = new Vec3dTransformer();
- public Vec3dTransformer endPosTransformer = new Vec3dTransformer();
+ Vec3 getStart(boolean lerp);
+ Vec3 getEnd(boolean lerp);
+
+ class TwoPointsLineTransformer extends DefaultTransformer {
+ public LineModelInfo.TwoPointLineModelInfo lineModelInfo;
+ public TwoPointsLineTransformer(LineShape managedShape,Vec3 start, Vec3 end,float width,Vec3 center) {
+ super(managedShape,center);
+ lineModelInfo = new LineModelInfo.TwoPointLineModelInfo(start,end,width);
+ }
public void setStartEnd(Vec3 start, Vec3 end) {
- this.endPosTransformer.setTargetVector(end);
- this.startPosTransformer.setTargetVector(start);
+ this.lineModelInfo.setStart(start);
+ this.lineModelInfo.setEnd(end);
+ }
+ public Vec3 getStart(boolean lerp){
+ return lineModelInfo.getStart(lerp);
+ }
+ public Vec3 getEnd(boolean lerp){
+ return lineModelInfo.getEnd(lerp);
+ }
+ public void setWidth(float width){
+ lineModelInfo.setWidth(width);
+ }
+ public float getWidth(boolean lerp){
+ return lineModelInfo.getWidth(lerp);
}
public void setStart(Vec3 start) {
- this.startPosTransformer.setTargetVector(start);
+ lineModelInfo.setStart(start);
}
public void setEnd(Vec3 end) {
- this.endPosTransformer.setTargetVector(end);
- }
- @Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof TwoPointsLineShape twoPointLineShape) {
- startPosTransformer.updateVector(twoPointLineShape::setStart, deltaTime);
- endPosTransformer.updateVector(twoPointLineShape::setEnd, deltaTime);
- }
+ lineModelInfo.setEnd(end);
}
+
public void syncLastToTarget(){
- this.startPosTransformer.syncLastToTarget();
- this.endPosTransformer.syncLastToTarget();
+ lineModelInfo.syncLastToTarget();
super.syncLastToTarget();
}
+ public boolean asyncModelInfo(){
+ return lineModelInfo.async();
+ }
+ @Override
+ public void updateTickDelta(float delta){
+ super.updateTickDelta(delta);
+ this.lineModelInfo.update(delta);
+ }
}
}
diff --git a/src/main/java/mypals/ml/shape/basics/tags/EmptyMesh.java b/src/main/java/mypals/ml/shape/basics/tags/EmptyMesh.java
new file mode 100644
index 0000000..ed9b228
--- /dev/null
+++ b/src/main/java/mypals/ml/shape/basics/tags/EmptyMesh.java
@@ -0,0 +1,4 @@
+package mypals.ml.shape.basics.tags;
+
+public interface EmptyMesh {
+}
diff --git a/src/main/java/mypals/ml/shape/box/BoxFaceShape.java b/src/main/java/mypals/ml/shape/box/BoxFaceShape.java
index 8484854..d7b924c 100644
--- a/src/main/java/mypals/ml/shape/box/BoxFaceShape.java
+++ b/src/main/java/mypals/ml/shape/box/BoxFaceShape.java
@@ -6,75 +6,55 @@
import net.minecraft.world.phys.Vec3;
import java.awt.*;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public class BoxFaceShape extends BoxShape implements DrawableQuad{
- public Color faceputColor;
+
public BoxFaceShape(RenderingType type,
- BiConsumer transform,
+ Consumer transform,
Vec3 min,
Vec3 max,
Color faceputColor,
boolean seeThrough, BoxConstructionType constructionType)
{
- super(type, transform,min,max, seeThrough,constructionType);
- this.faceputColor = faceputColor;
- }
- @Override
- public void draw(VertexBuilder builder) {
- this.renderFaces(builder);
+ super(type, transform,min,max,faceputColor, seeThrough,constructionType);
+ generateRawGeometry(false);
}
- private void renderFaces(VertexBuilder vertexBuilder) {
- vertexBuilder.putColor(faceputColor);
-
- Vec3 dimensions = this.getDimensions();
- Vec3 center = this.getCenter();
-
- Vec3 halfDimensions = dimensions.scale(0.5);
- double halfWidth = halfDimensions.x;
- double halfHeight = halfDimensions.y;
- double halfLength = halfDimensions.z;
-
- Vec3 v1 = new Vec3(center.x - halfWidth, center.y - halfHeight, center.z - halfLength);
- Vec3 v2 = new Vec3(center.x + halfWidth, center.y - halfHeight, center.z - halfLength);
- Vec3 v3 = new Vec3(center.x + halfWidth, center.y - halfHeight, center.z + halfLength);
- Vec3 v4 = new Vec3(center.x - halfWidth, center.y - halfHeight, center.z + halfLength);
-
- Vec3 v5 = new Vec3(center.x - halfWidth, center.y + halfHeight, center.z - halfLength);
- Vec3 v6 = new Vec3(center.x + halfWidth, center.y + halfHeight, center.z - halfLength);
- Vec3 v7 = new Vec3(center.x + halfWidth, center.y + halfHeight, center.z + halfLength);
- Vec3 v8 = new Vec3(center.x - halfWidth, center.y + halfHeight, center.z + halfLength);
-
-
- vertexBuilder.putVertex((float) v1.x, (float) v1.y, (float) v1.z); // v1
- vertexBuilder.putVertex((float) v5.x, (float) v5.y, (float) v5.z); // v5
- vertexBuilder.putVertex((float) v6.x, (float) v6.y, (float) v6.z); // v6
- vertexBuilder.putVertex((float) v2.x, (float) v2.y, (float) v2.z); // v2
-
- vertexBuilder.putVertex((float) v4.x, (float) v4.y, (float) v4.z); // v4
- vertexBuilder.putVertex((float) v3.x, (float) v3.y, (float) v3.z); // v3
- vertexBuilder.putVertex((float) v7.x, (float) v7.y, (float) v7.z); // v7
- vertexBuilder.putVertex((float) v8.x, (float) v8.y, (float) v8.z); // v8
-
- vertexBuilder.putVertex((float) v1.x, (float) v1.y, (float) v1.z); // v1
- vertexBuilder.putVertex((float) v4.x, (float) v4.y, (float) v4.z); // v4
- vertexBuilder.putVertex((float) v8.x, (float) v8.y, (float) v8.z); // v8
- vertexBuilder.putVertex((float) v5.x, (float) v5.y, (float) v5.z); // v5
-
- vertexBuilder.putVertex((float) v2.x, (float) v2.y, (float) v2.z); // v2
- vertexBuilder.putVertex((float) v6.x, (float) v6.y, (float) v6.z); // v6
- vertexBuilder.putVertex((float) v7.x, (float) v7.y, (float) v7.z); // v7
- vertexBuilder.putVertex((float) v3.x, (float) v3.y, (float) v3.z); // v3
-
- vertexBuilder.putVertex((float) v1.x, (float) v1.y, (float) v1.z); // v1
- vertexBuilder.putVertex((float) v2.x, (float) v2.y, (float) v2.z); // v2
- vertexBuilder.putVertex((float) v3.x, (float) v3.y, (float) v3.z); // v3
- vertexBuilder.putVertex((float) v4.x, (float) v4.y, (float) v4.z); // v4
-
- vertexBuilder.putVertex((float) v5.x, (float) v5.y, (float) v5.z); // v5
- vertexBuilder.putVertex((float) v8.x, (float) v8.y, (float) v8.z); // v8
- vertexBuilder.putVertex((float) v7.x, (float) v7.y, (float) v7.z); // v7
- vertexBuilder.putVertex((float) v6.x, (float) v6.y, (float) v6.z); // v6
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+
+ BoxTransformer bt = (BoxTransformer) transformer;
+ Vec3 c = bt.getLocalPivot();
+ Vec3 d = bt.getDimension(lerp);
+ double hx = d.x * 0.5;
+ double hy = d.y * 0.5;
+ double hz = d.z * 0.5;
+
+ model_vertexes.add(new Vec3(c.x - hx, c.y - hy, c.z - hz)); // 0
+ model_vertexes.add(new Vec3(c.x + hx, c.y - hy, c.z - hz)); // 1
+ model_vertexes.add(new Vec3(c.x + hx, c.y + hy, c.z - hz)); // 2
+ model_vertexes.add(new Vec3(c.x - hx, c.y + hy, c.z - hz)); // 3
+ model_vertexes.add(new Vec3(c.x - hx, c.y - hy, c.z + hz)); // 4
+ model_vertexes.add(new Vec3(c.x + hx, c.y - hy, c.z + hz)); // 5
+ model_vertexes.add(new Vec3(c.x + hx, c.y + hy, c.z + hz)); // 6
+ model_vertexes.add(new Vec3(c.x - hx, c.y + hy, c.z + hz)); // 7
+
+ indexBuffer = new int[] {
+ // -Z
+ 0, 1, 2, 2, 3, 0,
+ // +Z
+ 4, 6, 5, 6, 4, 7,
+ // -Y
+ 0, 4, 1, 1, 4, 5,
+ // +Y
+ 3, 2, 6, 6, 7, 3,
+ // -X
+ 0, 3, 4, 4, 3, 7,
+ // +X
+ 1, 5, 2, 2, 5, 6
+ };
}
}
diff --git a/src/main/java/mypals/ml/shape/box/BoxShape.java b/src/main/java/mypals/ml/shape/box/BoxShape.java
index 9e78ab1..5dd0bb8 100644
--- a/src/main/java/mypals/ml/shape/box/BoxShape.java
+++ b/src/main/java/mypals/ml/shape/box/BoxShape.java
@@ -1,151 +1,131 @@
package mypals.ml.shape.box;
+import mypals.ml.Helpers;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.BoxLikeShape;
import net.minecraft.world.phys.Vec3;
-import java.util.function.BiConsumer;
+
+import java.awt.*;
+import java.util.function.Consumer;
public class BoxShape extends Shape implements BoxLikeShape {
- private Vec3 center;
- private Vec3 dimensions;
- private Vec3 min;
- private Vec3 max;
-
- public enum BoxConstructionType {
- CENTER_AND_DIMENSIONS,
- CORNERS
- }
- public BoxShape(RenderingType type, BiConsumer transform,
- Vec3 vec1, Vec3 vec2, boolean seeThrough, BoxConstructionType constructionType) {
- super(type, seeThrough);
- this.transformer = new BoxTransformer(this);
- this.transformFunction = (defaultTransformer, shape) -> transform.accept((BoxTransformer) this.transformer, shape);
+ public enum BoxConstructionType { CENTER_AND_DIMENSIONS, CORNERS }
+
+ public BoxShape(RenderingType type,
+ Consumer transform,
+ Vec3 vec1,
+ Vec3 vec2,
+ Color color,
+ boolean seeThrough,
+ BoxConstructionType constructionType) {
+ super(type, color, seeThrough);
+
+ this.transformFunction = (t)->{transform.accept((BoxTransformer)this.transformer);};
if (constructionType == BoxConstructionType.CENTER_AND_DIMENSIONS) {
- this.center = vec1;
- this.dimensions = new Vec3(Math.abs(vec2.x), Math.abs(vec2.y), Math.abs(vec2.z));
+ this.transformer = new BoxTransformer(this,new Vec3(Math.abs(vec2.x), Math.abs(vec2.y), Math.abs(vec2.z)),vec1);
} else {
-
- this.dimensions = new Vec3(
- Math.abs(vec2.x - vec1.x),
- Math.abs(vec2.y - vec1.y),
- Math.abs(vec2.z - vec1.z)
- );
- this.center = new Vec3(
- (vec1.x + vec2.x) / 2.0,
- (vec1.y + vec2.y) / 2.0,
- (vec1.z + vec2.z) / 2.0
- );
+ Vec3 min = Helpers.min(vec1, vec2);
+ Vec3 max = Helpers.max(vec1, vec2);
+ Vec3 dims = max.subtract(min);
+ Vec3 center = min.add(dims.scale(0.5));
+ this.transformer = new BoxTransformer(this,dims,center);
}
- this.transformer.setShapeCenterPos(this.center);
- ((BoxTransformer)this.transformer).setDimension(this.dimensions);
- updateCornersFromCenterAndDimensions();
- normalizeBounds();
+
+
syncLastToTarget();
}
- public BoxShape(RenderingType type, BiConsumer transform,
- Vec3 vec1, Vec3 vec2, BoxConstructionType constructionType) {
- this(type, transform, vec1, vec2, false, constructionType);
- }
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+
+ }
@Override
public Vec3 getMin() {
- return this.min;
+ BoxTransformer bt = (BoxTransformer) transformer;
+ Vec3 half = bt.getDimension(false).scale(0.5);
+ return bt.getWorldPivot().subtract(half);
}
@Override
public Vec3 getMax() {
- return this.max;
+ BoxTransformer bt = (BoxTransformer) transformer;
+ Vec3 half = bt.getDimension(false).scale(0.5);
+ return bt.getWorldPivot().add(half);
}
@Override
public void setMin(Vec3 min) {
- this.min = min;
- this.center = new Vec3(
- (min.x + max.x) / 2.0,
- (min.y + max.y) / 2.0,
- (min.z + max.z) / 2.0
- );
- this.dimensions = new Vec3(
- max.x - min.x,
- max.y - min.y,
- max.z - min.z
- );
+ Vec3 max = getMax();
+ Vec3 center = min.add(max).scale(0.5);
+ Vec3 dims = max.subtract(min);
+ BoxTransformer bt = (BoxTransformer) transformer;
+ bt.setShapeWorldPivot(center);
+ bt.setDimension(dims);
+
}
@Override
public void setMax(Vec3 max) {
- this.max = max;
- this.center = new Vec3(
- (min.x + max.x) / 2.0,
- (min.y + max.y) / 2.0,
- (min.z + max.z) / 2.0
- );
- this.dimensions = new Vec3(
- max.x - min.x,
- max.y - min.y,
- max.z - min.z
- );
+ Vec3 min = getMin();
+ Vec3 center = min.add(max).scale(0.5);
+ Vec3 dims = max.subtract(min);
+ BoxTransformer bt = (BoxTransformer) transformer;
+ bt.setShapeWorldPivot(center);
+ bt.setDimension(dims);
+
}
- public Vec3 getCenter() {
- return this.center;
- }
- public Vec3 getDimensions() {
- return this.dimensions;
+ public void setDimension(Vec3 dimensions) {
+ ((BoxTransformer) transformer).setDimension(
+ new Vec3(Math.abs(dimensions.x), Math.abs(dimensions.y), Math.abs(dimensions.z))
+ );
+
}
- @Override
- public void setShapeCenterPos(Vec3 center) {
- this.center = center;
- this.centerPoint = center;
- updateCornersFromCenterAndDimensions();
+ public void setCorners(Vec3 corner1, Vec3 corner2) {
+ Vec3 min = Helpers.min(corner1, corner2);
+ Vec3 max = Helpers.max(corner1, corner2);
+ Vec3 center = min.add(max).scale(0.5);
+ Vec3 dims = max.subtract(min);
+ BoxTransformer bt = (BoxTransformer) transformer;
+ bt.setShapeWorldPivot(center);
+ bt.setDimension(dims);
+
}
- public void setDimensions(Vec3 dimensions) {
- this.dimensions = new Vec3(Math.abs(dimensions.x), Math.abs(dimensions.y), Math.abs(dimensions.z));
- updateCornersFromCenterAndDimensions();
+ public void forceSetMax(Vec3 max) {
+ setMax(max);
+ ((BoxTransformer)this.transformer).boxModelInfo.syncLastToTarget();
+ generateRawGeometry(false);
}
-
- private void updateCornersFromCenterAndDimensions() {
- Vec3 half = dimensions.scale(0.5);
- this.min = center.subtract(half);
- this.max = center.add(half);
+ public void forceSetMin(Vec3 min) {
+ setMax(min);
+ ((BoxTransformer)this.transformer).boxModelInfo.syncLastToTarget();
+ generateRawGeometry(false);
}
-
- public void setCorners(Vec3 min, Vec3 max) {
- Vec3 dims = new Vec3(
- Math.abs(max.x - min.x),
- Math.abs(max.y - min.y),
- Math.abs(max.z - min.z)
- );
- Vec3 c = new Vec3(
- (min.x + max.x) / 2.0,
- (min.y + max.y) / 2.0,
- (min.z + max.z) / 2.0
- );
- setShapeCenterPos(c);
- setDimensions(dims);
+ public void forceSetDimensions(Vec3 dim) {
+ setDimension(dim);
+ ((BoxTransformer)this.transformer).boxModelInfo.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetCorners(Vec3 c1,Vec3 c2) {
+ setCorners(c1,c2);
+ ((BoxTransformer)this.transformer).boxModelInfo.syncLastToTarget();
+ generateRawGeometry(false);
}
@Override
public void normalizeBounds() {
- // 保证 min/max 永远小于等于 max
- double minX = Math.min(min.x, max.x);
- double minY = Math.min(min.y, max.y);
- double minZ = Math.min(min.z, max.z);
- double maxX = Math.max(min.x, max.x);
- double maxY = Math.max(min.y, max.y);
- double maxZ = Math.max(min.z, max.z);
- this.min = new Vec3(minX, minY, minZ);
- this.max = new Vec3(maxX, maxY, maxZ);
- }
- @Override
- public Vec3 calculateShapeCenterPos() {
- return this.center;
+ Vec3 min = Helpers.min(getMin(), getMax());
+ Vec3 max = Helpers.max(getMin(), getMax());
+ setCorners(min, max);
}
+
+
}
diff --git a/src/main/java/mypals/ml/shape/box/BoxWireframeShape.java b/src/main/java/mypals/ml/shape/box/BoxWireframeShape.java
index 205288a..6d0c2ff 100644
--- a/src/main/java/mypals/ml/shape/box/BoxWireframeShape.java
+++ b/src/main/java/mypals/ml/shape/box/BoxWireframeShape.java
@@ -3,74 +3,140 @@
import com.mojang.blaze3d.systems.RenderSystem;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
+import mypals.ml.shape.basics.core.LineLikeShape;
import mypals.ml.shape.basics.tags.DrawableLine;
+import mypals.ml.shape.cylinder.CylinderWireframeShape;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+import org.joml.Vector3f;
+
import java.awt.*;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.createViewMatrix;
public class BoxWireframeShape extends BoxShape implements DrawableLine {
- public final Color edgeputColor;
- public float edgeWidth;
+
+ public final float edgeWidth;
+
public BoxWireframeShape(RenderingType type,
- BiConsumer transform, Vec3 min, Vec3 max,
- Color edgeputColor, boolean seeThrough, float edgeWidth,BoxConstructionType constructionType) {
- super(type, transform,min,max,seeThrough,constructionType);
- this.edgeputColor = edgeputColor;
- this.edgeWidth = edgeWidth;
- this.seeThrough = seeThrough;
+ Consumer transform,
+ Vec3 vec1,
+ Vec3 vec2,
+ Color edgeColor,
+ boolean seeThrough,
+ float edgeWidth,
+ BoxConstructionType constructionType) {
+
+ super(type, transform, vec1, vec2,edgeColor, seeThrough, constructionType);
+ this.edgeWidth = Math.max(0.1f, edgeWidth);
+ generateRawGeometry(false);
}
+
@Override
- public void draw(VertexBuilder builder) {
- RenderSystem.lineWidth(edgeWidth);
- renderEdges(builder);
- }
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
+
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
+
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
- private void renderEdges(VertexBuilder vertexBuilder) {
- vertexBuilder.putColor(edgeputColor);
- Vec3 dimensions = this.getDimensions();
- Vec3 center = this.getCenter();
-
- Vec3 halfDimensions = dimensions.scale(0.5);
- double halfWidth = halfDimensions.x;
- double halfHeight = halfDimensions.y;
- double halfLength = halfDimensions.z;
-
- Vec3 v1 = new Vec3(center.x - halfWidth, center.y - halfHeight, center.z - halfLength);
- Vec3 v2 = new Vec3(center.x + halfWidth, center.y - halfHeight, center.z - halfLength);
- Vec3 v3 = new Vec3(center.x + halfWidth, center.y - halfHeight, center.z + halfLength);
- Vec3 v4 = new Vec3(center.x - halfWidth, center.y - halfHeight, center.z + halfLength);
-
- Vec3 v5 = new Vec3(center.x - halfWidth, center.y + halfHeight, center.z - halfLength);
- Vec3 v6 = new Vec3(center.x + halfWidth, center.y + halfHeight, center.z - halfLength);
- Vec3 v7 = new Vec3(center.x + halfWidth, center.y + halfHeight, center.z + halfLength);
- Vec3 v8 = new Vec3(center.x - halfWidth, center.y + halfHeight, center.z + halfLength);
-
- addLineSegment(vertexBuilder, v1, v2);
- addLineSegment(vertexBuilder, v2, v3);
- addLineSegment(vertexBuilder, v3, v4);
- addLineSegment(vertexBuilder, v4, v1);
-
- addLineSegment(vertexBuilder, v5, v6);
- addLineSegment(vertexBuilder, v6, v7);
- addLineSegment(vertexBuilder, v7, v8);
- addLineSegment(vertexBuilder, v8, v5);
-
- addLineSegment(vertexBuilder, v1, v5);
- addLineSegment(vertexBuilder, v2, v6);
- addLineSegment(vertexBuilder, v3, v7);
- addLineSegment(vertexBuilder, v4, v8);
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
+ }
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
+
+ return false;
+ }
+ public void forceSetLineWidth(float width) {
+ setLineWidth(width);
+ ((LineLikeShape.SimpleLineTransformer)this.transformer).lineModelInfo.widthTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void setLineWidth(float width) {
+ ((LineLikeShape.SimpleLineTransformer)this.transformer).setWidth(width);
}
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+
+ BoxTransformer bt = (BoxTransformer) transformer;
+ Vec3 c = bt.getLocalPivot();
+ Vec3 d = bt.getDimension(lerp);
+
+ double hx = d.x * 0.5;
+ double hy = d.y * 0.5;
+ double hz = d.z * 0.5;
- private void addLineSegment(VertexBuilder vertexBuilder, Vec3 start, Vec3 end) {
- double dx = end.x() - start.x();
- double dy = end.y() - start.y();
- double dz = end.z() - start.z();
+ Vec3 v0 = new Vec3(c.x - hx, c.y - hy, c.z - hz);
+ Vec3 v1 = new Vec3(c.x + hx, c.y - hy, c.z - hz);
+ Vec3 v2 = new Vec3(c.x + hx, c.y - hy, c.z + hz);
+ Vec3 v3 = new Vec3(c.x - hx, c.y - hy, c.z + hz);
+ Vec3 v4 = new Vec3(c.x - hx, c.y + hy, c.z - hz);
+ Vec3 v5 = new Vec3(c.x + hx, c.y + hy, c.z - hz);
+ Vec3 v6 = new Vec3(c.x + hx, c.y + hy, c.z + hz);
+ Vec3 v7 = new Vec3(c.x - hx, c.y + hy, c.z + hz);
- double distanceInv = 1.0 / Math.sqrt(dx * dx + dy * dy + dz * dz);
- Vec3 normal = new Vec3(dx * distanceInv, dy * distanceInv, dz * distanceInv);
+ model_vertexes.add(v0); // 0
+ model_vertexes.add(v1); // 1
+ model_vertexes.add(v2); // 2
+ model_vertexes.add(v3); // 3
+ model_vertexes.add(v4); // 4
+ model_vertexes.add(v5); // 5
+ model_vertexes.add(v6); // 6
+ model_vertexes.add(v7); // 7
- vertexBuilder.putVertex(start, normal);
- vertexBuilder.putVertex(end, normal);
+ indexBuffer = new int[] {
+ // Bottom
+ 0, 1, 1, 2, 2, 3, 3, 0,
+ // Top
+ 4, 5, 5, 6, 6, 7, 7, 4,
+ // Vert
+ 0, 4, 1, 5, 2, 6, 3, 7
+ };
}
+ @Override
+ protected void drawInternal(VertexBuilder builder) {
+ RenderSystem.lineWidth(edgeWidth);
+ builder.putColor(baseColor);
+
+ for (int i = 0; i < indexBuffer.length; i += 2) {
+ Vec3 start = model_vertexes.get(indexBuffer[i]);
+ Vec3 end = model_vertexes.get(indexBuffer[i + 1]);
+ addLineSegment(builder, start, end);
+ }
+ }
+ private void addLineSegment(VertexBuilder builder, Vec3 start, Vec3 end) {
+ Vec3 dir = end.subtract(start);
+ dir.normalize();
+
+ Vec3 normal = new Vec3(dir.x(), dir.y(), dir.z());
+
+ builder.putVertex(start, normal);
+ builder.putVertex(end, normal);
+ }
}
diff --git a/src/main/java/mypals/ml/shape/box/WireframedBoxShape.java b/src/main/java/mypals/ml/shape/box/WireframedBoxShape.java
index 814e203..bec45f9 100644
--- a/src/main/java/mypals/ml/shape/box/WireframedBoxShape.java
+++ b/src/main/java/mypals/ml/shape/box/WireframedBoxShape.java
@@ -7,6 +7,7 @@
import net.minecraft.world.phys.Vec3;
import java.awt.*;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public class WireframedBoxShape extends BoxShape implements ExtractableShape {
public Color faceputColor;
@@ -15,9 +16,9 @@ public class WireframedBoxShape extends BoxShape implements ExtractableShape {
public boolean lineSeeThrough;
public BoxConstructionType constructionType;
- public BiConsumer transformFunction;
+ public Consumer recordedTransformFunction;
public WireframedBoxShape(RenderingType type,
- BiConsumer transform,
+ Consumer transform,
Vec3 min,
Vec3 max,
Color faceputColor,
@@ -26,9 +27,9 @@ public WireframedBoxShape(RenderingType type,
boolean seeThrough,
boolean lineSeeThrough,BoxConstructionType constructionType)
{
- super(type, transform,min,max, seeThrough,constructionType);
- this.transformer = new BoxTransformer(this);
- this.transformFunction = transform;
+ super(type, transform,min,max,faceputColor, seeThrough,constructionType);
+
+ this.recordedTransformFunction = transform;
this.faceputColor = faceputColor;
this.edgeputColor = edgeputColor;
this.edgeWidth = edgeWidth;
@@ -41,7 +42,7 @@ public void addGroup(ResourceLocation identifier) {
identifier.withPath(identifier.getPath()+"/wireframe"),
new BoxWireframeShape(
this.type,
- this.transformFunction,
+ recordedTransformFunction,
this.getMin(),
this.getMax(),
this.edgeputColor,
@@ -50,11 +51,11 @@ public void addGroup(ResourceLocation identifier) {
constructionType
)
);
- ShapeManagers.QUADS_SHAPE_MANAGER.addShape(
+ ShapeManagers.TRIANGLES_SHAPE_MANAGER.addShape(
identifier.withPath(identifier.getPath()+"/face"),
new BoxFaceShape(
this.type,
- this.transformFunction,
+ recordedTransformFunction,
this.getMin(),
this.getMax(),
this.faceputColor,
@@ -63,4 +64,9 @@ public void addGroup(ResourceLocation identifier) {
)
);
}
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+
+ }
}
diff --git a/src/main/java/mypals/ml/shape/cylinder/ConeShape.java b/src/main/java/mypals/ml/shape/cylinder/ConeShape.java
index 9440117..cfb68e4 100644
--- a/src/main/java/mypals/ml/shape/cylinder/ConeShape.java
+++ b/src/main/java/mypals/ml/shape/cylinder/ConeShape.java
@@ -1,62 +1,34 @@
package mypals.ml.shape.cylinder;
+import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import net.minecraft.world.phys.Vec3;
import java.awt.*;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public class ConeShape extends CylinderShape {
- public ConeShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius, float height, Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.transformer = new CylinderTransformer(this,segments,radius,height);
- this.transformFunction = (defaultTransformer,shape)->transform.accept((CylinderTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- this.height = height;
- this.color = color;
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
- this.setAxis(circleAxis);
- syncLastToTarget();
+ public ConeShape(RenderingType type, Consumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius, float height, Color color, boolean seeThrough) {
+ super(type, transform, circleAxis, center, segments, radius, height, color, seeThrough);
}
- @Override
- public void generateCylinder() {
- ArrayList vs = new ArrayList<>();
- double halfH = height / 2.0;
-
- ArrayList baseRing = new ArrayList<>();
+ private List generateConeVertices(double halfH, int segments, float radius, CircleAxis axis) {
+ List vertices = new ArrayList<>();
for (int i = 0; i < segments; i++) {
double theta = 2 * Math.PI * i / segments;
double c = Math.cos(theta);
double s = Math.sin(theta);
- double x = 0, y = 0, z = 0;
-
- switch (axis) {
- case X -> {
- y = radius * c;
- z = radius * s;
- x = -halfH;
- baseRing.add(new Vec3(x, y, z));
- }
- case Y -> {
- x = radius * c;
- z = radius * s;
- y = -halfH;
- baseRing.add(new Vec3(x, y, z));
- }
- case Z -> {
- x = radius * c;
- y = radius * s;
- z = -halfH;
- baseRing.add(new Vec3(x, y, z));
- }
- default -> throw new IllegalStateException("Unexpected axis value: " + axis);
- }
+ Vec3 point = switch (axis) {
+ case X -> new Vec3(-halfH, radius * c, radius * s);
+ case Y -> new Vec3(radius * c, -halfH, radius * s);
+ case Z -> new Vec3(radius * c, radius * s, -halfH);
+ };
+ vertices.add(point);
}
Vec3 apex = switch (axis) {
@@ -64,34 +36,49 @@ public void generateCylinder() {
case Y -> new Vec3(0, halfH, 0);
case Z -> new Vec3(0, 0, halfH);
};
+ vertices.add(apex);
Vec3 baseCenter = switch (axis) {
case X -> new Vec3(-halfH, 0, 0);
case Y -> new Vec3(0, -halfH, 0);
case Z -> new Vec3(0, 0, -halfH);
};
+ vertices.add(baseCenter);
+
+ return vertices;
+ }
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+ List indices = new ArrayList<>();
+
+ float height = ((CylinderTransformer)this.transformer).getHeight(lerp);
+ int segments = ((CylinderTransformer)this.transformer).getSegments(lerp);
+ float radius = ((CylinderTransformer)this.transformer).getRadius(lerp);
+ double halfH = height / 2.0;
+
+ List verts = generateConeVertices(halfH, segments, radius, axis);
+ model_vertexes.addAll(verts);
+
+ int apexIndex = segments;
+ int baseCenterIndex = segments + 1;
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- Vec3 b0 = baseRing.get(i);
- Vec3 b1 = baseRing.get(next);
-
- vs.add(b0);
- vs.add(apex);
- vs.add(b1);
+ indices.add(i);
+ indices.add(apexIndex);
+ indices.add(next);
}
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- Vec3 b0 = baseRing.get(i);
- Vec3 b1 = baseRing.get(next);
-
- vs.add(baseCenter);
- vs.add(b1);
- vs.add(b0);
+ indices.add(baseCenterIndex);
+ indices.add(next);
+ indices.add(i);
}
- vertexes = vs;
-
+ this.indexBuffer = indices.stream().mapToInt(Integer::intValue).toArray();
}
+
}
diff --git a/src/main/java/mypals/ml/shape/cylinder/ConeWireframeShape.java b/src/main/java/mypals/ml/shape/cylinder/ConeWireframeShape.java
index 22fbf20..c7e0b32 100644
--- a/src/main/java/mypals/ml/shape/cylinder/ConeWireframeShape.java
+++ b/src/main/java/mypals/ml/shape/cylinder/ConeWireframeShape.java
@@ -2,49 +2,26 @@
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
-import mypals.ml.shape.basics.CircleLikeShape;
-import mypals.ml.shape.basics.tags.DrawableLine;
import net.minecraft.world.phys.Vec3;
-import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public class ConeWireframeShape extends CylinderWireframeShape {
- public ConeWireframeShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius, float height, float lineWidth, Color color, boolean seeThrough) {
- super(type, transform,circleAxis,center,segments, radius, height,lineWidth,color, seeThrough);
- }
- @Override
- public void generateCylinder() {
- ArrayList vs = new ArrayList<>();
- double halfH = height / 2.0;
-
- ArrayList baseRing = getBase(halfH);
-
- Vec3 apex = switch (axis) {
- case X -> new Vec3( halfH, 0, 0);
- case Y -> new Vec3(0, halfH, 0);
- case Z -> new Vec3(0, 0, halfH);
- default -> throw new IllegalStateException("Unexpected axis value: " + axis);
- };
-
- for (int i = 0; i < segments; i++) {
- int next = (i + 1) % segments;
- vs.add(baseRing.get(i));
- vs.add(baseRing.get(next));
- }
-
- for (int i = 0; i < segments; i++) {
- vs.add(baseRing.get(i));
- vs.add(apex);
- }
- vertexes = vs;
+ public ConeWireframeShape(RenderingType type,
+ Consumer transform,
+ CircleAxis circleAxis, Vec3 center,
+ int segments, float radius, float height,
+ float lineWidth, Color color, boolean seeThrough) {
+ super(type, transform, circleAxis, center, segments, radius, height, lineWidth, color, seeThrough);
}
+ private List generateConeVertices(double halfH, int segments, float radius, CircleAxis axis) {
+ List vertices = new ArrayList<>();
- private @NotNull ArrayList getBase(double halfH) {
- ArrayList baseRing = new ArrayList<>();
for (int i = 0; i < segments; i++) {
double theta = 2 * Math.PI * i / segments;
double c = Math.cos(theta);
@@ -54,10 +31,54 @@ public void generateCylinder() {
case X -> new Vec3(-halfH, radius * c, radius * s);
case Y -> new Vec3(radius * c, -halfH, radius * s);
case Z -> new Vec3(radius * c, radius * s, -halfH);
- default -> throw new IllegalStateException("Unexpected axis value: " + axis);
};
- baseRing.add(point);
+ vertices.add(point);
+ }
+
+ Vec3 apex = switch (axis) {
+ case X -> new Vec3(halfH, 0, 0);
+ case Y -> new Vec3(0, halfH, 0);
+ case Z -> new Vec3(0, 0, halfH);
+ };
+ vertices.add(apex);
+
+ Vec3 baseCenter = switch (axis) {
+ case X -> new Vec3(-halfH, 0, 0);
+ case Y -> new Vec3(0, -halfH, 0);
+ case Z -> new Vec3(0, 0, -halfH);
+ };
+ vertices.add(baseCenter);
+
+ return vertices;
+ }
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+ List indices = new ArrayList<>();
+
+ float height = ((CylinderWireframeTransformer)this.transformer).getHeight(lerp);
+ int segments = ((CylinderWireframeTransformer)this.transformer).getSegments(lerp);
+ float radius = ((CylinderWireframeTransformer)this.transformer).getRadius(lerp);
+ double halfH = height / 2.0;
+
+ List verts = generateConeVertices(halfH, segments, radius, axis);
+ model_vertexes.addAll(verts);
+
+ int apexIndex = segments;
+
+ for (int i = 0; i < segments; i++) {
+ int next = (i + 1) % segments;
+ indices.add(i);
+ indices.add(next);
}
- return baseRing;
+
+ for (int i = 0; i < segments; i++) {
+ indices.add(i);
+ indices.add(apexIndex);
+ }
+
+ this.indexBuffer = indices.stream().mapToInt(Integer::intValue).toArray();
}
+
}
+
diff --git a/src/main/java/mypals/ml/shape/cylinder/CylinderShape.java b/src/main/java/mypals/ml/shape/cylinder/CylinderShape.java
index 9e08966..cd641a3 100644
--- a/src/main/java/mypals/ml/shape/cylinder/CylinderShape.java
+++ b/src/main/java/mypals/ml/shape/cylinder/CylinderShape.java
@@ -3,221 +3,207 @@
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.CircleLikeShape;
+import mypals.ml.shape.basics.core.LineLikeShape;
import mypals.ml.shape.basics.tags.DrawableTriangle;
-import mypals.ml.transform.FloatValueTransformer;
-import mypals.ml.transform.IntValueTransformer;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.CircleModelInfo;
+import mypals.ml.transform.valueTransformers.FloatTransformer;
import net.minecraft.world.phys.Vec3;
-import com.mojang.blaze3d.vertex.PoseStack;
+
import java.awt.*;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
public class CylinderShape extends Shape implements CircleLikeShape, DrawableTriangle {
- public int segments = 180;
- public float radius = 1;
- public float height = 1;
public CircleAxis axis = CircleAxis.X;
- public ArrayList vertexes = new ArrayList<>();
- public Color color = Color.white;
- public CylinderShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius,float height, Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.transformer = new CylinderTransformer(this,segments,radius,height);
- this.transformFunction = (defaultTransformer,shape)->transform.accept((CylinderTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- this.height = height;
- this.color = color;
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
- this.setAxis(circleAxis);
+ public Color color = Color.WHITE;
+
+ public CylinderShape(RenderingType type, Consumer transform,
+ CircleAxis circleAxis, Vec3 center, int segments,
+ float radius, float height, Color color, boolean seeThrough) {
+ super(type, shape -> {}, color, center, seeThrough);
+
+ this.transformer = new CylinderTransformer(this, segments, radius, height,center);
+ this.transformFunction = t -> transform.accept((CylinderTransformer) this.transformer);
+ this.axis = circleAxis;
+ generateRawGeometry(false);
syncLastToTarget();
}
public CylinderShape(RenderingType type, boolean seeThrough) {
- super(type,seeThrough);
+ super(type, Color.WHITE, seeThrough);
}
+ void generateCylinderVertices(boolean lerp) {
+ model_vertexes.clear();
- public void generateCylinder() {
- ArrayList vs = new ArrayList<>();
+ float height = getHeight(lerp);
+ float radius = getRadius(lerp);
+ int segments = getSegments(lerp);
double halfH = height / 2.0;
- ArrayList bottomRing = new ArrayList<>();
- ArrayList topRing = new ArrayList<>();
-
for (int i = 0; i < segments; i++) {
- double theta = (2 * Math.PI * i) / segments;
+ double theta = 2 * Math.PI * i / segments;
double c = Math.cos(theta);
double s = Math.sin(theta);
- double x, y, z;
-
- switch (axis) {
- case X -> {
- y = radius * c;
- z = radius * s;
- x = 0;
- bottomRing.add(new Vec3(x - halfH, y, z));
- topRing.add(new Vec3(x + halfH, y, z));
- }
- case Y -> {
- x = radius * c;
- z = radius * s;
- y = 0;
- bottomRing.add(new Vec3(x, y - halfH, z));
- topRing.add(new Vec3(x, y + halfH, z));
- }
- case Z -> {
- x = radius * c;
- y = radius * s;
- z = 0;
- bottomRing.add(new Vec3(x, y, z - halfH));
- topRing.add(new Vec3(x, y, z + halfH));
- }
- }
+ Vec3 bottom = switch (axis) {
+ case X -> new Vec3(-halfH, radius * c, radius * s);
+ case Y -> new Vec3(radius * c, -halfH, radius * s);
+ case Z -> new Vec3(radius * c, radius * s, -halfH);
+ };
+ model_vertexes.add(bottom);
}
for (int i = 0; i < segments; i++) {
- int next = (i + 1) % segments;
-
- Vec3 b0 = bottomRing.get(i);
- Vec3 b1 = bottomRing.get(next);
- Vec3 t0 = topRing.get(i);
- Vec3 t1 = topRing.get(next);
-
- vs.add(b0);
- vs.add(t0);
- vs.add(t1);
+ double theta = 2 * Math.PI * i / segments;
+ double c = Math.cos(theta);
+ double s = Math.sin(theta);
- vs.add(b0);
- vs.add(t1);
- vs.add(b1);
+ Vec3 top = switch (axis) {
+ case X -> new Vec3( halfH, radius * c, radius * s);
+ case Y -> new Vec3(radius * c, halfH, radius * s);
+ case Z -> new Vec3(radius * c, radius * s, halfH);
+ };
+ model_vertexes.add(top);
}
- Vec3 baseCenter = switch (axis) {
+ model_vertexes.add(switch (axis) {
case X -> new Vec3(-halfH, 0, 0);
case Y -> new Vec3(0, -halfH, 0);
case Z -> new Vec3(0, 0, -halfH);
- };
+ });
+
+ model_vertexes.add(switch (axis) {
+ case X -> new Vec3( halfH, 0, 0);
+ case Y -> new Vec3(0, halfH, 0);
+ case Z -> new Vec3(0, 0, halfH);
+ });
+ }
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ generateCylinderVertices(lerp);
+
+ List indices = new ArrayList<>();
+ int segments = getSegments(lerp);
+
+ int bottomStart = 0;
+ int topStart = segments;
+ int bottomCenter = 2 * segments;
+ int topCenter = 2 * segments + 1;
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- Vec3 b0 = bottomRing.get(i);
- Vec3 b1 = bottomRing.get(next);
+ int b0 = bottomStart + i;
+ int b1 = bottomStart + next;
+ int t0 = topStart + i;
+ int t1 = topStart + next;
- vs.add(baseCenter);
- vs.add(b1);
- vs.add(b0);
+ indices.add(b0); indices.add(t0); indices.add(t1);
+ indices.add(b0); indices.add(t1); indices.add(b1);
}
- Vec3 topCenter = switch (axis) {
- case X -> new Vec3(halfH, 0, 0);
- case Y -> new Vec3(0, halfH, 0);
- case Z -> new Vec3(0, 0, halfH);
- };
-
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- Vec3 t0 = topRing.get(i);
- Vec3 t1 = topRing.get(next);
+ indices.add(bottomCenter);
+ indices.add(bottomStart + next);
+ indices.add(bottomStart + i);
+ }
- vs.add(topCenter);
- vs.add(t0);
- vs.add(t1);
+ for (int i = 0; i < segments; i++) {
+ int next = (i + 1) % segments;
+ indices.add(topCenter);
+ indices.add(topStart + i);
+ indices.add(topStart + next);
}
- vertexes = vs;
+ this.indexBuffer = indices.stream().mapToInt(Integer::intValue).toArray();
}
- public void setAxis(CircleAxis circleAxis){
+ public void setAxis(CircleAxis circleAxis) {
this.axis = circleAxis;
- generateCylinder();
+ generateRawGeometry(true);
}
- @Override
- public void draw(VertexBuilder builder) {
-
- builder.putColor(this.color);
- for(Vec3 v : vertexes){
- builder.putVertex(v.add(getShapeCenterPos()));
- }
- }
public static class CylinderTransformer extends DefaultTransformer {
- public IntValueTransformer segmentTransformer = new IntValueTransformer();
- public FloatValueTransformer radiusTransformer = new FloatValueTransformer();
- public FloatValueTransformer heightTransformer = new FloatValueTransformer();
- public CylinderTransformer(Shape managerShape,int seg,float rad,float height) {
- super(managerShape);
- setSegment(seg);
- setRadius(rad);
- setHeight(height);
- }
- public void setSegment(int segment){
- this.segmentTransformer.setTargetValue(segment);
- }
- public void setRadius(float radius){
- this.radiusTransformer.setTargetValue(radius);
+
+ public CircleModelInfo circleModelInfo;
+ public FloatTransformer heightTransformer;
+
+ public CylinderTransformer(Shape managedShape, int seg, float rad, float height,Vec3 vec3) {
+ super(managedShape,vec3);
+ circleModelInfo = new CircleModelInfo(seg,rad);
+ heightTransformer = new FloatTransformer(height);
}
- public void setHeight(float height){
- this.heightTransformer.setTargetValue(height);
+
+ public void setSegment(int segment) { this.circleModelInfo.setSegment(segment); }
+ public void setRadius(float radius) { this.circleModelInfo.setRadius(radius); }
+ public void setHeight(float height) { this.heightTransformer.setTargetValue(height); }
+
+ public float getRadius(boolean lerp) {
+ return circleModelInfo.getRadius(lerp);
}
- @Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof CylinderShape cylinderShape) {
- this.segmentTransformer.updateValue(cylinderShape::setSegments,deltaTime);
- this.radiusTransformer.updateValue(cylinderShape::setRadius,deltaTime);
- this.heightTransformer.updateValue(cylinderShape::setHeight,deltaTime);
- }
+
+ public int getSegments(boolean lerp) {
+ return circleModelInfo.getSegment(lerp);
}
+ public float getHeight(boolean lerp) { return heightTransformer.getValue(lerp); }
@Override
- public void syncLastToTarget(){
- this.segmentTransformer.syncLastToTarget();
- this.radiusTransformer.syncLastToTarget();
+ public void syncLastToTarget() {
+ this.circleModelInfo.syncLastToTarget();
this.heightTransformer.syncLastToTarget();
super.syncLastToTarget();
}
+ @Override
+ public boolean asyncModelInfo(){
+ return circleModelInfo.async() || heightTransformer.async();
+ }
}
+
@Override
public void setRadius(float radius) {
- boolean rebuild = this.radius != radius;
- this.radius = radius;
- if(rebuild){
- generateCylinder();
- }
-
+ ((CylinderTransformer)this.transformer).setRadius(radius);
}
public void setHeight(float height) {
- boolean rebuild = this.height != height;
- this.height = height;
- if(rebuild){
- generateCylinder();
- }
-
+ ((CylinderTransformer)this.transformer).setHeight(height);
}
@Override
public void setSegments(int segments) {
- boolean rebuild = this.segments != segments;
- this.segments = segments;
- if(rebuild){
- generateCylinder();
- }
+ ((CylinderTransformer)this.transformer).setSegment(segments);
}
@Override
- public float getRadius() {
- return radius;
+ public float getRadius(boolean lerp) {
+ return ((CylinderTransformer)this.transformer).getRadius(lerp);
}
@Override
- public int getSegments() {
- return segments;
+ public int getSegments(boolean lerp) {
+ return ((CylinderTransformer)this.transformer).getSegments(lerp);
}
- public float getHeight(){
- return height;
+
+ public float getHeight(boolean lerp) { return ((CylinderTransformer)this.transformer).getHeight(lerp); }
+
+ public void forceSetRadius(float radius) {
+ setRadius(radius);
+ ((CylinderTransformer)this.transformer).circleModelInfo.radiusTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetSegments(float segments) {
+ setRadius(segments);
+ ((CylinderTransformer)this.transformer).circleModelInfo.segmentTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetHeight(float height) {
+ setHeight(height);
+ ((CylinderTransformer)this.transformer).heightTransformer.syncLastToTarget();
+ generateRawGeometry(false);
}
}
+
diff --git a/src/main/java/mypals/ml/shape/cylinder/CylinderWireframeShape.java b/src/main/java/mypals/ml/shape/cylinder/CylinderWireframeShape.java
index 6797ebf..7f10a0d 100644
--- a/src/main/java/mypals/ml/shape/cylinder/CylinderWireframeShape.java
+++ b/src/main/java/mypals/ml/shape/cylinder/CylinderWireframeShape.java
@@ -6,144 +6,146 @@
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.core.LineLikeShape;
import mypals.ml.shape.basics.tags.DrawableLine;
-import mypals.ml.transform.FloatValueTransformer;
-import mypals.ml.transform.IntValueTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.LineModelInfo;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
+import org.joml.Matrix4f;
import java.awt.*;
import java.util.ArrayList;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
-public class CylinderWireframeShape extends CylinderShape implements DrawableLine,LineLikeShape {
- public float lineWidth;
+import static mypals.ml.Helpers.createViewMatrix;
- public CylinderWireframeShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius, float height, float lineWidth, Color color, boolean seeThrough) {
+public class CylinderWireframeShape extends CylinderShape implements DrawableLine, LineLikeShape {
+
+ public CylinderWireframeShape(RenderingType type, Consumer transform,
+ CircleAxis circleAxis, Vec3 center, int segments,
+ float radius, float height, float lineWidth, Color color, boolean seeThrough) {
super(type, seeThrough);
- this.transformer = new CylinderWireframeTransformer(this,segments,radius,height,lineWidth);
- this.transformFunction = (defaultTransformer,shape)->transform.accept((CylinderWireframeTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- this.height = height;
- this.lineWidth = lineWidth;
- this.color = color;
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
+ this.baseColor = color;
+ this.transformer = new CylinderWireframeTransformer(this, segments, radius, height, lineWidth,center);
+ this.transformFunction = t -> transform.accept((CylinderWireframeTransformer) this.transformer);
+
this.setAxis(circleAxis);
+ this.setWorldPosition(center);
+
syncLastToTarget();
}
+
@Override
- public void draw(VertexBuilder builder) {
- RenderSystem.lineWidth(lineWidth);
- builder.putColor(this.color);
- for (int i = 0; i < vertexes.size(); i += 2) {
- Vec3 a = vertexes.get(i);
- Vec3 b = vertexes.get(i + 1);
- addLineSegment(builder, a.add(getShapeCenterPos()), b.add(getShapeCenterPos()));
- }
- }
- @Override
- public void generateCylinder() {
- ArrayList vs = new ArrayList<>();
- double halfH = height / 2.0;
+ protected void generateRawGeometry(boolean lerp) {
+ generateCylinderVertices(lerp);
- ArrayList baseRing = getBase(halfH);
+ List indices = new ArrayList<>();
+ int segments = getSegments(lerp);
- ArrayList topRing = getTop(baseRing, halfH);
+ int bottomStart = 0;
+ int topStart = segments;
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- vs.add(baseRing.get(i));
- vs.add(baseRing.get(next));
+ indices.add(bottomStart + i);
+ indices.add(bottomStart + next);
}
for (int i = 0; i < segments; i++) {
int next = (i + 1) % segments;
- vs.add(topRing.get(i));
- vs.add(topRing.get(next));
+ indices.add(topStart + i);
+ indices.add(topStart + next);
}
for (int i = 0; i < segments; i++) {
- vs.add(baseRing.get(i));
- vs.add(topRing.get(i));
+ indices.add(bottomStart + i);
+ indices.add(topStart + i);
}
- vertexes = vs;
+ this.indexBuffer = indices.stream().mapToInt(Integer::intValue).toArray();
}
+ @Override
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
- private @NotNull ArrayList getTop(ArrayList baseRing, double halfH) {
- ArrayList topRing = new ArrayList<>();
- for (int i = 0; i < segments; i++) {
- Vec3 bottom = baseRing.get(i);
- Vec3 top = switch (axis) {
- case X -> new Vec3(halfH, bottom.y, bottom.z);
- case Y -> new Vec3(bottom.x, halfH, bottom.z);
- case Z -> new Vec3(bottom.x, bottom.y, halfH);
- };
- topRing.add(top);
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
+
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
+
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
}
- return topRing;
- }
- private @NotNull ArrayList getBase(double halfH) {
- ArrayList baseRing = new ArrayList<>();
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
- for (int i = 0; i < segments; i++) {
- double theta = 2 * Math.PI * i / segments;
- double c = Math.cos(theta);
- double s = Math.sin(theta);
-
- Vec3 point = switch (axis) {
- case X -> new Vec3(-halfH, radius * c, radius * s);
- case Y -> new Vec3(radius * c, -halfH, radius * s);
- case Z -> new Vec3(radius * c, radius * s, -halfH);
- };
- baseRing.add(point);
+ return false;
+ }
+ @Override
+ protected void drawInternal(VertexBuilder builder) {
+ RenderSystem.lineWidth(getLineWidth(true));
+ builder.putColor(this.color);
+
+ for (int i = 0; i < indexBuffer.length; i += 2) {
+ Vec3 a = model_vertexes.get(indexBuffer[i]);
+ Vec3 b = model_vertexes.get(indexBuffer[i + 1]);
+ addLineSegment(builder, a, b);
}
- return baseRing;
}
+ public void forceSetLineWidth(float width) {
+ setLineWidth(width);
+ ((CylinderWireframeTransformer)this.transformer).lineModelInfo.widthTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
@Override
public void setLineWidth(float width) {
- lineWidth = width;
+ ((CylinderWireframeTransformer)this.transformer).setWidth(width);
+ }
+ @Override
+ public float getLineWidth(boolean lerp) {
+ return ((CylinderWireframeTransformer)this.transformer).getWidth(lerp);
}
- public static class CylinderWireframeTransformer extends LineLikeShape.DefaultLineTransformer {
- public IntValueTransformer segmentTransformer = new IntValueTransformer();
- public FloatValueTransformer radiusTransformer = new FloatValueTransformer();
- public FloatValueTransformer heightTransformer = new FloatValueTransformer();
- public CylinderWireframeTransformer(Shape managerShape,int seg,float rad,float height,float lineWidth) {
- super(managerShape);
- setSegment(seg);
- setRadius(rad);
- setHeight(height);
- setWidth(lineWidth);
- }
- public void setSegment(int segment){
- this.segmentTransformer.setTargetValue(segment);
- }
- public void setRadius(float radius){
- this.radiusTransformer.setTargetValue(radius);
- }
- public void setHeight(float height){
- this.heightTransformer.setTargetValue(height);
+ public static class CylinderWireframeTransformer extends CylinderTransformer {
+ public LineModelInfo lineModelInfo;
+
+ public CylinderWireframeTransformer(Shape managedShape, int seg, float rad, float height, float lineWidth,Vec3 vec3) {
+ super(managedShape,seg,rad,height,vec3);
+ lineModelInfo = new LineModelInfo(lineWidth);
}
+
+ public void setWidth(float width) { lineModelInfo.setWidth(width); }
+ public float getWidth(boolean lerp) { return lineModelInfo.getWidth(lerp); }
+
@Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof CylinderShape cylinderShape) {
- this.segmentTransformer.updateValue(cylinderShape::setSegments,deltaTime);
- this.radiusTransformer.updateValue(cylinderShape::setRadius,deltaTime);
- this.heightTransformer.updateValue(cylinderShape::setHeight,deltaTime);
- }
+ public void syncLastToTarget() {
+ lineModelInfo.syncLastToTarget();
+ super.syncLastToTarget();
}
@Override
- public void syncLastToTarget(){
- this.segmentTransformer.syncLastToTarget();
- this.radiusTransformer.syncLastToTarget();
- this.heightTransformer.syncLastToTarget();
- super.syncLastToTarget();
+ public boolean asyncModelInfo(){
+ return super.asyncModelInfo() || lineModelInfo.async();
}
}
}
+
diff --git a/src/main/java/mypals/ml/shape/line/LineShape.java b/src/main/java/mypals/ml/shape/line/LineShape.java
index 1d8ec62..3d56aa4 100644
--- a/src/main/java/mypals/ml/shape/line/LineShape.java
+++ b/src/main/java/mypals/ml/shape/line/LineShape.java
@@ -2,87 +2,157 @@
import com.mojang.blaze3d.systems.RenderSystem;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
+import mypals.ml.collision.RayModelIntersection;
import mypals.ml.shape.Shape;
+import mypals.ml.shape.basics.core.LineLikeShape;
import mypals.ml.shape.basics.core.TwoPointsLineShape;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
+import net.minecraft.client.renderer.culling.Frustum;
+import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+import org.joml.Vector4f;
+
import java.awt.*;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.createViewMatrix;
public class LineShape extends Shape implements TwoPointsLineShape {
- public Vec3 start;
- public Vec3 end;
- public Color color;
- public float lineWidth;
+
public LineShape(RenderingType type,
- BiConsumer transform,
- Vec3 start,
- Vec3 end,
- Color color,
- float lineWidth,
- boolean seeThrough)
- {
- super(type, seeThrough);
- this.start = start;
- this.end = end;
- this.color = color;
- setShapeCenterPos(calculateShapeCenterPos());
- this.lineWidth = lineWidth;
- this.transformer = new TwoPointsLineTransformer(this);
- this.transformer.setShapeCenterPos(this.getShapeCenterPos());
- this.transformFunction = (defaultTransformer,shape)->transform.accept((TwoPointsLineTransformer) this.transformer, shape);
- ((TwoPointsLineTransformer)this.transformer).setStart(this.getStart());
- ((TwoPointsLineTransformer)this.transformer).setEnd(this.getEnd());
- ((TwoPointsLineTransformer)this.transformer).setWidth(this.lineWidth);
+ Consumer transform,
+ Vec3 start, Vec3 end,
+ Color color, float lineWidth,
+ boolean seeThrough) {
+
+ super(type, color, seeThrough);
+
+ this.transformer = new TwoPointsLineTransformer(this,start,end,lineWidth,Vec3.ZERO);
+ this.transformFunction = (defaultTransformer) ->
+ transform.accept((TwoPointsLineTransformer) this.transformer);
+
syncLastToTarget();
+ generateRawGeometry(false);
+ this.transformer.setShapeWorldPivot(calculateShapeCenterPos());
}
- @Override
+
public Vec3 calculateShapeCenterPos() {
- double centerX = (getStart().x + getEnd().x) / 2.0;
- double centerY = (getStart().y + getEnd().y) / 2.0;
- double centerZ = (getStart().z + getEnd().z) / 2.0;
+ double centerX = (getStart(false).x + getEnd(false).x) / 2.0;
+ double centerY = (getStart(false).y + getEnd(false).y) / 2.0;
+ double centerZ = (getStart(false).z + getEnd(false).z) / 2.0;
return new Vec3(centerX, centerY, centerZ);
}
-
- @Override
- public void setShapeCenterPos(Vec3 newCenter) {
- super.setShapeCenterPos(newCenter);
- Vec3 currentCenter = calculateShapeCenterPos();
- Vec3 offset = newCenter.subtract(currentCenter);
-
- setStart(getStart().add(offset));
- setEnd(getEnd().add(offset));
+ public void forceSetStart(Vec3 start) {
+ setStart(start);
+ ((TwoPointsLineTransformer)this.transformer).lineModelInfo.startPointTransformer.syncLastToTarget();
+ generateRawGeometry(false);
}
-
+ public void forceSetEnd(Vec3 end) {
+ setEnd(end);
+ ((TwoPointsLineTransformer)this.transformer).lineModelInfo.endPointTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetLineWidth(float width) {
+ setLineWidth(width);
+ ((TwoPointsLineTransformer)this.transformer).lineModelInfo.widthTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
@Override
public void setStart(Vec3 start) {
- this.start = start;
+ ((TwoPointsLineTransformer)this.transformer).setStart(start);
}
@Override
public void setEnd(Vec3 end) {
- this.end = end;
+ ((TwoPointsLineTransformer)this.transformer).setEnd(end);
}
@Override
public void setLineWidth(float width) {
- this.lineWidth = width;
+ ((TwoPointsLineTransformer)this.transformer).setWidth(width);
}
@Override
- public Vec3 getStart() {
- return start;
+ public float getLineWidth(boolean lerp) {
+ return ((TwoPointsLineTransformer)this.transformer).getWidth(lerp);
}
+
@Override
- public Vec3 getEnd() {
- return end;
- }
+ public Vec3 getStart(boolean lerp) { return ((TwoPointsLineTransformer)this.transformer).getStart(lerp);}
+
+ @Override
+ public Vec3 getEnd(boolean lerp) { return ((TwoPointsLineTransformer)this.transformer).getEnd(lerp);}
+
+ public float getWidth(boolean lerp) { return ((TwoPointsLineTransformer)this.transformer).getWidth(lerp);}
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+
+ Vec3 start = getStart(lerp);
+ Vec3 end = getEnd(lerp);
+ Vec3 center = calculateShapeCenterPos();
+
+ this.transformer.setShapeWorldPivot(center);
+ this.transformer.world.position.syncLastToTarget();
+
+ Vec3 localA = start.subtract(center);
+ Vec3 localB = end.subtract(center);
+
+ model_vertexes.add(localA);
+ model_vertexes.add(localB);
+ this.indexBuffer = new int[] { 0, 1 };
+ }
@Override
- public void draw(VertexBuilder builder) {
- RenderSystem.lineWidth(lineWidth);
- builder.putColor(color);
- addLineSegment(builder,getStart(),getEnd());
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
+
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
+
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
+
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
+ }
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
+
+ return false;
}
+
+ @Override
+ public RayModelIntersection.HitResult isPlayerLookingAt(){
+ return new RayModelIntersection.HitResult(false,null,-1);
+ }
+ protected void drawInternal(VertexBuilder builder) {
+ RenderSystem.lineWidth(getWidth(true));
+ builder.putColor(baseColor);
+ addLineSegment(builder,model_vertexes.getFirst(),model_vertexes.getLast());
+ }
}
+
diff --git a/src/main/java/mypals/ml/shape/line/StripLineShape.java b/src/main/java/mypals/ml/shape/line/StripLineShape.java
index f504179..da1800f 100644
--- a/src/main/java/mypals/ml/shape/line/StripLineShape.java
+++ b/src/main/java/mypals/ml/shape/line/StripLineShape.java
@@ -2,128 +2,180 @@
import com.mojang.blaze3d.systems.RenderSystem;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
+import mypals.ml.collision.RayModelIntersection;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.core.LineLikeShape;
import mypals.ml.shape.basics.core.StripLineLikeShape;
+import mypals.ml.shape.basics.core.TwoPointsLineShape;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.createViewMatrix;
public class StripLineShape extends Shape implements StripLineLikeShape {
- public List vertexes = new ArrayList<>();
- public float lineWidth;
- public Color color;
- public List vertexColors = new ArrayList<>();
- public StripLineShape(RenderingType type, Color color,float lineWidth,boolean seeThrough) {
- super(type,seeThrough);
- this.color = color;
- this.lineWidth = lineWidth;
+ private List vertexes = new ArrayList<>();
+ private List vertexColors = new ArrayList<>();
+
+ public StripLineShape(RenderingType type,
+ Consumer transform,
+ List vertexes,
+ float lineWidth,
+ Color color,
+ boolean seeThrough) {
+ super(type, color, seeThrough);
+ this.vertexes = new ArrayList<>(vertexes);
+ this.transformer = new SimpleLineTransformer(this,lineWidth,this.calculateShapeCenterPos());
+ this.transformFunction = (defaultTransformer) ->
+ transform.accept((SimpleLineTransformer) this.transformer);
- }
- public StripLineShape(RenderingType type, BiConsumer super LineLikeShape.DefaultLineTransformer, Shape> transform, List vertexes, float lineWidth, Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.setVertexes(vertexes);
- this.color = color;
- this.lineWidth = lineWidth;
- this.transformer = new LineLikeShape.DefaultLineTransformer(this);
- this.transformer.setShapeCenterPos(this.calculateShapeCenterPos());
- this.transformFunction = (defaultTransformer,shape)->transform.accept((LineLikeShape.DefaultLineTransformer) this.transformer, shape);
- ((LineLikeShape.DefaultLineTransformer)this.transformer).setWidth(this.lineWidth);
syncLastToTarget();
+ generateRawGeometry(false);
}
- @Override
+
+
public Vec3 calculateShapeCenterPos() {
- if (vertexes.isEmpty()) {
- return Vec3.ZERO;
- }
+ if (vertexes.isEmpty()) return Vec3.ZERO;
double sumX = 0, sumY = 0, sumZ = 0;
- for (Vec3 vertex : vertexes) {
- sumX += vertex.x;
- sumY += vertex.y;
- sumZ += vertex.z;
+ for (Vec3 v : vertexes) {
+ sumX += v.x;
+ sumY += v.y;
+ sumZ += v.z;
}
- int count = vertexes.size();
- return new Vec3(sumX / count, sumY / count, sumZ / count);
+ double n = vertexes.size();
+ return new Vec3(sumX / n, sumY / n, sumZ / n);
+ }
+ @Override
+ public RayModelIntersection.HitResult isPlayerLookingAt(){
+ return new RayModelIntersection.HitResult(false,null,-1);
}
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+ if (vertexes.size() < 2) return;
+ Vec3 localCenter = calculateShapeCenterPos();
+ transformer.setShapeWorldPivot(localCenter);
+ for (Vec3 v : vertexes) {
+ model_vertexes.add(v.subtract(localCenter));
+ }
- public void setVertexColors(List colors){
- vertexColors = colors;
+ int n = model_vertexes.size();
+ indexBuffer = new int[n];
+ for (int i = 0; i < n; i++) indexBuffer[i] = i;
}
@Override
- public void setShapeCenterPos(Vec3 newCenter) {
- super.setShapeCenterPos(newCenter);
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
- if (vertexes.isEmpty()) {
- return;
- }
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
- Vec3 currentCenter = calculateShapeCenterPos();
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
- Vec3 offset = newCenter.subtract(currentCenter);
+ Matrix4f viewMatrix = createViewMatrix(camera);
- vertexes.replaceAll(vec3 -> vec3.add(offset));
- //syncLastToTarget();
- }
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
- @Override
- public void setVertexes(List vertexes) {
- this.vertexes = vertexes;
- }
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
- @Override
- public List getVertexes() {
- return this.vertexes;
+ if (isVertexInFrustum(center, mvp)) return true;
+
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
+ }
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
+
+ return false;
}
- @Override
- public void draw(VertexBuilder builder) {
- RenderSystem.lineWidth(lineWidth);
- int n = vertexes.size();
- if (n < 2) return;
- builder.putColor(0x00000000F);
- Vec3 first = vertexes.getFirst();
- builder.putVertex((float) first.x, (float) first.y, (float) first.z, 0, 0, 0);
+ @Override
+ protected void drawInternal(VertexBuilder builder) {
+ RenderSystem.lineWidth(getLineWidth(true));
+
+ int n = model_vertexes.size();
+ if (n < 2) return;;
+ Vec3 first = model_vertexes.getFirst();
+ builder.putColor(new Color(0, 0, 0, 0));
+ builder.putVertex(first, Vec3.ZERO);
for (int i = 0; i < n; i++) {
- Color vColor = color;
- if(i 0 ? nextDir : prevDir;
+ normal = fallback.normalize();
+ }
}
- Vec3 pos = vertexes.get(i);
- builder.putVertex((float) pos.x, (float) pos.y, (float) pos.z,
- (float) normal.x, (float) normal.y, (float) normal.z);
+ Vec3 pos = model_vertexes.get(i);
+ builder.putVertex(pos, normal);
}
- builder.putColor(0x00000000F);
- Vec3 last = vertexes.getLast();
- builder.putVertex((float) last.x, (float) last.y, (float) last.z, 0, 0, 0);
+ Vec3 last = model_vertexes.get(n - 1);
+ builder.putColor(new Color(0, 0, 0, 0));
+ builder.putVertex(last, Vec3.ZERO);
+ }
+ @Override
+ public void setVertexes(List vertexes) {
+ this.vertexes = new ArrayList<>(vertexes);
+ generateRawGeometry(false);
}
+ @Override
+ public List getVertexes() {
+ return vertexes;
+ }
+
+ public void setVertexColors(List colors) {
+ this.vertexColors = new ArrayList<>(colors);
+ }
+ public void forceSetLineWidth(float width) {
+ setLineWidth(width);
+ ((SimpleLineTransformer)this.transformer).lineModelInfo.widthTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
@Override
public void setLineWidth(float width) {
- this.lineWidth = width;
+ ((SimpleLineTransformer)this.transformer).setWidth(width);
+ }
+
+ @Override
+ public float getLineWidth(boolean lerp) {
+ return ((SimpleLineTransformer)this.transformer).getWidth(lerp);
}
}
+
diff --git a/src/main/java/mypals/ml/shape/model/ObjModelShape.java b/src/main/java/mypals/ml/shape/model/ObjModelShape.java
index 4dc004a..17e32e6 100644
--- a/src/main/java/mypals/ml/shape/model/ObjModelShape.java
+++ b/src/main/java/mypals/ml/shape/model/ObjModelShape.java
@@ -2,6 +2,7 @@
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.Resource;
@@ -13,52 +14,62 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
-import java.util.function.BiConsumer;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
public class ObjModelShape extends Shape {
- public Color color = Color.white;
public Vec3 modelCenter = Vec3.ZERO;
public SimpleOBJModel model;
- public ObjModelShape(RenderingType type, BiConsumer super DefaultTransformer, Shape> transform, ResourceLocation resourceLocation, Vec3 center, Color color) {
- this(type, transform,resourceLocation,center,color,false);
+ public ObjModelShape(RenderingType type,
+ Consumer transform,
+ ResourceLocation resourceLocation,
+ Vec3 center,
+ Color color) {
+ this(type, transform, resourceLocation, center, color, false);
}
- protected ObjModelShape(RenderingType type) {
- super(type);
- }
- protected ObjModelShape(RenderingType type, boolean seeThrough) {
- super(type, seeThrough);
+ protected ObjModelShape(RenderingType type,Color color, boolean seeThrough) {
+ super(type,color, seeThrough);
}
- public ObjModelShape(RenderingType type, BiConsumer super DefaultTransformer, Shape> transform, ResourceLocation resourceLocation, Vec3 center, Color color, boolean seeThrough) {
- super(type, transform, seeThrough);
- this.transformer = new DefaultTransformer(this);
+ public ObjModelShape(RenderingType type,
+ Consumer transform,
+ ResourceLocation resourceLocation,
+ Vec3 center,
+ Color color,
+ boolean seeThrough) {
+ super(type,transform, color,center, seeThrough);
try {
loadOBJ(resourceLocation);
- }catch (IOException e){
+ } catch (IOException e) {
e.printStackTrace();
}
- this.color = color;
- this.centerPoint = center;
- this.centerPoint = calculateShapeCenterPos();
- this.transformer.setShapeCenterPos(center);
+
+
+ this.transformer.setShapeWorldPivot(center);
+
+ syncLastToTarget();
+ generateRawGeometry(false);
}
public static class SimpleOBJModel {
- public ArrayList vertices = new ArrayList<>();
- public ArrayList faces = new ArrayList<>();
+ public final ArrayList vertices = new ArrayList<>();
+ public final ArrayList faces = new ArrayList<>();
}
-
public void loadOBJ(ResourceLocation location) throws IOException {
ResourceManager manager = Minecraft.getInstance().getResourceManager();
+ if (manager.getResource(location).isEmpty()) return;
+
+ Optional optional = manager.getResource(location);
+ if (optional.isEmpty()) return;
- if(manager.getResource(location).isPresent()) {
- Resource resource = manager.getResource(location).get();
- BufferedReader reader = new BufferedReader(new InputStreamReader(resource.open()));
+ Resource resource = optional.get();
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.open()))) {
SimpleOBJModel m = new SimpleOBJModel();
String line;
while ((line = reader.readLine()) != null) {
@@ -67,64 +78,85 @@ public void loadOBJ(ResourceLocation location) throws IOException {
String[] parts = line.split("\\s+");
switch (parts[0]) {
- case "v":
+ case "v" -> {
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
m.vertices.add(new Vec3(x, y, z));
- break;
- case "f":
+ }
+ case "f" -> {
int[] faceIndices = new int[parts.length - 1];
for (int i = 1; i < parts.length; i++) {
- String vert = parts[i];
- String[] vParts = vert.split("/");
+ String[] vParts = parts[i].split("/");
faceIndices[i - 1] = Integer.parseInt(vParts[0]) - 1;
}
m.faces.add(faceIndices);
- break;
+ }
}
}
this.model = m;
}
+
+ }
+
+
+ public Vec3 calculateShapeCenterPos() {
+ if (model == null || model.vertices.isEmpty()) return Vec3.ZERO;
+
+ Vec3 min = new Vec3(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
+ Vec3 max = new Vec3(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
+
+ for (Vec3 v : model.vertices) {
+ min = new Vec3(Math.min(min.x, v.x), Math.min(min.y, v.y), Math.min(min.z, v.z));
+ max = new Vec3(Math.max(max.x, v.x), Math.max(max.y, v.y), Math.max(max.z, v.z));
+ }
+
+ this.modelCenter = new Vec3(
+ (min.x + max.x) / 2,
+ (min.y + max.y) / 2,
+ (min.z + max.z) / 2
+ );
+
+ return modelCenter;
}
@Override
- public void draw(VertexBuilder builder) {
- builder.putColor(this.color);
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
if (model == null) return;
+
+ model_vertexes.addAll(model.vertices);
+
+ List indices = new ArrayList<>();
for (int[] face : model.faces) {
if (face.length < 3) continue;
-
for (int i = 1; i < face.length - 1; i++) {
- Vec3 v0 = model.vertices.get(face[0]).subtract(modelCenter).add(centerPoint);
- Vec3 v1 = model.vertices.get(face[i]).subtract(modelCenter).add(centerPoint);
- Vec3 v2 = model.vertices.get(face[i + 1]).subtract(modelCenter).add(centerPoint);
-
- builder.putVertex(v0);
- builder.putVertex(v1);
- builder.putVertex(v2);
+ indices.add(face[0]);
+ indices.add(face[i]);
+ indices.add(face[i + 1]);
}
}
+
+ this.indexBuffer = indices.stream().mapToInt(i -> i).toArray();
}
+
@Override
- public Vec3 calculateShapeCenterPos(){
- if (model == null || model.vertices.isEmpty()) return centerPoint;
+ protected void drawInternal(VertexBuilder builder) {
+ if (model_vertexes.isEmpty() || indexBuffer == null || indexBuffer.length < 3)
+ return;
- Vec3 min = new Vec3(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
- Vec3 max = new Vec3(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
+ builder.putColor(baseColor);
- for (Vec3 v : model.vertices) {
- min = new Vec3(Math.min(min.x,v.x), Math.min(min.y,v.y), Math.min(min.z,v.z));
- max = new Vec3(Math.max(max.x,v.x), Math.max(max.y,v.y), Math.max(max.z,v.z));
- }
+ for (int i = 0; i < indexBuffer.length; i += 3) {
+ Vec3 v0 = model_vertexes.get(indexBuffer[i]);
+ Vec3 v1 = model_vertexes.get(indexBuffer[i + 1]);
+ Vec3 v2 = model_vertexes.get(indexBuffer[i + 2]);
- Vec3 modelCenter = new Vec3(
- (min.x + max.x)/2,
- (min.y + max.y)/2,
- (min.z + max.z)/2
- );
- this.modelCenter = modelCenter;
- return this.centerPoint;
+ builder.putVertex(v0);
+ builder.putVertex(v1);
+ builder.putVertex(v2);
+ }
}
}
+
diff --git a/src/main/java/mypals/ml/shape/model/ObjModelShapeOutline.java b/src/main/java/mypals/ml/shape/model/ObjModelShapeOutline.java
index 27922ce..83132e3 100644
--- a/src/main/java/mypals/ml/shape/model/ObjModelShapeOutline.java
+++ b/src/main/java/mypals/ml/shape/model/ObjModelShapeOutline.java
@@ -4,72 +4,116 @@
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.core.LineLikeShape;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
import java.awt.*;
import java.io.IOException;
+import java.util.List;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.createViewMatrix;
public class ObjModelShapeOutline extends ObjModelShape implements LineLikeShape {
public float lineWidth;
- public Color color = Color.white;
- public ObjModelShapeOutline(RenderingType type, BiConsumer transform, ResourceLocation resourceLocation, Vec3 center,float lineWidth, Color color) {
- this(type, transform,resourceLocation,center,lineWidth,color,false);
- }
- protected ObjModelShapeOutline(RenderingType type) {
- super(type);
- }
+ public ObjModelShapeOutline(RenderingType type,
+ Consumer transform,
+ ResourceLocation resourceLocation,
+ Vec3 center,
+ float lineWidth,
+ Color color,
+ boolean seeThrough) {
+ super(type, (d) -> {}, resourceLocation, center, color, seeThrough);
- protected ObjModelShapeOutline(RenderingType type, boolean seeThrough) {
- super(type, seeThrough);
- }
+ this.transformer = new SimpleLineTransformer(this,lineWidth,center);
+ this.transformFunction = (t) -> transform.accept((SimpleLineTransformer) this.transformer);
- public ObjModelShapeOutline(RenderingType type, BiConsumer transform, ResourceLocation resourceLocation, Vec3 center,float lineWidth, Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.transformer = new DefaultLineTransformer(this);
- this.transformFunction = (tr,s)->{transform.accept((DefaultLineTransformer)this.transformer,this);};
- try {
- loadOBJ(resourceLocation);
- }catch (IOException e){
- e.printStackTrace();
- }
this.lineWidth = lineWidth;
- ((DefaultLineTransformer)this.transformer).setWidth(this.lineWidth);
+ this.baseColor = color;
+
+ ((SimpleLineTransformer) this.transformer).setWidth(this.lineWidth);
+ this.transformer.setShapeWorldPivot(center);
+
syncLastToTarget();
- this.color = color;
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
}
@Override
public void setLineWidth(float width) {
this.lineWidth = width;
+ if (this.transformer instanceof SimpleLineTransformer slt) {
+ slt.setWidth(width);
+ }
}
@Override
- public void draw(VertexBuilder builder) {
- RenderSystem.lineWidth(this.lineWidth);
- builder.putColor(this.color);
+ public float getLineWidth(boolean lerp) {
+ return ((SimpleLineTransformer)this.transformer).getWidth(lerp);
+ }
+
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ super.generateRawGeometry(lerp);
+ }
+ @Override
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
+
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
- if (model == null) return;
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
+
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
+ }
+
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
+
+ return false;
+ }
+ @Override
+ protected void drawInternal(VertexBuilder builder) {
+ if (model_vertexes.isEmpty() || indexBuffer == null || indexBuffer.length < 3)
+ return;
+
+ RenderSystem.lineWidth(this.lineWidth);
+ builder.putColor(this.baseColor);
for (int[] face : model.faces) {
int n = face.length;
if (n < 2) continue;
for (int i = 0; i < n; i++) {
- int next = (i + 1) % n;
-
- Vec3 v0 = model.vertices.get(face[i]).subtract(modelCenter).add(centerPoint);
- Vec3 v1 = model.vertices.get(face[next]).subtract(modelCenter).add(centerPoint);
+ Vec3 v0 = model_vertexes.get(face[i]);
+ Vec3 v1 = model_vertexes.get(face[(i + 1) % n]);
- addLineSegment(builder,v0,v1);
+ addLineSegment(builder, v0, v1);
}
}
- }
-
+ }
}
+
diff --git a/src/main/java/mypals/ml/shape/round/FaceCircleShape.java b/src/main/java/mypals/ml/shape/round/FaceCircleShape.java
index 3afde93..dc5d0fd 100644
--- a/src/main/java/mypals/ml/shape/round/FaceCircleShape.java
+++ b/src/main/java/mypals/ml/shape/round/FaceCircleShape.java
@@ -1,159 +1,131 @@
package mypals.ml.shape.round;
-
-import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.CircleLikeShape;
-import mypals.ml.shape.basics.tags.DrawableTriangle;
-import mypals.ml.transform.FloatValueTransformer;
-import mypals.ml.transform.IntValueTransformer;
+import mypals.ml.shape.cylinder.CylinderShape;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.CircleModelInfo;
import net.minecraft.world.phys.Vec3;
-import com.mojang.blaze3d.vertex.PoseStack;
import java.awt.*;
-import java.util.ArrayList;
-import java.util.function.BiConsumer;
+import java.util.function.Consumer;
-public class FaceCircleShape extends Shape implements CircleLikeShape, DrawableTriangle {
+public class FaceCircleShape extends Shape implements CircleLikeShape {
- public int segments;
- public float radius;
public CircleAxis axis = CircleAxis.X;
- public ArrayList vertexes = new ArrayList<>();
- public Color color;
-
- public FaceCircleShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius,Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.transformer = new FaceCircleTransformer(this,segments,radius);
- this.transformFunction = (defaultTransformer,shape)->transform.accept((FaceCircleTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- this.color = color;
- ((FaceCircleTransformer)this.transformer).setRadius(this.radius);
- ((FaceCircleTransformer)this.transformer).setSegment(this.segments);
- this.setAxis(circleAxis);
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
+
+ public FaceCircleShape(RenderingType type,
+ Consumer transform,
+ CircleAxis axis,
+ Vec3 center,
+ int segments,
+ float radius,
+ Color color,
+ boolean seeThrough) {
+ super(type, color, seeThrough);
+ this.axis = axis;
+
+ this.transformer = new FaceCircleTransformer(this, segments, radius,center);
+ this.transformFunction = (t) -> transform.accept((FaceCircleTransformer) this.transformer);
+
+ generateRawGeometry(true);
syncLastToTarget();
}
- /*@Override
- public Vec3 calculateShapeCenterPos() {
- if (vertexes.isEmpty()) {
- return Vec3.ZERO;
- }
- double sumX = 0, sumY = 0, sumZ = 0;
- for (Vec3 vertex : vertexes) {
- sumX += vertex.x;
- sumY += vertex.y;
- sumZ += vertex.z;
- }
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+ if (this.getSegments(lerp) < 3) return;
+
+ int segments = getSegments(lerp);
+ float radius = getRadius(lerp);
+
+ model_vertexes.add(Vec3.ZERO);
- int count = vertexes.size();
- return new Vec3(sumX / count, sumY / count, sumZ / count);
- }*/
- public void generateCircle(){
- ArrayList vs = new ArrayList<>();
- Vec3 center = Vec3.ZERO;
for (int i = 0; i < segments; i++) {
- double theta = (2 * Math.PI * i) / segments;
- double x, y, z;
+ double theta = 2 * Math.PI * i / segments;
+ double x = 0, y = 0, z = 0;
switch (axis) {
case X -> {
- y = center.y + radius * Math.cos(theta);
- z = center.z + radius * Math.sin(theta);
- x = center.x;
+ y = radius * Math.cos(theta);
+ z = radius * Math.sin(theta);
+ x = 0;
}
case Y -> {
- x = center.x + radius * Math.cos(theta);
- z = center.z + radius * Math.sin(theta);
- y = center.y;
+ x = radius * Math.cos(theta);
+ z = radius * Math.sin(theta);
+ y = 0;
}
case Z -> {
- x = center.x + radius * Math.cos(theta);
- y = center.y + radius * Math.sin(theta);
- z = center.z;
+ x = radius * Math.cos(theta);
+ y = radius * Math.sin(theta);
+ z = 0;
}
- default -> throw new IllegalStateException("Unexpected axis value: " + axis);
}
-
- vs.add(new Vec3(x, y, z));
- }
- if (!vs.isEmpty()) {
- vs.add(vs.getFirst());
- }
- vertexes = vs;
- }
- public void setAxis(CircleAxis circleAxis){
- this.axis = circleAxis;
- generateCircle();
- }
- @Override
- public void draw(VertexBuilder builder) {
-
- builder.putColor(this.color);
-
- builder.putVertex(this.centerPoint);
- for(Vec3 v : vertexes){
- builder.putVertex(v.add(getShapeCenterPos()));
+ model_vertexes.add(new Vec3(x, y, z));
}
- }
- public static class FaceCircleTransformer extends DefaultTransformer {
- public IntValueTransformer segmentTransformer = new IntValueTransformer();
- public FloatValueTransformer radiusTransformer = new FloatValueTransformer();
- public FaceCircleTransformer(Shape managerShape,int seg,float rad) {
- super(managerShape);
- setSegment(seg);
- setRadius(rad);
- }
- public void setSegment(int segment){
- this.segmentTransformer.setTargetValue(segment);
- }
- public void setRadius(float radius){
- this.radiusTransformer.setTargetValue(radius);
- }
- @Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof FaceCircleShape circleShape) {
- this.segmentTransformer.updateValue(circleShape::setSegments,deltaTime);
- this.radiusTransformer.updateValue(circleShape::setRadius,deltaTime);
- }
- }
- @Override
- public void syncLastToTarget(){
- this.segmentTransformer.syncLastToTarget();
- this.radiusTransformer.syncLastToTarget();
- super.syncLastToTarget();
+ indexBuffer = new int[segments * 3];
+ for (int i = 0; i < segments; i++) {
+ int next = (i + 1) % segments;
+ indexBuffer[i * 3] = 0; // center
+ indexBuffer[i * 3 + 1] = i + 1;
+ indexBuffer[i * 3 + 2] = next + 1;
}
}
+
@Override
public void setRadius(float radius) {
- boolean rebuild = this.radius != radius;
- this.radius = radius;
- if(rebuild){
- generateCircle();
- }
-
+ ((FaceCircleTransformer)this.transformer).setRadius(radius);
}
@Override
public void setSegments(int segments) {
- boolean rebuild = this.segments != segments;
- this.segments = segments;
- if(rebuild){
- generateCircle();
- }
+ ((FaceCircleTransformer)this.transformer).setSegment(segments);
+ }
+ public void forceSetRadius(float radius) {
+ setRadius(radius);
+ ((FaceCircleTransformer)this.transformer).circleModelInfo.radiusTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetSegments(float segments) {
+ setRadius(segments);
+ ((FaceCircleTransformer)this.transformer).circleModelInfo.segmentTransformer.syncLastToTarget();
+ generateRawGeometry(false);
}
-
@Override
- public float getRadius() {
- return radius;
+ public float getRadius(boolean lerp) {
+ return ((FaceCircleTransformer)this.transformer).getRadius(lerp);
}
@Override
- public int getSegments() {
- return segments;
+ public int getSegments(boolean lerp) {
+ return ((FaceCircleTransformer)this.transformer).getSegment(lerp);
+ }
+
+ public static class FaceCircleTransformer extends DefaultTransformer {
+ public CircleModelInfo circleModelInfo;
+ public FaceCircleTransformer(Shape managedShape, int seg, float rad,Vec3 center) {
+ super(managedShape,center);
+ circleModelInfo = new CircleModelInfo(seg,rad);
+ }
+
+ public void setSegment(int segment) { this.circleModelInfo.setSegment(segment); }
+ public void setRadius(float radius) { this.circleModelInfo.setRadius(radius); }
+ public int getSegment(boolean lerp) {return this.circleModelInfo.getSegment(lerp); }
+ public float getRadius(boolean lerp) {return this.circleModelInfo.getRadius(lerp); }
+
+ @Override
+ public void updateTickDelta(float delta) {
+ this.circleModelInfo.update(delta);
+ super.updateTickDelta(delta);
+ }
+ @Override
+ public void syncLastToTarget() {
+ this.circleModelInfo.syncLastToTarget();
+ super.syncLastToTarget();
+ }
+ public boolean asyncModelInfo(){
+ return circleModelInfo.async();
+ }
}
}
diff --git a/src/main/java/mypals/ml/shape/round/LineCircleShape.java b/src/main/java/mypals/ml/shape/round/LineCircleShape.java
index f5312a4..5c6794d 100644
--- a/src/main/java/mypals/ml/shape/round/LineCircleShape.java
+++ b/src/main/java/mypals/ml/shape/round/LineCircleShape.java
@@ -1,149 +1,252 @@
package mypals.ml.shape.round;
+import com.mojang.blaze3d.systems.RenderSystem;
+import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.CircleLikeShape;
import mypals.ml.shape.basics.core.LineLikeShape;
-import mypals.ml.shape.line.StripLineShape;
-import mypals.ml.transform.FloatValueTransformer;
-import mypals.ml.transform.IntValueTransformer;
+import mypals.ml.shape.basics.core.TwoPointsLineShape;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.CircleModelInfo;
+import mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer.LineModelInfo;
+import net.minecraft.client.Camera;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.world.phys.Vec3;
-import com.mojang.blaze3d.vertex.PoseStack;
+import org.joml.Matrix4f;
+
import java.awt.*;
-import java.util.ArrayList;
-import java.util.function.BiConsumer;
+import java.util.List;
+import java.util.function.Consumer;
+
+import static mypals.ml.Helpers.createViewMatrix;
-public class LineCircleShape extends StripLineShape implements CircleLikeShape {
+public class LineCircleShape extends Shape implements CircleLikeShape, LineLikeShape {
- public int segments ;
- public float radius;
public CircleAxis axis = CircleAxis.X;
- public LineCircleShape(RenderingType type, BiConsumer transform, CircleAxis circleAxis, Vec3 center, int segments, float radius, float lineWidth, Color color, boolean seeThrough) {
- super(type,color,lineWidth, seeThrough);
- this.transformer = new LineCircleTransformer(this,segments,radius);
- this.transformFunction = (defaultTransformer,shape)->transform.accept((LineCircleTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- ((LineCircleTransformer)this.transformer).setWidth(this.lineWidth);
- ((LineCircleTransformer)this.transformer).setRadius(this.radius);
- ((LineCircleTransformer)this.transformer).setSegment(this.segments);
- this.setAxis(circleAxis);
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(center);
+ public LineCircleShape(RenderingType type,
+ Consumer transform,
+ CircleAxis axis,
+ Vec3 center,
+ int segments,
+ float radius,
+ float width,
+ Color color,
+ boolean seeThrough) {
+ super(type, color, seeThrough);
+ this.axis = axis;
+
+ this.transformer = new LineCircleTransformer(this, segments, radius,width, center);
+ this.transformFunction = t -> transform.accept((LineCircleTransformer) this.transformer);
+
+ generateRawGeometry(true);
syncLastToTarget();
}
- @Override
- public Vec3 calculateShapeCenterPos() {
- if (vertexes.isEmpty()) {
- return Vec3.ZERO;
- }
- double sumX = 0, sumY = 0, sumZ = 0;
- for (Vec3 vertex : vertexes) {
- sumX += vertex.x;
- sumY += vertex.y;
- sumZ += vertex.z;
- }
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
+ int segments = getSegments(lerp);
+ float radius = getRadius(lerp);
+ if (segments < 3) return;
- int count = vertexes.size();
- return new Vec3(sumX / count, sumY / count, sumZ / count);
- }
- public void generateCircle(){
- ArrayList vs = new ArrayList<>();
- Vec3 center = getShapeCenterPos();
for (int i = 0; i < segments; i++) {
- double theta = (2 * Math.PI * i) / segments;
- double x, y, z;
+ double theta = 2 * Math.PI * i / segments;
+ double x = 0, y = 0, z = 0;
switch (axis) {
case X -> {
- y = center.y + radius * Math.cos(theta);
- z = center.z + radius * Math.sin(theta);
- x = center.x;
+ y = radius * Math.cos(theta);
+ z = radius * Math.sin(theta);
+ x = 0;
}
case Y -> {
- x = center.x + radius * Math.cos(theta);
- z = center.z + radius * Math.sin(theta);
- y = center.y;
+ x = radius * Math.cos(theta);
+ z = radius * Math.sin(theta);
+ y = 0;
}
case Z -> {
- x = center.x + radius * Math.cos(theta);
- y = center.y + radius * Math.sin(theta);
- z = center.z;
+ x = radius * Math.cos(theta);
+ y = radius * Math.sin(theta);
+ z = 0;
}
- default -> throw new IllegalStateException("Unexpected axis value: " + axis);
}
-
- vs.add(new Vec3(x, y, z).add(getShapeCenterPos()));
+ model_vertexes.add(new Vec3(x, y, z));
}
- if (!vs.isEmpty()) {
- vs.add(vs.getFirst().add(getShapeCenterPos()));
+
+ indexBuffer = new int[segments * 2];
+ for (int i = 0; i < segments; i++) {
+ indexBuffer[i * 2] = i;
+ indexBuffer[i * 2 + 1] = (i + 1) % segments;
}
- this.setVertexes(vs);
}
- public void setAxis(CircleAxis circleAxis){
- this.axis = circleAxis;
- generateCircle();
+
+ @Override
+ public void setRadius(float radius) {
+ ((LineCircleTransformer) this.transformer).setRadius(radius);
+ }
+ public void forceSetRadius(float radius) {
+ setRadius(radius);
+ ((LineCircleTransformer)this.transformer).circleModelInfo.radiusTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ public void forceSetSegments(float segments) {
+ setRadius(segments);
+ ((LineCircleTransformer)this.transformer).circleModelInfo.segmentTransformer.syncLastToTarget();
+ generateRawGeometry(false);
}
- public static class LineCircleTransformer extends LineLikeShape.DefaultLineTransformer {
- public IntValueTransformer segmentTransformer = new IntValueTransformer();
- public FloatValueTransformer radiusTransformer = new FloatValueTransformer();
- public LineCircleTransformer(Shape managerShape) {
- super(managerShape);
+ public void forceSetLineWidth(float width) {
+ setLineWidth(width);
+ ((LineCircleTransformer)this.transformer).lineModelInfo.widthTransformer.syncLastToTarget();
+ generateRawGeometry(false);
+ }
+ @Override
+ public void setSegments(int segments) {
+ ((LineCircleTransformer) this.transformer).setSegment(segments);
+ }
+
+ @Override
+ public float getRadius(boolean lerp) {
+ return ((LineCircleTransformer) this.transformer).getRadius(lerp);
+ }
+
+ @Override
+ public int getSegments(boolean lerp) {
+ return ((LineCircleTransformer) this.transformer).getSegment(lerp);
+ }
+
+ @Override
+ public void setLineWidth(float width) {
+ ((LineCircleTransformer) this.transformer).setWidth(width);
+ }
+
+ @Override
+ public float getLineWidth(boolean lerp) {
+ return ((LineCircleTransformer) this.transformer).getWidth(lerp);
+ }
+
+ public static class LineCircleTransformer extends DefaultTransformer {
+ private final CircleModelInfo circleModelInfo;
+ private final LineModelInfo lineModelInfo;
+ public LineCircleTransformer(Shape managedShape, int segments, float radius,float width, Vec3 center) {
+ super(managedShape, center);
+ circleModelInfo = new CircleModelInfo(segments, radius);
+ lineModelInfo = new LineModelInfo(width);
}
- public LineCircleTransformer(Shape managerShape,int seg,float rad) {
- super(managerShape);
- setSegment(seg);
- setRadius(rad);
+
+ public void setSegment(int segments) {
+ circleModelInfo.setSegment(segments);
+ }
+
+ public void setRadius(float radius) {
+ circleModelInfo.setRadius(radius);
}
- public void setSegment(int segment){
- this.segmentTransformer.setTargetValue(segment);
+ public void setWidth(float radius) {
+ lineModelInfo.setWidth(radius);
+ }
+
+ public float getWidth(boolean lerp) {
+ return lineModelInfo.getWidth(lerp);
}
- public void setRadius(float radius){
- this.radiusTransformer.setTargetValue(radius);
+ public int getSegment(boolean lerp) {
+ return circleModelInfo.getSegment(lerp);
}
+
+ public float getRadius(boolean lerp) {
+ return circleModelInfo.getRadius(lerp);
+ }
+
@Override
- public void applyTransformations(PoseStack matrixStack){
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if(this.managedShape instanceof LineCircleShape circleShape) {
- this.segmentTransformer.updateValue(circleShape::setSegments,deltaTime);
- this.radiusTransformer.updateValue(circleShape::setRadius,deltaTime);
- }
+ public void updateTickDelta(float delta) {
+ circleModelInfo.update(delta);
+ lineModelInfo.update(delta);
+ super.updateTickDelta(delta);
}
+
@Override
- public void syncLastToTarget(){
- this.segmentTransformer.syncLastToTarget();
- this.radiusTransformer.syncLastToTarget();
+ public void syncLastToTarget() {
+ circleModelInfo.syncLastToTarget();
+ lineModelInfo.syncLastToTarget();
super.syncLastToTarget();
}
+ public boolean asyncModelInfo(){
+ return circleModelInfo.async() || lineModelInfo.async();
+ }
}
@Override
- public void setRadius(float radius) {
- boolean rebuild = this.radius != radius;
- this.radius = radius;
- if(rebuild){
- generateCircle();
+ public boolean shouldDraw() {
+ List vertices = this.getModel(true);
+ if (vertices.isEmpty()) return false;
+
+ Minecraft client = Minecraft.getInstance();
+ Camera camera = client.gameRenderer.getMainCamera();
+ GameRenderer gameRenderer = client.gameRenderer;
+
+ Vec3 center = this.transformer.getWorldPivot().add(this.transformer.getLocalPivot());
+
+ Matrix4f viewMatrix = createViewMatrix(camera);
+
+ float fov = client.options.fov().get().floatValue();
+ Matrix4f projectionMatrix = gameRenderer.getProjectionMatrix(fov);
+
+ Matrix4f mvp = new Matrix4f(projectionMatrix);
+ mvp.mul(viewMatrix);
+
+ if (isVertexInFrustum(center, mvp)) return true;
+
+ for (Vec3 v : vertices) {
+ if (isVertexInFrustum(v, mvp)) return true;
}
- }
+ for (int i = 0; i < vertices.size() - 1; i++) {
+ Vec3 a = vertices.get(i);
+ Vec3 b = vertices.get(i + 1);
+ if (LineLikeShape.isSegmentInFrustum(a, b, mvp)) return true;
+ }
+ return false;
+ }
@Override
- public void setSegments(int segments) {
- boolean rebuild = this.segments != segments;
- this.segments = segments;
- if(rebuild){
- generateCircle();
+ protected void drawInternal(VertexBuilder builder) {
+ RenderSystem.lineWidth(getLineWidth(true));
+
+ int n = model_vertexes.size();
+ if (n < 2) return;
+
+ Vec3 first = model_vertexes.getFirst();
+ builder.putColor(new Color(0, 0, 0, 0));
+ builder.putVertex(first, Vec3.ZERO);
+ builder.putColor(baseColor);
+ for (int i = 0; i < n; i++) {
+
+ Vec3 normal;
+ if (i == 0) {
+ Vec3 dir = model_vertexes.get(1).subtract(model_vertexes.get(0));
+ normal = dir.normalize();
+ } else if (i == n - 1) {
+ Vec3 dir = model_vertexes.get(n - 1).subtract(model_vertexes.get(n - 2));
+ normal = dir.normalize();
+ } else {
+ Vec3 prevDir = model_vertexes.get(i).subtract(model_vertexes.get(i - 1));
+ Vec3 nextDir = model_vertexes.get(i + 1).subtract(model_vertexes.get(i));
+ normal = prevDir.add(nextDir).normalize();
+ if (Double.isNaN(normal.x) || Double.isNaN(normal.y) || Double.isNaN(normal.z)) {
+ Vec3 fallback = nextDir.lengthSqr() > 0 ? nextDir : prevDir;
+ normal = fallback.normalize();
+ }
+ }
+
+ Vec3 pos = model_vertexes.get(i);
+ builder.putVertex(pos,normal);
}
- }
+ Vec3 finish = model_vertexes.getFirst();
- @Override
- public float getRadius() {
- return radius;
- }
+ builder.putVertex(finish,Vec3.ZERO);
- @Override
- public int getSegments() {
- return segments;
+ Vec3 last = model_vertexes.get(n - 1);
+ builder.putColor(new Color(0, 0, 0, 0));
+ builder.putVertex(last,Vec3.ZERO);
}
}
+
diff --git a/src/main/java/mypals/ml/shape/round/SphereShape.java b/src/main/java/mypals/ml/shape/round/SphereShape.java
index af2f29c..bcce438 100644
--- a/src/main/java/mypals/ml/shape/round/SphereShape.java
+++ b/src/main/java/mypals/ml/shape/round/SphereShape.java
@@ -4,8 +4,6 @@
import mypals.ml.shape.Shape;
import mypals.ml.shape.basics.CircleLikeShape;
import mypals.ml.shape.basics.tags.DrawableTriangle;
-import mypals.ml.transform.FloatValueTransformer;
-import mypals.ml.transform.IntValueTransformer;
import net.minecraft.world.phys.Vec3;
import com.mojang.blaze3d.vertex.PoseStack;
import java.awt.*;
@@ -14,94 +12,60 @@
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
-import static mypals.ml.shape.round.SphereShape.SphereMode.UV;
public class SphereShape extends Shape implements CircleLikeShape, DrawableTriangle {
- public enum SphereMode {
- UV,
- Ico
+ @Override
+ protected void generateRawGeometry(boolean lerp) {
+ generateSphereShape(lerp);
}
- public int segments = 180;
- public float radius = 1;
- public SphereMode mode = UV;
- public ArrayList vertexes = new ArrayList<>();
- public Color color = Color.white;
- public SphereShape(RenderingType type, BiConsumer transform, SphereMode mode, Vec3 center, int segments, float radius, Color color, boolean seeThrough) {
- super(type, seeThrough);
- this.transformer = new SphereTransformer(this, segments, radius);
- this.transformFunction = (defaultTransformer, shape) -> transform.accept((SphereTransformer) this.transformer, shape);
- this.segments = segments;
- this.radius = radius;
- this.color = color;
- ((SphereTransformer) this.transformer).setRadius(this.radius);
- ((SphereTransformer) this.transformer).setSegment(this.segments);
- this.setMode(mode);
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(this.centerPoint);
+
+ public SphereShape(RenderingType type, Consumer transform, Vec3 center, int segments, float radius, Color color, boolean seeThrough) {
+ super(type,color, seeThrough);
+ this.transformer = new FaceCircleShape.FaceCircleTransformer(this, segments, radius, center);
+ this.transformFunction = (defaultTransformer) -> transform.accept((FaceCircleShape.FaceCircleTransformer) this.transformer);
syncLastToTarget();
+ generateSphereShape(true);
}
- /*@Override
- public Vec3 calculateShapeCenterPos() {
- if (vertexes.isEmpty()) {
- return Vec3.ZERO;
- }
-
- double sumX = 0, sumY = 0, sumZ = 0;
- for (Vec3 vertex : vertexes) {
- sumX += vertex.x;
- sumY += vertex.y;
- sumZ += vertex.z;
- }
- int count = vertexes.size();
- return new Vec3(sumX / count, sumY / count, sumZ / count);
- }*/
- public void generateSphereShape() {
+ public void generateSphereShape(boolean lerp) {
ArrayList vs = new ArrayList<>();
Vec3 center = Vec3.ZERO;
- double radius = getRadius();
+ double radius = getRadius(lerp);
+ int segments = getSegments(lerp);
- switch (mode) {
- case UV -> {
- int latSegments = segments;
- int lonSegments = segments * 2;
+ int lonSegments = segments * 2;
- for (int i = 0; i < latSegments; i++) {
- double theta1 = i * Math.PI / latSegments;
- double theta2 = (i + 1) * Math.PI / latSegments;
+ Vec3[][] vertexGrid = new Vec3[segments + 1][lonSegments + 1];
- for (int j = 0; j < lonSegments; j++) {
- double phi1 = j * 2 * Math.PI / lonSegments;
- double phi2 = (j + 1) * 2 * Math.PI / lonSegments;
-
- Vec3 v0 = sphericalToCartesian(center, radius, theta1, phi1);
- Vec3 v1 = sphericalToCartesian(center, radius, theta1, phi2);
- Vec3 v2 = sphericalToCartesian(center, radius, theta2, phi1);
- Vec3 v3 = sphericalToCartesian(center, radius, theta2, phi2);
-
- vs.add(v0);
- vs.add(v2);
- vs.add(v1);
-
- vs.add(v1);
- vs.add(v2);
- vs.add(v3);
- }
- }
+ for (int i = 0; i <= segments; i++) {
+ double theta = i * Math.PI / segments;
+ for (int j = 0; j <= lonSegments; j++) {
+ double phi = j * 2 * Math.PI / lonSegments;
+ vertexGrid[i][j] = sphericalToCartesian(center, radius, theta, phi);
+ vs.add(vertexGrid[i][j]);
}
+ }
- case Ico -> {
- IcoSphereGenerator generator = new IcoSphereGenerator(center, radius, segments);
- vs.addAll(generator.getVertexList());
- }
+ ArrayList indices = new ArrayList<>();
+ for (int i = 0; i < segments; i++) {
+ for (int j = 0; j < lonSegments; j++) {
+ int v0 = i * (lonSegments + 1) + j;
+ int v1 = (i + 1) * (lonSegments + 1) + j;
+ int v2 = i * (lonSegments + 1) + (j + 1);
+ int v3 = (i + 1) * (lonSegments + 1) + (j + 1);
- default -> throw new IllegalStateException("Unexpected mode value: " + mode);
+ indices.add(v0); indices.add(v1); indices.add(v2);
+ indices.add(v2); indices.add(v1); indices.add(v3);
+ }
}
- vertexes = vs;
+ indexBuffer = indices.stream().mapToInt(Integer::intValue).toArray();
+
+ model_vertexes = vs;
}
private Vec3 sphericalToCartesian(Vec3 center, double r, double theta, double phi) {
@@ -111,198 +75,23 @@ private Vec3 sphericalToCartesian(Vec3 center, double r, double theta, double ph
return new Vec3(x, y, z);
}
- public void setMode(SphereMode mode) {
- this.mode = mode;
- generateSphereShape();
- }
-
- @Override
- public void draw(VertexBuilder builder) {
-
- builder.putColor(this.color);
-
- for (Vec3 v : vertexes) {
- builder.putVertex(v.add(getShapeCenterPos()));
- }
-
- }
-
- public static class SphereTransformer extends DefaultTransformer {
- public IntValueTransformer segmentTransformer = new IntValueTransformer();
- public FloatValueTransformer radiusTransformer = new FloatValueTransformer();
-
- public SphereTransformer(Shape managerShape, int seg, float rad) {
- super(managerShape);
- setSegment(seg);
- setRadius(rad);
- }
-
- public void setSegment(int segment) {
- this.segmentTransformer.setTargetValue(segment);
- }
-
- public void setRadius(float radius) {
- this.radiusTransformer.setTargetValue(radius);
- }
-
- @Override
- public void applyTransformations(PoseStack matrixStack) {
- super.applyTransformations(matrixStack);
- float deltaTime = getTickDelta();
- if (this.managedShape instanceof SphereShape shape) {
- this.segmentTransformer.updateValue(shape::setSegments, deltaTime);
- this.radiusTransformer.updateValue(shape::setRadius, deltaTime);
- }
- }
-
- @Override
- public void syncLastToTarget() {
- this.segmentTransformer.syncLastToTarget();
- this.radiusTransformer.syncLastToTarget();
- super.syncLastToTarget();
- }
- }
-
@Override
public void setRadius(float radius) {
- boolean rebuild = this.radius != radius;
- this.radius = radius;
- if (rebuild) {
- generateSphereShape();
- }
-
+ ((FaceCircleShape.FaceCircleTransformer)this.transformer).setRadius(radius);
}
@Override
public void setSegments(int segments) {
- boolean rebuild = this.segments != segments;
- this.segments = segments;
- if (rebuild) {
- generateSphereShape();
- }
+ ((FaceCircleShape.FaceCircleTransformer)this.transformer).setSegment(segments);
}
@Override
- public float getRadius() {
- return radius;
+ public float getRadius(boolean lerp) {
+ return ((FaceCircleShape.FaceCircleTransformer)this.transformer).getRadius(lerp);
}
@Override
- public int getSegments() {
- return segments;
- }
-
- public static class IcoSphereGenerator {
-
- private final Map middlePointCache = new HashMap<>();
- private final ArrayList vertices = new ArrayList<>();
- private final ArrayList faces = new ArrayList<>();
- private final Vec3 center;
- private final double radius;
- private final int segments;
-
- public IcoSphereGenerator(Vec3 center, double radius, int segments) {
- this.center = center;
- this.radius = radius;
- this.segments = segments;
- generateIcosahedron();
- refine();
- }
-
- private void generateIcosahedron() {
- vertices.clear();
- faces.clear();
-
- double t = (1.0 + Math.sqrt(5.0)) / 2.0; // 黄金分割
- double s = Math.sqrt(1 + t * t);
-
- vertices.add(normalize(new Vec3(-1, t, 0), radius));
- vertices.add(normalize(new Vec3(1, t, 0), radius));
- vertices.add(normalize(new Vec3(-1, -t, 0), radius));
- vertices.add(normalize(new Vec3(1, -t, 0), radius));
-
- vertices.add(normalize(new Vec3(0, -1, t), radius));
- vertices.add(normalize(new Vec3(0, 1, t), radius));
- vertices.add(normalize(new Vec3(0, -1, -t), radius));
- vertices.add(normalize(new Vec3(0, 1, -t), radius));
-
- vertices.add(normalize(new Vec3(t, 0, -1), radius));
- vertices.add(normalize(new Vec3(t, 0, 1), radius));
- vertices.add(normalize(new Vec3(-t, 0, -1), radius));
- vertices.add(normalize(new Vec3(-t, 0, 1), radius));
-
- faces.addAll(Arrays.asList(
- new int[]{0, 11, 5}, new int[]{0, 5, 1}, new int[]{0, 1, 7}, new int[]{0, 7, 10}, new int[]{0, 10, 11},
- new int[]{1, 5, 9}, new int[]{5, 11, 4}, new int[]{11, 10, 2}, new int[]{10, 7, 6}, new int[]{7, 1, 8},
- new int[]{3, 9, 4}, new int[]{3, 4, 2}, new int[]{3, 2, 6}, new int[]{3, 6, 8}, new int[]{3, 8, 9},
- new int[]{4, 9, 5}, new int[]{2, 4, 11}, new int[]{6, 2, 10}, new int[]{8, 6, 7}, new int[]{9, 8, 1}
- ));
- }
-
- private void refine() {
- for (int i = 0; i < segments; i++) {
- ArrayList newFaces = new ArrayList<>();
- for (int[] tri : faces) {
- int a = tri[0];
- int b = tri[1];
- int c = tri[2];
-
- int ab = getMiddlePoint(a, b);
- int bc = getMiddlePoint(b, c);
- int ca = getMiddlePoint(c, a);
-
- newFaces.add(new int[]{a, ab, ca});
- newFaces.add(new int[]{b, bc, ab});
- newFaces.add(new int[]{c, ca, bc});
- newFaces.add(new int[]{ab, bc, ca});
- }
- faces.clear();
- faces.addAll(newFaces);
- }
- }
-
- private int getMiddlePoint(int p1, int p2) {
- long smallerIndex = Math.min(p1, p2);
- long greaterIndex = Math.max(p1, p2);
- long key = (smallerIndex << 32) + greaterIndex;
-
- if (middlePointCache.containsKey(key)) {
- return middlePointCache.get(key);
- }
-
- Vec3 point1 = vertices.get(p1);
- Vec3 point2 = vertices.get(p2);
- Vec3 middle = new Vec3(
- (point1.x + point2.x) / 2,
- (point1.y + point2.y) / 2,
- (point1.z + point2.z) / 2
- );
-
- middle = normalize(middle, radius);
-
- vertices.add(middle);
- int index = vertices.size() - 1;
- middlePointCache.put(key, index);
- return index;
- }
-
- private Vec3 normalize(Vec3 v, double r) {
- double length = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
- return new Vec3(
- center.x + v.x / length * r,
- center.y + v.y / length * r,
- center.z + v.z / length * r
- );
- }
-
- public ArrayList getVertexList() {
- ArrayList result = new ArrayList<>();
- for (int[] tri : faces) {
- result.add(vertices.get(tri[0]));
- result.add(vertices.get(tri[1]));
- result.add(vertices.get(tri[2]));
- }
- return result;
- }
+ public int getSegments(boolean lerp) {
+ return ((FaceCircleShape.FaceCircleTransformer)this.transformer).getSegment(lerp);
}
}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/shape/text/TextShape.java b/src/main/java/mypals/ml/shape/text/TextShape.java
index 93e022c..5b9740a 100644
--- a/src/main/java/mypals/ml/shape/text/TextShape.java
+++ b/src/main/java/mypals/ml/shape/text/TextShape.java
@@ -1,111 +1,194 @@
package mypals.ml.shape.text;
+import com.mojang.blaze3d.systems.RenderSystem;
import mypals.ml.builders.vertexBuilders.VertexBuilder;
import mypals.ml.shape.Shape;
+import mypals.ml.shape.basics.tags.EmptyMesh;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
+import net.fabricmc.fabric.impl.client.indigo.renderer.helper.ColorHelper;
+import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.screens.inventory.AbstractSignEditScreen;
+import net.minecraft.client.gui.screens.inventory.SignEditScreen;
+import net.minecraft.client.renderer.LightTexture;
+import net.minecraft.client.renderer.MultiBufferSource;
+import net.minecraft.client.renderer.blockentity.SignRenderer;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.MutableComponent;
+import net.minecraft.util.FormattedCharSequence;
+import net.minecraft.world.level.block.entity.SignBlockEntity;
import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
-import org.joml.Vector3f;
import com.mojang.blaze3d.vertex.PoseStack;
+
import java.awt.*;
import java.util.ArrayList;
-import java.util.function.BiConsumer;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import static mypals.ml.Helpers.multiplyRGB;
+
+public class TextShape extends Shape implements EmptyMesh {
-public class TextShape extends Shape {
public ArrayList contents = new ArrayList<>();
- public ArrayList color = new ArrayList<>();
- public BillBoardMode bill = BillBoardMode.ALL;
+ public ArrayList colors = new ArrayList<>();
+ public boolean shadow;
+ public boolean outline;
+
+ public Color backgroundColor = new Color(0,0,0,0);
+ public BillBoardMode billBoardMode = BillBoardMode.ALL;
+ @Nullable
+ private FormattedCharSequence[] renderMessages;
+
+
public enum BillBoardMode {
- VERTICAL,
- HORIZONTAL,
- ALL
+ FIXED, VERTICAL, HORIZONTAL, ALL
}
- protected TextShape(RenderingType type, BiConsumer super DefaultTransformer, Shape> transform, ArrayList texts,ArrayList colors) {
- super(type, transform);
- this.color = colors;
- this.contents = texts;
- }
+ public TextShape(RenderingType type,
+ Consumer transform,
+ Vec3 center, List texts, List textColors,
+ Color backgroundColor,
+ BillBoardMode mode, boolean seeThrough,
+ boolean shadow,boolean outline) {
+ super(type, transform, Color.white, center, seeThrough);
+ this.seeThrough = seeThrough;
+ this.contents.addAll(texts);
+ this.colors.addAll(textColors);
+ this.billBoardMode = mode;
+ this.shadow = shadow;
+ this.outline = outline;
+ this.backgroundColor = backgroundColor;
- protected TextShape(RenderingType type) {
- super(type);
- }
+ this.transformer.setShapeWorldPivot(center);
- protected TextShape(RenderingType type, boolean seeThrough) {
- super(type, seeThrough);
+ syncLastToTarget();
}
+ public TextShape(RenderingType type,
+ Consumer transform,
+ Vec3 center, List texts, List textColors,
+ BillBoardMode mode, boolean seeThrough,boolean shadow,boolean outline) {
- public TextShape(RenderingType type, BiConsumer super DefaultTransformer, Shape> transform, boolean seeThrough) {
- super(type, transform, seeThrough);
- }
- public TextShape(RenderingType type, BiConsumer transform, BillBoardMode bill, Vec3 center,ArrayList texts,ArrayList colors, boolean seeThrough) {
- super(type,seeThrough);
- this.transformer = new DefaultTransformer(this);
- this.bill = bill;
- this.color = colors;
- this.contents = texts;
- this.transformFunction = (defaultTransformer,shape)->transform.accept(this.transformer, shape);
- this.centerPoint = center;
- this.transformer.setShapeCenterPos(this.calculateShapeCenterPos());
- syncLastToTarget();
+ this(type,transform,center,texts,textColors,new Color(0,0,0,0),mode,seeThrough,shadow,outline);
}
@Override
- public void beforeDraw(PoseStack matrixStack, float deltaTime) {
- applyBillboard(matrixStack,this.bill);
- super.beforeDraw(matrixStack,deltaTime);
+ protected void generateRawGeometry(boolean lerp) {
+ model_vertexes.clear();
}
- public Vec3 calculateShapeCenterPos(){
- return centerPoint;
+ public FormattedCharSequence[] getRenderMessages() {
+ if (this.renderMessages == null) {
+ Minecraft mc = Minecraft.getInstance();
+ Font font = mc.font;
+ this.renderMessages = new FormattedCharSequence[contents.size()];
+ MutableComponent[] components = this.getMessages();
+ for (int i = 0; i < components.length; i++) {
+ this.renderMessages[i] = font.split(components[i],Integer.MAX_VALUE).getFirst();
+ }
+ }
+
+ return this.renderMessages;
}
- @Override
- public void setMatrixScale(Vector3f scale, PoseStack matrixStack){
- matrixStack.scale(scale.x,-scale.y,1);
+ public MutableComponent[] getMessages() {
+ MutableComponent[] components = new MutableComponent[contents.size()];
+ for (String string : contents){
+ components[contents.indexOf(string)] = Component.literal(string);
+ }
+ return components;
}
@Override
- public void draw(VertexBuilder builder) {
- Minecraft client = Minecraft.getInstance();
- Font textRenderer = client.font;
-
- float[] lineHeights = new float[this.contents.size()];
- float totalHeight = 0.0f;
- for (int i = 0; i < this.contents.size(); i++) {
- lineHeights[i] = textRenderer.wordWrapHeight(this.contents.get(i), Integer.MAX_VALUE) * 1.25f;
+ protected void drawInternal(VertexBuilder builder) {
+
+ MultiBufferSource.BufferSource bufferSource = Minecraft.getInstance()
+ .renderBuffers().bufferSource();
+
+ Minecraft mc = Minecraft.getInstance();
+ Font font = mc.font;
+ float totalHeight = 0f;
+ float[] lineHeights = new float[contents.size()];
+
+ for (int i = 0; i < contents.size(); i++) {
+ String line = contents.get(i);
+ int wrappedHeight = font.wordWrapHeight(line, Integer.MAX_VALUE);
+ lineHeights[i] = wrappedHeight * 1.25f;
totalHeight += lineHeights[i];
}
- float renderYBase = -totalHeight / 2.0f;
- for (int i = 0; i < this.contents.size(); i++) {
- String text = this.contents.get(i);
- float renderX = -textRenderer.width(text) * 0.5f;
- float renderY = renderYBase + (i > 0 ? lineHeights[i - 1] : 0);
- int colorValue = (this.color.size() > i && this.color.get(i) != null) ? this.color.get(i).getRGB() : Color.WHITE.getRGB();
-
- textRenderer.drawInBatch(
- text, renderX, renderY, colorValue, true,
- builder.getPositionMatrix(), new NonDrawVertexConsumerProvider(builder.getBufferBuilder()),
- seeThrough ? Font.DisplayMode.SEE_THROUGH : Font.DisplayMode.NORMAL,
- 0, 0xF000F0
- );
-
- if (i > 0) renderYBase += lineHeights[i - 1];
+
+ float yOffset = -totalHeight / 2f;
+
+ FormattedCharSequence[] renderMessages = getRenderMessages();
+ for (int i = 0; i < contents.size(); i++) {
+ String text = contents.get(i);
+ Color color = i < colors.size() ? colors.get(i) : baseColor;
+
+ float x = -font.width(text) / 2f;
+ float y = yOffset;
+ if(outline) {
+ font.drawInBatch8xOutline(renderMessages[i],x, y,
+ color.getRGB(),
+ multiplyRGB(color.getRGB(),0.8f),
+ builder.getPositionMatrix(),
+ bufferSource, LightTexture.FULL_BRIGHT);
+ }else {
+ font.drawInBatch(
+ text,
+ x, y,
+ outline ? multiplyRGB(color.getRGB(), 0.9f) : color.getRGB(),
+ shadow,
+ builder.getPositionMatrix(),
+ bufferSource,
+ seeThrough ? Font.DisplayMode.SEE_THROUGH : Font.DisplayMode.POLYGON_OFFSET,
+ backgroundColor.getRGB(),
+ LightTexture.FULL_BRIGHT
+ );
+ }
+
+ yOffset += lineHeights[i];
+ }
+ RenderSystem.setShaderColor(1,1,1,1);
+ }
+ @Override
+ public void beforeDraw(PoseStack poseStack, float deltaTime) {
+ super.beforeDraw(poseStack, deltaTime);
+
+ Camera camera = Minecraft.getInstance().gameRenderer.getMainCamera();
+ Quaternionf camRot = camera.rotation();
+
+ switch (billBoardMode) {
+ case ALL -> {
+ poseStack.mulPose(camRot);
+ }
+ case VERTICAL -> {
+ float yaw = (float) Math.toRadians(camera.getYRot() + 180);
+ poseStack.mulPose(new Quaternionf().rotateY(yaw));
+ }
+ case HORIZONTAL -> {
+ float pitch = (float) Math.toRadians(camera.getXRot());
+ poseStack.mulPose(new Quaternionf().rotateX(pitch));
+ }
}
+ poseStack.scale(0.015625F, -0.015625F, 0.015625F);
}
- public void applyBillboard(PoseStack matrices, BillBoardMode mode) {
- float yaw = Minecraft.getInstance().gameRenderer.getMainCamera().getYRot();
- float pitch = Minecraft.getInstance().gameRenderer.getMainCamera().getXRot();
-
- switch (mode) {
- case VERTICAL:
- matrices.mulPose(new Quaternionf().rotateY((float)Math.toRadians(yaw)));
- break;
- case HORIZONTAL:
- matrices.mulPose(new Quaternionf().rotateX((float)Math.toRadians(pitch)));
- break;
- case ALL:
- matrices.mulPose(Minecraft.getInstance().gameRenderer.getMainCamera().rotation());
- break;
+ public void setText(int line, String text) {
+ line--;
+ if (line >= 0 && line < contents.size()) {
+ contents.set(line, text);
}
}
+ public void setColor(int line, Color color) {
+ while (colors.size() <= line) colors.add(Color.WHITE);
+ colors.set(line, color);
+ }
+
+ public void setBillboardMode(BillBoardMode mode) {
+ this.billBoardMode = mode;
+ }
+ @Override
+ public boolean shouldDraw() {
+ return true;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/shapeManagers/EmptyShapeManager.java b/src/main/java/mypals/ml/shapeManagers/EmptyShapeManager.java
new file mode 100644
index 0000000..b328860
--- /dev/null
+++ b/src/main/java/mypals/ml/shapeManagers/EmptyShapeManager.java
@@ -0,0 +1,86 @@
+package mypals.ml.shapeManagers;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import mypals.ml.builderManager.BuilderManager;
+import mypals.ml.builderManager.EmptyBuilderManager;
+import mypals.ml.shape.Shape;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.phys.Vec3;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static mypals.ml.shapeManagers.ShapeManagers.TEMP_HEADER;
+
+public class EmptyShapeManager {
+ public String id;
+ public EmptyShapeGroup shapeGroup;
+ public EmptyBuilderManager builderManager;
+ public static Comparator SHAPE_ORDER_COMPARATOR = (s1, s2) -> {
+ Vec3 shape1Pos = s1.transformer.getWorldPivot();
+ Vec3 shape2Pos = s2.transformer.getWorldPivot();
+ double distance1 = shape1Pos.lengthSqr(); // Square of distance for efficiency
+ double distance2 = shape2Pos.lengthSqr();
+ return Double.compare(distance2, distance1);
+ };
+ public EmptyShapeManager(EmptyBuilderManager builderManager, String id){
+ this.id = id;
+ shapeGroup = new EmptyShapeGroup();
+ this.builderManager = builderManager;
+ }
+ public void syncShapeTransform(){
+ shapeGroup.syncShapeTransform();
+ }
+ public void addShape(ResourceLocation identifier,Shape shape){
+ shapeGroup.addShape(identifier, shape);
+ }
+ public void removeShape(ResourceLocation identifier){
+ shapeGroup.removeShape(identifier);
+ }
+ public void removeShapes(ResourceLocation root){
+ shapeGroup.removeShape(root);
+ }
+ public void draw(PoseStack matrixStack,float tickDelta){
+ shapeGroup.drawAll(builderManager,matrixStack,tickDelta);
+ }
+ public void clearTempAfterRender(){
+ shapeGroup.clearTemp();
+ }
+ public static class EmptyShapeGroup{
+ public ConcurrentHashMap shapeMap = new ConcurrentHashMap<>();
+ public void addShape(ResourceLocation id,Shape shape){
+ shapeMap.put(id,shape);
+ }
+ public void removeShape(@NotNull ResourceLocation identifier){
+ shapeMap.remove(identifier);
+ }
+ public void removeShapes(@NotNull ResourceLocation identifier) {
+ shapeMap.entrySet().removeIf(entry -> entry.getKey().getPath().startsWith(identifier.getPath()));
+ }
+ public void clear(){
+ shapeMap.clear();
+ }
+ public void clearTemp(){
+ shapeMap.entrySet().removeIf(entry -> entry.getKey().getPath().startsWith(TEMP_HEADER));
+ }
+ public void syncShapeTransform(){
+ for (Shape shape : shapeMap.values()) {
+ shape.syncLastToTarget();
+ }
+ }
+ public void drawAll(EmptyBuilderManager builderManager, PoseStack matrixStack, float tickDelta){
+ if(!shapeMap.isEmpty()) {
+ List sortedShapes = new ArrayList<>(shapeMap.values());
+ sortedShapes.sort(SHAPE_ORDER_COMPARATOR);
+ for (Shape shape : sortedShapes) {
+ builderManager.draw(builder -> {
+ shape.draw(true, builder, matrixStack,tickDelta);
+ });
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/mypals/ml/shapeManagers/ShapeManager.java b/src/main/java/mypals/ml/shapeManagers/ShapeManager.java
index ece65eb..345da74 100644
--- a/src/main/java/mypals/ml/shapeManagers/ShapeManager.java
+++ b/src/main/java/mypals/ml/shapeManagers/ShapeManager.java
@@ -20,8 +20,8 @@ public class ShapeManager {
public ShapeGroup bufferedShapeGroup;
public BuilderManager builderManager;
public static Comparator SHAPE_ORDER_COMPARATOR = (s1, s2) -> {
- Vec3 shape1Pos = s1.centerPoint;
- Vec3 shape2Pos = s2.centerPoint;
+ Vec3 shape1Pos = s1.transformer.getWorldPivot();
+ Vec3 shape2Pos = s2.transformer.getWorldPivot();
double distance1 = shape1Pos.lengthSqr(); // Square of distance for efficiency
double distance2 = shape2Pos.lengthSqr();
return Double.compare(distance2, distance1);
@@ -115,7 +115,7 @@ public void drawImmediate(BuilderManager builderManager, PoseStack matrixStack,f
for (Shape shape : sortedShapes) {
builderManager.drawImmediate(shape, builder -> {
- shape.draw(builder, matrixStack,tickDelta);
+ shape.draw(true, builder, matrixStack,tickDelta);
});
}
}
@@ -125,7 +125,7 @@ public void drawImmediate(BuilderManager builderManager, PoseStack matrixStack,f
for (Shape shape : sortedShapes) {
builderManager.drawImmediate(shape, builder -> {
- shape.draw(builder, matrixStack,tickDelta);
+ shape.draw(true, builder, matrixStack,tickDelta);
});
}
}
@@ -137,7 +137,7 @@ public void drawBatched(BuilderManager builderManager, PoseStack matrixStack,flo
sortedShapes.sort(SHAPE_ORDER_COMPARATOR);
for (Shape shape : sortedShapes) {
- shape.draw(builder, matrixStack,tickDelta);
+ shape.draw(true,builder, matrixStack,tickDelta);
}
}, false);
}
@@ -147,7 +147,7 @@ public void drawBatched(BuilderManager builderManager, PoseStack matrixStack,flo
sortedShapes.sort(SHAPE_ORDER_COMPARATOR);
for (Shape shape : sortedShapes) {
- shape.draw(builder, matrixStack,tickDelta);
+ shape.draw(true,builder, matrixStack,tickDelta);
}
}, true);
}
diff --git a/src/main/java/mypals/ml/shapeManagers/ShapeManagers.java b/src/main/java/mypals/ml/shapeManagers/ShapeManagers.java
index 9213889..716a2dd 100644
--- a/src/main/java/mypals/ml/shapeManagers/ShapeManagers.java
+++ b/src/main/java/mypals/ml/shapeManagers/ShapeManagers.java
@@ -1,4 +1,6 @@
package mypals.ml.shapeManagers;
+import mypals.ml.builderManager.EmptyBuilderManager;
+import mypals.ml.shape.basics.tags.EmptyMesh;
import mypals.ml.shape.basics.tags.ExtractableShape;
import net.minecraft.resources.ResourceLocation;
import mypals.ml.builderManager.BuilderManager;
@@ -13,22 +15,17 @@
public class ShapeManagers {
public static final String TEMP_HEADER = "temp_shape";
- public static ShapeManager QUADS_SHAPE_MANAGER;
public static ShapeManager LINES_SHAPE_MANAGER;
public static ShapeManager LINE_STRIP_SHAPE_MANAGER;
- public static ShapeManager TEXT;
public static ShapeManager TRIANGLES_SHAPE_MANAGER;
- public static ShapeManager TRIANGLES_STRIP_SHAPE_MANAGER;
- public static ShapeManager TRIANGLES_FAN_SHAPE_MANAGER;
+ public static EmptyShapeManager NON_SHAPE_OBJECTS;
public static List managers = new ArrayList<>();
+ public static List emptyManagers = new ArrayList<>();
public static void init(){
- QUADS_SHAPE_MANAGER = register(BuilderManagers.QUADS_BUILDER_MANAGER,"quads_shape_manager");
LINE_STRIP_SHAPE_MANAGER = register(BuilderManagers.LINE_STRIP_BUILDER_MANAGER,"line_strip_shape_manager");
LINES_SHAPE_MANAGER = register(BuilderManagers.LINES_BUILDER_MANAGER,"lines_shape_manager");
TRIANGLES_SHAPE_MANAGER = register(BuilderManagers.TRIANGLES_BUILDER_MANAGER,"triangles_shape_manager");
- TRIANGLES_STRIP_SHAPE_MANAGER = register(BuilderManagers.TRIANGLES_STRIP_BUILDER_MANAGER,"triangles_strip_shape_manager");
- TRIANGLES_FAN_SHAPE_MANAGER = register(BuilderManagers.TRIANGLES_FAN_BUILDER_MANAGER,"triangles_fan_shape_manager");
- TEXT = register(BuilderManagers.TEXT,"text_manager");
+ NON_SHAPE_OBJECTS = registerEmpty(BuilderManagers.NON_SHAPE_OBJECTS,"empty");
}
public static void renderAll(PoseStack matrixStack, float tickDelta){
for(ShapeManager manager : managers
@@ -36,24 +33,36 @@ public static void renderAll(PoseStack matrixStack, float tickDelta){
manager.draw(matrixStack, tickDelta);
manager.clearTempAfterRender();
}
+ for(EmptyShapeManager manager : emptyManagers
+ ){
+ manager.draw(matrixStack, tickDelta);
+ manager.clearTempAfterRender();
+ }
}
public static ShapeManager register(BuilderManager builderManager,String id){
ShapeManager shapeManager = new ShapeManager(builderManager,id);
managers.add(shapeManager);
return shapeManager;
}
+ public static EmptyShapeManager registerEmpty(EmptyBuilderManager builderManager, String id){
+ EmptyShapeManager shapeManager = new EmptyShapeManager(builderManager,id);
+ emptyManagers.add(shapeManager);
+ return shapeManager;
+ }
public static void removeShape(ResourceLocation identifier){
managers.forEach(
- (shapeManager) -> {
- shapeManager.removeShape(identifier);
- }
+ (shapeManager) -> shapeManager.removeShape(identifier)
+ );
+ emptyManagers.forEach(
+ (shapeManager) -> shapeManager.removeShape(identifier)
);
}
public static void removeShapes(ResourceLocation root){
managers.forEach(
- (shapeManager) ->{
- shapeManager.removeShapes(root);
- }
+ (shapeManager) -> shapeManager.removeShapes(root)
+ );
+ managers.forEach(
+ (shapeManager) -> shapeManager.removeShape(root)
);
}
@@ -63,12 +72,18 @@ public static void addShape(ResourceLocation identifier, Shape shape){
exts.addGroup(identifier);
return;
}
- VertexBuilderGetter.getBuilderManager(shape).addShape(identifier,shape);
+ if( shape instanceof EmptyMesh )
+ VertexBuilderGetter.getEmptyBuilderManager(shape).addShape(identifier,shape);
+ else
+ VertexBuilderGetter.getBuilderManager(shape).addShape(identifier,shape);
}
public static void syncShapeTransform(){
for(ShapeManager manager : managers){
manager.syncShapeTransform();
}
+ for(EmptyShapeManager manager : emptyManagers){
+ manager.syncShapeTransform();
+ }
}
public static void addShape(Shape shape){
addShape(generateUniqueId(TEMP_HEADER),shape);
diff --git a/src/main/java/mypals/ml/shapeManagers/VertexBuilderGetter.java b/src/main/java/mypals/ml/shapeManagers/VertexBuilderGetter.java
index 94e00cd..7a1ed11 100644
--- a/src/main/java/mypals/ml/shapeManagers/VertexBuilderGetter.java
+++ b/src/main/java/mypals/ml/shapeManagers/VertexBuilderGetter.java
@@ -1,5 +1,6 @@
package mypals.ml.shapeManagers;
+import mypals.ml.shape.basics.tags.EmptyMesh;
import mypals.ml.shape.box.BoxFaceShape;
import mypals.ml.shape.box.BoxWireframeShape;
import mypals.ml.shape.Shape;
@@ -21,17 +22,22 @@
public class VertexBuilderGetter {
public static Map, ShapeManager> shapeManagerMap = new HashMap<>();
+ public static Map, EmptyShapeManager> emptyShapeManagerMap = new HashMap<>();
+
public static void registerShapeBuilder(Class extends Shape> shapeClass, ShapeManager manager){
shapeManagerMap.put(shapeClass,manager);
}
+ public static void registerEmptyShapeBuilder(Class extends Shape> shapeClass, EmptyShapeManager manager){
+ emptyShapeManagerMap.put(shapeClass,manager);
+ }
public static void init(){
registerShapeBuilder(BoxWireframeShape.class, ShapeManagers.LINES_SHAPE_MANAGER);
- registerShapeBuilder(BoxFaceShape.class, ShapeManagers.QUADS_SHAPE_MANAGER);
+ registerShapeBuilder(BoxFaceShape.class, ShapeManagers.TRIANGLES_SHAPE_MANAGER);
registerShapeBuilder(LineShape.class,ShapeManagers.LINES_SHAPE_MANAGER);
registerShapeBuilder(StripLineShape.class,ShapeManagers.LINE_STRIP_SHAPE_MANAGER);
registerShapeBuilder(LineCircleShape.class,ShapeManagers.LINE_STRIP_SHAPE_MANAGER);
- registerShapeBuilder(TextShape.class,ShapeManagers.TEXT);
- registerShapeBuilder(FaceCircleShape.class,ShapeManagers.TRIANGLES_FAN_SHAPE_MANAGER);
+ //registerShapeBuilder(TextShape.class,ShapeManagers.TEXT);
+ registerShapeBuilder(FaceCircleShape.class,ShapeManagers.TRIANGLES_SHAPE_MANAGER);
registerShapeBuilder(SphereShape.class,ShapeManagers.TRIANGLES_SHAPE_MANAGER);
registerShapeBuilder(ObjModelShape.class,ShapeManagers.TRIANGLES_SHAPE_MANAGER);
registerShapeBuilder(ObjModelShapeOutline.class,ShapeManagers.LINES_SHAPE_MANAGER);
@@ -39,12 +45,14 @@ public static void init(){
registerShapeBuilder(ConeWireframeShape.class,ShapeManagers.LINES_SHAPE_MANAGER);
registerShapeBuilder(CylinderShape.class,ShapeManagers.TRIANGLES_SHAPE_MANAGER);
registerShapeBuilder(ConeShape.class,ShapeManagers.TRIANGLES_SHAPE_MANAGER);
-
+ registerEmptyShapeBuilder(TextShape.class,ShapeManagers.NON_SHAPE_OBJECTS);
}
public static ShapeManager getBuilderManager(Shape shape){
return shapeManagerMap.getOrDefault(shape.getClass(),null);
}
-
+ public static EmptyShapeManager getEmptyBuilderManager(Shape shape){
+ return emptyShapeManagerMap.getOrDefault(shape.getClass(),null);
+ }
public void removeShapes(ResourceLocation root){
}
diff --git a/src/main/java/mypals/ml/test/Tester.java b/src/main/java/mypals/ml/test/Tester.java
index cbe77bc..469db98 100644
--- a/src/main/java/mypals/ml/test/Tester.java
+++ b/src/main/java/mypals/ml/test/Tester.java
@@ -1,29 +1,42 @@
package mypals.ml.test;
+import com.mojang.brigadier.CommandDispatcher;
import mypals.ml.builders.shapeBuilders.ShapeGenerator;
+import mypals.ml.collision.RayModelIntersection;
import mypals.ml.shape.basics.BoxLikeShape;
import mypals.ml.shape.basics.CircleLikeShape;
+import mypals.ml.shape.basics.core.TwoPointsLineShape;
import mypals.ml.shape.box.BoxFaceShape;
import mypals.ml.shape.box.BoxShape;
import mypals.ml.shape.Shape;
import mypals.ml.shape.line.LineShape;
import mypals.ml.shape.line.StripLineShape;
import mypals.ml.shape.round.SphereShape;
+import mypals.ml.shape.text.TextShape;
+import mypals.ml.shapeManagers.ShapeManager;
import mypals.ml.shapeManagers.ShapeManagers;
+import mypals.ml.transform.shapeTransformers.DefaultTransformer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
+import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.MouseHandler;
+import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
+import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.Vec3;
import java.awt.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Random;
+import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal;
import static mypals.ml.RyansRenderingKit.MOD_ID;
import com.mojang.blaze3d.vertex.PoseStack;
@@ -31,34 +44,72 @@
public class Tester {
public static boolean added =false;
public static Random random = new Random();
- public static float spacing = 8.0f; // 每个图形间隔 8 格
+ public static float spacing = 8.0f;
public static int index = 0;
+ public static boolean ENABLE_DEBUG = false;
static Color randomColor() {
return new Color(
random.nextInt(256),
random.nextInt(256),
random.nextInt(256),
- 120 + random.nextInt(136) // 透明度 120~255
+ 120 + random.nextInt(136)
);
}
static float xPos() {
return (index++ * spacing);
}
-
- public static void init(){
- ClientCommandRegistrationCallback.EVENT.register((commandDispatcher, commandRegistryAccess) -> {
- commandDispatcher.register(
- ClientCommandManager.literal("reload")
- .executes(context -> {
+ public static void registerDebugCommands(CommandDispatcher dispatcher) {
+
+ dispatcher.register(
+ ClientCommandManager.literal("ryansRenderingKit_DEBUG")
+ .then(ClientCommandManager.literal("toggle")
+ .executes(ctx -> {
+ boolean newValue = toggleDebugMode();
+ ctx.getSource().sendFeedback(
+ Component.nullToEmpty("Ryan's Rendering Kit Debug Mode: " + (newValue ?
+ "§aENABLED"
+ : "§cDISABLED")));
+ return 1;
+ })
+ ).then(ClientCommandManager.literal("reload")
+ .executes(ctx -> {
added = false;
+ ctx.getSource().sendFeedback(
+ Component.nullToEmpty("Ryan's Rendering Kit Debug Shapes Reloaded."));
return 0;
})
- );
- });
+ )
+ );
+ }
+ private static boolean toggleDebugMode(){
+ ENABLE_DEBUG = !ENABLE_DEBUG;
+ if(!ENABLE_DEBUG){
+ List.of(
+ "demo_face_circle",
+ "demo_line_circle",
+ "demo_sphere",
+ "demo_obj_model",
+ "demo_obj_outline",
+ "demo_cone",
+ "demo_cylinder",
+ "demo_cone_wire",
+ "demo_cylinder_wire",
+ "demo_line",
+ "demo_strip_line",
+ "demo_box_face",
+ "demo_box_wire",
+ "demo_wireframed_box"
+ ).forEach(name -> ShapeManagers.removeShapes(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, name)
+ ));
+ }
+ return ENABLE_DEBUG;
+ }
+ public static void init(){
ClientTickEvents.START_WORLD_TICK.register(client -> {
- if (added) return;
+ if (added || !ENABLE_DEBUG) return;
index = 0;
List.of(
"demo_face_circle",
@@ -79,7 +130,6 @@ public static void init(){
ResourceLocation.fromNamespaceAndPath(MOD_ID, name)
));
- // 1. FaceCircle
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_face_circle"),
ShapeGenerator.generateFaceCircle()
@@ -88,15 +138,14 @@ public static void init(){
.segments(64)
.axis(CircleLikeShape.CircleAxis.Y)
.color(randomColor())
- .seeThrough(true)
- .transform((t, s) -> {
+ .seeThrough(false)
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(0, time * 3, 0));
+ t.setShapeWorldRotationDegrees(0, time * 3, 0);
})
.build(Shape.RenderingType.BATCH)
);
- // 2. LineCircle
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_line_circle"),
ShapeGenerator.generateLineCircle()
@@ -107,46 +156,132 @@ public static void init(){
.lineWidth(3.0f)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(0, time * 4, 0));
+ t.setShapeLocalRotationDegrees(0,time*4,0);
+ t.setShapeWorldRotationDegrees(time*4, 0, 0);
})
- .build(Shape.RenderingType.BATCH)
+ .build(Shape.RenderingType.BUFFERED)
);
- // 3. Sphere
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_sphere"),
ShapeGenerator.generateSphere()
.pos(new Vec3(xPos(), 0,0))
.radius(2.0f)
.segments(32)
- .mode(SphereShape.SphereMode.UV)
.color(randomColor())
- .seeThrough(true)
- .transform((t, s) -> {
+ .seeThrough(false)
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 2, time * 3, 0));
+ t.setShapeWorldRotationDegrees(time * 2, time * 3, 0);
})
- .build(Shape.RenderingType.BATCH)
+ .build(Shape.RenderingType.BUFFERED)
+ );
+
+ Vec3 spos = new Vec3(xPos(), 0,20);
+ Shape s1 = ShapeGenerator.generateSphere()
+ .pos(spos)
+ .radius(2.0f)
+ .segments(6)
+ .color(randomColor())
+ .seeThrough(false)
+ .transform((t) -> {
+ float time = client.getGameTime();
+ t.setShapeWorldRotationDegrees(0, time * 3, 0);
+
+ float yOffset = (float)Math.sin(time * 0.1) * 2f;
+ Vec3 worldPivot = t.getShapeWorldPivot(false);
+ t.setShapeWorldPivot(new Vec3(worldPivot.x, 0 + yOffset, worldPivot.z));
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ Shape s2 = ShapeGenerator.generateSphere()
+ .pos(new Vec3(15,0,0))
+ .radius(1.0f)
+ .segments(3)
+ .color(randomColor())
+ .seeThrough(false)
+ .transform((t) -> {
+ float time = client.getGameTime();
+ t.setShapeWorldRotationDegrees(0, time*6, 0);
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ Shape s3 = ShapeGenerator.generateSphere()
+ .pos(new Vec3(7,0,0))
+ .radius(0.3f)
+ .segments(5)
+ .color(randomColor())
+ .seeThrough(false)
+ .transform((t) -> {
+ float time = client.getGameTime();
+ if(t.shape.isPlayerLookingAt().hit){
+ t.shape.baseColor = new Color(255, 234, 0,100);
+ }else{
+ t.shape.baseColor = new Color(255, 0, 251,100);
+ }
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ s2.addChild(s3);
+ s1.addChild(s2);
+
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_sphere_2"),
+ s1
+ );
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_sphere_2_child"),
+ s2
+ );
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_sphere_3_child"),
+ s3
);
- // 4. ObjModel
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_obj_model"),
ShapeGenerator.generateObjModel()
- .pos(new Vec3(xPos(), 0,0))
+ .pos(new Vec3(xPos(), 0, 0))
.model(ResourceLocation.fromNamespaceAndPath(MOD_ID, "models/monkey.obj"))
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((transformer) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(0, time * 5, 0));
+ transformer.setShapeWorldRotationDegrees(0, time * 5, 0);
+ Shape shape = transformer.shape;
+ if (shape.isPlayerLookingAt().hit) {
+ if (Minecraft.getInstance().mouseHandler.isLeftPressed()) {
+ Player player = Minecraft.getInstance().player;
+ if (!shape.getCustomData("isHolding", false)) {
+ shape.putCustomData("isHolding", true);
+ double distance = transformer
+ .getShapeWorldPivot(true)
+ .distanceTo(player.getEyePosition());
+ shape.putCustomData("distance", distance);
+ }
+ transformer.setShapeLocalPivot(
+ player.getEyePosition(transformer.getTickDelta())
+ .add(player.getLookAngle().scale(shape.getCustomData("distance", 5.0)))
+ .add(0, -1, 0)
+ );
+ transformer.world.position.syncLastToTarget();
+ } else {
+ if (shape.getCustomData("isHolding", false))
+ shape.putCustomData("isHolding", false);
+ }
+
+ shape.baseColor = new Color(255, 0, 72, 100);
+ } else {
+ if (shape.getCustomData("isHolding", false))
+ shape.putCustomData("isHolding", false);
+ shape.baseColor = new Color(0, 255, 72, 100);
+ }
})
.build(Shape.RenderingType.BATCH)
);
- // 5. ObjModelOutline
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_obj_outline"),
ShapeGenerator.generateObjModelOutline()
@@ -155,14 +290,18 @@ public static void init(){
.lineWidth(4.0f)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(0, time * 5, 0));
+ t.setShapeWorldRotationDegrees(0, time * 5, 0);
+ if(t.shape.isPlayerLookingAt().hit){
+ t.shape.baseColor = new Color(255,0,72,100);
+ }else{
+ t.shape.baseColor = new Color(0, 255, 72,100);
+ }
})
.build(Shape.RenderingType.BATCH)
);
- // 6. Cone
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_cone"),
ShapeGenerator.generateCone()
@@ -172,20 +311,23 @@ public static void init(){
.segments(32)
.axis(CircleLikeShape.CircleAxis.Y)
.color(randomColor())
- .seeThrough(true)
- .transform((t, s) -> {
+ .seeThrough(false)
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 1, 0, 0));
+ t.setShapeWorldRotationDegrees(time, 0, 0);
- double f = (Math.sin(time * 0.1) + 1) / 2; // 0 → 1 → 0
+ double f = (Math.sin(time * 0.1) + 1) / 2;
int seg = (int)(3 + f * 20-3);
-
+ if(t.shape.isPlayerLookingAt().hit){
+ t.shape.baseColor = new Color(0, 255, 149,100);
+ }else{
+ t.shape.baseColor = new Color(136, 136, 136,100);
+ }
t.setSegment(Math.max(3,seg));
})
.build(Shape.RenderingType.BATCH)
);
- // 7. Cylinder
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_cylinder"),
ShapeGenerator.generateCylinder()
@@ -196,9 +338,9 @@ public static void init(){
.axis(CircleLikeShape.CircleAxis.Z)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 3, time * 4, 0));
+ t.setShapeLocalPivot(new Vec3(0,0,0));
})
.build(Shape.RenderingType.BATCH)
);
@@ -212,13 +354,13 @@ public static void init(){
.segments(32)
.axis(CircleLikeShape.CircleAxis.Y)
.color(randomColor())
- .seeThrough(true)
+ .seeThrough(false)
.width(3)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 1, 0, 0));
+ t.setShapeWorldRotationDegrees(time, 0, 0);
- double f = (Math.sin(time * 0.1) + 1) / 2; // 0 → 1 → 0
+ double f = (Math.sin(time * 0.1) + 1) / 2;
int seg = (int)(3 + f * 20-3);
t.setSegment(Math.max(3,seg));
@@ -236,15 +378,14 @@ public static void init(){
.axis(CircleLikeShape.CircleAxis.Z)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 3, time * 4, 0));
+ t.setShapeWorldRotationDegrees(time*2, time * 5, 0);
})
.build(Shape.RenderingType.BATCH)
);
float linex = xPos();
- // 8. Line
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_line"),
ShapeGenerator.generateLine()
@@ -253,7 +394,7 @@ public static void init(){
.lineWidth(3.0f)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
t.setStart(new Vec3(linex - 2, 0,0));
t.setEnd(new Vec3(linex + 2, 4 + (float)Math.sin(time * 0.1) * 2,0));
@@ -261,7 +402,7 @@ public static void init(){
.build(Shape.RenderingType.BATCH)
);
- // 9. StripLine(螺旋线)
+ float cx = xPos();
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_strip_line"),
ShapeGenerator.generateStripLine()
@@ -269,31 +410,28 @@ public static void init(){
.lineWidth(2.0f)
.color(randomColor())
.seeThrough(false)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- // 动态更新顶点(旋转螺旋)
- ((StripLineShape)s).setVertexes(generateSpiral(xPos(), 100, 2.0f, 5.0f, time * 0.05f));
+ ((StripLineShape)t.getShape()).setVertexes(generateSpiral(cx, 100, 2.0f, 5.0f, time * 0.05f));
})
.build(Shape.RenderingType.BATCH)
);
- // 10. BoxFace
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_box_face"),
ShapeGenerator.generateBoxFace()
.pos(new Vec3(xPos(), 0, 0))
.size(new Vec3(2,2,2))
.color(randomColor())
- .seeThrough(true)
+ .seeThrough(false)
.construction(BoxShape.BoxConstructionType.CENTER_AND_DIMENSIONS )
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 2, time * 3, time * 1.5f));
+ t.setShapeWorldRotationDegrees(time * 2, time * 3, time * 1.5f);
})
.build(Shape.RenderingType.BATCH)
);
- // 11. BoxWireframe
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_box_wire"),
ShapeGenerator.generateBoxWireframe()
@@ -303,32 +441,48 @@ public static void init(){
.color(randomColor())
.seeThrough(false)
.construction(BoxShape.BoxConstructionType.CORNERS)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(0, time * 4, 0));
+ t.setShapeWorldRotationDegrees(0, time * 4, 0);
})
.build(Shape.RenderingType.BATCH)
);
- // 12. WireframedBox
ShapeManagers.addShape(
ResourceLocation.fromNamespaceAndPath(MOD_ID, "demo_wireframed_box"),
ShapeGenerator.generateWireframedBox()
.aabb(new Vec3(xPos() - 2, 0, -2),
new Vec3(xPos() + 2, 4, 2))
- .color(randomColor()) // 面颜色
+ .color(randomColor())
.edgeColor(new Color(255, 255, 255, 200))
.edgeWidth(2.0f)
- .seeThrough(true)
+ .seeThrough(false)
.lineSeeThrough(false)
.construction(BoxShape.BoxConstructionType.CORNERS)
- .transform((t, s) -> {
+ .transform((t) -> {
float time = client.getGameTime();
- t.setMatrixRotation(new Vec3(time * 1.5f, time * 2.5f, 0));
+ t.setShapeWorldRotationDegrees(time * 1.5f, time * 2.5f, time*0.5f);
})
.build(Shape.RenderingType.BATCH)
);
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "test_text1"),
+ ShapeGenerator.generateText()
+ .pos(new Vec3(xPos(), 0, 0))
+ .type(Shape.RenderingType.BATCH)
+ .billBoardMode(TextShape.BillBoardMode.ALL)
+ .seeThrough(false)
+ .shadow(true)
+ .outline(true)
+ .texts("§b§l!TEST!", "§e你好", "§aAWA", "§dBillBoardMode.ALL")
+ .textColors(Color.CYAN, Color.YELLOW, Color.GREEN, Color.MAGENTA)
+ .transform(t -> t.setShapeMatrixPivot(
+ new Vec3(0, Math.sin(Minecraft.getInstance().player.tickCount * 0.05) * 0.3, 0)
+ ))
+
+ .build(Shape.RenderingType.BATCH)
+ );
added = true;
});
@@ -351,15 +505,137 @@ private static List generateSpiral(float centerX, int segments, float radi
}
public static void renderTick(PoseStack matrixStack){
}
+ public static void generateLineTracker(){
+ Minecraft mc = Minecraft.getInstance();
+ Shape anchor1 = ShapeGenerator.generateSphere()
+ .pos(new Vec3(xPos(), 0,0))
+ .radius(0.1f)
+ .segments(16)
+ .color(new Color(0,0,1,0.5f))
+ .seeThrough(false)
+ .transform((transformer) -> {
+ Shape shape = transformer.getShape();
+ handleMouseGrab(mc.player,shape,transformer);
+
+ })
+ .build(Shape.RenderingType.BATCH);
+ Shape anchor2 = ShapeGenerator.generateSphere()
+ .pos(new Vec3(xPos(), 0,0))
+ .radius(0.1f)
+ .segments(16)
+ .color(new Color(1,0,0,0.5f))
+ .seeThrough(false)
+ .transform((transformer) -> {
+ Shape shape = transformer.getShape();
+ handleMouseGrab(mc.player,shape,transformer);
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ Shape line = ShapeGenerator.generateLine()
+ .pos(new Vec3(0, 0,0))
+ .lineWidth(2.1f)
+ .color(Color.WHITE)
+ .seeThrough(false)
+ .transform((transformer) -> {
+ transformer.setStart(anchor1.transformer.getShapeWorldPivot(true));
+ transformer.setEnd(anchor2.transformer.getShapeWorldPivot(true));
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ Shape text = ShapeGenerator.generateText()
+ .pos(new Vec3(xPos(), 0, 0))
+ .type(Shape.RenderingType.BATCH)
+ .billBoardMode(TextShape.BillBoardMode.ALL)
+ .seeThrough(false)
+ .shadow(true)
+ .outline(false)
+ .texts("-")
+ .textColors(Color.CYAN, Color.YELLOW, Color.GREEN, Color.MAGENTA)
+ .transform(t -> {
+ Vec3 start = ((TwoPointsLineShape.TwoPointsLineTransformer)line.transformer).getStart(true);
+ Vec3 end = ((TwoPointsLineShape.TwoPointsLineTransformer)line.transformer).getEnd(true);
+ Entity player = Minecraft.getInstance().player;
+ if (player == null) return;
+ Vec3 eyePos = player.getPosition(t.getTickDelta()).add(0, player.getEyeHeight(), 0);
+ Vec3 lineDir = end.subtract(start);
+ double lineLength = lineDir.length();
+ if (lineLength < 0.001) {
+ t.setShapeMatrixPivot(start.add(0, 0.1, 0));
+ return;
+ }
+ Vec3 toEye = eyePos.subtract(start);
+ double proj = toEye.dot(lineDir) / (lineLength * lineLength);
+ proj = Mth.clamp(proj, 0.0, 1.0);
+ Vec3 closestPoint = start.add(lineDir.scale(proj));
+ Vec3 labelOffset = new Vec3(0, 0.3, 0);
+ Vec3 towardsPlayer = eyePos.subtract(closestPoint).normalize().scale(0.15);
+ Vec3 finalPos = closestPoint.add(labelOffset).add(towardsPlayer.yRot((float)Math.toRadians(15)));
+ t.setShapeWorldPivot(finalPos);
+ t.world.syncLastToTarget();
+ double d = anchor1.transformer.getWorldPivot().distanceTo(anchor2.transformer.getWorldPivot());
+ ((TextShape)t.shape).setText(1,"Distance : " + String.format("%.2f", d));
+ })
+ .build(Shape.RenderingType.BATCH);
+
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "a1"),
+ anchor1
+ );
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "a2"),
+ anchor2
+ );
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "l1"),
+ line
+ );
+ ShapeManagers.addShape(
+ ResourceLocation.fromNamespaceAndPath(MOD_ID, "tex"),
+ text
+ );
+ }
+ public static void handleMouseGrab(Player player, Shape shape, DefaultTransformer transformer) {
+ Minecraft mc = Minecraft.getInstance();
+ boolean isLeftPressed = mc.mouseHandler.isLeftPressed();
+ boolean wasHolding = shape.getCustomData("isHolding", false);
+ boolean isLookingAt = shape.isPlayerLookingAt().hit;
+ if(!wasHolding) shape.putCustomData("color",shape.baseColor);
+ boolean shouldHold = wasHolding || (isLeftPressed && isLookingAt);
+ if (shouldHold && !wasHolding) {
+ double distance = transformer.getShapeWorldPivot(true)
+ .distanceTo(player.getEyePosition());
+ shape.putCustomData("grabDistance", distance);
+ shape.putCustomData("isHolding", true);
+ }
+ if (isLeftPressed && shape.getCustomData("isHolding", false)) {
+ double savedDistance = shape.getCustomData("grabDistance", 4.0);
+ Vec3 eyePos = player.getEyePosition(transformer.getTickDelta());
+ Vec3 look = player.getLookAngle();
+
+ Vec3 targetPos = eyePos.add(look.scale(savedDistance));
+
+ transformer.setShapeWorldPivot(targetPos);
+ transformer.world.position.syncLastToTarget();
+ shape.baseColor = new Color(255, 255, 255, 200);
+ }
+ else if (!isLeftPressed && wasHolding) {
+ shape.putCustomData("isHolding", false);
+ shape.putCustomData("grabDistance", null);
+ shape.baseColor = shape.getCustomData("color",Color.WHITE);
+ }
+ else if (!isLeftPressed) {
+ shape.baseColor = shape.getCustomData("color",Color.WHITE);
+ }
+ }
public static void rotate(BoxLikeShape.BoxTransformer boxTransformer, Shape shape){
float gameTime = Minecraft.getInstance().level.getGameTime();
float rotationAngle = (gameTime % 3600) * 2f;
- boxTransformer.setMatrixRotation(new Vec3(rotationAngle, rotationAngle, rotationAngle));
+ boxTransformer.setShapeWorldRotationDegrees(rotationAngle, rotationAngle, rotationAngle);
}
public static void addEntity(Entity entity) {
Player player = Minecraft.getInstance().player;
- if (player == null || entity == null || entity == player) return;
+ if (player == null || entity == null || entity == player || !ENABLE_DEBUG) return;
int entityId = entity.getId();
EntityDimensions dimensions = entity.getDimensions(entity.getPose());
@@ -367,13 +643,13 @@ public static void addEntity(Entity entity) {
ResourceLocation.fromNamespaceAndPath(MOD_ID, "entity_tracker_" + entityId + "/bounding_box"),
new BoxFaceShape(
Shape.RenderingType.BATCH,
- (transformer, shape) -> {
+ (transformer) -> {
Vec3 entityCenter = entity.position().add(0, dimensions.height() / 2, 0);
- if (entity.isRemoved()) {
- shape.discard();
+ if (entity.isRemoved() || !ENABLE_DEBUG) {
+ transformer.shape.discard();
return;
}
- transformer.setShapeCenterPos(entityCenter);
+ transformer.setShapeWorldPivot(entityCenter);
},
entity.position().add(0, dimensions.height() / 2, 0),
new Vec3(dimensions.width(), dimensions.height(), dimensions.width()),
@@ -387,13 +663,13 @@ public static void addEntity(Entity entity) {
ResourceLocation.fromNamespaceAndPath(MOD_ID, "entity_tracker_" + entityId + "/line"),
new LineShape(
Shape.RenderingType.BATCH,
- (transformer, shape) -> {
- if (entity.isRemoved()) {
- shape.discard();
+ (transformer) -> {
+ if (entity.isRemoved() || !ENABLE_DEBUG) {
+ transformer.getShape().discard();
return;
}
if (Minecraft.getInstance().level != null && Minecraft.getInstance().player != null) {
- transformer.setStart(player.getEyePosition().add(player.getLookAngle().scale(2)));
+ ((LineShape)transformer.getShape()).forceSetStart(player.getEyePosition(transformer.getTickDelta()).add(player.getLookAngle().scale(2)));
transformer.setEnd(entity.position());
}
},
diff --git a/src/main/java/mypals/ml/transform/FloatValueTransformer.java b/src/main/java/mypals/ml/transform/FloatValueTransformer.java
deleted file mode 100644
index 18c1102..0000000
--- a/src/main/java/mypals/ml/transform/FloatValueTransformer.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package mypals.ml.transform;
-
-import java.util.function.Consumer;
-import net.minecraft.util.Mth;
-
-public class FloatValueTransformer {
- private float last = 0;
- private float target = 0;
- private float current = 0;
- public FloatValueTransformer(float init){
- this.target = init;
- syncLastToTarget();
- }
- public FloatValueTransformer(){
-
- }
- public void setTargetValue(float target) {
- this.target = target;
- }
- public void updateValue(Consumer setter, float delta) {
- current = (float) Mth.lerp((double)delta, last, target);
- setter.accept(current);
- }
- public void syncLastToTarget() {
- this.last = this.target;
- }
- public float getCurrentValue(){
- return current;
- }
-}
diff --git a/src/main/java/mypals/ml/transform/IntValueTransformer.java b/src/main/java/mypals/ml/transform/IntValueTransformer.java
deleted file mode 100644
index 55e4c92..0000000
--- a/src/main/java/mypals/ml/transform/IntValueTransformer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package mypals.ml.transform;
-
-import java.util.function.Consumer;
-import net.minecraft.util.Mth;
-
-public class IntValueTransformer {
- private int last = 0;
- private int target = 0;
- private int current = 0;
-
- public IntValueTransformer(int init) {
- this.target = init;
- syncLastToTarget();
- }
-
- public IntValueTransformer() {
- }
-
- public void setTargetValue(int target) {
- this.target = target;
- }
-
- public void updateValue(Consumer setter, float delta) {
-
- float lerped = Mth.lerp(delta, (float) last, (float) target);
- current = Math.round(lerped);
- setter.accept(current);
- }
-
- public void syncLastToTarget() {
- this.last = this.target;
- }
-
- public int getCurrentValue() {
- return current;
- }
-}
-
diff --git a/src/main/java/mypals/ml/transform/QuaternionTransformer.java b/src/main/java/mypals/ml/transform/QuaternionTransformer.java
deleted file mode 100644
index 3f1b797..0000000
--- a/src/main/java/mypals/ml/transform/QuaternionTransformer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package mypals.ml.transform;
-
-import java.util.function.Consumer;
-import org.joml.Quaternionf;
-import org.joml.Quaternionfc;
-
-public class QuaternionTransformer {
- private Quaternionf lastRotation = new Quaternionf();
- private Quaternionf targetRotation = new Quaternionf();
- private Quaternionf currentRotation = new Quaternionf();
- public QuaternionTransformer(Quaternionf init){
- this.targetRotation = init;
- syncLastToTarget();
- }
- public QuaternionTransformer(){
-
- }
- public void setTargetRotation(Quaternionfc targetRotation) {
- this.targetRotation.set(targetRotation);
- }
-
- public void updateRotation(Consumer setter, float delta) {
- currentRotation = new Quaternionf();
- lastRotation.slerp(targetRotation, delta, currentRotation);
-
- setter.accept(currentRotation);
-
- }
- public void syncLastToTarget() {
- this.lastRotation.set(targetRotation);
- }
-}
diff --git a/src/main/java/mypals/ml/transform/Vec3dTransformer.java b/src/main/java/mypals/ml/transform/Vec3dTransformer.java
deleted file mode 100644
index 1af21c5..0000000
--- a/src/main/java/mypals/ml/transform/Vec3dTransformer.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package mypals.ml.transform;
-
-import java.util.function.Consumer;
-import net.minecraft.util.Mth;
-import net.minecraft.world.phys.Vec3;
-
-public class Vec3dTransformer {
- private Vec3 lastVector = Vec3.ZERO;
- private Vec3 targetVector = Vec3.ZERO;
- private Vec3 currentVector = Vec3.ZERO;
- public Vec3dTransformer(Vec3 init){
- this.targetVector = init;
- syncLastToTarget();
- }
- public Vec3dTransformer(){
-
- }
- public void setTargetVector(Vec3 targetPosition) {
- this.targetVector = targetPosition;
- }
- public void updateVector(Consumer setter, float delta) {
- double d = Mth.lerp((double)delta, lastVector.x, targetVector.x);
- double e = Mth.lerp((double)delta, lastVector.y, targetVector.y);
- double f = Mth.lerp((double)delta, lastVector.z, targetVector.z);
- currentVector = new Vec3(d,e,f);
- setter.accept(currentVector);
- }
- public void syncLastToTarget() {
- this.lastVector = this.targetVector;
- }
- public Vec3 getCurrentVector(){
- return currentVector;
- }
-}
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/DefaultTransformer.java b/src/main/java/mypals/ml/transform/shapeTransformers/DefaultTransformer.java
new file mode 100644
index 0000000..9ca6a4a
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/DefaultTransformer.java
@@ -0,0 +1,155 @@
+package mypals.ml.transform.shapeTransformers;
+
+import com.mojang.blaze3d.vertex.PoseStack;
+import mypals.ml.shape.Shape;
+import mypals.ml.transform.valueTransformers.QuaternionTransformer;
+import mypals.ml.transform.valueTransformers.Vec3Transformer;
+import net.minecraft.world.phys.Vec3;
+import org.joml.Matrix4f;
+import org.joml.Quaternionf;
+
+public class DefaultTransformer {
+ private float delta = 0;
+ public final Shape shape;
+
+ public final TransformLayer local = new TransformLayer();
+ public final TransformLayer world = new TransformLayer();
+ public final TransformLayer matrix = new TransformLayer();
+
+ public DefaultTransformer(Shape s,Vec3 center) {
+ this.shape = s;
+ this.world.setPosition(center);
+ this.world.syncLastToTarget();
+ }
+
+ public Shape getShape() {
+ return shape;
+ }
+
+ public void updateTickDelta(float d) {
+ this.delta = d;
+ updateAll(d);
+ }
+ public float getTickDelta() { return delta; }
+ public void updateAll(float t) {
+ local.update(t);
+ world.update(t);
+ matrix.update(t);
+ }
+
+ public void syncLastToTarget() {
+ local.syncLastToTarget();
+ world.syncLastToTarget();
+ matrix.syncLastToTarget();
+ }
+
+ public void applyTransformations(PoseStack stack,boolean lerp) {
+ applyLayer(stack,world,lerp);
+ applyLayer(stack,local, lerp);
+ applyLayer(stack, matrix, lerp);
+ }
+ public void applyModelTransformations(PoseStack stack,boolean lerp) {
+ applyLayer(stack,world,lerp);
+ applyLayer(stack,local,lerp);
+ }
+
+ private void applyLayer(PoseStack stack, TransformLayer layer, boolean lerp) {
+ Vec3 p = layer.position.getValue(lerp);
+ Quaternionf r = layer.rotation.getValue(lerp);
+ Vec3 s = layer.scale.getValue(lerp);
+
+ stack.translate(p.x, p.y, p.z);
+ stack.mulPose(r);
+ stack.scale((float) s.x, (float) s.y, (float) s.z);
+ }
+
+
+ public TransformLayer local() { return local; }
+ public TransformLayer world() { return world; }
+ public TransformLayer matrix() { return matrix; }
+
+ public Vec3 getShapeWorldPivot(boolean lerp) {
+ return world.getPosition(lerp);
+ }
+
+ public Quaternionf getShapeWorldRotation(boolean lerp) {
+ return world.getRotation(lerp);
+ }
+
+ public Vec3 getShapeWorldScale(boolean lerp) {
+ return world.getScale(lerp);
+ }
+
+ public Vec3 getShapeLocalPivot(boolean lerp) {
+ return local.getPosition(lerp);
+ }
+
+ public Quaternionf getShapeLocalRotation(boolean lerp) {
+ return local.getRotation(lerp);
+ }
+
+ public Vec3 getShapeLocalScale(boolean lerp) {
+ return local.getScale(lerp);
+ }
+
+ public Vec3 getShapeMatrixPivot(boolean lerp) {
+ return matrix.getPosition(lerp);
+ }
+
+ public Quaternionf getShapeMatrixRotation(boolean lerp) {
+ return matrix.getRotation(lerp);
+ }
+
+ public Vec3 getShapeMatrixScale(boolean lerp) {
+ return matrix.getScale(lerp);
+ }
+
+ public Vec3 getWorldPivot() { return getShapeWorldPivot(true); }
+ public Quaternionf getWorldRotation() { return getShapeWorldRotation(true); }
+ public Vec3 getWorldScale() { return getShapeWorldScale(true); }
+
+ public Vec3 getLocalPivot() { return getShapeLocalPivot(true); }
+ public Quaternionf getLocalRotation() { return getShapeLocalRotation(true); }
+ public Vec3 getLocalScale() { return getShapeLocalScale(true); }
+
+ public Vec3 getMatrixPivot() { return getShapeMatrixPivot(true); }
+ public Quaternionf getMatrixRotation() { return getShapeMatrixRotation(true); }
+ public Vec3 getMatrixScale() { return getShapeMatrixScale(true); }
+
+
+ public void setShapeWorldPivot(Vec3 v) { world.setPosition(v); }
+ public void setShapeWorldRotation(Quaternionf q) { world.setRotation(q); }
+ public void setShapeWorldRotationDegrees(float x, float y, float z) {
+ world.setRotation(new Quaternionf().rotateXYZ(
+ (float) Math.toRadians(x),
+ (float) Math.toRadians(y),
+ (float) Math.toRadians(z)
+ ));
+ }
+ public void setShapeWorldScale(Vec3 s) { world.setScale(s); }
+
+ public void setShapeLocalPivot(Vec3 v) { local.setPosition(v); }
+ public void setShapeLocalRotation(Quaternionf q) { local.setRotation(q); }
+ public void setShapeLocalRotationDegrees(float x, float y, float z) {
+ local.setRotation(new Quaternionf().rotateXYZ(
+ (float) Math.toRadians(x),
+ (float) Math.toRadians(y),
+ (float) Math.toRadians(z)
+ ));
+ }
+ public void setShapeLocalScale(Vec3 s) { local.setScale(s); }
+
+ public void setShapeMatrixPivot(Vec3 v) { matrix.setPosition(v); }
+ public void setShapeMatrixRotation(Quaternionf q) { matrix.setRotation(q); }
+ public void setShapeMatrixRotationDegrees(float x, float y, float z) {
+ matrix.setRotation(new Quaternionf().rotateXYZ(
+ (float) Math.toRadians(x),
+ (float) Math.toRadians(y),
+ (float) Math.toRadians(z)
+ ));
+ }
+ public void setShapeMatrixScale(Vec3 s) { matrix.setScale(s); }
+ public boolean asyncModelInfo(){
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/ModelInfoLayer.java b/src/main/java/mypals/ml/transform/shapeTransformers/ModelInfoLayer.java
new file mode 100644
index 0000000..e88fbb5
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/ModelInfoLayer.java
@@ -0,0 +1,10 @@
+package mypals.ml.transform.shapeTransformers;
+
+public abstract class ModelInfoLayer {
+ public void update(float delta){}
+ public boolean async(){
+ return false;
+ }
+
+ public void syncLastToTarget() {}
+}
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/TransformLayer.java b/src/main/java/mypals/ml/transform/shapeTransformers/TransformLayer.java
new file mode 100644
index 0000000..52cf064
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/TransformLayer.java
@@ -0,0 +1,38 @@
+package mypals.ml.transform.shapeTransformers;
+
+import mypals.ml.transform.valueTransformers.QuaternionTransformer;
+import mypals.ml.transform.valueTransformers.Vec3Transformer;
+import net.minecraft.world.phys.Vec3;
+import org.joml.Quaternionf;
+
+public class TransformLayer {
+ public final Vec3Transformer position = new Vec3Transformer(Vec3.ZERO);
+ public final QuaternionTransformer rotation = new QuaternionTransformer();
+ public final Vec3Transformer scale = new Vec3Transformer(Vec3.ZERO.add(1));
+
+ public void update(float delta) {
+ position.update(delta);
+ rotation.update(delta);
+ scale.update(delta);
+ }
+
+ public void syncLastToTarget() {
+ position.syncLastToTarget();
+ rotation.syncLastToTarget();
+ scale.syncLastToTarget();
+ }
+
+ public void setPosition(Vec3 v) { position.setTargetVector(v); }
+ public void setRotation(Quaternionf q) { rotation.setTargetRotation(q); }
+ public void setRotationDegrees(float x, float y, float z) {
+ rotation.setTargetRotation(new Quaternionf().rotateXYZ(
+ (float)Math.toRadians(x),
+ (float)Math.toRadians(y),
+ (float)Math.toRadians(z)
+ ));
+ }
+ public void setScale(Vec3 s) { scale.setTargetVector(s); }
+ public Vec3 getPosition(boolean useLerp) { return position.getValue(useLerp); }
+ public Vec3 getScale(boolean useLerp) { return scale.getValue(useLerp); }
+ public Quaternionf getRotation(boolean useLerp) { return rotation.getValue(useLerp); }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/BoxModelInfo.java b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/BoxModelInfo.java
new file mode 100644
index 0000000..a5647bc
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/BoxModelInfo.java
@@ -0,0 +1,30 @@
+package mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer;
+
+import mypals.ml.transform.shapeTransformers.ModelInfoLayer;
+import mypals.ml.transform.valueTransformers.Vec3Transformer;
+import net.minecraft.world.phys.Vec3;
+
+public class BoxModelInfo extends ModelInfoLayer {
+ public Vec3Transformer boxDimensionTransformer;
+ public BoxModelInfo(Vec3 dim){
+ boxDimensionTransformer = new Vec3Transformer(dim);
+ }
+ public boolean async(){
+ return boxDimensionTransformer.async();
+ }
+ public void update(float delta){
+ boxDimensionTransformer.update(delta);
+ }
+ public Vec3 getDimension(boolean lerp){
+ return boxDimensionTransformer.getValue(lerp);
+ }
+ public void setDimension(Vec3 target){
+ boxDimensionTransformer.setTargetVector(target);
+ }
+
+ @Override
+ public void syncLastToTarget() {
+ this.boxDimensionTransformer.syncLastToTarget();
+ super.syncLastToTarget();
+ }
+}
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/CircleModelInfo.java b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/CircleModelInfo.java
new file mode 100644
index 0000000..dec7842
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/CircleModelInfo.java
@@ -0,0 +1,42 @@
+package mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer;
+
+import mypals.ml.transform.shapeTransformers.ModelInfoLayer;
+import mypals.ml.transform.valueTransformers.FloatTransformer;
+import mypals.ml.transform.valueTransformers.IntTransformer;
+import mypals.ml.transform.valueTransformers.Vec3Transformer;
+import net.minecraft.world.phys.Vec3;
+
+public class CircleModelInfo extends ModelInfoLayer {
+ public IntTransformer segmentTransformer;
+ public FloatTransformer radiusTransformer;
+
+ public CircleModelInfo(int seg,float rad){
+ segmentTransformer = new IntTransformer(seg);
+ radiusTransformer = new FloatTransformer(rad);
+ }
+ public boolean async(){
+ return radiusTransformer.async() || segmentTransformer.async();
+ }
+ public void update(float delta){
+ radiusTransformer.update(delta);
+ segmentTransformer.update(delta);
+ }
+ public float getRadius(boolean lerp){
+ return radiusTransformer.getValue(lerp);
+ }
+ public void setRadius(float target){
+ radiusTransformer.setTargetValue(target);
+ }
+ public int getSegment(boolean lerp){
+ return segmentTransformer.getValue(lerp);
+ }
+ public void setSegment(int target){
+ segmentTransformer.setTargetValue(target);
+ }
+ @Override
+ public void syncLastToTarget() {
+ this.segmentTransformer.syncLastToTarget();
+ this.radiusTransformer.syncLastToTarget();
+ super.syncLastToTarget();
+ }
+}
diff --git a/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/LineModelInfo.java b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/LineModelInfo.java
new file mode 100644
index 0000000..dfe4ed9
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/shapeTransformers/shapeModelInfoTransformer/LineModelInfo.java
@@ -0,0 +1,67 @@
+package mypals.ml.transform.shapeTransformers.shapeModelInfoTransformer;
+
+import mypals.ml.transform.shapeTransformers.ModelInfoLayer;
+import mypals.ml.transform.valueTransformers.FloatTransformer;
+import mypals.ml.transform.valueTransformers.Vec3Transformer;
+import net.minecraft.world.phys.Vec3;
+
+public class LineModelInfo extends ModelInfoLayer {
+ public FloatTransformer widthTransformer;
+ public LineModelInfo(float width){
+ this.widthTransformer = new FloatTransformer(width);
+ }
+ public boolean async(){
+ return widthTransformer.async();
+ }
+ public void update(float delta){
+ widthTransformer.update(delta);
+ }
+ public float getWidth(boolean lerp){
+ return widthTransformer.getValue(lerp);
+ }
+ public void setWidth(float target){
+ widthTransformer.setTargetValue(target);
+ }
+
+ @Override
+ public void syncLastToTarget() {
+ this.widthTransformer.syncLastToTarget();
+ super.syncLastToTarget();
+ }
+ public static class TwoPointLineModelInfo extends LineModelInfo {
+ public Vec3Transformer endPointTransformer;
+ public Vec3Transformer startPointTransformer;
+ public TwoPointLineModelInfo(Vec3 start, Vec3 end,float width){
+ super(width);
+ endPointTransformer = new Vec3Transformer(end);
+ startPointTransformer = new Vec3Transformer(start);
+ }
+ public boolean async(){
+ return super.async() || endPointTransformer.async() || startPointTransformer.async();
+ }
+ public void update(float delta){
+ endPointTransformer.update(delta);
+ startPointTransformer.update(delta);
+ super.update(delta);
+ }
+ public Vec3 getStart(boolean lerp){
+ return startPointTransformer.getValue(lerp);
+ }
+ public Vec3 getEnd(boolean lerp){
+ return endPointTransformer.getValue(lerp);
+ }
+ public void setStart(Vec3 target){
+ startPointTransformer.setTargetVector(target);
+ }
+ public void setEnd(Vec3 target){
+ endPointTransformer.setTargetVector(target);
+ }
+
+ @Override
+ public void syncLastToTarget() {
+ super.syncLastToTarget();
+ this.startPointTransformer.syncLastToTarget();
+ this.endPointTransformer.syncLastToTarget();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/transform/valueTransformers/FloatTransformer.java b/src/main/java/mypals/ml/transform/valueTransformers/FloatTransformer.java
new file mode 100644
index 0000000..771af35
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/valueTransformers/FloatTransformer.java
@@ -0,0 +1,30 @@
+package mypals.ml.transform.valueTransformers;
+
+import net.minecraft.util.Mth;
+
+public final class FloatTransformer extends ValueTransformer {
+
+ public FloatTransformer(float initial) {
+ this.target = initial;
+ syncLastToTarget();
+ }
+
+ public FloatTransformer() { this(0f); }
+
+ @Override public void update(float delta) {
+ current = (float) Mth.lerp(delta, last, target);
+ }
+
+ @Override public void syncLastToTarget() {
+ this.last = this.target;
+ this.current = this.target;
+ }
+
+ @Override protected void setTarget(Float value) {
+ this.target = value;
+ }
+
+ public void setTargetValue(float v) { setTarget(v); }
+
+ public float getCurrentValue() { return current; }
+}
diff --git a/src/main/java/mypals/ml/transform/valueTransformers/IntTransformer.java b/src/main/java/mypals/ml/transform/valueTransformers/IntTransformer.java
new file mode 100644
index 0000000..b2c965e
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/valueTransformers/IntTransformer.java
@@ -0,0 +1,32 @@
+package mypals.ml.transform.valueTransformers;
+
+import net.minecraft.util.Mth;
+
+public final class IntTransformer extends ValueTransformer {
+
+ public IntTransformer(int initial) {
+ this.target = initial;
+ syncLastToTarget();
+ }
+
+ public IntTransformer() { this(0); }
+
+ @Override public void update(float delta) {
+ float lerped = Mth.lerp(delta, last.floatValue(), target.floatValue());
+ current = Math.round(lerped);
+ }
+
+ @Override public void syncLastToTarget() {
+ this.last = this.target;
+ this.current = this.target;
+ }
+
+ @Override protected void setTarget(Integer value) {
+ this.target = value;
+ }
+
+ public void setTargetValue(int v) { setTarget(v); }
+
+ public int getCurrentValue() { return current; }
+}
+
diff --git a/src/main/java/mypals/ml/transform/valueTransformers/QuaternionTransformer.java b/src/main/java/mypals/ml/transform/valueTransformers/QuaternionTransformer.java
new file mode 100644
index 0000000..c57aa39
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/valueTransformers/QuaternionTransformer.java
@@ -0,0 +1,28 @@
+package mypals.ml.transform.valueTransformers;
+import org.joml.Quaternionf;
+import org.joml.Quaternionfc;
+public final class QuaternionTransformer extends ValueTransformer {
+
+ public QuaternionTransformer(Quaternionf initial) {
+ this.target = new Quaternionf(initial);
+ syncLastToTarget();
+ }
+
+ public QuaternionTransformer() { this(new Quaternionf()); }
+
+ @Override public void update(float delta) {
+ current = new Quaternionf();
+ last.slerp(target, delta, current);
+ }
+
+ @Override public void syncLastToTarget() {
+ this.last = new Quaternionf(target);
+ this.current = new Quaternionf(target);
+ }
+
+ @Override protected void setTarget(Quaternionf value) {
+ this.target.set(value);
+ }
+
+ public void setTargetRotation(Quaternionfc rot) { setTarget(new Quaternionf(rot)); }
+}
diff --git a/src/main/java/mypals/ml/transform/valueTransformers/ValueTransformer.java b/src/main/java/mypals/ml/transform/valueTransformers/ValueTransformer.java
new file mode 100644
index 0000000..0daaef1
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/valueTransformers/ValueTransformer.java
@@ -0,0 +1,23 @@
+package mypals.ml.transform.valueTransformers;
+
+public abstract class ValueTransformer {
+
+ protected T last; // value at the start of the current tick
+ protected T target; // value we are moving toward
+ protected T current; // interpolated value (updated each frame)
+
+ /** Update tick-delta */
+ public abstract void update(float delta);
+
+ /** Set last → target (instant change) */
+ public abstract void syncLastToTarget();
+
+ /** Current interpolated value */
+ public T getValue(boolean lerp) { return lerp?current:target; }
+
+ public boolean async() {
+ return !current.equals(target);
+ }
+ /** Set a new target*/
+ protected abstract void setTarget(T value);
+}
\ No newline at end of file
diff --git a/src/main/java/mypals/ml/transform/valueTransformers/Vec3Transformer.java b/src/main/java/mypals/ml/transform/valueTransformers/Vec3Transformer.java
new file mode 100644
index 0000000..b75671b
--- /dev/null
+++ b/src/main/java/mypals/ml/transform/valueTransformers/Vec3Transformer.java
@@ -0,0 +1,32 @@
+package mypals.ml.transform.valueTransformers;
+
+import net.minecraft.util.Mth;
+import net.minecraft.world.phys.Vec3;
+
+public final class Vec3Transformer extends ValueTransformer {
+
+ public Vec3Transformer(Vec3 initial) {
+ this.target = initial;
+ syncLastToTarget();
+ }
+
+ public Vec3Transformer() { this(Vec3.ZERO); }
+
+ @Override public void update(float delta) {
+ double x = Mth.lerp(delta, last.x, target.x);
+ double y = Mth.lerp(delta, last.y, target.y);
+ double z = Mth.lerp(delta, last.z, target.z);
+ current = new Vec3(x, y, z);
+ }
+
+ @Override public void syncLastToTarget() {
+ this.last = this.target;
+ this.current = this.target;
+ }
+
+ @Override protected void setTarget(Vec3 value) {
+ this.target = value;
+ }
+
+ public void setTargetVector(Vec3 v) { setTarget(v); }
+}
\ No newline at end of file
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index 43030c3..f9359b5 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -4,6 +4,7 @@
"version": "${version}",
"name": "RyansRenderingKit",
"description": "This is an example description! Tell everyone what your mod is about!",
+ "access_widener": "ryansRenderingKit.accesswidener",
"authors": [
"Me!"
],
diff --git a/src/main/resources/ryansRenderingKit.accesswidener b/src/main/resources/ryansRenderingKit.accesswidener
new file mode 100644
index 0000000..68105db
--- /dev/null
+++ b/src/main/resources/ryansRenderingKit.accesswidener
@@ -0,0 +1,2 @@
+accessWidener v2 named
+accessible field com/mojang/blaze3d/vertex/BufferBuilder vertices I
\ No newline at end of file
diff --git a/src/main/resources/ryansrenderingkit.mixins.json b/src/main/resources/ryansrenderingkit.mixins.json
index 05d1725..72054a9 100644
--- a/src/main/resources/ryansrenderingkit.mixins.json
+++ b/src/main/resources/ryansrenderingkit.mixins.json
@@ -11,6 +11,8 @@
"requireAnnotations": true
},
"client": [
- "ClientWorldMixin"
- ]
+ "ClientWorldMixin",
+ "MeshDataMixin",
+ "MeshDataMixin$SortStateMixin"
+ ]
}
\ No newline at end of file