All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yungnickyoung.minecraft.yungsapi.util.BoxOctree Maven / Gradle / Ivy

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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy