Trazado de Rayos (Ray Tracing)
Genéricamente, el trazado de rayos es un método para determinar el camino de una partícula a través de un sistema de coordenadas. En SpongeAPI, esto se implementa con la clase :javadoc: BlockRay para descubrir bloques en la ruta de una línea arbitraria en el espacio. Un caso de uso común podría ser encontrar el bloque que está mirando a :javadoc: Player.
Puede especificar el origen del rayo utilizando el método BlockRay # from
, pasando ya sea a :javadoc: Location, una :javadoc:`Extensión` y Vector3d
, o una :javadoc:`Entidad`. El método devolverá a BlockRay.BlockRayBuilder.
Truco
Si especifica que el origen del rayo es una Entidad
, la dirección predeterminada será la dirección a la que apunta Entidad
.
Para especificar el punto final, puede usar el método BlockRay.BlockRayBuilder#to(Vector3d), que establecerá tanto la dirección como la ubicación final. Alternativamente, puede especificar una dirección usando BlockRay.BlockRayBuilder#direction(Vector3d) y también un límite de bloque usando BlockRay.BlockRayBuilder#blockLimit(int).
Nota
El límite de bloque predeterminado es de 1000 bloques como medida de seguridad para evitar la iteración infinita. Para desactivar el límite de bloque, use un valor negativo con BlockRayBuilder#blockLimit(int)
.
Filtración
Los filtros determinan qué bloques son aceptados por BlockRay
. Para agregar un filtro, use el método BlockRayBuilder#filter
, pasando uno o muchos Predicate<BlockRayHit<E >>
s (donde `` E`` se extiende Extent
). Para mayor comodidad, BlockRay
contiene los siguientes métodos para casos comunes de uso de filtros:
allFilter
: devuelve un filtro que acepta todos los bloques
onlyAirFilter
: devuelve un filtro que acepta solo aire
blockTypeFilter(BlockType)
: devuelve un filtro que acepta solo lo especificado :javadoc: BlockType
maxDistanceFilter(Vector3d, double)
: devuelve un filtro que se detiene a cierta distancia del dadoVector3d
continueAfterFilter(Predicate<BlockRayHit<E >>, int)
: devuelve un filtro que continúa más allá del filtro dado por el número especificado de bloques.
Por supuesto, también puede escribir su propio filtro Predicate<BlockRayHit<E>>
.
Finalmente, use BlockRay.BlockRayBuilder#build() para terminar de construir el BlockRay
. Un ejemplo de uso de BlockRayBuilder
para obtener el primer bloque no aéreo que se ve en Player
se proporciona a continuación.
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.util.blockray.BlockRay;
import org.spongepowered.api.world.World;
Player player;
BlockRay<World> blockRay = BlockRay.from(player)
.filter(BlockRay.continueAfterFilter(BlockRay.onlyAirFilter(), 1)).build();
Usando BlockRay
Como BlockRay
implementa Iterator
, puedes usar métodos como hasNext
y next
(pero no remove
) para iterar a través de BlockRayHits generados por el BlockRay
. Además, puede usar el método BlockRay#reset() para restablecer el iterador a la ubicación de inicio. En lugar de iterar a través del BlockRayHit
s, también puede usar el método BlockRay#end() para rastrear el bloque de rayos hasta el final de su ruta para obtener el último bloque aceptado por el filtro (o ninguno si se alcanzó el límite de bloque).
Usando BlockRayHit
BlockRayHit
contiene información sobre cada bloque intersectado por el rayo. Contiene la ubicación del bloque, la dirección del rayo, las coordenadas de la intersección del rayo y el bloque, y otros datos similares. El siguiente código usa BlockRay
del ejemplo anterior para imprimir la ubicación del primer bloque no aéreo delante del jugador.
import org.spongepowered.api.util.blockray.BlockRayHit;
import java.util.Optional;
BlockRay<World> blockRay;
Optional<BlockRayHit<World>> hitOpt = blockRay.end();
if (hitOpt.isPresent()) {
BlockRayHit<World> hit = hitOpt.get();
System.out.println("Found " + hit.getLocation().getBlockType() + " block at "
+ hit.getLocation() + " with intersection at " + hit.getPosition());
}