From 80e0e1c670b71100943872de9a63ebf97c0e0521 Mon Sep 17 00:00:00 2001 From: xTracr Date: Wed, 8 May 2024 21:30:26 +0800 Subject: [PATCH] Compatible with different draw modes --- README.md | 14 ++-- README_ZH.md | 9 +-- .../com/xtracr/realcamera/RealCameraCore.java | 13 ++-- .../compat/CompatibilityHelper.java | 2 +- .../realcamera/compat/DisableHelper.java | 11 +-- .../realcamera/config/ConfigScreen.java | 4 +- .../xtracr/realcamera/gui/ModelAnalyser.java | 70 ++++++++--------- .../realcamera/gui/ModelViewScreen.java | 4 +- .../realcamera/util/VertexRecorder.java | 77 +++++++++++-------- .../assets/realcamera/lang/ko_kr.json | 4 +- .../assets/realcamera/lang/zh_cn.json | 2 +- gradle.properties | 2 +- 12 files changed, 105 insertions(+), 107 deletions(-) diff --git a/README.md b/README.md index 2247cdb..d904d08 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@ Make the camera more realistic in the first-person view. Supported versions: 1.18-1.20 Forge & Fabric. -Download the mod -from [Releases](https://github.com/xTracr/RealCamera/releases), [Modrinth](https://modrinth.com/mod/real-camera) -or [CurseForge](https://curseforge.com/minecraft/mc-mods/real-camera) +Download the mod from [Releases](https://github.com/xTracr/RealCamera/releases), [Modrinth](https://modrinth.com/mod/real-camera) or [CurseForge](https://curseforge.com/minecraft/mc-mods/real-camera) Snapshots are [here](https://github.com/xTracr/RealCamera/actions/workflows/build.yml) ## Features ## @@ -17,21 +15,19 @@ Snapshots are [here](https://github.com/xTracr/RealCamera/actions/workflows/buil * Use F6 to toggle the feature on or off and other hotkeys to adjust the camera. * Configure these features in the config screen (Cloth Config required). * Theoretically, most mod models are supported, but need to be configured manually: - * First, set the key binding for `Open Model View GUI`. + * First, set the key binding for `Open Model View Screen`. * Open the model view gui and left click with left Alt held to select the corresponding face of the model, scroll with left Alt held to switch between the different layers of the model. * By clicking the `Selecting` button on the left, switch between the three to select the `Forward Vector`, `Upward Vector`, and `Target Plane`. * Enter the `Preview` section, where you can see the relative relationship between the camera and the model and make certain adjustments (you can also adjust through key bindings). - * Enter a name and save (if needed, other settings can be changed). + * Enter a name and save (if needed, other settings such as priority can be changed). ### Dependencies ### * Fabric: * [Fabric Loader](https://fabricmc.net/use/installer/) * [Fabric API](https://modrinth.com/mod/fabric-api) - * Forge: * [Forge Mod Loader](https://files.minecraftforge.net/) - * Both: * (Optional but recommended) [Cloth Config API](https://modrinth.com/mod/cloth-config) @@ -43,8 +39,8 @@ Snapshots are [here](https://github.com/xTracr/RealCamera/actions/workflows/buil * Incompatible: * OptiFine + * Armourer's Workshop + * Armors based on GeckoLib * Compatible: * most camera mods * most player model mods - -## [Change Log](changelog.md#English) ## diff --git a/README_ZH.md b/README_ZH.md index fe4c9fd..66ab1c8 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -4,8 +4,7 @@ 使第一人称视角下的摄像头更加真实。 支持的版本: 1.18-1.20 Forge & Fabric -从[Releases](https://github.com/xTracr/RealCamera/releases)、[Modrinth](https://modrinth.com/mod/real-camera) -或[CurseForge](https://curseforge.com/minecraft/mc-mods/real-camera)下载 +从[Releases](https://github.com/xTracr/RealCamera/releases)、[Modrinth](https://modrinth.com/mod/real-camera)或[CurseForge](https://curseforge.com/minecraft/mc-mods/real-camera)下载 快照版在[这里](https://github.com/xTracr/RealCamera/actions/workflows/build.yml) ## 特性 ## @@ -20,7 +19,7 @@ * 打开模型视图界面,左Alt+左键选择模型的对应的面,左Alt+滚轮可以在模型的不同层间切换 * 通过点击左侧的`选择`按钮,在三者间切换,选好`向前矢量`、`向上矢量`和`目标平面` * 进入`预览`部分,在这里可以看到摄像头与模型的相对关系并进行一定的调整(也可以通过按键绑定调整) - * 输入名称并保存(如果需要,还有其他设置可以更改) + * 输入名称并保存(如果需要,还有其他设置如优先级可以更改) ### 依赖项目 ### @@ -40,8 +39,8 @@ * 不兼容: * OptiFine + * Armourer's Workshop + * 基于GeckoLib的盔甲 * 兼容: * 多数摄像头模组 * 多数模型模组 - -## [更新日志](changelog.md#中文) ## diff --git a/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java b/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java index cdea26e..6a0bbf9 100644 --- a/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java +++ b/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java @@ -97,14 +97,13 @@ public static void renderCameraEntity(VertexConsumerProvider vertexConsumers) { .rotate(RotationAxis.POSITIVE_Y.rotationDegrees(yaw + 180.0f)) .transpose().invert(); Matrix4f positionMatrix = new Matrix4f(normalMatrix).translate(offset.subtract(pos).toVector3f()); - recorder.drawByAnother(vertexConsumers, record -> { - if (currentTarget.disabledTextureIds.stream().anyMatch(record.textureId()::contains)) return new VertexRecorder.Vertex[0][]; + recorder.drawByAnother(vertexConsumers, record -> currentTarget.disabledTextureIds.stream().noneMatch(record.textureId()::contains), record -> { final double depth = currentTarget.disablingDepth; - final int vertexCount = record.additionalVertexCount(); - return Arrays.stream(record.vertices()).map(quad -> { - VertexRecorder.Vertex[] newQuad = new VertexRecorder.Vertex[vertexCount]; - for (int j = 0; j < vertexCount ; j++) newQuad[j] = quad[j].transform(positionMatrix, normalMatrix); - for (VertexRecorder.Vertex vertex : newQuad) if (vertex.z() < -depth) return newQuad; + final int primitiveLength = record.primitiveLength(); + return Arrays.stream(record.primitives()).map(primitive -> { + VertexRecorder.Vertex[] newPrimitive = new VertexRecorder.Vertex[primitiveLength]; + for (int j = 0; j < primitiveLength ; j++) newPrimitive[j] = primitive[j].transform(positionMatrix, normalMatrix); + for (VertexRecorder.Vertex vertex : newPrimitive) if (vertex.z() < -depth) return newPrimitive; return null; }).filter(Objects::nonNull).toArray(VertexRecorder.Vertex[][]::new); }); diff --git a/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java b/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java index 4176259..9455582 100644 --- a/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java +++ b/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java @@ -6,7 +6,7 @@ import java.lang.reflect.Method; import java.util.function.Supplier; -public final class CompatibilityHelper { +public class CompatibilityHelper { private static Class NEA_NEAnimationsLoader = null; private static Method NEA_playerTransformer_setDeltaTick = null; diff --git a/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java b/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java index 3bc01e2..970a518 100644 --- a/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java +++ b/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java @@ -4,21 +4,20 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; import java.util.HashMap; import java.util.Map; import java.util.function.Predicate; -public final class DisableHelper { +public class DisableHelper { private static final Map> predicates = new HashMap<>(); public static void initialize() { registerOr("mainFeature", LivingEntity::isSleeping); registerOr("renderModel", entity -> entity instanceof PlayerEntity player && player.isUsingSpyglass()); - registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(getItemId(entity.getMainHandStack()))); - registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(getItemId(entity.getOffHandStack()))); + registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(Registries.ITEM.getId(entity.getMainHandStack().getItem()).toString())); + registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(Registries.ITEM.getId(entity.getOffHandStack().getItem()).toString())); } public static void registerOr(String type, Predicate predicate) { @@ -30,8 +29,4 @@ public static boolean isDisabled(String type, Entity cameraEntity) { if (ConfigFile.config().isClassic() || predicate == null) return false; return cameraEntity instanceof LivingEntity entity && predicate.test(entity); } - - private static String getItemId(ItemStack stack) { - return Registries.ITEM.getId(stack.getItem()).toString(); - } } diff --git a/common/src/main/java/com/xtracr/realcamera/config/ConfigScreen.java b/common/src/main/java/com/xtracr/realcamera/config/ConfigScreen.java index 824ff2b..f2d083e 100644 --- a/common/src/main/java/com/xtracr/realcamera/config/ConfigScreen.java +++ b/common/src/main/java/com/xtracr/realcamera/config/ConfigScreen.java @@ -127,10 +127,10 @@ public static Screen create(Screen parent) { .setTooltip(LocUtil.CONFIG_TOOLTIP("adjustOffset")) .setSaveConsumer(b -> config.binding.adjustOffset = b) .build()); - binding.addEntry(entryBuilder.startBooleanToggle(LocUtil.CONFIG_OPTION("renderStuckObjects"), config.renderModel) + binding.addEntry(entryBuilder.startBooleanToggle(LocUtil.CONFIG_OPTION("renderStuckObjects"), config.binding.renderStuckObjects) .setDefaultValue(true) .setTooltip(LocUtil.CONFIG_TOOLTIP("renderStuckObjects")) - .setSaveConsumer(b -> config.renderModel = b) + .setSaveConsumer(b -> config.binding.renderStuckObjects = b) .build()); binding.addEntry(entryBuilder.startStrList(LocUtil.CONFIG_OPTION("disableRenderItems"), config.binding.disableRenderItems) .setDefaultValue(ModConfig.Binding.defaultDisableRenderItems) diff --git a/common/src/main/java/com/xtracr/realcamera/gui/ModelAnalyser.java b/common/src/main/java/com/xtracr/realcamera/gui/ModelAnalyser.java index 79ba931..93a6fe7 100644 --- a/common/src/main/java/com/xtracr/realcamera/gui/ModelAnalyser.java +++ b/common/src/main/java/com/xtracr/realcamera/gui/ModelAnalyser.java @@ -19,7 +19,7 @@ public class ModelAnalyser extends VertexRecorder { private static final Set unfocusableLayers = Set.of(RenderLayer.getArmorGlint(), RenderLayer.getArmorEntityGlint(), RenderLayer.getGlintTranslucent(), RenderLayer.getGlint(), RenderLayer.getDirectGlint(), RenderLayer.getEntityGlint(), RenderLayer.getDirectEntityGlint()); - private static final int quadArgb = 0x6F3333CC, forwardArgb = 0xFF00CC00, upwardArgb = 0xFFCC0000, leftArgb = 0xFF0000CC; + private static final int primitiveArgb = 0x6F3333CC, forwardArgb = 0xFF00CC00, upwardArgb = 0xFFCC0000, leftArgb = 0xFF0000CC; private static final int focusedArgb = 0x7FFFFFFF, sideArgb = 0x3FFFFFFF; private final BindingTarget target; private final Matrix3f normal = new Matrix3f(); @@ -32,16 +32,16 @@ public ModelAnalyser(BindingTarget target) { this.target = target; } - private static boolean intersects(Vertex[] quad, List quads) { + private static boolean intersects(Vertex[] p1, List primitives) { final float precision = 1.0E-05f; - for (Vertex[] q : quads) for (Vertex v1 : quad) for (Vertex v2 : q) if (v1.pos().squaredDistanceTo(v2.pos()) < precision) return true; + for (Vertex[] p2 : primitives) for (Vertex v1 : p1) for (Vertex v2 : p2) if (v1.pos().squaredDistanceTo(v2.pos()) < precision) return true; return false; } - private static void drawQuad(DrawContext context, Vertex[] quad, int argb, int offset) { + private static void drawPrimitive(DrawContext context, Vertex[] primitive, int argb, int offset) { VertexConsumer vertexConsumer = context.getVertexConsumers().getBuffer(RenderLayer.getGui()); - for (Vertex vertex : quad) vertexConsumer.vertex(vertex.x(), vertex.y(), vertex.z() + offset).color(argb).next(); - if (quad.length == 3) vertexConsumer.vertex(quad[2].x(), quad[2].y(), quad[2].z() + offset).color(argb).next(); + for (Vertex vertex : primitive) vertexConsumer.vertex(vertex.x(), vertex.y(), vertex.z() + offset).color(argb).next(); + if (primitive.length == 3) vertexConsumer.vertex(primitive[2].x(), primitive[2].y(), primitive[2].z() + offset).color(argb).next(); context.draw(); } @@ -62,13 +62,13 @@ public void initialize(int entitySize, int mouseX, int mouseY, int layers, boole records.removeAll(removedRecords); List sortByDepth = new ArrayList<>(); records.stream().filter(record -> !unfocusableLayers.contains(record.renderLayer())).forEach(record -> { - Vertex[][] vertices = record.vertices(); - for (int i = 0, size = vertices.length; i < size; i++) { + Vertex[][] primitives = record.primitives(); + for (int i = 0, primitiveCount = primitives.length; i < primitiveCount; i++) { Polygon polygon = new Polygon(); - Vertex[] quad = vertices[i]; - for (Vertex vertex : quad) polygon.addPoint((int) vertex.x(), (int) vertex.y()); + Vertex[] primitive = primitives[i]; + for (Vertex vertex : primitive) polygon.addPoint((int) vertex.x(), (int) vertex.y()); if (!polygon.contains(mouseX, mouseY)) continue; - Vertex point = quad[0]; + Vertex point = primitive[0]; double deltaZ = 0; if (point.normalZ() != 0) deltaZ = (point.normalX() * (mouseX - point.x()) + point.normalY() * (mouseY - point.y())) / point.normalZ(); sortByDepth.add(new Triple(point.z() + deltaZ, record, i)); @@ -97,16 +97,16 @@ public String focusedTextureId() { public Vec2f getFocusedUV() { if (focusedIndex == -1 || focusedRecord == null) return null; float u = 0, v = 0; - Vertex[] quad = focusedRecord.vertices()[focusedIndex]; - for (Vertex vertex : quad) { + Vertex[] primitive = focusedRecord.primitives()[focusedIndex]; + for (Vertex vertex : primitive) { u += vertex.u(); v += vertex.v(); } - return new Vec2f(u / quad.length, v / quad.length); + return new Vec2f(u / primitive.length, v / primitive.length); } public void previewEffect(DrawContext context, int entitySize, boolean canSelect) { - drawByAnother(context.getVertexConsumers(), BuiltRecord::vertices); + drawByAnother(context.getVertexConsumers(), record -> true, BuiltRecord::primitives); context.draw(); if (canSelect) drawFocused(context); if (normal.m00() == 0 && normal.m11() == 0 && normal.m22() == 0) return; @@ -117,47 +117,47 @@ public void previewEffect(DrawContext context, int entitySize, boolean canSelect } public void drawModelWithNormals(DrawContext context, int entitySize) { - drawByAnother(context.getVertexConsumers(), BuiltRecord::vertices); + drawByAnother(context.getVertexConsumers(), record -> true, BuiltRecord::primitives); context.draw(); drawPolyhedron(context); drawFocused(context); if (currentRecord == null) return; - Vertex[] quad; - if ((quad = getQuad(currentRecord, target.posU, target.posV)) != null) drawQuad(context, quad, quadArgb, 1000); - if ((quad = getQuad(currentRecord, target.forwardU, target.forwardV)) != null) drawNormal(context, getPos(quad, target.forwardU, target.forwardV), quad[0].normal(), entitySize / 2, forwardArgb); - if ((quad = getQuad(currentRecord, target.upwardU, target.upwardV)) != null) drawNormal(context, getPos(quad, target.upwardU, target.upwardV), quad[0].normal(), entitySize / 2, upwardArgb); + Vertex[] primitive; + if ((primitive = getPrimitive(currentRecord, target.posU, target.posV)) != null) drawPrimitive(context, primitive, primitiveArgb, 1000); + if ((primitive = getPrimitive(currentRecord, target.forwardU, target.forwardV)) != null) drawNormal(context, getPos(primitive, target.forwardU, target.forwardV), primitive[0].normal(), entitySize / 2, forwardArgb); + if ((primitive = getPrimitive(currentRecord, target.upwardU, target.upwardV)) != null) drawNormal(context, getPos(primitive, target.upwardU, target.upwardV), primitive[0].normal(), entitySize / 2, upwardArgb); } private void drawFocused(DrawContext context) { if (focusedIndex == -1 || focusedRecord == null) return; - Vertex[] focused = focusedRecord.vertices()[focusedIndex]; - drawQuad(context, focused, focusedArgb, 1100); - int size = focused.length; - Vertex[] reversed = new Vertex[size]; - for (int i = 0; i < size; i++) reversed[i] = focused[size - 1 - i]; - drawQuad(context, reversed, focusedArgb, 1100); + Vertex[] focused = focusedRecord.primitives()[focusedIndex]; + drawPrimitive(context, focused, focusedArgb, 1100); + int length = focused.length; + Vertex[] reversed = new Vertex[length]; + for (int i = 0; i < length; i++) reversed[i] = focused[length - 1 - i]; + drawPrimitive(context, reversed, focusedArgb, 1100); } private void drawPolyhedron(DrawContext context) { if (focusedIndex == -1 || focusedRecord == null) return; List polyhedron = new ArrayList<>(); - polyhedron.add(focusedRecord.vertices()[focusedIndex]); + polyhedron.add(focusedRecord.primitives()[focusedIndex]); List indexes = new ArrayList<>(List.of(focusedIndex)); - Vertex[][] vertices = focusedRecord.vertices(); + Vertex[][] primitives = focusedRecord.primitives(); + final int primitiveCount = primitives.length; boolean added; - int size = focusedRecord.quadCount(); do { added = false; - for (int i = 0; i < size; i++) { - Vertex[] quad = vertices[i]; - if (indexes.contains(i) | !intersects(quad, polyhedron)) continue; - polyhedron.add(quad); + for (int i = 0; i < primitiveCount; i++) { + Vertex[] primitive = primitives[i]; + if (indexes.contains(i) | !intersects(primitive, polyhedron)) continue; + polyhedron.add(primitive); indexes.add(i); added = true; } } while (added); List resultIndexes = new ArrayList<>(List.of(focusedIndex)); - for (int i = focusedIndex + 1; i < size; i++) { + for (int i = focusedIndex + 1; i < primitiveCount; i++) { if (!indexes.contains(i)) break; resultIndexes.add(i); } @@ -165,7 +165,7 @@ private void drawPolyhedron(DrawContext context) { if (!indexes.contains(i)) break; resultIndexes.add(i); } - resultIndexes.forEach(i -> drawQuad(context, vertices[i], sideArgb, 1000)); + resultIndexes.forEach(i -> drawPrimitive(context, primitives[i], sideArgb, 1000)); } record Triple(double depth, BuiltRecord record, int index) {} diff --git a/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java b/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java index 3a8e51e..0e2af5b 100644 --- a/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java +++ b/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java @@ -297,8 +297,6 @@ protected BindingTarget generateBindingTarget() { protected void loadBindingTarget(BindingTarget target) { if (target.isEmpty()) return; - disabledIds.clear(); - disabledIds.addAll(target.disabledTextureIds); nameField.setText(target.name); textureIdField.setText(target.textureId); priorityField.setValue(target.priority); @@ -320,6 +318,8 @@ protected void loadBindingTarget(BindingTarget target) { pitchSlider.setValue(target.pitch); yawSlider.setValue(target.yaw); rollSlider.setValue(target.roll); + disabledIds.clear(); + disabledIds.addAll(target.disabledTextureIds); } private ButtonWidget createButton(Text message, int width, ButtonWidget.PressAction onPress) { diff --git a/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java b/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java index bf0d364..701b3a7 100644 --- a/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java +++ b/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java @@ -4,6 +4,7 @@ import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.VertexFormat; import net.minecraft.util.math.Vec3d; import org.joml.Matrix3f; import org.joml.Matrix4f; @@ -13,6 +14,7 @@ import java.util.*; import java.util.List; import java.util.function.Function; +import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -20,19 +22,19 @@ public class VertexRecorder implements VertexConsumerProvider { protected final List records = new ArrayList<>(); private final Stack recordStack = new Stack<>(); - protected static Vec3d getPos(Vertex[] quad, float u, float v) { - if (quad.length < 3) return quad[0].pos(); - float u0 = quad[0].u, v0 = quad[0].v, u1 = quad[1].u, v1 = quad[1].v, u2 = quad[2].u, v2 = quad[2].v; + protected static Vec3d getPos(Vertex[] primitive, float u, float v) { + if (primitive.length < 3) return primitive[0].pos(); + float u0 = primitive[0].u, v0 = primitive[0].v, u1 = primitive[1].u, v1 = primitive[1].v, u2 = primitive[2].u, v2 = primitive[2].v; float alpha = ((u - u1) * (v1 - v2) - (v - v1) * (u1 - u2)) / ((u0 - u1) * (v1 - v2) - (v0 - v1) * (u1 - u2)), beta = ((u - u2) * (v2 - v0) - (v - v2) * (u2 - u0)) / ((u1 - u2) * (v2 - v0) - (v1 - v2) * (u2 - u0)); - return quad[0].pos().multiply(alpha).add(quad[1].pos().multiply(beta)).add(quad[2].pos().multiply(1 - alpha - beta)); + return primitive[0].pos().multiply(alpha).add(primitive[1].pos().multiply(beta)).add(primitive[2].pos().multiply(1 - alpha - beta)); } - protected static Vertex[] getQuad(BuiltRecord record, float u, float v) { + protected static Vertex[] getPrimitive(BuiltRecord record, float u, float v) { final int resolution = 1000000; - return Arrays.stream(record.vertices).filter(quad -> { + return Arrays.stream(record.primitives).filter(primitive -> { Polygon polygon = new Polygon(); - for (Vertex vertex : quad) polygon.addPoint((int) (resolution * vertex.u), (int) (resolution * vertex.v)); + for (Vertex vertex : primitive) polygon.addPoint((int) (resolution * vertex.u), (int) (resolution * vertex.v)); return polygon.contains(resolution * u, resolution * v); }).findAny().orElse(new Vertex[]{new Vertex(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)}); } @@ -50,28 +52,27 @@ public void buildRecords() { public BuiltRecord getTargetPosAndRot(BindingTarget target, Matrix3f normal, Vector3f position) { return records.stream().map(record -> { if (!record.textureId().contains(target.textureId)) return null; - Vec3d forward = getQuad(record, target.forwardU, target.forwardV)[0].normal().normalize(); - Vec3d left = getQuad(record, target.upwardU, target.upwardV)[0].normal().crossProduct(forward).normalize(); - Vertex[] positionQuad = getQuad(record, target.posU, target.posV); - if (positionQuad[0].normal().equals(Vec3d.ZERO) && forward.equals(Vec3d.ZERO) && left.equals(Vec3d.ZERO)) return null; + Vec3d forward = getPrimitive(record, target.forwardU, target.forwardV)[0].normal().normalize(); + Vec3d left = getPrimitive(record, target.upwardU, target.upwardV)[0].normal().crossProduct(forward).normalize(); + Vertex[] face = getPrimitive(record, target.posU, target.posV); + if (face[0].normal().equals(Vec3d.ZERO) && forward.equals(Vec3d.ZERO) && left.equals(Vec3d.ZERO)) return null; normal.set(left.toVector3f(), forward.crossProduct(left).toVector3f(), forward.toVector3f()); - Vec3d center = getPos(positionQuad, target.posU, target.posV); + Vec3d center = getPos(face, target.posU, target.posV); if (!Double.isFinite(center.lengthSquared())) return null; position.set((float) target.getOffsetZ(), (float) target.getOffsetY(), (float) target.getOffsetX()).mul(normal).add(center.toVector3f()); return record; }).filter(Objects::nonNull).findAny().orElse(null); } - public void drawByAnother(VertexConsumerProvider anotherProvider, Function function) { + public void drawByAnother(VertexConsumerProvider anotherProvider, Predicate predicate, Function function) { records.forEach(record -> { - int argb; + if (!predicate.test(record)) return; VertexConsumer buffer = anotherProvider.getBuffer(record.renderLayer); - Vertex[][] vertices = function.apply(record); - for (Vertex[] quad : vertices) for (Vertex vertex : quad) { - argb = vertex.argb; - buffer.vertex((float) vertex.x, (float) vertex.y, (float) vertex.z, - (float) (argb >> 16 & 0xFF) / 255, (float) (argb >> 8 & 0xFF) / 255, (float) (argb & 0xFF) / 255, (float) (argb >> 24) / 255, - vertex.u, vertex.v, vertex.overlay, vertex.light, vertex.normalX, vertex.normalY, vertex.normalZ); + if (record.distinct) { + Vertex[][] primitives = function.apply(record); + for (Vertex[] primitive : primitives) for (Vertex vertex : primitive) vertex.apply(buffer); + } else { + for (Vertex vertex : record.vertices) vertex.apply(buffer); } }); } @@ -85,6 +86,7 @@ public VertexConsumer getBuffer(RenderLayer renderLayer) { } private static class VertexRecord implements VertexConsumer { + private static final Pattern textureIdPattern = Pattern.compile("texture\\[Optional\\[(.*?)]"); private final List vertices = new ArrayList<>(); private final RenderLayer renderLayer; private Vec3d pos = Vec3d.ZERO, normal = Vec3d.ZERO; @@ -96,18 +98,20 @@ private static class VertexRecord implements VertexConsumer { } private BuiltRecord build() { - int additionalVertexCount = renderLayer.getDrawMode().additionalVertexCount; - int quadCount = vertices.size() / additionalVertexCount; - Vertex[][] quads = new Vertex[quadCount][additionalVertexCount]; - for (int i = 0; i < quadCount; i++) { - int index = i * additionalVertexCount; - for (int j = 0; j < additionalVertexCount; j++) { - quads[i][j] = vertices.get(index + j); - } - } String layerName = renderLayer.toString(); - Matcher matcher = Pattern.compile("texture\\[Optional\\[(.*?)]").matcher(layerName); - return new BuiltRecord(renderLayer, matcher.find() ? matcher.group(1) : layerName, quads, quadCount, additionalVertexCount); + Matcher matcher = textureIdPattern.matcher(layerName); + String textureId = matcher.find() ? matcher.group(1) : layerName; + Vertex[] vertices = this.vertices.toArray(Vertex[]::new); + VertexFormat.DrawMode drawMode = renderLayer.getDrawMode(); + final int primitiveLength = drawMode.firstVertexCount, primitiveStride = drawMode.additionalVertexCount; + final int primitiveCount = (vertices.length - primitiveLength) / primitiveStride + 1; + final boolean startWithFirst = drawMode == VertexFormat.DrawMode.TRIANGLE_FAN; + Vertex[][] primitives = new Vertex[primitiveCount][primitiveLength]; + for (int i = 0, k = 0; i < primitiveCount; i++, k += primitiveStride) { + primitives[i][0] = vertices[startWithFirst ? 0 : k]; + System.arraycopy(vertices, k + 1, primitives[i], 1, primitiveLength - 1); + } + return new BuiltRecord(renderLayer, textureId, vertices, primitives, primitiveLength, primitiveLength == primitiveStride); } @Override @@ -149,8 +153,7 @@ public VertexConsumer normal(float x, float y, float z) { @Override public void next() { - vertices.add(new Vertex(pos.getX(), pos.getY(), pos.getZ(), argb, u, v, overlay, light, - (float) normal.getX(), (float) normal.getY(), (float) normal.getZ())); + vertices.add(new Vertex(pos.getX(), pos.getY(), pos.getZ(), argb, u, v, overlay, light, (float) normal.getX(), (float) normal.getY(), (float) normal.getZ())); pos = normal = Vec3d.ZERO; u = v = overlay = light = argb = 0; } @@ -170,7 +173,7 @@ public void unfixColor() { } } - public record BuiltRecord(RenderLayer renderLayer, String textureId, Vertex[][] vertices, int quadCount, int additionalVertexCount) { } + public record BuiltRecord(RenderLayer renderLayer, String textureId, Vertex[] vertices, Vertex[][] primitives, int primitiveLength, boolean distinct) {} public record Vertex(double x, double y, double z, int argb, float u, float v, int overlay, int light, float normalX, float normalY, float normalZ) { public Vec3d pos() { @@ -186,5 +189,11 @@ public Vertex transform(Matrix4f positionMatrix, Matrix3f normalMatrix) { Vector3f normal = new Vector3f(normalX, normalY, normalZ).mul(normalMatrix); return new Vertex(pos.x(), pos.y(), pos.z(), argb, u, v, overlay, light, normal.x(), normal.y(), normal.z()); } + + public void apply(VertexConsumer buffer) { + buffer.vertex((float) x, (float) y, (float) z, + (float) (argb >> 16 & 0xFF) / 255, (float) (argb >> 8 & 0xFF) / 255, (float) (argb & 0xFF) / 255, (float) (argb >> 24) / 255, + u, v, overlay, light, normalX, normalY, normalZ); + } } } diff --git a/common/src/main/resources/assets/realcamera/lang/ko_kr.json b/common/src/main/resources/assets/realcamera/lang/ko_kr.json index 41452a1..ac64ad0 100644 --- a/common/src/main/resources/assets/realcamera/lang/ko_kr.json +++ b/common/src/main/resources/assets/realcamera/lang/ko_kr.json @@ -1,6 +1,6 @@ { "general.xtracr_realcamera.modName": "Real Camera", - "key.xtracr_realcamera.modelViewGui": "모델 뷰 GUI 열기", + "key.xtracr_realcamera.modelViewScreen": "모델 뷰 GUI 열기", "key.xtracr_realcamera.togglePerspective": "활성화/비활성화", "key.xtracr_realcamera.toggleAdjustMode": "조정 모드 전환", "key.xtracr_realcamera.toggleCameraMode": "카메라 모드 전환", @@ -35,7 +35,7 @@ "config.option.xtracr_realcamera.pitch": "피치", "config.option.xtracr_realcamera.yaw": "요", "config.option.xtracr_realcamera.roll": "롤", - "config.option.xtracr_realcamera.toModelViewGui": "자세한 설정은 %s 화면으로 이동하세요 (키 바인드 설정 필요)", + "config.option.xtracr_realcamera.toModelViewScreen": "자세한 설정은 %s 화면으로 이동하세요 (키 바인드 설정 필요)", "config.option.xtracr_realcamera.adjustOffset": "카메라 오프셋 조정", "config.option.xtracr_realcamera.renderStuckObjects": "끼인 물체 렌더링", "config.option.xtracr_realcamera.disableRenderItems": "누른 상태에서는 렌더링 비활성화", diff --git a/common/src/main/resources/assets/realcamera/lang/zh_cn.json b/common/src/main/resources/assets/realcamera/lang/zh_cn.json index 9b1062b..104bcc2 100644 --- a/common/src/main/resources/assets/realcamera/lang/zh_cn.json +++ b/common/src/main/resources/assets/realcamera/lang/zh_cn.json @@ -48,7 +48,7 @@ "config.tooltip.xtracr_realcamera.adjustOffset": "当前按下调整键时是调整摄像头的偏移还是旋转", "config.tooltip.xtracr_realcamera.renderStuckObjects": "箭,蜂刺和其它会卡在玩家身体里的物体", - "message.xtracr_realcamera.bindingFailed": "[Real Camera]: 绑定失败,请前往模型视图界面手动设置", + "message.xtracr_realcamera.bindingFailed": "[%s]: 绑定失败,请前往%s界面手动设置", "screen.xtracr_realcamera.modelView_title": "模型视图", "screen.widget.xtracr_realcamera.modelView_selectMode": "选择", diff --git a/gradle.properties b/gradle.properties index 1fa6dd0..ef9aa6d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ forge_version=1.20.1-47.2.30 fabric_loader_version=0.15.10 yarn_mappings=1.20.1+build.10 # Mod Properties -mod_version=0.6.1-alpha.7 +mod_version=0.6.1-beta maven_group=com.xtracr.realcamera archives_base_name=realcamera # Dependencies