/** * Gets the point of collision between a BoundingSphere and a Ray. * * @param a * @param b * @return */ public static Vector3 getCollision(BoundingSphere a, Ray b) { Vector3 m = b.origin.subtract(a.center); float e = m.dot(b.direction); float f = (float) (m.dot(m) - a.radius * a.radius); // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) if (f > 0.0f && e > 0.0f) { return null; } float discr = e * e - f; // A negative discriminant corresponds to ray missing sphere if (discr < 0.0f) { return null; } // Ray now found to intersect sphere, compute smallest t value of intersection float t = (float) (-e - MathHelper.sqrt(discr)); // If t is negative, ray started inside sphere so clamp t to zero if (t < 0.0f) { t = 0.0f; } return b.origin.add(b.direction.multiply(t)); }
public void setBlockMaterial(int xx, int yy, int zz, BlockMaterial material, short data) { final Vector3 transformed = transform(xx, yy, zz); position .getWorld() .setBlockMaterial( transformed.getFloorX(), transformed.getFloorY(), transformed.getFloorZ(), material, data, null); if (material instanceof Directional) { final Directional directional = (Directional) material; final Block block = position.getWorld().getBlock(transformed); final BlockFace face = directional.getFacing(block); if (face != BlockFace.BOTTOM && face != BlockFace.TOP) { directional.setFacing( block, BlockFace.fromYaw(face.getDirection().getYaw() + rotation.getYaw())); } } else if (material instanceof Attachable) { final Attachable attachable = (Attachable) material; final Block block = position.getWorld().getBlock(transformed); final BlockFace face = attachable.getAttachedFace(block); if (face != BlockFace.BOTTOM && face != BlockFace.TOP) { attachable.setAttachedFace( block, BlockFace.fromYaw(face.getDirection().getYaw() + rotation.getYaw()), null); } } }
public BlockMaterial getBlockMaterial(int xx, int yy, int zz) { final Vector3 transformed = transform(xx, yy, zz); return position .getWorld() .getBlockMaterial( transformed.getFloorX(), transformed.getFloorY(), transformed.getFloorZ()); }
@Override public int hashCode() { int hash = 5; hash = 89 * hash + (min != null ? min.hashCode() : 0); hash = 89 * hash + (max != null ? max.hashCode() : 0); return hash; }
@Override public BoundingBox getBoundingBox() { final Vector3 rotatedMin = transform(0, 0, 0); final Vector3 rotatedMax = transform(4, 4, 4); return new BoundingBox( Vector3.min(rotatedMin, rotatedMax), Vector3.max(rotatedMin, rotatedMax)); }
/** * Gets the collision point between two BoundingBoxes. * * @param a * @param b * @return */ public static Vector3 getCollision(BoundingBox a, BoundingBox b) { BoundingBox intersection = getIntersection(a, b); if (intersection == null) { return null; } Vector3 ret = new Vector3(intersection.min); ret.add(intersection.max); ret.multiply(0.5f); return ret; }
@Override public boolean commitCuboid(CuboidBlockMaterialBuffer buffer, Cause<?> cause) { Vector3 base = buffer.getBase(); int x = base.getFloorX(); int y = base.getFloorY(); int z = base.getFloorZ(); SpoutChunk[][][] chunks = getChunks(x, y, z, buffer); return commitCuboid(chunks, buffer, cause); }
public BlockFaces(BlockFace... blockfaces) { this.faces = blockfaces; byte mask = 0; Vector3 offsetc = new Vector3(); for (BlockFace face : this.faces) { offsetc = offsetc.add(face.getOffset()); mask |= face.getMask(); } offset = offsetc; this.mask = mask; }
private static byte getOffsetHash(Vector3 offset) { offset = offset.normalize(); offset = offset.round(); int x = offset.getFloorX(); int y = offset.getFloorY(); int z = offset.getFloorZ(); x += 1; y += 1; z += 1; return (byte) (x | y << 2 | z << 4); }
/** * Checks collision between a BoundingSphere and a Ray. * * @param a * @param b * @return */ public static boolean checkCollision(BoundingSphere a, Ray b) { Vector3 m = b.origin.subtract(a.center); float e = m.dot(b.direction); float f = (float) (m.dot(m) - a.radius * a.radius); // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) if (f > 0.0f && e > 0.0f) { return false; } float discr = e * e - f; // A negative discriminant corresponds to ray missing sphere if (discr < 0.0f) { return false; } // Ray now found to intersect sphere return true; }
@Override public void setAttachedFace(Block block, BlockFace attachedFace) { if (attachedFace == BlockFace.BOTTOM) { Source source = block.getSource(); short data = 0; if (source instanceof Entity) { Vector3 direction = block.getPosition().subtract(((Entity) source).getTransform().getPosition()); float rotation = direction.rotationTo(Vector3.RIGHT).getYaw(); rotation = rotation / 360f * 16f; data = (short) rotation; } block.setMaterial(VanillaMaterials.SIGN_POST, data).queueUpdate(EffectRange.THIS); } else { // get the data for this face short data = (short) (BlockFaces.NSWE.indexOf(attachedFace, 0) + 2); block.setMaterial(VanillaMaterials.WALL_SIGN, data).queueUpdate(EffectRange.THIS); } }
@Override public void queueChunkForGeneration(final Vector3 chunk) { final int rx = (chunk.getFloorX() >> Region.CHUNKS.BITS); final int ry = (chunk.getFloorY() >> Region.CHUNKS.BITS); final int rz = (chunk.getFloorZ() >> Region.CHUNKS.BITS); SpoutRegion region = getRegion(rx, ry, rz, LoadOption.NO_LOAD); if (region != null) { region.queueChunkForGeneration(chunk); } else { Spout.getScheduler() .scheduleSyncDelayedTask( this, new Runnable() { @Override public void run() { SpoutRegion region = getRegion(rx, ry, rz, LoadOption.LOAD_GEN); region.queueChunkForGeneration(chunk); } }); } }
private SpoutChunk[][][] getChunks(int x, int y, int z, CuboidBlockMaterialBuffer buffer) { Vector3 size = buffer.getSize(); int startX = x; int startY = y; int startZ = z; int endX = x + size.getFloorX(); int endY = y + size.getFloorY(); int endZ = z + size.getFloorZ(); Chunk start = getChunkFromBlock(startX, startY, startZ); Chunk end = getChunkFromBlock(endX - 1, endY - 1, endZ - 1); int chunkStartX = start.getX(); int chunkStartY = start.getY(); int chunkStartZ = start.getZ(); int chunkEndX = end.getX(); int chunkEndY = end.getY(); int chunkEndZ = end.getZ(); int chunkSizeX = chunkEndX - chunkStartX + 1; int chunkSizeY = chunkEndY - chunkStartY + 1; int chunkSizeZ = chunkEndZ - chunkStartZ + 1; SpoutChunk[][][] chunks = new SpoutChunk[chunkSizeX][chunkSizeY][chunkSizeZ]; for (int dx = chunkStartX; dx <= chunkEndX; dx++) { for (int dy = chunkStartY; dy <= chunkEndY; dy++) { for (int dz = chunkStartZ; dz <= chunkEndZ; dz++) { SpoutChunk chunk = getChunk(dx, dy, dz, LoadOption.LOAD_GEN); if (chunk == null) { throw new IllegalStateException("Null chunk loaded with LoadOption.LOAD_GEN"); } chunks[dx - chunkStartX][dy - chunkStartY][dz - chunkStartZ] = chunk; } } } return chunks; }
protected boolean commitCuboid( SpoutChunk[][][] chunks, CuboidBlockMaterialBuffer buffer, Cause<?> cause) { Vector3 base = buffer.getBase(); int x = base.getFloorX(); int y = base.getFloorY(); int z = base.getFloorZ(); lockChunks(chunks); try { for (int dx = 0; dx < chunks.length; dx++) { SpoutChunk[][] subArray1 = chunks[dx]; for (int dy = 0; dy < subArray1.length; dy++) { SpoutChunk[] subArray2 = subArray1[dy]; for (int dz = 0; dz < subArray2.length; dz++) { if (!subArray2[dz].testCuboid(x, y, z, buffer)) { return false; } } } } // set for (int dx = 0; dx < chunks.length; dx++) { SpoutChunk[][] subArray1 = chunks[dx]; for (int dy = 0; dy < subArray1.length; dy++) { SpoutChunk[] subArray2 = subArray1[dy]; for (int dz = 0; dz < subArray2.length; dz++) { subArray2[dz].setCuboid(x, y, z, buffer, cause); } } } return true; } finally { unlockChunks(chunks); } }
@Override public Point[] generatePoints(Point center, int number) { float angle = 0; float distance = 1; Point[] points = new Point[number]; points[0] = center; for (int i = 1; i < number; i++) { distance = (float) Math.sqrt(i); Vector3 offset = Point.FORWARD.transform(MathHelper.rotateY(angle)); offset = offset.multiply(distance).multiply(scaleRadius); points[i] = center.add(offset); angle += scaleCircumference * 360.0 / (Math.PI * distance); } return points; }
public void placeObject(int xx, int yy, int zz, WorldGeneratorObject object) { final Vector3 transformed = transform(xx, yy, zz); if (object.canPlaceObject( position.getWorld(), transformed.getFloorX(), transformed.getFloorY(), transformed.getFloorZ())) { object.placeObject( position.getWorld(), transformed.getFloorX(), transformed.getFloorY(), transformed.getFloorZ()); } }
/** * Checks the collision between a BoundingSphere and a Segment. * * @param a * @param b * @return */ public static boolean checkCollision(BoundingSphere a, Segment b) { Vector3 m = b.origin.subtract(a.center); Vector3 l = b.endpoint.subtract(b.origin); float lnorm = l.fastLength(); Vector3 d = l.multiply(1f / lnorm); float e = m.dot(d); float f = (float) (m.dot(m) - a.radius * a.radius); // Exit if r’s origin outside s (c > 0) and r pointing away from s (b > 0) if (f > 0.0f && e > 0.0f) { return false; } float discr = e * e - f; // A negative discriminant corresponds to ray missing sphere if (discr < 0.0f) { return false; } // Check that the intersection is not past the segment return -e - MathHelper.sqrt(discr) <= lnorm; }
public EntityVelocityMessage(int id, Vector3 velocity) { this(id, (int) velocity.getX(), (int) velocity.getY(), (int) velocity.getZ()); }
public float distance(Vector3 b) { return b.subtract(point).dot(normal); }
public static Plane fromTwoVectors(Vector3 a, Vector3 b) { return new Plane(a, a.cross(b)); }
/** * Updates the list of chunks around the player. * * @param force Forces the update * @return True if the list was changed */ public boolean updateNearbyChunkMeshes(boolean force) { if (world == null) { world = client.getDefaultWorld(); if (world != null) System.out.println("World updated to " + world.getName() + "-" + world.getUID()); } if (world == null) { try { Thread.sleep(5); } catch (InterruptedException e) { } return false; } int chunkViewDistance = client.getActivePlayer().getViewDistance() / 16; Point currentPos = client.getActivePlayer().getTransform().getPosition(); int currentChunkX = currentPos.getChunkX(); int currentChunkY = currentPos.getChunkY(); int currentChunkZ = currentPos.getChunkZ(); if (currentChunkX == lastChunkX && currentChunkY == lastChunkY && currentChunkZ == lastChunkZ && !force && !firstUpdate) { return false; } // just add all visible chunks if (chunkRenderers.size() == 0 || force) { chunkRenderers.clear(); int cubeMinX = currentChunkX - chunkViewDistance; int cubeMinY = currentChunkY - chunkViewDistance; int cubeMinZ = currentChunkZ - chunkViewDistance; int cubeMaxX = currentChunkX + chunkViewDistance; int cubeMaxY = currentChunkY + chunkViewDistance; int cubeMaxZ = currentChunkZ + chunkViewDistance; Vector3 batchMin = ChunkMeshBatch.getBatchCoordinates(new Vector3(cubeMinX, cubeMinY, cubeMinZ)); Vector3 batchMax = ChunkMeshBatch.getBatchCoordinates(new Vector3(cubeMaxX, cubeMaxY, cubeMaxZ)); for (int x = batchMin.getFloorX(); x <= batchMax.getFloorX(); x++) { for (int y = batchMin.getFloorY(); y <= batchMax.getFloorY(); y++) { for (int z = batchMin.getFloorZ(); z <= batchMax.getFloorZ(); z++) { Vector3 chunkCoords = ChunkMeshBatch.getChunkCoordinates(new Vector3(x, y, z)); ChunkMeshBatch batch = new ChunkMeshBatch( material, world, chunkCoords.getFloorX(), chunkCoords.getFloorY(), chunkCoords.getFloorZ()); addChunkMeshBatch(batch); batch.update(); System.out.println(batch); } } } } else { Cube oldView = new Cube( new Point( world, lastChunkX - chunkViewDistance, lastChunkY - chunkViewDistance, lastChunkZ - chunkViewDistance), chunkViewDistance * 2); Cube newView = new Cube( new Point( world, currentChunkX - chunkViewDistance, currentChunkY - chunkViewDistance, currentChunkZ - chunkViewDistance), chunkViewDistance * 2); Vector3 min = oldView.getBase().min(newView.getBase()); Vector3 max = oldView.getBase().add(oldView.getSize()).max(newView.getBase().add(newView.getSize())); // Shared area Vector3 ignoreMin = oldView.getBase().max(newView.getBase()); Vector3 ignoreMax = oldView.getBase().add(oldView.getSize()).min(newView.getBase().add(newView.getSize())); Cuboid ignore = new Cuboid(new Point(ignoreMin, world), ignoreMax.subtract(ignoreMin)); for (int x = min.getFloorX(); x < max.getFloorX(); x++) { for (int y = min.getFloorY(); y < max.getFloorY(); y++) { for (int z = min.getFloorZ(); z < max.getFloorZ(); z++) { Vector3 vec = new Vector3(x, y, z); if (ignore.contains(vec)) { continue; } Vector3 pos = ChunkMeshBatch.getChunkCoordinates(vec); if (oldView.contains(vec)) { ChunkMeshBatch c = chunkRenderersByPosition.get(pos.getFloorX(), pos.getFloorY(), pos.getFloorZ()); removeChunkMeshBatch(c); continue; } if (newView.contains(vec)) { ChunkMeshBatch c = new ChunkMeshBatch( material, world, pos.getFloorX(), pos.getFloorY(), pos.getFloorZ()); addChunkMeshBatch(c); c.update(); } } } } } firstUpdate = false; lastChunkX = currentChunkX; lastChunkY = currentChunkY; lastChunkZ = currentChunkZ; return true; }
@Override public SpoutChunk getChunkFromBlock(Vector3 position, LoadOption loadopt) { return this.getChunkFromBlock( position.getFloorX(), position.getFloorY(), position.getFloorZ(), loadopt); }
@Override public SpoutBlock getBlock(Vector3 position) { return this.getBlock(position.getX(), position.getY(), position.getZ()); }
/** Called when the tick is finished and collisions need to be resolved and move events fired */ public void resolve() { if (Spout.debugMode()) { // System.out.println("COLLISION DEBUGGING"); // System.out.println("Current Collision: " + this.collision.toString()); } List<CollisionVolume> colliding = ((SpoutWorld) collisionPoint.getWorld()).getCollidingObject(this.collision); Vector3 offset = this.lastTransform.getPosition().subtract(collisionPoint); for (CollisionVolume box : colliding) { if (Spout.debugMode()) { // System.out.println("Colliding box: " + box.toString()); } Vector3 collision = this.collision.resolve(box); if (Spout.debugMode()) { // System.out.println("Collision vector: " + collision.toString()); } if (collision != null) { collision = collision.subtract(collisionPoint); if (Spout.debugMode()) { // System.out.println("Collision point: " + collision.toString() + " Collision vector: " + // collision); } if (collision.getX() != 0F) { offset = new Vector3(collision.getX(), offset.getY(), offset.getZ()); } if (collision.getY() != 0F) { offset = new Vector3(offset.getX(), collision.getY(), offset.getZ()); } if (collision.getZ() != 0F) { offset = new Vector3(offset.getX(), offset.getY(), collision.getZ()); } if (Spout.debugMode()) { // System.out.println("Collision offset: " + offset.toString()); } if (this.getCollision().getStrategy() == CollisionStrategy.SOLID && box.getStrategy() == CollisionStrategy.SOLID) { this.setPosition(collisionPoint.add(offset)); if (Spout.debugMode()) { // System.out.println("New Position: " + this.getPosition()); } } controllerLive.get().onCollide(getWorld().getBlock(box.getPosition())); } } // Check to see if we should fire off a Move event }
@Override public void getCuboid(CuboidBlockMaterialBuffer buffer) { Vector3 base = buffer.getBase(); getCuboid(base.getFloorX(), base.getFloorY(), base.getFloorZ(), buffer); }
/** * Checks if a bounding box and a line segment collide. Based off of * people.csail.mit.edu/amy/papers/box-jgt.ps * * <p>There must be a better way to do this. * * @param a * @param b * @return */ public static boolean checkCollision(BoundingBox a, Segment b) { Vector3 box = a.max.subtract(a.min); Vector3 seg = b.endpoint.subtract(b.origin); Vector3 m = b.origin.add(b.endpoint).subtract(a.max).subtract(a.min); // Try world coordinate axes as separating axes float adx = Math.abs(seg.getX()); if (Math.abs(m.getX()) > box.getX() + adx) { return false; } float ady = Math.abs(seg.getY()); if (Math.abs(m.getY()) > box.getY() + ady) { return false; } float adz = Math.abs(seg.getZ()); if (Math.abs(m.getZ()) > box.getZ() + adz) { return false; } // Add in an epsilon term to counteract arithmetic errors when segment is // (near) parallel to a coordinate axis (see text for detail) adx += MathHelper.FLT_EPSILON; ady += MathHelper.FLT_EPSILON; adz += MathHelper.FLT_EPSILON; // Try cross products of segment direction vector with coordinate axes if (Math.abs(m.getY() * seg.getZ() - m.getZ() * seg.getY()) > box.getY() * adz + box.getZ() * ady) { return false; } if (Math.abs(m.getZ() * seg.getX() - m.getX() * seg.getZ()) > box.getX() * adz + box.getZ() * adx) { return false; } if (Math.abs(m.getX() * seg.getY() - m.getY() * seg.getX()) > box.getX() * ady + box.getY() * adx) { return false; } // No separating axis found; segment must be overlapping AABB return true; }
public ExplosionMessage(Vector3 position, float radius, byte[] coordinates) { this(position.getX(), position.getY(), position.getZ(), radius, coordinates); }
@Override public Block translate(Vector3 offset) { return this.translate((int) offset.getX(), (int) offset.getY(), (int) offset.getZ()); }
public static Vector3 getProtocolVelocity(Vector3 velocity) { final float x = velocity.getX() * 32000; final float y = velocity.getY() * 32000; final float z = velocity.getZ() * 32000; return new Vector3(x, y, z); }
@Override public void setCuboid(CuboidBlockMaterialBuffer buffer, Cause<?> cause) { Vector3 base = buffer.getBase(); setCuboid(base.getFloorX(), base.getFloorY(), base.getFloorZ(), buffer, cause); }