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 dado Vector3d
  • 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 BlockRayHits, 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());
}