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),
|
||||
yLength = UniformFloat.of(40f, 90f),
|
||||
zLength = UniformFloat.of(30f, 70f),
|
||||
rotateXZ = BooleanProvider.AlwaysTrue,
|
||||
),
|
||||
ore.placement()
|
||||
)
|
||||
|
@ -8,9 +8,11 @@ import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Vec3i
|
||||
import net.minecraft.world.level.ChunkPos
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.AxisAngle4d
|
||||
import org.joml.AxisAngle4f
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Matrix4f
|
||||
import org.joml.Quaterniond
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
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_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_NEGATIVE_X = VECTOR_BACKWARD
|
||||
val VECTOR_DOWN = Vector(0.0, -1.0, 0.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_NEGATIVE_Z = VECTOR_LEFT
|
||||
|
||||
private const val DEGREES_TO_RADIANS = 0.017453292f
|
||||
|
||||
@ -36,6 +42,10 @@ fun toRadians(angle: Float): Float {
|
||||
return angle * DEGREES_TO_RADIANS
|
||||
}
|
||||
|
||||
fun toRadians(angle: Double): Double {
|
||||
return Math.toRadians(angle)
|
||||
}
|
||||
|
||||
fun Vector.asAngle(): Angle {
|
||||
val norm = normalize()
|
||||
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())
|
||||
}
|
||||
|
||||
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 {
|
||||
// TODO: 1.19.3
|
||||
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 {
|
||||
// TODO: 1.19.3
|
||||
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 {
|
||||
return Matrix3f().also {
|
||||
it[0, 0] = x.toFloat()
|
||||
|
@ -4,17 +4,29 @@ import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.util.valueproviders.ConstantFloat
|
||||
import net.minecraft.util.valueproviders.FloatProvider
|
||||
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.PlacementModifier
|
||||
import net.minecraft.world.level.levelgen.placement.PlacementModifierType
|
||||
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.worldgen.EnhancedPlacementContext
|
||||
import ru.dbotthepony.mc.otm.worldgen.PlacementPos
|
||||
import java.util.*
|
||||
import java.util.stream.Stream
|
||||
import kotlin.math.PI
|
||||
|
||||
/**
|
||||
* Ellipsoid ("cloud") placement
|
||||
@ -54,6 +66,10 @@ data class EllipsoidPlacement(
|
||||
* Ellipsoid size sampler on Y axis
|
||||
*/
|
||||
val yLength: FloatProvider,
|
||||
|
||||
val rotateXZ: BooleanProvider = BooleanProvider.AlwaysFalse,
|
||||
val rotateXY: FloatProvider = ConstantFloat.ZERO,
|
||||
val rotateZY: FloatProvider = ConstantFloat.ZERO,
|
||||
) : PlacementModifier(), EnhancedPlacement {
|
||||
init {
|
||||
require(xLength.minValue >= 1f) { "Bad ellipsoid x minimal size: $xLength" }
|
||||
@ -79,6 +95,22 @@ data class EllipsoidPlacement(
|
||||
var iterations = 0
|
||||
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) {
|
||||
val x = this.x.sample(random) * xLength
|
||||
val y = this.y.sample(random) * yLength
|
||||
@ -89,7 +121,13 @@ data class EllipsoidPlacement(
|
||||
(z * z) / zPow <= 1.0f
|
||||
|
||||
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("z_size").forGetter(EllipsoidPlacement::zLength),
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user