Add ellipsoid placement rotation

This commit is contained in:
DBotThePony 2025-03-30 15:13:56 +07:00
parent 9cfbab6c3c
commit ac1c9a1ad4
Signed by: DBot
GPG Key ID: DCC23B5715498507
3 changed files with 73 additions and 1 deletions

View File

@ -208,6 +208,7 @@ fun registerPlacedFeatures(context: BootstrapContext<PlacedFeature>) {
xLength = UniformFloat.of(30f, 70f), xLength = UniformFloat.of(30f, 70f),
yLength = UniformFloat.of(40f, 90f), yLength = UniformFloat.of(40f, 90f),
zLength = UniformFloat.of(30f, 70f), zLength = UniformFloat.of(30f, 70f),
rotateXZ = BooleanProvider.AlwaysTrue,
), ),
ore.placement() ore.placement()
) )

View File

@ -8,9 +8,11 @@ import net.minecraft.core.Direction
import net.minecraft.core.Vec3i import net.minecraft.core.Vec3i
import net.minecraft.world.level.ChunkPos import net.minecraft.world.level.ChunkPos
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import org.joml.AxisAngle4d
import org.joml.AxisAngle4f import org.joml.AxisAngle4f
import org.joml.Matrix3f import org.joml.Matrix3f
import org.joml.Matrix4f import org.joml.Matrix4f
import org.joml.Quaterniond
import org.joml.Quaternionf import org.joml.Quaternionf
import org.joml.Vector3f import org.joml.Vector3f
import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.filter
@ -25,10 +27,14 @@ typealias Vector = Vec3
val VECTOR_UP = Vector(0.0, 1.0, 0.0) val VECTOR_UP = Vector(0.0, 1.0, 0.0)
val VECTOR_FORWARD = Vector(1.0, 0.0, 0.0) val VECTOR_FORWARD = Vector(1.0, 0.0, 0.0)
val VECTOR_POSITIVE_X = VECTOR_FORWARD
val VECTOR_BACKWARD = Vector(-1.0, 0.0, 0.0) val VECTOR_BACKWARD = Vector(-1.0, 0.0, 0.0)
val VECTOR_NEGATIVE_X = VECTOR_BACKWARD
val VECTOR_DOWN = Vector(0.0, -1.0, 0.0) val VECTOR_DOWN = Vector(0.0, -1.0, 0.0)
val VECTOR_RIGHT = Vector(0.0, 0.0, 1.0) val VECTOR_RIGHT = Vector(0.0, 0.0, 1.0)
val VECTOR_POSITIVE_Z = VECTOR_RIGHT
val VECTOR_LEFT = Vector(0.0, 0.0, -1.0) val VECTOR_LEFT = Vector(0.0, 0.0, -1.0)
val VECTOR_NEGATIVE_Z = VECTOR_LEFT
private const val DEGREES_TO_RADIANS = 0.017453292f private const val DEGREES_TO_RADIANS = 0.017453292f
@ -36,6 +42,10 @@ fun toRadians(angle: Float): Float {
return angle * DEGREES_TO_RADIANS return angle * DEGREES_TO_RADIANS
} }
fun toRadians(angle: Double): Double {
return Math.toRadians(angle)
}
fun Vector.asAngle(): Angle { fun Vector.asAngle(): Angle {
val norm = normalize() val norm = normalize()
return Angle(asin(norm.y), atan2(norm.x, norm.z)) return Angle(asin(norm.y), atan2(norm.x, norm.z))
@ -173,16 +183,36 @@ fun Vector.rotate(q: Quaternionf): Vector {
return Vector(quaternion.x.toDouble(), quaternion.y.toDouble(), quaternion.z.toDouble()) return Vector(quaternion.x.toDouble(), quaternion.y.toDouble(), quaternion.z.toDouble())
} }
fun Vector.rotate(q: Quaterniond): Vector {
// TODO: 1.19.3
val quaternion = Quaterniond(q)
quaternion.mul(rotateAroundThisDouble())
val quaternion1 = Quaterniond(q)
quaternion1.conjugate()
quaternion.mul(quaternion1)
return Vector(quaternion.x, quaternion.y, quaternion.z)
}
fun Vector.rotateAroundThis(rotation: Float, isDegrees: Boolean = false): Quaternionf { fun Vector.rotateAroundThis(rotation: Float, isDegrees: Boolean = false): Quaternionf {
// TODO: 1.19.3 // TODO: 1.19.3
return Quaternionf(AxisAngle4f(if (isDegrees) toRadians(rotation) else rotation, x.toFloat(), y.toFloat(), z.toFloat())) return Quaternionf(AxisAngle4f(if (isDegrees) toRadians(rotation) else rotation, x.toFloat(), y.toFloat(), z.toFloat()))
} }
fun Vector.rotateAroundThis(rotation: Double, isDegrees: Boolean = false): Quaterniond {
// TODO: 1.19.3
return Quaterniond(AxisAngle4d(if (isDegrees) toRadians(rotation) else rotation, x, y, z))
}
fun Vector.rotateAroundThis(): Quaternionf { fun Vector.rotateAroundThis(): Quaternionf {
// TODO: 1.19.3 // TODO: 1.19.3
return Quaternionf(AxisAngle4f(0f, x.toFloat(), y.toFloat(), z.toFloat())) return Quaternionf(AxisAngle4f(0f, x.toFloat(), y.toFloat(), z.toFloat()))
} }
fun Vector.rotateAroundThisDouble(): Quaterniond {
// TODO: 1.19.3
return Quaterniond(AxisAngle4d(0.0, x, y, z))
}
fun Vector.asMatrix(): Matrix3f { fun Vector.asMatrix(): Matrix3f {
return Matrix3f().also { return Matrix3f().also {
it[0, 0] = x.toFloat() it[0, 0] = x.toFloat()

View File

@ -4,17 +4,29 @@ import com.mojang.serialization.MapCodec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
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.ConstantFloat
import net.minecraft.util.valueproviders.FloatProvider import net.minecraft.util.valueproviders.FloatProvider
import net.minecraft.util.valueproviders.IntProvider import net.minecraft.util.valueproviders.IntProvider
import net.minecraft.util.valueproviders.UniformFloat
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.collect.Vec3iHashStrategy import ru.dbotthepony.mc.otm.core.collect.Vec3iHashStrategy
import ru.dbotthepony.mc.otm.core.math.VECTOR_POSITIVE_X
import ru.dbotthepony.mc.otm.core.math.VECTOR_POSITIVE_Z
import ru.dbotthepony.mc.otm.core.math.VECTOR_RIGHT
import ru.dbotthepony.mc.otm.core.math.VECTOR_UP
import ru.dbotthepony.mc.otm.core.math.Vector
import ru.dbotthepony.mc.otm.core.math.rotate
import ru.dbotthepony.mc.otm.core.math.rotateAroundThis
import ru.dbotthepony.mc.otm.core.nextDouble
import ru.dbotthepony.mc.otm.data.world.BooleanProvider
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 ru.dbotthepony.mc.otm.worldgen.PlacementPos import ru.dbotthepony.mc.otm.worldgen.PlacementPos
import java.util.* import java.util.*
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.math.PI
/** /**
* Ellipsoid ("cloud") placement * Ellipsoid ("cloud") placement
@ -54,6 +66,10 @@ data class EllipsoidPlacement(
* Ellipsoid size sampler on Y axis * Ellipsoid size sampler on Y axis
*/ */
val yLength: FloatProvider, val yLength: FloatProvider,
val rotateXZ: BooleanProvider = BooleanProvider.AlwaysFalse,
val rotateXY: FloatProvider = ConstantFloat.ZERO,
val rotateZY: FloatProvider = ConstantFloat.ZERO,
) : PlacementModifier(), EnhancedPlacement { ) : PlacementModifier(), EnhancedPlacement {
init { init {
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" } require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
@ -79,6 +95,22 @@ data class EllipsoidPlacement(
var iterations = 0 var iterations = 0
val maxIterations = count * 10 val maxIterations = count * 10
val rotateXZ = rotateXZ.instance().sample(random)
val rotateXY = rotateXY.sample(random)
val rotateZY = rotateZY.sample(random)
val rotationXZ: Double
if (rotateXZ) {
rotationXZ = random.nextDouble(-PI, PI)
} else {
rotationXZ = 0.0
}
val qXZ = VECTOR_UP.rotateAroundThis(rotationXZ)
val qXY = VECTOR_POSITIVE_Z.rotateAroundThis(rotateXY)
val qZY = VECTOR_POSITIVE_X.rotateAroundThis(rotateZY)
while (results.size < count && ++iterations < maxIterations) { 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
@ -89,7 +121,13 @@ data class EllipsoidPlacement(
(z * z) / zPow <= 1.0f (z * z) / zPow <= 1.0f
if (isValidPoint) { if (isValidPoint) {
results.add(BlockPos(x.toInt() + position.x, y.toInt() + position.y, z.toInt() + position.z)) var point = Vector(x.toDouble(), y.toDouble(), z.toDouble())
point = point.rotate(qXZ)
point = point.rotate(qXY)
point = point.rotate(qZY)
results.add(BlockPos(point.x.toInt() + position.x, point.y.toInt() + position.y, point.z.toInt() + position.z))
} }
} }
@ -130,6 +168,9 @@ data class EllipsoidPlacement(
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EllipsoidPlacement::xLength), FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("x_size").forGetter(EllipsoidPlacement::xLength),
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EllipsoidPlacement::zLength), FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("z_size").forGetter(EllipsoidPlacement::zLength),
FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("y_size").forGetter(EllipsoidPlacement::yLength), FloatProvider.codec(1f, Float.MAX_VALUE).fieldOf("y_size").forGetter(EllipsoidPlacement::yLength),
BooleanProvider.CODEC.optionalFieldOf("rotateXZ", BooleanProvider.AlwaysFalse).forGetter(EllipsoidPlacement::rotateXZ),
FloatProvider.CODEC.optionalFieldOf("rotateXY", ConstantFloat.ZERO).forGetter(EllipsoidPlacement::rotateXY),
FloatProvider.CODEC.optionalFieldOf("rotateZY", ConstantFloat.ZERO).forGetter(EllipsoidPlacement::rotateZY),
).apply(it, ::EllipsoidPlacement) ).apply(it, ::EllipsoidPlacement)
} }
} }