use of org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider 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;
}
use of org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider 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);
}
}
}
}
}
}
}
use of org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider 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;
}
use of org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider 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);
}
}
}
}
use of org.valkyrienskies.mod.common.util.datastructures.ITerrainOctreeProvider in project Valkyrien-Warfare-Revamped by ValkyrienWarfare.
the class WorldWaterCollider 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) {
final Vector3d temp1 = new Vector3d();
final Vector3d temp2 = 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 + 15;
int maxStorageY = Math.min(maxY, minStorageY + 15);
int maxStorageZ = minStorageZ + 15;
ITerrainOctreeProvider provider = (ITerrainOctreeProvider) extendedblockstorage.data;
IBitOctree octree = provider.getLiquidOctree();
for (int x = minStorageX; x <= maxStorageX; x++) {
for (int y = minStorageY; y <= maxStorageY; y++) {
for (int z = minStorageZ; z <= maxStorageZ; z++) {
checkIfCollidesWithinRangeCheckRadius(x, y, z, octree, temp1, temp2, shipBB, output);
}
}
}
}
}
}
}
Aggregations