Add ellipsoid placement rotation
This commit is contained in:
parent
9cfbab6c3c
commit
ac1c9a1ad4
@ -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()
|
||||||
)
|
)
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user