正确实现OBB旋转

This commit is contained in:
Atsuishio 2025-06-15 12:37:02 +08:00 committed by Light_Quanta
parent b6ddd1557f
commit 219fe939a3
No known key found for this signature in database
GPG key ID: 11A39A1B8C890959
4 changed files with 33 additions and 11 deletions

View file

@ -1,10 +1,11 @@
package com.atsuishio.superbwarfare.client.renderer.special; package com.atsuishio.superbwarfare.client.renderer.special;
import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity;
import com.atsuishio.superbwarfare.tools.OBB; import com.atsuishio.superbwarfare.tools.OBB;
import com.atsuishio.superbwarfare.tools.VectorTool;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf; import org.joml.Quaternionf;
import org.joml.Vector3f; import org.joml.Vector3f;
@ -16,11 +17,11 @@ public class OBBRenderer {
public static final OBBRenderer INSTANCE = new OBBRenderer(); public static final OBBRenderer INSTANCE = new OBBRenderer();
public void render(Entity entity, OBB obb, PoseStack poseStack, VertexConsumer buffer, float red, float green, float blue, float alpha) { public void render(VehicleEntity entity, OBB obb, PoseStack poseStack, VertexConsumer buffer, float red, float green, float blue, float alpha, float pPartialTicks) {
Vec3 position = entity.position(); Vec3 position = entity.position();
Vector3f center = obb.center(); Vector3f center = obb.center();
Vector3f halfExtents = obb.extents(); Vector3f halfExtents = obb.extents();
Quaternionf rotation = obb.rotation(); Quaternionf rotation = VectorTool.combineRotations(pPartialTicks, entity);
renderOBB( renderOBB(
poseStack, buffer, poseStack, buffer,
(float) (center.x() - position.x()), (float) (center.y() - position.y()), (float) (center.z() - position.z()), (float) (center.x() - position.x()), (float) (center.y() - position.y()), (float) (center.z() - position.z()),

View file

@ -92,7 +92,7 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
public Yx100Entity(EntityType<Yx100Entity> type, Level world) { public Yx100Entity(EntityType<Yx100Entity> type, Level world) {
super(type, world); super(type, world);
this.obb = new OBB(this.position().toVector3f(), new Vector3f(3.5f, 3.0f, 5.0f), new Quaternionf()); this.obb = new OBB(this.position().toVector3f(), new Vector3f(2.53125f, 1.0625f, 4.75f), new Quaternionf());
} }
@Override @Override
@ -1297,11 +1297,12 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
return this.obb; return this.obb;
} }
// TODO 实现正确的旋转设置
@Override @Override
public void updateOBB() { public void updateOBB() {
Quaternionf rotation = eulerToQuaternion(-getRoll(), -getYRot(), getXRot()); Matrix4f transform = getVehicleTransform(1);
this.obb.setRotation(rotation); Vector4f worldPosition = transformPosition(transform, 0, 1.125f, 0.25f);
this.obb.center().set(this.position().toVector3f()); this.obb.center().set(new Vector3f(worldPosition.x, worldPosition.y, worldPosition.z));
this.obb.setRotation(VectorTool.combineRotations(1, this));
} }
} }

View file

@ -2,8 +2,10 @@ package com.atsuishio.superbwarfare.mixins;
import com.atsuishio.superbwarfare.client.renderer.special.OBBRenderer; import com.atsuishio.superbwarfare.client.renderer.special.OBBRenderer;
import com.atsuishio.superbwarfare.entity.OBBEntity; import com.atsuishio.superbwarfare.entity.OBBEntity;
import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -16,9 +18,9 @@ public class EntityRenderDispatcherMixin {
@Inject(method = "renderHitbox", @Inject(method = "renderHitbox",
at = @At("RETURN")) at = @At("RETURN"))
private static void renderHitbox(PoseStack poseStack, VertexConsumer buffer, Entity entity, float red, float green, float blue, float alpha, CallbackInfo ci) { private static void renderHitbox(PoseStack poseStack, VertexConsumer buffer, Entity p_entity, float red, float green, float blue, float alpha, CallbackInfo ci) {
if (entity instanceof OBBEntity obbEntity) { if (p_entity instanceof OBBEntity obbEntity && p_entity instanceof VehicleEntity vehicle) {
OBBRenderer.INSTANCE.render(entity, obbEntity.getOBB(), poseStack, buffer, 1, 1, 1, 1); OBBRenderer.INSTANCE.render(vehicle, obbEntity.getOBB(), poseStack, buffer, 1, 1, 1, 1, Minecraft.getInstance().getTimer().getRealtimeDeltaTicks());
} }
} }
} }

View file

@ -1,7 +1,10 @@
package com.atsuishio.superbwarfare.tools; package com.atsuishio.superbwarfare.tools;
import com.atsuishio.superbwarfare.entity.vehicle.base.VehicleEntity;
import com.mojang.math.Axis;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
public class VectorTool { public class VectorTool {
public static double calculateAngle(Vec3 start, Vec3 end) { public static double calculateAngle(Vec3 start, Vec3 end) {
@ -23,4 +26,19 @@ public class VectorTool {
return ((180.0f - x) / 90.0f); // x (90, 180] return ((180.0f - x) / 90.0f); // x (90, 180]
} }
} }
// 合并三个旋转Yaw -> Pitch -> Roll
public static Quaternionf combineRotations(float partialTicks, VehicleEntity entity) {
// 1. 获取三个独立的旋转四元数
Quaternionf yawRot = Axis.YP.rotationDegrees(-Mth.lerp(partialTicks, entity.yRotO, entity.getYRot()));
Quaternionf pitchRot = Axis.XP.rotationDegrees(Mth.lerp(partialTicks, entity.xRotO, entity.getXRot()));
Quaternionf rollRot = Axis.ZP.rotationDegrees(Mth.lerp(partialTicks, entity.prevRoll, entity.getRoll()));
// 2. 按照正确顺序合并先Yaw再Pitch最后Roll
Quaternionf combined = new Quaternionf(yawRot); // 初始化为Yaw旋转
combined.mul(pitchRot); // 应用Pitch旋转
combined.mul(rollRot); // 应用Roll旋转
return combined;
}
} }