added curves

This commit is contained in:
2024-11-17 12:56:00 +01:00
parent e6c2858bb6
commit f9212345f7
3 changed files with 57 additions and 23 deletions
@@ -155,4 +155,24 @@ fun transformOffsetByScale(offset: Vector3f, scale: Vector3f): Vector3f {
fun lerp(x: Float, y: Float, t: Float) : Float { fun lerp(x: Float, y: Float, t: Float) : Float {
return x + (y - x) * t return x + (y - x) * t
}
fun interpolateCurve(curve: Array<Vector3f>, t: Float): Vector3f {
if (curve.size < 2) { return curve[0] }
val clampedT = t.coerceIn(0.0f, 1.0f)
val scaledT = clampedT * (curve.size - 1)
val segmentIndex = scaledT.toInt()
val segmentT = scaledT - segmentIndex
val start = curve[segmentIndex]
val end = curve[(segmentIndex + 1).coerceAtMost(curve.size - 1)] // Ensure bounds
return Vector3f(
start.x + (end.x - start.x) * segmentT,
start.y + (end.y - start.y) * segmentT,
start.z + (end.z - start.z) * segmentT
)
} }
@@ -18,8 +18,8 @@ class Particle(private val particleParams: ParticleParams) {
private var rot = randomBetweenVector3f(particleParams.rotRandom.first, particleParams.rotRandom.second) private var rot = randomBetweenVector3f(particleParams.rotRandom.first, particleParams.rotRandom.second)
private val rotVel = randomBetweenVector3f(particleParams.rotVelRandom.first, particleParams.rotVelRandom.second) private val rotVel = randomBetweenVector3f(particleParams.rotVelRandom.first, particleParams.rotVelRandom.second)
private val scale = randomBetweenVector3f(particleParams.sizeRandom.first, particleParams.sizeRandom.second)
private var vel = randomBetweenVector3f(particleParams.velRandom.first, particleParams.velRandom.second) private var vel = randomBetweenVector3f(particleParams.velRandom.first, particleParams.velRandom.second)
private var scale = randomBetweenVector3f(particleParams.sizeRandom.first, particleParams.sizeRandom.second)
private var blockDisplay: DisplayEntity? = null private var blockDisplay: DisplayEntity? = null
@@ -32,6 +32,13 @@ class Particle(private val particleParams: ParticleParams) {
fun init(pos: Vec3d) { fun init(pos: Vec3d) {
this.pos = pos this.pos = pos
if ( particleParams.uniformSize ) {
val randomUniform = randomFloatBetween(particleParams.sizeRandom.first.x, particleParams.sizeRandom.second.x)
scale.x = randomUniform
scale.y = randomUniform
scale.z = randomUniform
}
val (quatRot, newOffset) = calcTransformOffset(rot, initOffset, scale) val (quatRot, newOffset) = calcTransformOffset(rot, initOffset, scale)
val properties = DisplayEntityProperties( val properties = DisplayEntityProperties(
@@ -81,23 +88,20 @@ class Particle(private val particleParams: ParticleParams) {
} }
// TODO: rotVelRandom, rotVelCurve, sizeCurve, forceFields // TODO: forceFields, shape
private fun calcNewProperties() : DisplayEntityProperties { private fun calcNewProperties() : DisplayEntityProperties {
fun calcBlockCurve() : String {
val newBlockIdx = round(
lerp(
0.0f,
particleParams.blockCurve.lastIndex.toFloat(),
(timeAlive.toFloat() / particleParams.lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
)
).toInt()
fun calcBlockCurve(timeAliveClamped: Float) : String {
val newBlockIdx = round(lerp(0.0f, particleParams.blockCurve.lastIndex.toFloat(), timeAliveClamped)).toInt()
return particleParams.blockCurve[newBlockIdx] return particleParams.blockCurve[newBlockIdx]
} }
fun calcRot() : Vector3f { fun calcRot(timeAliveClamped: Float) : Vector3f {
val newRot = Vector3f(rot) val newRot = Vector3f(rot)
newRot.add(rotVel) val newVel = Vector3f(rotVel)
newVel.mul(interpolateCurve(particleParams.sizeCurve, timeAliveClamped))
newRot.add(newVel)
return newRot return newRot
} }
@@ -115,17 +119,24 @@ class Particle(private val particleParams: ParticleParams) {
return Pair(vel, newOffset) return Pair(vel, newOffset)
} }
fun calcSize(timeAliveClamped: Float) : Vector3f {
val scale = Vector3f(scale)
scale.mul(interpolateCurve(particleParams.sizeCurve, timeAliveClamped))
return scale
}
val timeAliveClamped = (timeAlive.toFloat() / particleParams.lifeTime.toFloat()).coerceIn(0.0f, 1.0f)
val newBlock = calcBlockCurve() val newBlock = calcBlockCurve(timeAliveClamped)
val (newVel, newOffset) = calcOffset() val (newVel, newOffset) = calcOffset()
val newRot = calcRot() val newRot = calcRot(timeAliveClamped)
val newScale = calcSize(timeAliveClamped)
vel = newVel vel = newVel
offset = newOffset offset = newOffset
rot = newRot rot = newRot
val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, scale /* newScale */) val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, newScale)
val combinedOffset = transformOffset.add(newOffset) val combinedOffset = transformOffset.add(newOffset)
val newProperties = DisplayEntityProperties( val newProperties = DisplayEntityProperties(
@@ -133,7 +144,7 @@ class Particle(private val particleParams: ParticleParams) {
blockType = newBlock, blockType = newBlock,
translation = combinedOffset, translation = combinedOffset,
leftRotation = quatRot, leftRotation = quatRot,
scale = scale, //fix scale = newScale,
tags = arrayOf("BPS_Particle") tags = arrayOf("BPS_Particle")
) )
@@ -2,21 +2,24 @@ package com.bytedice.bde_particles.particle
import org.joml.Vector3f import org.joml.Vector3f
// sizeRandom: set y and z on both vectors to -1 for uniform scale // not implemented // TODO: order these correctly, explain all
// sizeRandom: if uniformSize is true then sizeRandom will be uniform (cubic) and the values are taken from X
// lifeTime: any value below 1 will result in a particle not spawning // lifeTime: any value below 1 will result in a particle not spawning
// minVel values 0 or less mean the particle can travel however slow it wants // minVel: values 0 or less mean the particle can travel however slow it wants
// gravity: Y being -0.025 is close to regular gravity
data class ParticleParams ( data class ParticleParams (
//val shape: Shape, // add later, start with single point //val shape: Shape, // add later, start with single point
val blockCurve: Array<String> = arrayOf("minecraft:purple_concrete", "minecraft:purple_stained_glass"), val blockCurve: Array<String> = arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"),
val rotRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)), val rotRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
val rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)), val rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
val rotVelCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), val rotVelCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)),
val sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)), val sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
val sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), val uniformSize: Boolean = true,
val velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.3f, 0.3f, -0.3f), Vector3f(0.3f, 0.6f, 0.3f)), val sizeCurve: Array<Vector3f> = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f)),
val velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)),
val forceFields: ForceField = ForceField(), val forceFields: ForceField = ForceField(),
val gravity: Vector3f = Vector3f(0.0f, -0.025f, 0.0f), val gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
val drag: Float = 0.075f, val drag: Float = 0.075f,
val minVel: Float = 0.0f, val minVel: Float = 0.0f,
val lifeTime: Int = 20 val lifeTime: Int = 30
) )