More efficient ellipsoid placement

This commit is contained in:
DBotThePony 2025-03-25 12:14:11 +07:00
parent f74dbbd84a
commit d683ea1e38
Signed by: DBot
GPG Key ID: DCC23B5715498507

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.worldgen.placement
import com.mojang.serialization.MapCodec import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.ObjectRBTreeSet
import net.minecraft.core.BlockPos import net.minecraft.core.BlockPos
import net.minecraft.util.RandomSource import net.minecraft.util.RandomSource
import net.minecraft.util.valueproviders.FloatProvider import net.minecraft.util.valueproviders.FloatProvider
@ -9,16 +10,10 @@ import net.minecraft.util.valueproviders.IntProvider
import net.minecraft.world.level.levelgen.placement.PlacementContext import net.minecraft.world.level.levelgen.placement.PlacementContext
import net.minecraft.world.level.levelgen.placement.PlacementModifier import net.minecraft.world.level.levelgen.placement.PlacementModifier
import net.minecraft.world.level.levelgen.placement.PlacementModifierType import net.minecraft.world.level.levelgen.placement.PlacementModifierType
import ru.dbotthepony.mc.otm.core.math.component1 import ru.dbotthepony.mc.otm.core.collect.Vec3iHashStrategy
import ru.dbotthepony.mc.otm.core.math.component2
import ru.dbotthepony.mc.otm.core.math.component3
import ru.dbotthepony.mc.otm.core.math.minus
import ru.dbotthepony.mc.otm.core.math.plus
import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers import ru.dbotthepony.mc.otm.registry.data.MPlacementModifiers
import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext import ru.dbotthepony.mc.otm.worldgen.EnhancedPlacementContext
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.math.PI
import kotlin.math.roundToInt
/** /**
* Ellipsoid ("cloud") placement * Ellipsoid ("cloud") placement
@ -65,11 +60,12 @@ data class EllipsoidPlacement(
require(yLength.minValue >= 1f) { "Bad ellipsoid y minimal size: $yLength" } require(yLength.minValue >= 1f) { "Bad ellipsoid y minimal size: $yLength" }
} }
private fun evaluate(random: RandomSource, position: BlockPos, result: ArrayList<BlockPos>) { private fun evaluate(random: RandomSource, position: BlockPos): ObjectRBTreeSet<BlockPos> {
val count = count.sample(random) val count = count.sample(random)
val results = ObjectRBTreeSet<BlockPos>(Vec3iHashStrategy)
if (count <= 0) if (count <= 0)
return return results
val xLength = xLength.sample(random) val xLength = xLength.sample(random)
val zLength = zLength.sample(random) val zLength = zLength.sample(random)
@ -79,26 +75,24 @@ data class EllipsoidPlacement(
val zPow = zLength * zLength val zPow = zLength * zLength
val yPow = yLength * yLength val yPow = yLength * yLength
result.ensureCapacity(result.size + count + 1) var iterations = 0
val maxIterations = count * 10
Stream.generate { while (results.size < count && ++iterations < maxIterations) {
val x = this.x.sample(random) * xLength val x = this.x.sample(random) * xLength
val y = this.y.sample(random) * yLength val y = this.y.sample(random) * yLength
val z = this.z.sample(random) * zLength val z = this.z.sample(random) * zLength
BlockPos(x.toInt(), y.toInt(), z.toInt())
}
.limit(count.toLong() * 10)
.filter {
val (ellipsoidX, ellipsoidY, ellipsoidZ) = it
(ellipsoidX * ellipsoidX) / xPow + val isValidPoint = (x * x) / xPow +
(ellipsoidY * ellipsoidY) / yPow + (y * y) / yPow +
(ellipsoidZ * ellipsoidZ) / zPow <= 1.0f (z * z) / zPow <= 1.0f
if (isValidPoint) {
results.add(BlockPos(x.toInt() + position.x, y.toInt() + position.y, z.toInt() + position.z))
} }
.distinct() }
.limit(count.toLong())
.map { it + position } return results
.forEach { result.add(it) }
} }
override fun getPositions( override fun getPositions(
@ -106,14 +100,14 @@ data class EllipsoidPlacement(
random: RandomSource, random: RandomSource,
position: BlockPos position: BlockPos
): Stream<BlockPos> { ): Stream<BlockPos> {
val result = ArrayList<BlockPos>() return evaluate(random, position).stream()
evaluate(random, position, result)
return result.stream()
} }
override fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos> { override fun evaluate(context: EnhancedPlacementContext, positions: List<BlockPos>): List<BlockPos> {
val result = ArrayList<BlockPos>() val result = ArrayList<BlockPos>()
positions.forEach { evaluate(context.random, it, result) } val results = positions.map { evaluate(context.random, it) }
result.ensureCapacity(result.size + results.sumOf { it.size } + 1)
results.forEach { result.addAll(it) }
return result return result
} }