public BlockSelection GetSelectedBlock(float maxDistance, BlockFilter filter = null) { float distanceSq = 0; // Get the face where our ray will exit BlockFacing lastExitedBlockFace = GetExitingFullBlockFace(pos, ref lastExitedBlockFacePos); if (lastExitedBlockFace == null) { return(null); } float maxDistanceSq = (maxDistance + 1) * (maxDistance + 1); // Wander along the block exiting faces until we collide with a block selection box while (!RayIntersectsBlockSelectionBox(pos, filter)) { if (distanceSq >= maxDistanceSq) { return(null); } pos.Offset(lastExitedBlockFace); lastExitedBlockFace = GetExitingFullBlockFace(pos, ref lastExitedBlockFacePos); if (lastExitedBlockFace == null) { return(null); } distanceSq = pos.DistanceSqTo(ray.origin.X - 0.5f, ray.origin.Y - 0.5f, ray.origin.Z - 0.5f); } if (hitPosition.SquareDistanceTo(ray.origin) > maxDistance * maxDistance) { return(null); } return(new BlockSelection() { Face = hitOnBlockFace, Position = pos.Copy(), HitPosition = hitPosition.SubCopy(pos.X, pos.Y, pos.Z), SelectionBoxIndex = hitOnSelectionBox }); }
public bool RayIntersectsBlockSelectionBox(BlockPos pos, BlockFilter filter) { if (filter?.Invoke(pos, blockSelectionTester.GetBlock(pos)) == false) { return(false); } Cuboidf[] selectionBoxes = blockSelectionTester.GetBlockIntersectionBoxes(pos); if (selectionBoxes == null) { return(false); } bool intersects = false; for (int i = 0; i < selectionBoxes.Length; i++) { tmpCuboidd.Set(selectionBoxes[i]).Translate(pos.X, pos.Y, pos.Z); if (RayIntersectsWithCuboid(tmpCuboidd, ref hitOnBlockFaceTmp, ref hitPositionTmp)) { if (intersects && hitPosition.SquareDistanceTo(ray.origin) <= hitPositionTmp.SquareDistanceTo(ray.origin)) { continue; } hitOnSelectionBox = i; intersects = true; hitOnBlockFace = hitOnBlockFaceTmp; hitPosition.Set(hitPositionTmp); } } return(intersects); }
public bool RayIntersectsBlockSelectionBox(BlockPos pos, BlockFilter filter) { if (filter?.Invoke(pos, blockSelectionTester.GetBlock(pos)) == false) { return(false); } Cuboidf[] selectionBoxes = blockSelectionTester.GetBlockIntersectionBoxes(pos); if (selectionBoxes == null) { return(false); } bool intersects = false; bool wasDecor = false; for (int i = 0; i < selectionBoxes.Length; i++) { tmpCuboidd.Set(selectionBoxes[i]).Translate(pos.X, pos.Y, pos.Z); if (RayIntersectsWithCuboid(tmpCuboidd, ref hitOnBlockFaceTmp, ref hitPositionTmp)) { bool isDecor = selectionBoxes[i] is DecorSelectionBox; if (intersects && (!wasDecor || isDecor) && hitPosition.SquareDistanceTo(ray.origin) <= hitPositionTmp.SquareDistanceTo(ray.origin)) { continue; } hitOnSelectionBox = i; intersects = true; wasDecor = isDecor; hitOnBlockFace = hitOnBlockFaceTmp; hitPosition.Set(hitPositionTmp); } } if (intersects && selectionBoxes[hitOnSelectionBox] is DecorSelectionBox dsb) { Vec3i posAdjust = dsb.PosAdjust; if (posAdjust != null) { pos.Add(posAdjust); } } return(intersects); }