com.yungnickyoung.minecraft.yungsapi.util.BoxOctree Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of YungsApi-1.21-Fabric Show documentation
Show all versions of YungsApi-1.21-Fabric Show documentation
A common API for YUNG's Minecraft mods
The newest version!
package com.yungnickyoung.minecraft.yungsapi.util;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.class_238;
import net.minecraft.class_2382;
/**
* Thanks to TelepathicGrunt for letting me use this octree implementation!
* Original: https://github.com/TelepathicGrunt/RepurposedStructures/blob/latest-released/src/main/java/com/telepathicgrunt/repurposedstructures/utils/BoxOctree.java
*/
public class BoxOctree {
private static final int subdivideThreshold = 10;
private static final int maximumDepth = 3;
private final class_238 boundary;
private final class_2382 size;
private final int depth;
private final List innerBoxes = new ArrayList<>();
private final List childrenOctants = new ArrayList<>();
public BoxOctree(class_238 axisAlignedBB) {
this(axisAlignedBB, 0);
}
private BoxOctree(class_238 axisAlignedBB, int parentDepth) {
boundary = axisAlignedBB.method_989(0, 0, 0); // deep copy
size = new class_2382((int) boundary.method_17939(),(int) boundary.method_17940(),(int) boundary.method_17941());
depth = parentDepth + 1;
}
private void subdivide() {
if (!childrenOctants.isEmpty()) {
throw new UnsupportedOperationException("YUNG's API - Tried to subdivide when there are already children octants.");
}
int halfXSize = size.method_10263() / 2;
int halfYSize = size.method_10264() / 2;
int halfZSize = size.method_10260() / 2;
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323, boundary.field_1322, boundary.field_1321,
boundary.field_1323 + halfXSize, boundary.field_1322 + halfYSize, boundary.field_1321 + halfZSize),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323 + halfXSize, boundary.field_1322, boundary.field_1321,
boundary.field_1320, boundary.field_1322 + halfYSize, boundary.field_1321 + halfZSize),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323, boundary.field_1322 + halfYSize, boundary.field_1321,
boundary.field_1323 + halfXSize, boundary.field_1325, boundary.field_1321 + halfZSize),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323, boundary.field_1322, boundary.field_1321 + halfZSize,
boundary.field_1323 + halfXSize, boundary.field_1322 + halfYSize, boundary.field_1324),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323 + halfXSize, boundary.field_1322 + halfYSize, boundary.field_1321,
boundary.field_1320, boundary.field_1325, boundary.field_1321 + halfZSize),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323, boundary.field_1322 + halfYSize, boundary.field_1321 + halfZSize,
boundary.field_1323 + halfXSize, boundary.field_1325, boundary.field_1324),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323 + halfXSize, boundary.field_1322, boundary.field_1321 + halfZSize,
boundary.field_1320, boundary.field_1322 + halfYSize, boundary.field_1324),
depth));
childrenOctants.add(new BoxOctree(new class_238(
boundary.field_1323 + halfXSize, boundary.field_1322 + halfYSize, boundary.field_1321 + halfZSize,
boundary.field_1320, boundary.field_1325, boundary.field_1324),
depth));
for (class_238 parentInnerBox : innerBoxes) {
for (BoxOctree octree : childrenOctants) {
if (octree.boundaryIntersectsFuzzy(parentInnerBox)) {
octree.addBox(parentInnerBox);
}
}
}
innerBoxes.clear();
}
public void addBox(class_238 axisAlignedBB) {
if (depth < maximumDepth && innerBoxes.size() > subdivideThreshold) {
subdivide();
}
if (!childrenOctants.isEmpty()) {
for (BoxOctree octree : childrenOctants) {
if (octree.boundaryIntersectsFuzzy(axisAlignedBB)) {
octree.addBox(axisAlignedBB);
}
}
} else {
// Prevent re-adding the same box if it already exists
for (class_238 parentInnerBox : innerBoxes) {
if (parentInnerBox.equals(axisAlignedBB)) {
return;
}
}
innerBoxes.add(axisAlignedBB);
}
}
public void removeBox(class_238 axisAlignedBB) {
if (!childrenOctants.isEmpty()) {
for (BoxOctree octree : childrenOctants) {
if (octree.boundaryIntersectsFuzzy(axisAlignedBB)) {
octree.removeBox(axisAlignedBB);
}
}
} else {
for (class_238 innerBox : innerBoxes) {
if (innerBox.equals(axisAlignedBB)) {
innerBoxes.remove(innerBox);
return;
}
}
}
}
public boolean boundaryIntersectsFuzzy(class_238 axisAlignedBB) {
return boundary.method_1014(axisAlignedBB.method_995() / 2).method_994(axisAlignedBB);
}
public boolean boundaryContains(class_238 axisAlignedBB) {
return boundary.method_1008(axisAlignedBB.field_1323, axisAlignedBB.field_1322, axisAlignedBB.field_1321) &&
boundary.method_1008(axisAlignedBB.field_1320, axisAlignedBB.field_1325, axisAlignedBB.field_1324);
}
public boolean intersectsAnyBox(class_238 axisAlignedBB) {
if (!childrenOctants.isEmpty()) {
for (BoxOctree octree : childrenOctants) {
if (octree.intersectsAnyBox(axisAlignedBB)) {
return true;
}
}
} else {
for (class_238 innerBox : innerBoxes) {
if (innerBox.method_994(axisAlignedBB)) {
return true;
}
}
}
return false;
}
}