diff --git a/src/main/kotlin/com/bytedice/bde_particles/math/main.kt b/src/main/kotlin/com/bytedice/bde_particles/math/main.kt index 42d8ee8..c1c81c3 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/math/main.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/math/main.kt @@ -155,4 +155,24 @@ fun transformOffsetByScale(offset: Vector3f, scale: Vector3f): Vector3f { fun lerp(x: Float, y: Float, t: Float) : Float { return x + (y - x) * t +} + + +fun interpolateCurve(curve: Array, 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 + ) } \ No newline at end of file diff --git a/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt b/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt index 5ba8d6b..22382a1 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particle/Particle.kt @@ -18,8 +18,8 @@ class Particle(private val particleParams: ParticleParams) { private var rot = randomBetweenVector3f(particleParams.rotRandom.first, particleParams.rotRandom.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 scale = randomBetweenVector3f(particleParams.sizeRandom.first, particleParams.sizeRandom.second) private var blockDisplay: DisplayEntity? = null @@ -32,6 +32,13 @@ class Particle(private val particleParams: ParticleParams) { fun init(pos: Vec3d) { 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 properties = DisplayEntityProperties( @@ -81,23 +88,20 @@ class Particle(private val particleParams: ParticleParams) { } - // TODO: rotVelRandom, rotVelCurve, sizeCurve, forceFields + // TODO: forceFields, shape 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] } - fun calcRot() : Vector3f { + fun calcRot(timeAliveClamped: Float) : Vector3f { val newRot = Vector3f(rot) - newRot.add(rotVel) + val newVel = Vector3f(rotVel) + + newVel.mul(interpolateCurve(particleParams.sizeCurve, timeAliveClamped)) + newRot.add(newVel) return newRot } @@ -115,17 +119,24 @@ class Particle(private val particleParams: ParticleParams) { 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 newRot = calcRot() + val newRot = calcRot(timeAliveClamped) + val newScale = calcSize(timeAliveClamped) vel = newVel offset = newOffset rot = newRot - val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, scale /* newScale */) + val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, newScale) val combinedOffset = transformOffset.add(newOffset) val newProperties = DisplayEntityProperties( @@ -133,7 +144,7 @@ class Particle(private val particleParams: ParticleParams) { blockType = newBlock, translation = combinedOffset, leftRotation = quatRot, - scale = scale, //fix + scale = newScale, tags = arrayOf("BPS_Particle") ) diff --git a/src/main/kotlin/com/bytedice/bde_particles/particle/ParticleParams.kt b/src/main/kotlin/com/bytedice/bde_particles/particle/ParticleParams.kt index cdad700..2127287 100644 --- a/src/main/kotlin/com/bytedice/bde_particles/particle/ParticleParams.kt +++ b/src/main/kotlin/com/bytedice/bde_particles/particle/ParticleParams.kt @@ -2,21 +2,24 @@ package com.bytedice.bde_particles.particle 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 -// 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 ( //val shape: Shape, // add later, start with single point - val blockCurve: Array = arrayOf("minecraft:purple_concrete", "minecraft:purple_stained_glass"), + val blockCurve: Array = arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"), val rotRandom: Pair = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)), val rotVelRandom: Pair = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)), val rotVelCurve: Array = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), val sizeRandom: Pair = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)), - val sizeCurve: Array = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f)), - val velRandom: Pair = Pair(Vector3f(-0.3f, 0.3f, -0.3f), Vector3f(0.3f, 0.6f, 0.3f)), + val uniformSize: Boolean = true, + val sizeCurve: Array = arrayOf(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f)), + val velRandom: Pair = Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)), 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 minVel: Float = 0.0f, - val lifeTime: Int = 20 + val lifeTime: Int = 30 ) \ No newline at end of file