Search in sources :

Example 1 with IBitOctree

use of org.valkyrienskies.mod.common.util.datastructures.IBitOctree in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class WaterForcesTask method call.

/**
 * Computes the force and torque resulting from the water collisions handled by this task.
 */
@Override
public Void call() {
    final BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos();
    final ShipTransform physicsTransform = parent.getShipTransformationManager().getCurrentPhysicsTransform();
    final PhysicsCalculations physicsEngine = parent.getPhysicsCalculations();
    // Vector objects reused in this method.
    final Vector3d temp0 = new Vector3d();
    final Vector3d temp1 = new Vector3d();
    final Vector3d temp2 = new Vector3d();
    final Vector3d temp3 = new Vector3d();
    final Vector3d temp4 = new Vector3d();
    final Vector3d temp5 = new Vector3d();
    final Vector3d temp6 = new Vector3d();
    final Vector3d temp7 = new Vector3d();
    final Vector3d temp8 = new Vector3d();
    final Vector3d temp9 = new Vector3d();
    for (int index = minHitIndex; index <= maxHitIndex; index++) {
        final int waterHitPosHash = waterHitsToCheck.get(index);
        SpatialDetector.setPosWithRespectTo(waterHitPosHash, colliderCenter, currentPos);
        final Vector3dc waterPosInShipSpace = physicsTransform.transformPositionNew(JOML.convertDouble(currentPos, temp0).add(.5, .5, .5), TransformType.GLOBAL_TO_SUBSPACE);
        final int minX = (int) Math.floor(waterPosInShipSpace.x() - .5);
        final int minY = (int) Math.floor(waterPosInShipSpace.y() - .5);
        final int minZ = (int) Math.floor(waterPosInShipSpace.z() - .5);
        final int maxX = (int) Math.ceil(waterPosInShipSpace.x() + .5);
        final int maxY = (int) Math.ceil(waterPosInShipSpace.y() + .5);
        final int maxZ = (int) Math.ceil(waterPosInShipSpace.z() + .5);
        final Vector3dc waterPosInWorld = JOML.convertDouble(currentPos, temp1).add(.5, .5, .5);
        for (int x = minX; x <= maxX; x++) {
            for (int z = minZ; z <= maxZ; z++) {
                final Chunk chunk = parent.getChunkClaim().containsChunk(x >> 4, z >> 4) ? parent.getChunkAt(x >> 4, z >> 4) : null;
                if (chunk == null)
                    continue;
                for (int y = minY; y <= maxY; y++) {
                    final ExtendedBlockStorage blockStorage = chunk.storageArrays[y >> 4];
                    if (blockStorage != null) {
                        final IBitOctree terrainOctree = ((ITerrainOctreeProvider) blockStorage.data).getSolidOctree();
                        if (terrainOctree.get(x & 15, y & 15, z & 15)) {
                            // Assume both the water block and terrain block are spheres, then compute the volume
                            // that overlaps
                            final Vector3dc shipSolidBlockPosInWorld = physicsTransform.transformPositionNew(temp2.set(x + .5, y + .5, z + .5), TransformType.SUBSPACE_TO_GLOBAL);
                            final double volumeDisplaced = calculateAABBOverlap(waterPosInWorld.x() - shipSolidBlockPosInWorld.x(), waterPosInWorld.y() - shipSolidBlockPosInWorld.y(), waterPosInWorld.z() - shipSolidBlockPosInWorld.z());
                            if (volumeDisplaced <= 0) {
                                // No intersection
                                continue;
                            }
                            // Collision position is average of ship solid block pos and water pos
                            final Vector3dc collisionPosInWorld = shipSolidBlockPosInWorld.add(waterPosInWorld, temp3).mul(.5);
                            final Vector3dc buoyancyForce = temp4.set(0, volumeDisplaced * GRAVITY_ACCELERATION * MASS_OF_CUBIC_METER_OF_WATER, 0);
                            final Vector3dc collisionPosRelativeToShipCenterInWorld = temp5.set(collisionPosInWorld).sub(physicsTransform.getPosX(), physicsTransform.getPosY(), physicsTransform.getPosZ());
                            addForceAtPoint(collisionPosRelativeToShipCenterInWorld, buoyancyForce, temp7);
                            {
                                // Compute water damping force
                                final Vector3dc velocity = physicsEngine.getVelocityAtPoint(collisionPosRelativeToShipCenterInWorld, temp9);
                                if (!isVectorLengthZero(velocity)) {
                                    // TODO: This is WRONG, but it'll do for now
                                    // The distance between the water block and the solid block its pushing upwards
                                    double distance = waterPosInWorld.distance(shipSolidBlockPosInWorld);
                                    final double area = Math.PI * (SPHERE_RADIUS - (distance * .5)) * (SPHERE_RADIUS - (distance * .5));
                                    final double velocitySquared = velocity.lengthSquared();
                                    // Drag formula from https://en.wikipedia.org/wiki/Drag_(physics)
                                    final double forceMagnitude = (.5) * DENSITY_OF_WATER * velocitySquared * DRAG_COEFFICIENT_OF_WATER * area;
                                    final Vector3dc dragForce = temp6.set(velocity).normalize().mul(-forceMagnitude);
                                    addForceAtPoint(collisionPosRelativeToShipCenterInWorld, dragForce, temp8);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    return null;
}
Also used : ITerrainOctreeProvider(org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider) IBitOctree(org.valkyrienskies.mod.common.util.datastructures.IBitOctree) Chunk(net.minecraft.world.chunk.Chunk) ExtendedBlockStorage(net.minecraft.world.chunk.storage.ExtendedBlockStorage) Vector3dc(org.joml.Vector3dc) ShipTransform(org.valkyrienskies.mod.common.ships.ship_transform.ShipTransform) Vector3d(org.joml.Vector3d) BlockPos(net.minecraft.util.math.BlockPos) PhysicsCalculations(org.valkyrienskies.mod.common.physics.PhysicsCalculations)

Example 2 with IBitOctree

use of org.valkyrienskies.mod.common.util.datastructures.IBitOctree in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class WorldPhysicsCollider method updateCollisionCacheSequential.

private void updateCollisionCacheSequential(ChunkCache cache, int chunkX, int chunkZ, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, AxisAlignedBB shipBB, TIntList output) {
    int arrayChunkX = chunkX - cache.chunkX;
    int arrayChunkZ = chunkZ - cache.chunkZ;
    if (!(arrayChunkX < 0 || arrayChunkZ < 0 || arrayChunkX > cache.chunkArray.length - 1 || arrayChunkZ > cache.chunkArray[0].length - 1) && cache.chunkArray[arrayChunkX][arrayChunkZ] != null) {
        Vector3d temp1 = new Vector3d();
        Vector3d temp2 = new Vector3d();
        Vector3d temp3 = new Vector3d();
        Chunk chunk = cache.chunkArray[arrayChunkX][arrayChunkZ];
        for (int storageY = minY >> 4; storageY <= maxY >> 4; storageY++) {
            ExtendedBlockStorage extendedblockstorage = chunk.storageArrays[storageY];
            if (extendedblockstorage != null) {
                int minStorageX = chunkX << 4;
                int minStorageY = storageY << 4;
                int minStorageZ = chunkZ << 4;
                int maxStorageX = minStorageX + 16;
                int maxStorageY = minStorageY + 16;
                int maxStorageZ = minStorageZ + 16;
                final ITerrainOctreeProvider provider = (ITerrainOctreeProvider) extendedblockstorage.data;
                final IBitOctree octree = provider.getSolidOctree();
                for (int x = minStorageX; x < maxStorageX; x++) {
                    for (int y = minStorageY; y < maxStorageY; y++) {
                        for (int z = minStorageZ; z < maxStorageZ; z++) {
                            checkForCollision(x, y, z, extendedblockstorage, octree, temp1, temp2, temp3, shipBB, output);
                        }
                    }
                }
            }
        }
    }
}
Also used : Vector3d(org.joml.Vector3d) ITerrainOctreeProvider(org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider) IBitOctree(org.valkyrienskies.mod.common.util.datastructures.IBitOctree) Chunk(net.minecraft.world.chunk.Chunk) ExtendedBlockStorage(net.minecraft.world.chunk.storage.ExtendedBlockStorage)

Example 3 with IBitOctree

use of org.valkyrienskies.mod.common.util.datastructures.IBitOctree in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class WorldPhysicsCollider method isBlockInWorldSolidFast.

private boolean isBlockInWorldSolidFast(final int posX, final int posY, final int posZ) {
    if (posY < 0 || posY >= 256) {
        return false;
    }
    final ChunkCache surroundingChunks = parent.getCachedSurroundingChunks();
    final int relativeChunkX = (posX >> 4) - surroundingChunks.chunkX;
    final int relativeChunkZ = (posZ >> 4) - surroundingChunks.chunkZ;
    if (relativeChunkX < 0 || relativeChunkX >= surroundingChunks.chunkArray.length || relativeChunkZ < 0 || relativeChunkZ >= surroundingChunks.chunkArray[relativeChunkX].length) {
        return false;
    }
    final Chunk chunk = surroundingChunks.chunkArray[relativeChunkX][relativeChunkZ];
    if (chunk == null) {
        return false;
    }
    final ExtendedBlockStorage blockStorage = chunk.storageArrays[posY >> 4];
    if (blockStorage == null) {
        return false;
    }
    final IBitOctree octree = ITerrainOctreeProvider.class.cast(blockStorage.data).getSolidOctree();
    return octree.get(posX & 15, posY & 15, posZ & 15);
}
Also used : ChunkCache(net.minecraft.world.ChunkCache) ITerrainOctreeProvider(org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider) IBitOctree(org.valkyrienskies.mod.common.util.datastructures.IBitOctree) Chunk(net.minecraft.world.chunk.Chunk) ExtendedBlockStorage(net.minecraft.world.chunk.storage.ExtendedBlockStorage)

Example 4 with IBitOctree

use of org.valkyrienskies.mod.common.util.datastructures.IBitOctree in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class WorldPhysicsCollider method checkForCollisionFast.

private boolean checkForCollisionFast(final Chunk chunk, final int localX, final int localY, final int localZ, final int x, final int y, final int z, final TIntList output) {
    if (chunk.storageArrays[localY >> 4] != null) {
        ITerrainOctreeProvider provider = (ITerrainOctreeProvider) chunk.storageArrays[localY >> 4].getData();
        IBitOctree octreeInLocal = provider.getSolidOctree();
        if (octreeInLocal.get(localX & 15, localY & 15, localZ & 15)) {
            int hash = SpatialDetector.getHashWithRespectTo(x, y, z, centerPotentialHit);
            // Sometimes we end up adding to the hits array in multiple threads at once,
            // crashing the physics.
            output.add(hash);
            return true;
        // break outermostloop;
        }
    // }
    }
    return false;
}
Also used : ITerrainOctreeProvider(org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider) IBitOctree(org.valkyrienskies.mod.common.util.datastructures.IBitOctree)

Example 5 with IBitOctree

use of org.valkyrienskies.mod.common.util.datastructures.IBitOctree in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class ShipCollisionTask method checkPosition.

public void checkPosition(int x, int y, int z, int positionHash) {
    if (!toTask.getParent().getChunkClaim().containsChunk(x >> 4, z >> 4)) {
        return;
    }
    final Chunk chunkIn = toTask.getParent().getChunkAt(x >> 4, z >> 4);
    y = Math.max(0, Math.min(y, 255));
    ExtendedBlockStorage storage = chunkIn.storageArrays[y >> 4];
    if (storage != null) {
        ITerrainOctreeProvider provider = (ITerrainOctreeProvider) storage.data;
        IBitOctree octree = provider.getSolidOctree();
        if (octree.get(x & 15, y & 15, z & 15)) {
            IBlockState inLocalState = chunkIn.getBlockState(x, y, z);
            inLocalPos.setPos(x, y, z);
            final ShipTransform shipTransform = toTask.getParent().getShipTransformationManager().getCurrentPhysicsTransform();
            final Vector3dc shipBlockInGlobal = shipTransform.transformPositionNew(temp0.set(inLocalPos.getX() + .5, inLocalPos.getY() + .5, inLocalPos.getZ() + .5), TransformType.SUBSPACE_TO_GLOBAL);
            final double distanceSq = shipBlockInGlobal.distanceSquared(mutablePos.getX() + .5, mutablePos.getY() + .5, mutablePos.getZ() + .5);
            // If it is less than sqrt(3) then collision is possible.
            if (distanceSq < 3) {
                CollisionInformationHolder holder = new CollisionInformationHolder(mutablePos.getX(), mutablePos.getY(), mutablePos.getZ(), inLocalPos.getX(), inLocalPos.getY(), inLocalPos.getZ(), inWorldState, inLocalState);
                collisionInformationGenerated.add(holder);
            }
        }
    }
}
Also used : Vector3dc(org.joml.Vector3dc) IBlockState(net.minecraft.block.state.IBlockState) ShipTransform(org.valkyrienskies.mod.common.ships.ship_transform.ShipTransform) ITerrainOctreeProvider(org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider) IBitOctree(org.valkyrienskies.mod.common.util.datastructures.IBitOctree) Chunk(net.minecraft.world.chunk.Chunk) ExtendedBlockStorage(net.minecraft.world.chunk.storage.ExtendedBlockStorage)

Aggregations

IBitOctree (org.valkyrienskies.mod.common.util.datastructures.IBitOctree)7 ITerrainOctreeProvider (org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider)7 Chunk (net.minecraft.world.chunk.Chunk)5 ExtendedBlockStorage (net.minecraft.world.chunk.storage.ExtendedBlockStorage)5 Vector3d (org.joml.Vector3d)3 Vector3dc (org.joml.Vector3dc)2 ShipTransform (org.valkyrienskies.mod.common.ships.ship_transform.ShipTransform)2 IBlockState (net.minecraft.block.state.IBlockState)1 BlockPos (net.minecraft.util.math.BlockPos)1 ChunkCache (net.minecraft.world.ChunkCache)1 PhysicsCalculations (org.valkyrienskies.mod.common.physics.PhysicsCalculations)1