Search in sources :

Example 1 with PhysicsCalculations

use of org.valkyrienskies.mod.common.physics.PhysicsCalculations 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 PhysicsCalculations

use of org.valkyrienskies.mod.common.physics.PhysicsCalculations in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class WaterForcesTask method addForcesToShip.

/**
 * Adds the computed force and torque to the parent ship
 */
public void addForcesToShip() {
    final PhysicsCalculations physicsEngine = parent.getPhysicsCalculations();
    physicsEngine.addForceAndTorque(addedForce, addedTorque);
}
Also used : PhysicsCalculations(org.valkyrienskies.mod.common.physics.PhysicsCalculations)

Example 3 with PhysicsCalculations

use of org.valkyrienskies.mod.common.physics.PhysicsCalculations in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.

the class MainCommand method teleportShipToPosition.

private static void teleportShipToPosition(final ShipData ship, final Vec3d position, final ICommandSender sender) {
    try {
        final World world = sender.getEntityWorld();
        final WorldServerShipManager shipManager = ValkyrienUtils.getServerShipManager(world);
        final PhysicsObject shipObject = shipManager.getPhysObjectFromUUID(ship.getUuid());
        // Create the new ship transform that moves the ship to this position
        final ShipTransform shipTransform = ship.getShipTransform();
        final ShipTransform newTransform = new ShipTransform(JOML.convert(position), shipTransform.getCenterCoord());
        if (shipObject != null) {
            // The ship already exists in the world, so we need to update the physics transform as well
            final PhysicsCalculations physicsCalculations = shipObject.getPhysicsCalculations();
            physicsCalculations.setForceToUseGameTransform(true);
            // Also update the transform in the ShipTransformationManager
            shipObject.setForceToUseShipDataTransform(true);
            shipObject.setTicksSinceShipTeleport(0);
        }
        // Update the ship transform of the ship data.
        ship.setPhysicsEnabled(false);
        ship.setPrevTickShipTransform(newTransform);
        ship.setShipTransform(newTransform);
        System.out.println(String.format("Teleporting ship %s to %s", ship.getName(), position.toString()));
    } catch (final Exception e) {
        e.printStackTrace();
    }
}
Also used : ShipTransform(org.valkyrienskies.mod.common.ships.ship_transform.ShipTransform) World(net.minecraft.world.World) PhysicsObject(org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject) PhysicsCalculations(org.valkyrienskies.mod.common.physics.PhysicsCalculations) WorldServerShipManager(org.valkyrienskies.mod.common.ships.ship_world.WorldServerShipManager)

Aggregations

PhysicsCalculations (org.valkyrienskies.mod.common.physics.PhysicsCalculations)3 ShipTransform (org.valkyrienskies.mod.common.ships.ship_transform.ShipTransform)2 BlockPos (net.minecraft.util.math.BlockPos)1 World (net.minecraft.world.World)1 Chunk (net.minecraft.world.chunk.Chunk)1 ExtendedBlockStorage (net.minecraft.world.chunk.storage.ExtendedBlockStorage)1 Vector3d (org.joml.Vector3d)1 Vector3dc (org.joml.Vector3dc)1 PhysicsObject (org.valkyrienskies.mod.common.ships.ship_world.PhysicsObject)1 WorldServerShipManager (org.valkyrienskies.mod.common.ships.ship_world.WorldServerShipManager)1 IBitOctree (org.valkyrienskies.mod.common.util.datastructures.IBitOctree)1 ITerrainOctreeProvider (org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider)1