From 85e0613e2069afc7d8109a878f758a4f1d108b5a Mon Sep 17 00:00:00 2001 From: xTracr Date: Thu, 11 Jul 2024 11:17:05 +0800 Subject: [PATCH] Fixed #88, #89 and #90 --- README.md | 19 ++++++++++++------- README_ZH.md | 19 ++++++++++++------- .../com/xtracr/realcamera/RealCameraCore.java | 7 +++---- .../compat/CompatibilityHelper.java | 7 +++++++ .../realcamera/compat/DisableHelper.java | 14 ++++++++++++++ .../realcamera/config/BindingTarget.java | 15 ++++++++------- .../xtracr/realcamera/config/ModConfig.java | 4 ++-- .../realcamera/gui/ModelViewScreen.java | 8 ++++---- .../mixin/GameRendererAccessor.java | 14 ++++++++++++++ .../xtracr/realcamera/mixin/MixinCamera.java | 14 +++++++++++--- .../realcamera/util/VertexRecorder.java | 6 +++--- .../resources/realcamera-common.mixins.json | 9 +++++---- gradle.properties | 10 +++++----- 13 files changed, 100 insertions(+), 46 deletions(-) create mode 100644 common/src/main/java/com/xtracr/realcamera/mixin/GameRendererAccessor.java diff --git a/README.md b/README.md index 40cacc0..cefda59 100644 --- a/README.md +++ b/README.md @@ -14,18 +14,23 @@ Snapshots are [here](https://github.com/xTracr/RealCamera/actions/workflows/buil * Render player model in first-person perspective. * 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). + +### Configuration (0.6+) ### + * Theoretically, most mod models are supported, but need to be configured manually: - * 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 such as priority can be changed). +* First, set the key binding for `Open Model View Screen`. + * ![model view screen](https://cdn.modrinth.com/data/fYYSAh4R/images/cc484d54238992077ab3632c274a2631efeca35f.png) +* Open the model view screen 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). + * ![preview](https://cdn.modrinth.com/data/fYYSAh4R/images/22cfcf444bbf2d3c0d0280e470a29f01b9308617.png) +* Enter a name and save (if needed, other settings such as priority can be changed). -### Dependencies ### +## Dependencies ## * Fabric: * [Fabric API](https://modrinth.com/mod/fabric-api) -* 所有平台: +* Both: * (Optional but recommended) [Cloth Config API](https://modrinth.com/mod/cloth-config) ## FAQ ## diff --git a/README_ZH.md b/README_ZH.md index 195f138..2dcf5dd 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -14,18 +14,23 @@ * 在第一人称视角下渲染玩家模型 * 按下F6来开关,另外一些键来调整摄像头 * 在配置界面配置以上特性(需Cloth Config) + +### 配置 ### + * 理论上支持大多数模组模型,但需要手动进行配置: - * 首先设置`打开模型视图界面`的按键绑定 - * 打开模型视图界面,左Alt+左键选择模型的对应的面,左Alt+滚轮可以在模型的不同层间切换 - * 通过点击左侧的`选择`按钮,在三者间切换,选好`向前矢量`、`向上矢量`和`目标平面` - * 进入`预览`部分,在这里可以看到摄像头与模型的相对关系并进行一定的调整(也可以通过按键绑定调整) - * 输入名称并保存(如果需要,还有其他设置如优先级可以更改) +* 首先设置`打开模型视图界面`的按键绑定 + * ![model view screen](https://cdn.modrinth.com/data/fYYSAh4R/images/cc484d54238992077ab3632c274a2631efeca35f.png) +* 打开模型视图界面,左Alt+左键选择模型的对应的面,左Alt+滚轮可以在模型的不同层间切换 +* 通过点击左侧的`选择`按钮,在三者间切换,选好`向前矢量`、`向上矢量`和`目标平面` +* 进入`预览`部分,在这里可以看到摄像头与模型的相对关系并进行一定的调整(也可以通过按键绑定调整) + * ![preview](https://cdn.modrinth.com/data/fYYSAh4R/images/22cfcf444bbf2d3c0d0280e470a29f01b9308617.png) +* 输入名称并保存(如果需要,还有其他设置如优先级可以更改) -### 依赖项目 ### +## 依赖项目 ## * Fabric: * [Fabric API](https://modrinth.com/mod/fabric-api) -* Both: +* 所有平台: * (可选但建议)[Cloth Config API](https://modrinth.com/mod/cloth-config) ## 常见问题 ## diff --git a/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java b/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java index 24b0ba6..008527b 100644 --- a/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java +++ b/common/src/main/java/com/xtracr/realcamera/RealCameraCore.java @@ -105,10 +105,9 @@ public static void renderCameraEntity(MultiBufferSource bufferSource, Matrix4f p final double depth = currentTarget.disablingDepth; for (VertexRecorder.Vertex[] primitive : record.primitives()) { for (VertexRecorder.Vertex vertex : primitive) { - if (Math.fma(m02, vertex.x(), Math.fma(m12, vertex.y(), Math.fma(m22, vertex.z(), m32))) < -depth) { - VertexRecorder.renderVertices(primitive, buffer, positionMatrix, normalMatrix); - break; - } + if (Math.fma(m02, vertex.x(), Math.fma(m12, vertex.y(), Math.fma(m22, vertex.z(), m32))) > -depth) continue; + VertexRecorder.renderVertices(primitive, buffer, positionMatrix, normalMatrix); + break; } } }); 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 9455582..8cff172 100644 --- a/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java +++ b/common/src/main/java/com/xtracr/realcamera/compat/CompatibilityHelper.java @@ -1,6 +1,7 @@ package com.xtracr.realcamera.compat; import com.xtracr.realcamera.RealCameraCore; +import net.minecraft.world.item.ItemStack; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -9,6 +10,7 @@ public class CompatibilityHelper { private static Class NEA_NEAnimationsLoader = null; private static Method NEA_playerTransformer_setDeltaTick = null; + protected static Method Exposure_CameraItem_isActive = null; @SuppressWarnings("unchecked") public static void initialize() { @@ -26,6 +28,11 @@ public static void initialize() { NEA_playerTransformer_setDeltaTick = NEA_PlayerTransformer.getDeclaredMethod("setDeltaTick", float.class); } catch (Exception ignored) { } + if (isClassLoaded("io.github.mortuusars.exposure.Exposure")) try { + Class Exposure_CameraItem = Class.forName("io.github.mortuusars.exposure.item.CameraItem"); + Exposure_CameraItem_isActive = Exposure_CameraItem.getDeclaredMethod("isActive", ItemStack.class); + } catch (Exception ignored) { + } } public static void NEA_setDeltaTick(float tickDelta) { 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 376408b..dd8d281 100644 --- a/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java +++ b/common/src/main/java/com/xtracr/realcamera/compat/DisableHelper.java @@ -5,6 +5,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; import java.util.HashMap; import java.util.Map; @@ -12,12 +13,25 @@ public class DisableHelper { private static final Map> predicates = new HashMap<>(); + private static final String EXPOSURE_CAMERA = "exposure:camera"; public static void initialize() { registerOr("mainFeature", LivingEntity::isSleeping); registerOr("renderModel", entity -> entity instanceof Player player && player.isScoping()); registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(BuiltInRegistries.ITEM.getKey(entity.getMainHandItem().getItem()).toString())); registerOr("renderModel", entity -> ConfigFile.config().getDisableRenderItems().contains(BuiltInRegistries.ITEM.getKey(entity.getOffhandItem().getItem()).toString())); + registerOr("renderModel", entity -> { + if (CompatibilityHelper.Exposure_CameraItem_isActive == null) return false; + final ItemStack itemStack; + if (EXPOSURE_CAMERA.equals(BuiltInRegistries.ITEM.getKey(entity.getMainHandItem().getItem()).toString())) itemStack = entity.getMainHandItem(); + else if (EXPOSURE_CAMERA.equals(BuiltInRegistries.ITEM.getKey(entity.getOffhandItem().getItem()).toString())) itemStack = entity.getOffhandItem(); + else return false; + try { + return (boolean) CompatibilityHelper.Exposure_CameraItem_isActive.invoke(itemStack.getItem(), itemStack); + } catch (Exception ignored) { + return false; + } + }); } public static void registerOr(String type, Predicate predicate) { diff --git a/common/src/main/java/com/xtracr/realcamera/config/BindingTarget.java b/common/src/main/java/com/xtracr/realcamera/config/BindingTarget.java index 633886e..a7d6ed8 100644 --- a/common/src/main/java/com/xtracr/realcamera/config/BindingTarget.java +++ b/common/src/main/java/com/xtracr/realcamera/config/BindingTarget.java @@ -5,10 +5,12 @@ import java.util.List; public class BindingTarget { - protected static final List defaultTargets = List.of(createDefaultTarget("minecraft_head", "minecraft:textures/entity/player/", 5, false), - createDefaultTarget("skin_head", "minecraft:skins/", 5, false), - createDefaultTarget("minecraft_head_2", "minecraft:textures/entity/player/", 0, true), - createDefaultTarget("skin_head_2", "minecraft:skins/", 0, true)); + protected static final List defaultTargets = List.of(vanillaTarget("minecraft_head", 5, false).offsetX(-0.1), + vanillaTarget("skin_head", 5, false).offsetX(-0.1), + vanillaTarget("minecraft_head_2", 1, true).offsetX(-0.1), + vanillaTarget("skin_head_2", 1, true).offsetX(-0.1), + vanillaTarget("minecraft_head_3", 0, true).offsetX(-0.06).offsetY(-0.08).disablingDepth(0.08f), + vanillaTarget("skin_head_3", 0, true).offsetX(-0.06).offsetY(-0.08).disablingDepth(0.08f)); public final String name, textureId; public int priority = 0; public float forwardU = 0, forwardV = 0, upwardU = 0, upwardV = 0, posU = 0, posV = 0, disablingDepth = 0.2f; @@ -26,13 +28,12 @@ public BindingTarget(String name, String textureId) { this.textureId = textureId; } - private static BindingTarget createDefaultTarget(String name, String textureId, int priority, boolean shouldBind) { - return new BindingTarget(name, textureId).priority(priority) + private static BindingTarget vanillaTarget(String name, int priority, boolean shouldBind) { + return new BindingTarget(name, name.contains("skin") ? "minecraft:skins/" : "minecraft:textures/entity/player/").priority(priority) .forwardU(0.1875f).forwardV(0.2f) .upwardU(0.1875f).upwardV(0.075f) .posU(0.1875f).posV(0.2f) .bindX(shouldBind).bindZ(shouldBind).bindRotation(shouldBind) - .offsetX(-0.1) .disabledTextureIds(List.of("minecraft:textures/entity/enderdragon/dragon.png")); } diff --git a/common/src/main/java/com/xtracr/realcamera/config/ModConfig.java b/common/src/main/java/com/xtracr/realcamera/config/ModConfig.java index 82dd1a4..6a21e55 100644 --- a/common/src/main/java/com/xtracr/realcamera/config/ModConfig.java +++ b/common/src/main/java/com/xtracr/realcamera/config/ModConfig.java @@ -214,11 +214,11 @@ public static class Binding { protected static final List defaultDisableRenderItems = List.of("minecraft:filled_map"); public boolean adjustOffset = true; public boolean renderStuckObjects = true; - public List disableRenderItems = new ArrayList<>(defaultDisableRenderItems); + public List disableRenderItems = defaultDisableRenderItems; public List targetList = new ArrayList<>(BindingTarget.defaultTargets); private void clamp() { - if (disableRenderItems == null) disableRenderItems = new ArrayList<>(); + if (disableRenderItems == null) disableRenderItems = List.of(); if (targetList == null || targetList.isEmpty()) targetList = new ArrayList<>(BindingTarget.defaultTargets); } } 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 f0c5149..eafbe8a 100644 --- a/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java +++ b/common/src/main/java/com/xtracr/realcamera/gui/ModelViewScreen.java @@ -227,7 +227,7 @@ private void initRightWidgets(final int category, final int page) { @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float delta) { super.render(graphics, mouseX, mouseY, delta); - drawEntity(graphics, x + (xSize - ySize) / 2, y, x + (xSize + ySize) / 2, y + ySize, mouseX, mouseY, minecraft.player); + renderEntityInViewArea(graphics, x + (xSize - ySize) / 2, y, x + (xSize + ySize) / 2, y + ySize, mouseX, mouseY, minecraft.player); } @Override @@ -238,7 +238,7 @@ public void renderBackground(GuiGraphics graphics, int mouseX, int mouseY, float graphics.fill(x + (xSize + ySize) / 2 + 4, y, x + xSize, y + ySize, 0xFF444444); } - protected void drawEntity(GuiGraphics graphics, int x1, int y1, int x2, int y2, int mouseX, int mouseY, LivingEntity entity) { + protected void renderEntityInViewArea(GuiGraphics graphics, int x1, int y1, int x2, int y2, int mouseX, int mouseY, LivingEntity entity) { float centerX = (float) (x1 + x2) / 2.0f; float centerY = (float) (y1 + y2) / 2.0f; graphics.enableScissor(x1, y1, x2, y2); @@ -254,7 +254,7 @@ protected void drawEntity(GuiGraphics graphics, int x1, int y1, int x2, int y2, entity.yHeadRot = entity.getYRot(); entity.yHeadRotO = entity.getYRot(); Vector3f vector3f = new Vector3f((float) entityX, (float) entityY, -2.0f); - drawEntity(graphics, centerX, centerY, mouseX, mouseY, vector3f, quaternionf, entity); + renderEntityWithAnalyser(graphics, centerX, centerY, mouseX, mouseY, vector3f, quaternionf, entity); entity.yBodyRot = entityBodyYaw; entity.setYRot(entityYaw); entity.setXRot(entityPitch); @@ -263,7 +263,7 @@ protected void drawEntity(GuiGraphics graphics, int x1, int y1, int x2, int y2, graphics.disableScissor(); } - protected void drawEntity(GuiGraphics graphics, float x, float y, int mouseX, int mouseY, Vector3f offset, Quaternionf quaternionf, LivingEntity entity) { + protected void renderEntityWithAnalyser(GuiGraphics graphics, float x, float y, int mouseX, int mouseY, Vector3f offset, Quaternionf quaternionf, LivingEntity entity) { graphics.pose().pushPose(); graphics.pose().translate(x, y, 0); graphics.pose().mulPose(new Matrix4f().scaling(entitySize, entitySize, -entitySize)); diff --git a/common/src/main/java/com/xtracr/realcamera/mixin/GameRendererAccessor.java b/common/src/main/java/com/xtracr/realcamera/mixin/GameRendererAccessor.java new file mode 100644 index 0000000..f06020b --- /dev/null +++ b/common/src/main/java/com/xtracr/realcamera/mixin/GameRendererAccessor.java @@ -0,0 +1,14 @@ +package com.xtracr.realcamera.mixin; + +import net.minecraft.client.renderer.GameRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(GameRenderer.class) +public interface GameRendererAccessor { + @Accessor + float getFov(); + + @Accessor + float getOldFov(); +} diff --git a/common/src/main/java/com/xtracr/realcamera/mixin/MixinCamera.java b/common/src/main/java/com/xtracr/realcamera/mixin/MixinCamera.java index c9733af..1c07b93 100644 --- a/common/src/main/java/com/xtracr/realcamera/mixin/MixinCamera.java +++ b/common/src/main/java/com/xtracr/realcamera/mixin/MixinCamera.java @@ -4,6 +4,7 @@ import com.xtracr.realcamera.config.ConfigFile; import com.xtracr.realcamera.config.ModConfig; import net.minecraft.client.Camera; +import net.minecraft.client.Minecraft; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; @@ -55,14 +56,14 @@ public abstract class MixinCamera { setPosition(prevPos); setRotation(RealCameraCore.getYaw(yRot), RealCameraCore.getPitch(xRot)); } - realcamera$clipToSpace(startVec); + realcamera$clipToSpace(startVec, realcamera$getFov(tickDelta)); RealCameraCore.setCameraPos(position); } @Unique - private void realcamera$clipToSpace(Vec3 startVec) { + private void realcamera$clipToSpace(Vec3 startVec, double fov) { Vec3 offset = position.subtract(startVec); - final float depth = 0.085f; + final float depth = 0.05f + (float) (fov * (0.0001 + 0.000005 * fov)); for (int i = 0; i < 8; ++i) { float f = depth * ((i & 1) * 2 - 1); float g = depth * ((i >> 1 & 1) * 2 - 1); @@ -77,6 +78,13 @@ public abstract class MixinCamera { setPosition(startVec.add(offset)); } + @Unique + private static float realcamera$getFov(float tickDelta) { + Minecraft client = Minecraft.getInstance(); + float multiplier = Mth.lerp(tickDelta, ((GameRendererAccessor) client.gameRenderer).getOldFov(), ((GameRendererAccessor) client.gameRenderer).getFov()); + return client.options.fov().get() * multiplier; + } + @Shadow protected abstract void move(float x, float y, float z); 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 56ca949..d75a112 100644 --- a/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java +++ b/common/src/main/java/com/xtracr/realcamera/util/VertexRecorder.java @@ -60,8 +60,8 @@ public void buildRecords() { public BuiltRecord getTargetPosAndRot(BindingTarget target, Matrix3f normal, Vector3f position, boolean mirrored) { return records.stream().map(record -> { if (!record.textureId().contains(target.textureId)) return null; - Vec3 forward = getPrimitive(record, target.forwardU, target.forwardV)[0].normal().normalize(); - Vec3 left = getPrimitive(record, target.upwardU, target.upwardV)[0].normal().cross(forward).normalize(); + Vec3 forward = getPrimitive(record, target.forwardU, target.forwardV)[0].normal(); + Vec3 left = getPrimitive(record, target.upwardU, target.upwardV)[0].normal().cross(forward); Vertex[] face = getPrimitive(record, target.posU, target.posV); if (face[0].normal().equals(Vec3.ZERO) && forward.equals(Vec3.ZERO) && left.equals(Vec3.ZERO)) return null; normal.set(left.scale(mirrored ? -1 : 1).toVector3f(), forward.cross(left).toVector3f(), forward.toVector3f()); @@ -194,7 +194,7 @@ public Vec3 pos() { } public Vec3 normal() { - return new Vec3(normalX, normalY, normalZ); + return new Vec3(normalX, normalY, normalZ).normalize(); } public void render(VertexConsumer buffer, Matrix4f positionMatrix, Matrix3f normalMatrix) { diff --git a/common/src/main/resources/realcamera-common.mixins.json b/common/src/main/resources/realcamera-common.mixins.json index 528857c..6493449 100644 --- a/common/src/main/resources/realcamera-common.mixins.json +++ b/common/src/main/resources/realcamera-common.mixins.json @@ -7,14 +7,15 @@ ], "client": [ "CameraAccessor", + "GameRendererAccessor", "MixinCamera", - "MixinLocalPlayer", "MixinGameRenderer", - "MixinItemInHandRenderer", "MixinGui", "MixinItem", - "MixinStuckInBodyLater", - "MixinLevelRenderer" + "MixinItemInHandRenderer", + "MixinLevelRenderer", + "MixinLocalPlayer", + "MixinStuckInBodyLater" ], "server": [ ], diff --git a/gradle.properties b/gradle.properties index 070280d..ab78c78 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,13 +5,13 @@ org.gradle.parallel=true minecraft_version=1.21 enabled_platforms=fabric,neoforge fabric_loader_version=0.15.11 -neoforge_version=21.0.1-beta -#yarn_mappings=1.21+build.1 +neoforge_version=21.0.83-beta +#yarn_mappings=1.21+build.7 # Mod Properties -mod_version=0.6.1-beta +mod_version=0.6.2-beta.1 maven_group=com.xtracr.realcamera archives_base_name=realcamera # Dependencies -fabric_api_version=0.100.1+1.21 +fabric_api_version=0.100.6+1.21 cloth_config_version=15.0.127 -modmenu_version=11.0.0-beta.1 +modmenu_version=11.0.1