OBB再次大失败(?)
This commit is contained in:
parent
d14710743c
commit
9b7773350f
7 changed files with 246 additions and 3 deletions
|
@ -0,0 +1,40 @@
|
||||||
|
package com.atsuishio.superbwarfare.client.renderer.special;
|
||||||
|
|
||||||
|
import com.atsuishio.superbwarfare.tools.OBB;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Codes based on @AnECanSaiTin's <a href="https://github.com/AnECanSaiTin/HitboxAPI">HitboxAPI</a>
|
||||||
|
**/
|
||||||
|
public class 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) {
|
||||||
|
Vec3 position = entity.position();
|
||||||
|
Vector3f center = obb.center();
|
||||||
|
Vector3f halfExtents = obb.extents();
|
||||||
|
Quaternionf rotation = obb.rotation();
|
||||||
|
renderOBB(
|
||||||
|
poseStack, buffer,
|
||||||
|
(float) (center.x() - position.x()), (float) (center.y() - position.y()), (float) (center.z() - position.z()),
|
||||||
|
rotation,
|
||||||
|
halfExtents.x(), halfExtents.y(), halfExtents.z(),
|
||||||
|
red, green, blue, alpha
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderOBB(PoseStack poseStack, VertexConsumer buffer, float centerX, float centerY, float centerZ, Quaternionf rotation, float halfX, float halfY, float halfZ, float red, float green, float blue, float alpha) {
|
||||||
|
poseStack.pushPose();
|
||||||
|
poseStack.translate(centerX, centerY, centerZ);
|
||||||
|
poseStack.mulPose(rotation);
|
||||||
|
LevelRenderer.renderLineBox(poseStack, buffer, -halfX, -halfY, -halfZ, halfX, halfY, halfZ, red, green, blue, alpha);
|
||||||
|
poseStack.popPose();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package com.atsuishio.superbwarfare.entity;
|
||||||
|
|
||||||
|
import com.atsuishio.superbwarfare.tools.OBB;
|
||||||
|
|
||||||
|
public interface OBBEntity {
|
||||||
|
|
||||||
|
OBB getOBB();
|
||||||
|
|
||||||
|
void updateOBB();
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package com.atsuishio.superbwarfare.entity.vehicle;
|
||||||
import com.atsuishio.superbwarfare.Mod;
|
import com.atsuishio.superbwarfare.Mod;
|
||||||
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
|
import com.atsuishio.superbwarfare.config.server.ExplosionConfig;
|
||||||
import com.atsuishio.superbwarfare.config.server.VehicleConfig;
|
import com.atsuishio.superbwarfare.config.server.VehicleConfig;
|
||||||
|
import com.atsuishio.superbwarfare.entity.OBBEntity;
|
||||||
import com.atsuishio.superbwarfare.entity.projectile.SwarmDroneEntity;
|
import com.atsuishio.superbwarfare.entity.projectile.SwarmDroneEntity;
|
||||||
import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity;
|
import com.atsuishio.superbwarfare.entity.vehicle.base.ContainerMobileVehicleEntity;
|
||||||
import com.atsuishio.superbwarfare.entity.vehicle.base.LandArmorEntity;
|
import com.atsuishio.superbwarfare.entity.vehicle.base.LandArmorEntity;
|
||||||
|
@ -62,8 +63,7 @@ import net.neoforged.neoforge.network.PacketDistributor;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Math;
|
import org.joml.Math;
|
||||||
import org.joml.Matrix4f;
|
import org.joml.*;
|
||||||
import org.joml.Vector4f;
|
|
||||||
import software.bernie.geckolib.animatable.GeoEntity;
|
import software.bernie.geckolib.animatable.GeoEntity;
|
||||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||||
import software.bernie.geckolib.animation.*;
|
import software.bernie.geckolib.animation.*;
|
||||||
|
@ -77,7 +77,7 @@ import java.util.List;
|
||||||
import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit;
|
import static com.atsuishio.superbwarfare.client.RenderHelper.preciseBlit;
|
||||||
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
import static com.atsuishio.superbwarfare.tools.ParticleTool.sendParticle;
|
||||||
|
|
||||||
public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEntity, LandArmorEntity, WeaponVehicleEntity {
|
public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEntity, LandArmorEntity, WeaponVehicleEntity, OBBEntity {
|
||||||
|
|
||||||
public static final EntityDataAccessor<Integer> MG_AMMO = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
|
public static final EntityDataAccessor<Integer> MG_AMMO = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
|
||||||
public static final EntityDataAccessor<Integer> LOADED_AP = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
|
public static final EntityDataAccessor<Integer> LOADED_AP = SynchedEntityData.defineId(Yx100Entity.class, EntityDataSerializers.INT);
|
||||||
|
@ -88,8 +88,11 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this);
|
||||||
public int droneReloadCoolDown;
|
public int droneReloadCoolDown;
|
||||||
|
|
||||||
|
public OBB obb;
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -227,6 +230,8 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
public void baseTick() {
|
public void baseTick() {
|
||||||
super.baseTick();
|
super.baseTick();
|
||||||
|
|
||||||
|
this.updateOBB();
|
||||||
|
|
||||||
if (getLeftTrack() < 0) {
|
if (getLeftTrack() < 0) {
|
||||||
setLeftTrack(80);
|
setLeftTrack(80);
|
||||||
}
|
}
|
||||||
|
@ -1286,4 +1291,17 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
||||||
public @Nullable ResourceLocation getVehicleItemIcon() {
|
public @Nullable ResourceLocation getVehicleItemIcon() {
|
||||||
return Mod.loc("textures/gui/vehicle/type/land.png");
|
return Mod.loc("textures/gui/vehicle/type/land.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OBB getOBB() {
|
||||||
|
return this.obb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO 实现正确的旋转设置
|
||||||
|
@Override
|
||||||
|
public void updateOBB() {
|
||||||
|
Quaternionf rotation = eulerToQuaternion(-getRoll(), -getYRot(), getXRot());
|
||||||
|
this.obb.setRotation(rotation);
|
||||||
|
this.obb.center().set(this.position().toVector3f());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -816,6 +816,23 @@ public abstract class VehicleEntity extends Entity {
|
||||||
return transform.transform(new Vector4f(x, y, z, 1));
|
return transform.transform(new Vector4f(x, y, z, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Quaternionf eulerToQuaternion(float yaw, float pitch, float roll) {
|
||||||
|
double cy = Math.cos(yaw * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
double sy = Math.sin(yaw * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
double cp = Math.cos(pitch * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
double sp = Math.sin(pitch * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
double cr = Math.cos(roll * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
double sr = Math.sin(roll * 0.5 * Mth.DEG_TO_RAD);
|
||||||
|
|
||||||
|
Quaternionf q = new Quaternionf();
|
||||||
|
q.w = (float) (cy * cp * cr + sy * sp * sr);
|
||||||
|
q.x = (float) (cy * cp * sr - sy * sp * cr);
|
||||||
|
q.y = (float) (sy * cp * sr + cy * sp * cr);
|
||||||
|
q.z = (float) (sy * cp * cr - cy * sp * sr);
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
public void handleClientSync() {
|
public void handleClientSync() {
|
||||||
if (isControlledByLocalInstance()) {
|
if (isControlledByLocalInstance()) {
|
||||||
interpolationSteps = 0;
|
interpolationSteps = 0;
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.atsuishio.superbwarfare.mixins;
|
||||||
|
|
||||||
|
import com.atsuishio.superbwarfare.client.renderer.special.OBBRenderer;
|
||||||
|
import com.atsuishio.superbwarfare.entity.OBBEntity;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||||
|
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(EntityRenderDispatcher.class)
|
||||||
|
public class EntityRenderDispatcherMixin {
|
||||||
|
|
||||||
|
@Inject(method = "renderHitbox",
|
||||||
|
at = @At("RETURN"))
|
||||||
|
private static void renderHitbox(PoseStack poseStack, VertexConsumer buffer, Entity entity, float red, float green, float blue, float alpha, CallbackInfo ci) {
|
||||||
|
if (entity instanceof OBBEntity obbEntity) {
|
||||||
|
OBBRenderer.INSTANCE.render(entity, obbEntity.getOBB(), poseStack, buffer, 1, 1, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
133
src/main/java/com/atsuishio/superbwarfare/tools/OBB.java
Normal file
133
src/main/java/com/atsuishio/superbwarfare/tools/OBB.java
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
package com.atsuishio.superbwarfare.tools;
|
||||||
|
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import org.joml.Intersectionf;
|
||||||
|
import org.joml.Math;
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Codes based on @AnECanSaiTin's <a href="https://github.com/AnECanSaiTin/HitboxAPI">HitboxAPI</a>
|
||||||
|
*
|
||||||
|
* @param center 旋转中心
|
||||||
|
* @param extents 三个轴向上的半长
|
||||||
|
* @param rotation 旋转
|
||||||
|
*/
|
||||||
|
public record OBB(Vector3f center, Vector3f extents, Quaternionf rotation) {
|
||||||
|
|
||||||
|
public void setCenter(Vector3f center) {
|
||||||
|
this.center.set(center);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtents(Vector3f extents) {
|
||||||
|
this.extents.set(extents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRotation(Quaternionf rotation) {
|
||||||
|
this.rotation.set(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取OBB的8个顶点坐标
|
||||||
|
*
|
||||||
|
* @return 顶点坐标
|
||||||
|
*/
|
||||||
|
public Vector3f[] getVertices() {
|
||||||
|
Vector3f[] vertices = new Vector3f[8];
|
||||||
|
|
||||||
|
Vector3f[] localVertices = new Vector3f[]{
|
||||||
|
new Vector3f(-extents.x, -extents.y, -extents.z),
|
||||||
|
new Vector3f(extents.x, -extents.y, -extents.z),
|
||||||
|
new Vector3f(extents.x, extents.y, -extents.z),
|
||||||
|
new Vector3f(-extents.x, extents.y, -extents.z),
|
||||||
|
new Vector3f(-extents.x, -extents.y, extents.z),
|
||||||
|
new Vector3f(extents.x, -extents.y, extents.z),
|
||||||
|
new Vector3f(extents.x, extents.y, extents.z),
|
||||||
|
new Vector3f(-extents.x, extents.y, extents.z)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
Vector3f vertex = localVertices[i];
|
||||||
|
vertex.rotate(rotation);
|
||||||
|
vertex.add(center);
|
||||||
|
vertices[i] = vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return vertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取OBB的三个正交轴
|
||||||
|
*
|
||||||
|
* @return 正交轴
|
||||||
|
*/
|
||||||
|
public Vector3f[] getAxes() {
|
||||||
|
Vector3f[] axes = new Vector3f[]{
|
||||||
|
new Vector3f(1, 0, 0),
|
||||||
|
new Vector3f(0, 1, 0),
|
||||||
|
new Vector3f(0, 0, 1)};
|
||||||
|
rotation.transform(axes[0]);
|
||||||
|
rotation.transform(axes[1]);
|
||||||
|
rotation.transform(axes[2]);
|
||||||
|
return axes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断两个OBB是否相撞
|
||||||
|
*/
|
||||||
|
public static boolean isColliding(OBB obb, OBB other) {
|
||||||
|
Vector3f[] axes1 = obb.getAxes();
|
||||||
|
Vector3f[] axes2 = other.getAxes();
|
||||||
|
return Intersectionf.testObOb(obb.center(), axes1[0], axes1[1], axes1[2], obb.extents(),
|
||||||
|
other.center(), axes2[0], axes2[1], axes2[2], other.extents());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断OBB和AABB是否相撞
|
||||||
|
*/
|
||||||
|
public static boolean isColliding(OBB obb, AABB aabb) {
|
||||||
|
Vector3f obbCenter = obb.center();
|
||||||
|
Vector3f[] obbAxes = obb.getAxes();
|
||||||
|
Vector3f obbHalfExtents = obb.extents();
|
||||||
|
Vector3f aabbCenter = aabb.getCenter().toVector3f();
|
||||||
|
Vector3f aabbHalfExtents = new Vector3f((float) (aabb.getXsize() / 2f), (float) (aabb.getYsize() / 2f), (float) (aabb.getZsize() / 2f));
|
||||||
|
return Intersectionf.testObOb(
|
||||||
|
obbCenter.x, obbCenter.y, obbCenter.z,
|
||||||
|
obbAxes[0].x, obbAxes[0].y, obbAxes[0].z,
|
||||||
|
obbAxes[1].x, obbAxes[1].y, obbAxes[1].z,
|
||||||
|
obbAxes[2].x, obbAxes[2].y, obbAxes[2].z,
|
||||||
|
obbHalfExtents.x, obbHalfExtents.y, obbHalfExtents.z,
|
||||||
|
aabbCenter.x, aabbCenter.y, aabbCenter.z,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1,
|
||||||
|
aabbHalfExtents.x, aabbHalfExtents.y, aabbHalfExtents.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算OBB上离待判定点最近的点
|
||||||
|
*
|
||||||
|
* @param point 待判定点
|
||||||
|
* @param obb OBB盒
|
||||||
|
* @return 在OBB上离待判定点最近的点
|
||||||
|
*/
|
||||||
|
public static Vector3f getClosestPointOBB(Vector3f point, OBB obb) {
|
||||||
|
Vector3f nearP = new Vector3f(obb.center());
|
||||||
|
Vector3f dist = point.sub(nearP, new Vector3f());
|
||||||
|
|
||||||
|
float[] extents = new float[]{obb.extents().x, obb.extents().y, obb.extents().z};
|
||||||
|
Vector3f[] axes = obb.getAxes();
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
float distance = dist.dot(axes[i]);
|
||||||
|
distance = Math.clamp(distance, -extents[i], extents[i]);
|
||||||
|
|
||||||
|
nearP.x += distance * axes[i].x;
|
||||||
|
nearP.y += distance * axes[i].y;
|
||||||
|
nearP.z += distance * axes[i].z;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearP;
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
"CameraMixin",
|
"CameraMixin",
|
||||||
"ClientPacketListenerMixin",
|
"ClientPacketListenerMixin",
|
||||||
"ClientPlayerEntityMixin",
|
"ClientPlayerEntityMixin",
|
||||||
|
"EntityRenderDispatcherMixin",
|
||||||
"GameRendererMixin",
|
"GameRendererMixin",
|
||||||
"ItemInHandLayerMixin",
|
"ItemInHandLayerMixin",
|
||||||
"KeyboardInputMixin",
|
"KeyboardInputMixin",
|
||||||
|
|
Loading…
Add table
Reference in a new issue