mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
修复剔除点
This commit is contained in:
@@ -31,6 +31,7 @@ import net.momirealms.craftengine.core.world.WorldPosition;
|
|||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
import net.momirealms.sparrow.nbt.CompoundTag;
|
import net.momirealms.sparrow.nbt.CompoundTag;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -119,6 +120,9 @@ public class FurnitureItemBehavior extends ItemBehavior {
|
|||||||
// 检查方块、实体阻挡
|
// 检查方块、实体阻挡
|
||||||
if (!aabbs.isEmpty()) {
|
if (!aabbs.isEmpty()) {
|
||||||
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) {
|
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), aabbs.stream().map(it -> FastNMS.INSTANCE.constructor$AABB(it.minX, it.minY, it.minZ, it.maxX, it.maxY, it.maxZ)).toList())) {
|
||||||
|
if (player != null && player.enableFurnitureDebug() && VersionHelper.isPaper()) {
|
||||||
|
// bukkitPlayer.getWorld().spawnParticle(Particle.FLAME, , List.of(bukkitPlayer), );
|
||||||
|
}
|
||||||
return InteractionResult.FAIL;
|
return InteractionResult.FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ public class SetEntityViewDistanceScaleCommand extends BukkitCommandFeature<Comm
|
|||||||
.required("scale", DoubleParser.doubleParser(0.125, 8))
|
.required("scale", DoubleParser.doubleParser(0.125, 8))
|
||||||
.handler(context -> {
|
.handler(context -> {
|
||||||
if (!Config.enableEntityCulling()) {
|
if (!Config.enableEntityCulling()) {
|
||||||
context.sender().sendMessage(Component.text("Entity culling is not enabled on this server").color(NamedTextColor.RED));
|
plugin().senderFactory().wrap(context.sender()).sendMessage(Component.text("Entity culling is not enabled on this server").color(NamedTextColor.RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Config.entityCullingViewDistance() <= 0) {
|
if (Config.entityCullingViewDistance() <= 0) {
|
||||||
context.sender().sendMessage(Component.text("View distance is not enabled on this server").color(NamedTextColor.RED));
|
plugin().senderFactory().wrap(context.sender()).sendMessage(Component.text("View distance is not enabled on this server").color(NamedTextColor.RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Player player = context.get("player");
|
Player player = context.get("player");
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class ToggleEntityCullingCommand extends BukkitCommandFeature<CommandSend
|
|||||||
.optional("state", BooleanParser.booleanParser())
|
.optional("state", BooleanParser.booleanParser())
|
||||||
.handler(context -> {
|
.handler(context -> {
|
||||||
if (!Config.enableEntityCulling()) {
|
if (!Config.enableEntityCulling()) {
|
||||||
context.sender().sendMessage(Component.text("Entity culling is not enabled on this server").color(NamedTextColor.RED));
|
plugin().senderFactory().wrap(context.sender()).sendMessage(Component.text("Entity culling is not enabled on this server").color(NamedTextColor.RED));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Player player = context.get("player");
|
Player player = context.get("player");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.momirealms.craftengine.bukkit.plugin.network;
|
package net.momirealms.craftengine.bukkit.plugin.network;
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.ParticleBuilder;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
|||||||
@@ -1480,6 +1480,14 @@ public class BukkitServerPlayer extends Player {
|
|||||||
return LocationUtils.toWorldPosition(this.getEyeLocation());
|
return LocationUtils.toWorldPosition(this.getEyeLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playParticle(Key particleId, double x, double y, double z) {
|
||||||
|
Particle particle = Registry.PARTICLE_TYPE.get(KeyUtils.toNamespacedKey(particleId));
|
||||||
|
if (particle != null) {
|
||||||
|
platformPlayer().getWorld().spawnParticle(particle, List.of(platformPlayer()), null, x, y, z, 1, 0, 0,0, 0, null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Location getEyeLocation() {
|
public Location getEyeLocation() {
|
||||||
org.bukkit.entity.Player player = platformPlayer();
|
org.bukkit.entity.Player player = platformPlayer();
|
||||||
Location eyeLocation = player.getEyeLocation();
|
Location eyeLocation = player.getEyeLocation();
|
||||||
|
|||||||
@@ -146,28 +146,9 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
hitboxes = List.of(defaultHitBox());
|
hitboxes = List.of(defaultHitBox());
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AABB> aabbs = new ArrayList<>();
|
|
||||||
for (FurnitureHitBoxConfig<?> hitBox : hitboxes) {
|
|
||||||
hitBox.collectBoundingBox(aabbs::add);
|
|
||||||
}
|
|
||||||
double minX = 0;
|
|
||||||
double minY = 0;
|
|
||||||
double minZ = 0;
|
|
||||||
double maxX = 0;
|
|
||||||
double maxY = 0;
|
|
||||||
double maxZ = 0;
|
|
||||||
for (AABB aabb : aabbs) {
|
|
||||||
minX = Math.min(minX, aabb.minX);
|
|
||||||
minY = Math.min(minY, aabb.minY);
|
|
||||||
minZ = Math.min(minZ, aabb.minZ);
|
|
||||||
maxX = Math.max(maxX, aabb.maxX);
|
|
||||||
maxY = Math.max(maxY, aabb.maxY);
|
|
||||||
maxZ = Math.max(maxZ, aabb.maxZ);
|
|
||||||
}
|
|
||||||
AABB maxAABB = new AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
|
||||||
variants.put(variantName, new FurnitureVariant(
|
variants.put(variantName, new FurnitureVariant(
|
||||||
variantName,
|
variantName,
|
||||||
parseCullingData(section.get("entity-culling"), maxAABB),
|
parseCullingData(section.get("entity-culling")),
|
||||||
elements.toArray(new FurnitureElementConfig[0]),
|
elements.toArray(new FurnitureElementConfig[0]),
|
||||||
hitboxes.toArray(new FurnitureHitBoxConfig[0]),
|
hitboxes.toArray(new FurnitureHitBoxConfig[0]),
|
||||||
externalModel,
|
externalModel,
|
||||||
@@ -185,16 +166,18 @@ public abstract class AbstractFurnitureManager implements FurnitureManager {
|
|||||||
AbstractFurnitureManager.this.byId.put(id, furniture);
|
AbstractFurnitureManager.this.byId.put(id, furniture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CullingData parseCullingData(Object arguments, AABB maxHitbox) {
|
|
||||||
|
|
||||||
|
private CullingData parseCullingData(Object arguments) {
|
||||||
if (arguments instanceof Boolean b && !b)
|
if (arguments instanceof Boolean b && !b)
|
||||||
return null;
|
return null;
|
||||||
if (!(arguments instanceof Map))
|
if (!(arguments instanceof Map))
|
||||||
return new CullingData(maxHitbox, Config.entityCullingViewDistance(), 0.5, true);
|
return new CullingData(null, Config.entityCullingViewDistance(), 0.25, true);
|
||||||
Map<String, Object> argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling");
|
Map<String, Object> argumentsMap = ResourceConfigUtils.getAsMap(arguments, "entity-culling");
|
||||||
return new CullingData(
|
return new CullingData(
|
||||||
ResourceConfigUtils.getAsAABB(argumentsMap.getOrDefault("aabb", maxHitbox), "aabb"),
|
ResourceConfigUtils.getOrDefault(argumentsMap.get("aabb"), it -> ResourceConfigUtils.getAsAABB(it, "aabb"), null),
|
||||||
ResourceConfigUtils.getAsInt(argumentsMap.getOrDefault("view-distance", Config.entityCullingViewDistance()), "view-distance"),
|
ResourceConfigUtils.getAsInt(argumentsMap.getOrDefault("view-distance", Config.entityCullingViewDistance()), "view-distance"),
|
||||||
ResourceConfigUtils.getAsDouble(argumentsMap.getOrDefault("aabb-expansion", 0.5), "aabb-expansion"),
|
ResourceConfigUtils.getAsDouble(argumentsMap.getOrDefault("aabb-expansion", 0.25), "aabb-expansion"),
|
||||||
ResourceConfigUtils.getAsBoolean(argumentsMap.getOrDefault("ray-tracing", true), "ray-tracing")
|
ResourceConfigUtils.getAsBoolean(argumentsMap.getOrDefault("ray-tracing", true), "ray-tracing")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,13 @@ import net.momirealms.craftengine.core.world.Vec3d;
|
|||||||
import net.momirealms.craftengine.core.world.World;
|
import net.momirealms.craftengine.core.world.World;
|
||||||
import net.momirealms.craftengine.core.world.WorldPosition;
|
import net.momirealms.craftengine.core.world.WorldPosition;
|
||||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Quaternionf;
|
import org.joml.Quaternionf;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@@ -109,9 +112,62 @@ public abstract class Furniture implements Cullable {
|
|||||||
if (parent == null) return null;
|
if (parent == null) return null;
|
||||||
AABB aabb = parent.aabb;
|
AABB aabb = parent.aabb;
|
||||||
WorldPosition position = position();
|
WorldPosition position = position();
|
||||||
Vec3d pos1 = getRelativePosition(position, new Vector3f((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ));
|
if (aabb == null) {
|
||||||
Vec3d pos2 = getRelativePosition(position, new Vector3f((float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ));
|
List<AABB> aabbs = new ArrayList<>();
|
||||||
return new CullingData(new AABB(pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z), parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
|
for (FurnitureHitBoxConfig<?> hitBoxConfig : this.currentVariant.hitBoxConfigs()) {
|
||||||
|
hitBoxConfig.prepareForPlacement(position, aabbs::add);
|
||||||
|
}
|
||||||
|
return new CullingData(getMaxAABB(aabbs), parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
|
||||||
|
} else {
|
||||||
|
Vector3f[] vertices = new Vector3f[] {
|
||||||
|
// 底面两个对角点
|
||||||
|
new Vector3f((float) aabb.minX, (float) aabb.minY, (float) aabb.minZ),
|
||||||
|
new Vector3f((float) aabb.maxX, (float) aabb.minY, (float) aabb.maxZ),
|
||||||
|
// 顶面两个对角点
|
||||||
|
new Vector3f((float) aabb.minX, (float) aabb.maxY, (float) aabb.minZ),
|
||||||
|
new Vector3f((float) aabb.maxX, (float) aabb.maxY, (float) aabb.maxZ)
|
||||||
|
};
|
||||||
|
double minX = Double.MAX_VALUE, minY = aabb.minY; // Y方向不变
|
||||||
|
double maxX = -Double.MAX_VALUE, maxY = aabb.maxY; // Y方向不变
|
||||||
|
double minZ = Double.MAX_VALUE, maxZ = -Double.MAX_VALUE;
|
||||||
|
for (Vector3f vertex : vertices) {
|
||||||
|
Vec3d rotatedPos = getRelativePosition(position, vertex);
|
||||||
|
minX = Math.min(minX, rotatedPos.x);
|
||||||
|
minZ = Math.min(minZ, rotatedPos.z);
|
||||||
|
maxX = Math.max(maxX, rotatedPos.x);
|
||||||
|
maxZ = Math.max(maxZ, rotatedPos.z);
|
||||||
|
}
|
||||||
|
return new CullingData(new AABB(minX, minY, minZ, maxX, maxY, maxZ),
|
||||||
|
parent.maxDistance, parent.aabbExpansion, parent.rayTracing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull AABB getMaxAABB(List<AABB> aabbs) {
|
||||||
|
double minX = 0;
|
||||||
|
double minY = 0;
|
||||||
|
double minZ = 0;
|
||||||
|
double maxX = 0;
|
||||||
|
double maxY = 0;
|
||||||
|
double maxZ = 0;
|
||||||
|
for (int i = 0; i < aabbs.size(); i++) {
|
||||||
|
AABB aabb = aabbs.get(i);
|
||||||
|
if (i == 0) {
|
||||||
|
minX = aabb.minX;
|
||||||
|
minY = aabb.minY;
|
||||||
|
minZ = aabb.minZ;
|
||||||
|
maxX = aabb.maxX;
|
||||||
|
maxY = aabb.maxY;
|
||||||
|
maxZ = aabb.maxZ;
|
||||||
|
} else {
|
||||||
|
minX = Math.min(minX, aabb.minX);
|
||||||
|
minY = Math.min(minY, aabb.minY);
|
||||||
|
minZ = Math.min(minZ, aabb.minZ);
|
||||||
|
maxX = Math.max(maxX, aabb.maxX);
|
||||||
|
maxY = Math.max(maxY, aabb.maxY);
|
||||||
|
maxZ = Math.max(maxZ, aabb.maxZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new AABB(minX, minY, minZ, maxX, maxY, maxZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
@@ -230,6 +230,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser {
|
|||||||
public void remove() {
|
public void remove() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract void playParticle(Key particleId, double x, double y, double z);
|
||||||
|
|
||||||
public abstract void removeTrackedFurniture(int entityId);
|
public abstract void removeTrackedFurniture(int entityId);
|
||||||
|
|
||||||
public abstract void clearTrackedFurniture();
|
public abstract void clearTrackedFurniture();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.entityculling;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.core.entity.player.Player;
|
import net.momirealms.craftengine.core.entity.player.Player;
|
||||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||||
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||||
import net.momirealms.craftengine.core.world.MutableVec3d;
|
import net.momirealms.craftengine.core.world.MutableVec3d;
|
||||||
@@ -59,13 +60,12 @@ public final class EntityCulling {
|
|||||||
AABB aabb = cullable.aabb;
|
AABB aabb = cullable.aabb;
|
||||||
double aabbExpansion = cullable.aabbExpansion;
|
double aabbExpansion = cullable.aabbExpansion;
|
||||||
|
|
||||||
// 根据AABB获取能包裹此AABB的最小长方体
|
double minX = aabb.minX - aabbExpansion;
|
||||||
int minX = MiscUtils.floor(aabb.minX - aabbExpansion);
|
double minY = aabb.minY - aabbExpansion;
|
||||||
int minY = MiscUtils.floor(aabb.minY - aabbExpansion);
|
double minZ = aabb.minZ - aabbExpansion;
|
||||||
int minZ = MiscUtils.floor(aabb.minZ - aabbExpansion);
|
double maxX = aabb.maxX + aabbExpansion;
|
||||||
int maxX = MiscUtils.ceil(aabb.maxX + aabbExpansion);
|
double maxY = aabb.maxY + aabbExpansion;
|
||||||
int maxY = MiscUtils.ceil(aabb.maxY + aabbExpansion);
|
double maxZ = aabb.maxZ + aabbExpansion;
|
||||||
int maxZ = MiscUtils.ceil(aabb.maxZ + aabbExpansion);
|
|
||||||
|
|
||||||
double cameraX = cameraPos.x;
|
double cameraX = cameraPos.x;
|
||||||
double cameraY = cameraPos.y;
|
double cameraY = cameraPos.y;
|
||||||
@@ -95,6 +95,10 @@ public final class EntityCulling {
|
|||||||
if (distanceSq > maxDistanceSq) {
|
if (distanceSq > maxDistanceSq) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// 太近了,不剔除
|
||||||
|
else if (distanceSq < 1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rayTracing || !cullable.rayTracing) {
|
if (!rayTracing || !cullable.rayTracing) {
|
||||||
@@ -120,25 +124,31 @@ public final class EntityCulling {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int size = 0;
|
int size = 0;
|
||||||
if (this.dotSelectors[0]) targetPoints[size++].set(minX + 0.05, minY + 0.05, minZ + 0.05);
|
if (this.dotSelectors[0]) targetPoints[size++].set(minX, minY, minZ);
|
||||||
if (this.dotSelectors[1]) targetPoints[size++].set(maxX - 0.05, minY + 0.05, minZ + 0.05);
|
if (this.dotSelectors[1]) targetPoints[size++].set(maxX, minY, minZ);
|
||||||
if (this.dotSelectors[2]) targetPoints[size++].set(minX + 0.05, minY + 0.05, maxZ - 0.05);
|
if (this.dotSelectors[2]) targetPoints[size++].set(minX, minY, maxZ);
|
||||||
if (this.dotSelectors[3]) targetPoints[size++].set(maxX - 0.05, minY + 0.05, maxZ - 0.05);
|
if (this.dotSelectors[3]) targetPoints[size++].set(maxX, minY, maxZ);
|
||||||
if (this.dotSelectors[4]) targetPoints[size++].set(minX + 0.05, maxY - 0.05, minZ + 0.05);
|
if (this.dotSelectors[4]) targetPoints[size++].set(minX, maxY, minZ);
|
||||||
if (this.dotSelectors[5]) targetPoints[size++].set(maxX - 0.05, maxY - 0.05, minZ + 0.05);
|
if (this.dotSelectors[5]) targetPoints[size++].set(maxX, maxY, minZ);
|
||||||
if (this.dotSelectors[6]) targetPoints[size++].set(minX + 0.05, maxY - 0.05, maxZ - 0.05);
|
if (this.dotSelectors[6]) targetPoints[size++].set(minX, maxY, maxZ);
|
||||||
if (this.dotSelectors[7]) targetPoints[size++].set(maxX - 0.05, maxY - 0.05, maxZ - 0.05);
|
if (this.dotSelectors[7]) targetPoints[size++].set(maxX, maxY, maxZ);
|
||||||
// 面中心点
|
// 面中心点
|
||||||
double averageX = (minX + maxX) / 2.0;
|
double averageX = (minX + maxX) / 2.0;
|
||||||
double averageY = (minY + maxY) / 2.0;
|
double averageY = (minY + maxY) / 2.0;
|
||||||
double averageZ = (minZ + maxZ) / 2.0;
|
double averageZ = (minZ + maxZ) / 2.0;
|
||||||
if (this.dotSelectors[8]) targetPoints[size++].set(averageX, averageY, minZ + 0.05);
|
if (this.dotSelectors[8]) targetPoints[size++].set(averageX, averageY, minZ);
|
||||||
if (this.dotSelectors[9]) targetPoints[size++].set(averageX, averageY, maxZ - 0.05);
|
if (this.dotSelectors[9]) targetPoints[size++].set(averageX, averageY, maxZ);
|
||||||
if (this.dotSelectors[10]) targetPoints[size++].set(minX + 0.05, averageY, averageZ);
|
if (this.dotSelectors[10]) targetPoints[size++].set(minX, averageY, averageZ);
|
||||||
if (this.dotSelectors[11]) targetPoints[size++].set(maxX - 0.05, averageY, averageZ);
|
if (this.dotSelectors[11]) targetPoints[size++].set(maxX, averageY, averageZ);
|
||||||
if (this.dotSelectors[12]) targetPoints[size++].set(averageX, minY + 0.05, averageZ);
|
if (this.dotSelectors[12]) targetPoints[size++].set(averageX, minY, averageZ);
|
||||||
if (this.dotSelectors[13]) targetPoints[size].set(averageX, maxY - 0.05, averageZ);
|
if (this.dotSelectors[13]) targetPoints[size++].set(averageX, maxY, averageZ);
|
||||||
|
|
||||||
|
// if (Config.debugEntityCulling()) {
|
||||||
|
// for (int i = 0; i < size; i++) {
|
||||||
|
// MutableVec3d targetPoint = this.targetPoints[i];
|
||||||
|
// this.player.playParticle(Key.of("flame"), targetPoint.x, targetPoint.y, targetPoint.z);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
return isVisible(cameraPos, this.targetPoints, size);
|
return isVisible(cameraPos, this.targetPoints, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,7 +366,7 @@ public final class EntityCulling {
|
|||||||
return deltaX + 32 * deltaY + 32 * 32 * deltaZ;
|
return deltaX + 32 * deltaY + 32 * 32 * deltaZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private double distanceSq(int min, int max, double camera, Relative rel) {
|
private double distanceSq(double min, double max, double camera, Relative rel) {
|
||||||
if (rel == Relative.NEGATIVE) {
|
if (rel == Relative.NEGATIVE) {
|
||||||
double dx = camera - max;
|
double dx = camera - max;
|
||||||
return dx * dx;
|
return dx * dx;
|
||||||
@@ -394,7 +404,7 @@ public final class EntityCulling {
|
|||||||
|
|
||||||
private enum Relative {
|
private enum Relative {
|
||||||
INSIDE, POSITIVE, NEGATIVE;
|
INSIDE, POSITIVE, NEGATIVE;
|
||||||
public static Relative from(int min, int max, double pos) {
|
public static Relative from(double min, double max, double pos) {
|
||||||
if (min > pos) return POSITIVE;
|
if (min > pos) return POSITIVE;
|
||||||
else if (max < pos) return NEGATIVE;
|
else if (max < pos) return NEGATIVE;
|
||||||
return INSIDE;
|
return INSIDE;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import net.momirealms.craftengine.core.world.Vec3d;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public class AABB {
|
public class AABB {
|
||||||
@@ -159,6 +161,78 @@ public class AABB {
|
|||||||
return (value >= min - EPSILON) && (value <= max + EPSILON);
|
return (value >= min - EPSILON) && (value <= max + EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Vec3d> getEdgePoints(double interval) {
|
||||||
|
List<Vec3d> points = new ArrayList<>();
|
||||||
|
|
||||||
|
// AABB的8个顶点
|
||||||
|
Vec3d[] vertices = {
|
||||||
|
new Vec3d(minX, minY, minZ), // 0
|
||||||
|
new Vec3d(maxX, minY, minZ), // 1
|
||||||
|
new Vec3d(minX, maxY, minZ), // 2
|
||||||
|
new Vec3d(maxX, maxY, minZ), // 3
|
||||||
|
new Vec3d(minX, minY, maxZ), // 4
|
||||||
|
new Vec3d(maxX, minY, maxZ), // 5
|
||||||
|
new Vec3d(minX, maxY, maxZ), // 6
|
||||||
|
new Vec3d(maxX, maxY, maxZ) // 7
|
||||||
|
};
|
||||||
|
|
||||||
|
// 12条边的定义(连接哪两个顶点)
|
||||||
|
int[][] edges = {
|
||||||
|
{0, 1}, // 底部X边(前)
|
||||||
|
{1, 3}, // 底部Y边(右)
|
||||||
|
{3, 2}, // 底部X边(后)
|
||||||
|
{2, 0}, // 底部Y边(左)
|
||||||
|
|
||||||
|
{4, 5}, // 顶部X边(前)
|
||||||
|
{5, 7}, // 顶部Y边(右)
|
||||||
|
{7, 6}, // 顶部X边(后)
|
||||||
|
{6, 4}, // 顶部Y边(左)
|
||||||
|
|
||||||
|
{0, 4}, // Z边(左下前)
|
||||||
|
{1, 5}, // Z边(右下前)
|
||||||
|
{2, 6}, // Z边(左后上)
|
||||||
|
{3, 7} // Z边(右后上)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int[] edge : edges) {
|
||||||
|
Vec3d start = vertices[edge[0]];
|
||||||
|
Vec3d end = vertices[edge[1]];
|
||||||
|
points.addAll(sampleLine(start, end, interval));
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Vec3d> sampleLine(Vec3d start, Vec3d end, double interval) {
|
||||||
|
List<Vec3d> points = new ArrayList<>();
|
||||||
|
|
||||||
|
// 计算线段长度
|
||||||
|
double dx = end.x - start.x;
|
||||||
|
double dy = end.y - start.y;
|
||||||
|
double dz = end.z - start.z;
|
||||||
|
double length = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
|
|
||||||
|
// 计算采样点数(去掉终点避免重复)
|
||||||
|
int numPoints = (int) Math.floor(length / interval);
|
||||||
|
|
||||||
|
// 如果线段太短,至少返回起点
|
||||||
|
if (numPoints <= 0) {
|
||||||
|
points.add(start);
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按间隔采样
|
||||||
|
for (int i = 0; i <= numPoints; i++) {
|
||||||
|
double t = (double) i / numPoints;
|
||||||
|
double x = start.x + dx * t;
|
||||||
|
double y = start.y + dy * t;
|
||||||
|
double z = start.z + dz * t;
|
||||||
|
points.add(new Vec3d(x, y, z));
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AABB{" +
|
return "AABB{" +
|
||||||
|
|||||||
Reference in New Issue
Block a user