feat: ブロック円表示のライブラリ化

This commit is contained in:
Keisuke Hirata 2025-12-12 06:59:13 +09:00
parent 79aab94341
commit 637f2cdf0a
2 changed files with 64 additions and 59 deletions

View File

@ -172,61 +172,33 @@ class VisualizerTask(
}
}
val redDust = Particle.DustOptions(Color.RED, 1.0f)
drawFaceOutline(player, faceBlocks, bottomY, redDust, cylinder)
drawFaceOutline(player, faceBlocks, topY, redDust, cylinder)
}
/**
* Draws only the outer edges of a face outline (excluding inner holes).
*/
private fun drawFaceOutline(
player: Player,
faceBlocks: Set<Pair<Int, Int>>,
y: Double,
dustOptions: Particle.DustOptions,
cylinder: Shape.Cylinder
) {
// Use the cylinder's vertical center for the 'contains' check to ensure we are within Y bounds
// This effectively checks if the neighbor is outside the radius laterally
val red = Color.RED
val checkY = cylinder.y + 0.5
// For each block in the face, check which edges face outward (not toward inner holes)
for ((bx, bz) in faceBlocks) {
// Check each of the 4 edges
// An edge should be drawn if the adjacent block is NOT in the face
// AND is outside the cylinder (not an inner hole)
GeometryVisualizer.drawBlockSurfaceOutline(
player,
bottomY,
faceBlocks,
{ x, y, z -> cylinder.contains(x, y, z) },
red,
checkY
)
// Top edge (z- direction)
val topNeighbor = Pair(bx, bz - 1)
if (!faceBlocks.contains(topNeighbor) && !cylinder.contains(topNeighbor.first + 0.5, checkY, topNeighbor.second + 0.5)) {
GeometryVisualizer.drawLine(player, bx.toDouble(), y, bz.toDouble(), bx + 1.0, y, bz.toDouble(), dustOptions, 0.25)
}
// Right edge (x+ direction)
val rightNeighbor = Pair(bx + 1, bz)
if (!faceBlocks.contains(rightNeighbor) && !cylinder.contains(rightNeighbor.first + 0.5, checkY, rightNeighbor.second + 0.5)) {
GeometryVisualizer.drawLine(player, bx + 1.0, y, bz.toDouble(), bx + 1.0, y, bz + 1.0, dustOptions, 0.25)
}
// Bottom edge (z+ direction)
val bottomNeighbor = Pair(bx, bz + 1)
if (!faceBlocks.contains(bottomNeighbor) && !cylinder.contains(bottomNeighbor.first + 0.5, checkY, bottomNeighbor.second + 0.5)) {
GeometryVisualizer.drawLine(player, bx + 1.0, y, bz + 1.0, bx.toDouble(), y, bz + 1.0, dustOptions, 0.25)
}
// Left edge (x- direction)
val leftNeighbor = Pair(bx - 1, bz)
if (!faceBlocks.contains(leftNeighbor) && !cylinder.contains(leftNeighbor.first + 0.5, checkY, leftNeighbor.second + 0.5)) {
GeometryVisualizer.drawLine(player, bx.toDouble(), y, bz + 1.0, bx.toDouble(), y, bz.toDouble(), dustOptions, 0.25)
}
}
GeometryVisualizer.drawBlockSurfaceOutline(
player,
topY,
faceBlocks,
{ x, y, z -> cylinder.contains(x, y, z) },
red,
checkY
)
}
private fun createDisplayForLand(player: Player, land: net.hareworks.hcu.lands.model.Land): DisplayController<TextDisplay> {
val position = calculateBestAttachmentLocation(player, land)
val controller = displayService!!.createTextDisplay(position)

View File

@ -13,24 +13,16 @@ import kotlin.math.sqrt
object GeometryVisualizer {
fun drawCuboid(player: Player, minX: Double, minY: Double, minZ: Double, maxX: Double, maxY: Double, maxZ: Double) {
// Draw outline of min corner block (conceptually logic from original task, but generalized)
// Original task drew specific block outlines for corners. Here we just draw the box edges?
// Original:
// drawBlockOutline(player, minCorner..., Color.LIME)
// drawBlockOutline(player, maxCorner..., Color.YELLOW)
// drawLine edges...
// For generic visualizer, maybe just draw the wireframe box.
val edgeColor = Particle.DustOptions(Color.fromRGB(100, 255, 100), 0.75f)
val step = 0.5
// Bottom face edges (minY)
// Bottom face edges
drawLine(player, minX, minY, minZ, maxX, minY, minZ, edgeColor, step)
drawLine(player, maxX, minY, minZ, maxX, minY, maxZ, edgeColor, step)
drawLine(player, maxX, minY, maxZ, minX, minY, maxZ, edgeColor, step)
drawLine(player, minX, minY, maxZ, minX, minY, minZ, edgeColor, step)
// Top face edges (maxY)
// Top face edges
drawLine(player, minX, maxY, minZ, maxX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, maxY, minZ, maxX, maxY, maxZ, edgeColor, step)
drawLine(player, maxX, maxY, maxZ, minX, maxY, maxZ, edgeColor, step)
@ -44,7 +36,7 @@ object GeometryVisualizer {
}
fun drawCylinder(player: Player, centerX: Double, centerY: Double, centerZ: Double, radius: Double, minY: Double, maxY: Double) {
val actualRadius = radius // or radius + 0.5 if passed as block radius? Caller should decide.
val actualRadius = radius
val segments = 32
val step = (Math.PI * 2) / segments
@ -85,6 +77,47 @@ object GeometryVisualizer {
}
}
/**
* Draws the outline of a set of blocks that form a horizontal surface.
* Useful for visualizing the exact block-grid coverage of a shape.
*/
fun drawBlockSurfaceOutline(
player: Player,
surfaceY: Double,
blocks: Set<Pair<Int, Int>>,
predicate: (Double, Double, Double) -> Boolean,
color: Color,
checkY: Double
) {
val dustOptions = Particle.DustOptions(color, 1.0f)
for ((bx, bz) in blocks) {
// Top (Z-)
val topNeighbor = Pair(bx, bz - 1)
if (!blocks.contains(topNeighbor) && !predicate(topNeighbor.first + 0.5, checkY, topNeighbor.second + 0.5)) {
drawLine(player, bx.toDouble(), surfaceY, bz.toDouble(), bx + 1.0, surfaceY, bz.toDouble(), dustOptions, 0.25)
}
// Right (X+)
val rightNeighbor = Pair(bx + 1, bz)
if (!blocks.contains(rightNeighbor) && !predicate(rightNeighbor.first + 0.5, checkY, rightNeighbor.second + 0.5)) {
drawLine(player, bx + 1.0, surfaceY, bz.toDouble(), bx + 1.0, surfaceY, bz + 1.0, dustOptions, 0.25)
}
// Bottom (Z+)
val bottomNeighbor = Pair(bx, bz + 1)
if (!blocks.contains(bottomNeighbor) && !predicate(bottomNeighbor.first + 0.5, checkY, bottomNeighbor.second + 0.5)) {
drawLine(player, bx + 1.0, surfaceY, bz + 1.0, bx.toDouble(), surfaceY, bz + 1.0, dustOptions, 0.25)
}
// Left (X-)
val leftNeighbor = Pair(bx - 1, bz)
if (!blocks.contains(leftNeighbor) && !predicate(leftNeighbor.first + 0.5, checkY, leftNeighbor.second + 0.5)) {
drawLine(player, bx.toDouble(), surfaceY, bz + 1.0, bx.toDouble(), surfaceY, bz.toDouble(), dustOptions, 0.25)
}
}
}
fun drawBlockOutline(player: Player, x: Int, y: Int, z: Int, color: Color) {
val dustOptions = Particle.DustOptions(color, 1.0f)
val step = 0.25
@ -105,7 +138,7 @@ object GeometryVisualizer {
drawLine(player, x.toDouble(), y.toDouble(), z.toDouble(), x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z.toDouble(), x + 1.0, y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z + 1.0, x + 1.0, y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
}
fun drawLine(