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.config.server.ExplosionConfig;
|
||||
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.vehicle.base.ContainerMobileVehicleEntity;
|
||||
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.Nullable;
|
||||
import org.joml.Math;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
import org.joml.*;
|
||||
import software.bernie.geckolib.animatable.GeoEntity;
|
||||
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
|
||||
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.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> 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);
|
||||
public int droneReloadCoolDown;
|
||||
|
||||
public OBB obb;
|
||||
|
||||
public Yx100Entity(EntityType<Yx100Entity> type, Level world) {
|
||||
super(type, world);
|
||||
this.obb = new OBB(this.position().toVector3f(), new Vector3f(3.5f, 3.0f, 5.0f), new Quaternionf());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -227,6 +230,8 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
|||
public void baseTick() {
|
||||
super.baseTick();
|
||||
|
||||
this.updateOBB();
|
||||
|
||||
if (getLeftTrack() < 0) {
|
||||
setLeftTrack(80);
|
||||
}
|
||||
|
@ -1286,4 +1291,17 @@ public class Yx100Entity extends ContainerMobileVehicleEntity implements GeoEnti
|
|||
public @Nullable ResourceLocation getVehicleItemIcon() {
|
||||
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));
|
||||
}
|
||||
|
||||
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() {
|
||||
if (isControlledByLocalInstance()) {
|
||||
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",
|
||||
"ClientPacketListenerMixin",
|
||||
"ClientPlayerEntityMixin",
|
||||
"EntityRenderDispatcherMixin",
|
||||
"GameRendererMixin",
|
||||
"ItemInHandLayerMixin",
|
||||
"KeyboardInputMixin",
|
||||
|
|
Loading…
Add table
Reference in a new issue