reworked a bunch of stuff. Contains errors
This commit is contained in:
@@ -27,6 +27,37 @@ import net.minecraft.world.World
|
||||
import java.util.*
|
||||
|
||||
|
||||
// TODO:
|
||||
// Allowing the use of regular Minecraft particles instead of just BDEs.
|
||||
// Better command auto-completion. (and change names of args)
|
||||
// force field "config" option
|
||||
// blockCurve array not needing "minecraft:"
|
||||
|
||||
// Adding a parameter for an initial velocity from an origin point (you currently have to use force fields)
|
||||
// Pair<Pair<Vec3f, Vec3f>, Pair<Vec3f, Vec3f>>
|
||||
// "min center vel", "max center vel", "min edge vel", "max edge vel"
|
||||
|
||||
// Parameters
|
||||
// localOffset (Vec3f)
|
||||
// velocity based, relative coordinate based, or rotation based
|
||||
// localOffsetCurve (curve)
|
||||
// spawnOffset (Vec3f)
|
||||
// velRot (bool)
|
||||
// rotates the particle to face the velocity
|
||||
// spawnChance (Float)
|
||||
|
||||
// Move most (if not all) particle params to emitters.
|
||||
// 3D curves (curves for all X Y Z)
|
||||
// Custom curve equation command args (parse from strings)
|
||||
// Cylinder and cone force field shape.
|
||||
// Better particle performance.
|
||||
// Global max particles variable.
|
||||
// gamerule max particles
|
||||
|
||||
// Emitter groups (multiple emitters for EmitterTool)
|
||||
// Private functions/classes
|
||||
|
||||
|
||||
var ALL_PARTICLE_EMITTERS: Array<ParticleEmitter> = emptyArray()
|
||||
val sessionUuid: UUID = UUID.randomUUID()
|
||||
|
||||
|
||||
@@ -12,18 +12,18 @@ import kotlin.math.*
|
||||
import kotlin.random.Random
|
||||
|
||||
|
||||
class InterpolationCurves(val function: (Float) -> Float) {
|
||||
class LerpCurves(val function: (Float) -> Float) {
|
||||
companion object {
|
||||
val LINEAR = InterpolationCurves { y -> y }
|
||||
val SQRT = InterpolationCurves { y -> sqrt(y) }
|
||||
val EXPONENT = InterpolationCurves { y -> y.pow(2.0f) }
|
||||
val CUBIC = InterpolationCurves { y -> y.pow(3.0f) }
|
||||
val SINE = InterpolationCurves { y -> sin(y * PI.toFloat() / 2) }
|
||||
val COSINE = InterpolationCurves { y -> 1 - cos(y * PI.toFloat() / 2) }
|
||||
val INVERSE = InterpolationCurves { y -> 1 - y }
|
||||
val LOG = InterpolationCurves { y -> if (y > 0) ln(y + 1) else 0f }
|
||||
val EXP = InterpolationCurves { y -> exp(y) - 1 }
|
||||
val BOUNCE = InterpolationCurves { y ->
|
||||
val Linear = LerpCurves { y -> y }
|
||||
val Sqrt = LerpCurves { y -> sqrt(y) }
|
||||
val Exponent = LerpCurves { y -> y.pow(2.0f) }
|
||||
val Cubic = LerpCurves { y -> y.pow(3.0f) }
|
||||
val Sine = LerpCurves { y -> sin(y * PI.toFloat() / 2) }
|
||||
val Cosine = LerpCurves { y -> 1 - cos(y * PI.toFloat() / 2) }
|
||||
val Inverse = LerpCurves { y -> 1 - y }
|
||||
val Log = LerpCurves { y -> if (y > 0) ln(y + 1) else 0f }
|
||||
val Exp = LerpCurves { y -> exp(y) - 1 }
|
||||
val Bounce = LerpCurves { y ->
|
||||
val n1 = 7.5625f
|
||||
val d1 = 2.75f
|
||||
when {
|
||||
@@ -43,7 +43,7 @@ class InterpolationCurves(val function: (Float) -> Float) {
|
||||
}
|
||||
}
|
||||
|
||||
fun custom(equation: (Float) -> Float) = InterpolationCurves(equation)
|
||||
fun custom(equation: (Float) -> Float) = LerpCurves(equation)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,7 @@ fun lerp(x: Float, y: Float, t: Float) : Float {
|
||||
}
|
||||
|
||||
|
||||
fun interpolateCurve(start: Vector3f, end: Vector3f, t: Float, curve: InterpolationCurves): Vector3f {
|
||||
fun interpolateCurve(start: Vector3f, end: Vector3f, t: Float, curve: LerpCurves): Vector3f {
|
||||
val clampedT = t.coerceIn(0.0f, 1.0f)
|
||||
|
||||
val curvedT = curve.function(clampedT)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.bytedice.bde_particles.commands
|
||||
|
||||
import com.bytedice.bde_particles.InterpolationCurves
|
||||
import com.bytedice.bde_particles.LerpCurves
|
||||
import com.bytedice.bde_particles.particles.*
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType
|
||||
@@ -127,7 +127,7 @@ class ArgConfigParticleKeys {
|
||||
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
||||
.executes { context ->
|
||||
val radius = FloatArgumentType.getFloat(context, "Radius")
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.CIRCLE(radius))
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.Circle(radius))
|
||||
context.source.sendFeedback( { feedback }, false)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class ArgConfigParticleKeys {
|
||||
.executes { context ->
|
||||
val w = FloatArgumentType.getFloat(context, "Width")
|
||||
val h = FloatArgumentType.getFloat(context, "Height")
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.RECT(Vector2f(w, h)))
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.Rect(Vector2f(w, h)))
|
||||
context.source.sendFeedback( { feedback }, false)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
@@ -154,7 +154,7 @@ class ArgConfigParticleKeys {
|
||||
val x = FloatArgumentType.getFloat(context, "X")
|
||||
val y = FloatArgumentType.getFloat(context, "Y")
|
||||
val z = FloatArgumentType.getFloat(context, "Z")
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.CUBE(Vector3f(x, y, z)))
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.Cube(Vector3f(x, y, z)))
|
||||
context.source.sendFeedback( { feedback }, false)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
@@ -166,7 +166,7 @@ class ArgConfigParticleKeys {
|
||||
.then(CommandManager.argument("Radius", FloatArgumentType.floatArg())
|
||||
.executes { context ->
|
||||
val radius = FloatArgumentType.getFloat(context, "Radius")
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.SPHERE(radius))
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.Sphere(radius))
|
||||
context.source.sendFeedback( { feedback }, false)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
@@ -174,7 +174,7 @@ class ArgConfigParticleKeys {
|
||||
)
|
||||
.then(CommandManager.literal("point")
|
||||
.executes { context ->
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.POINT)
|
||||
val feedback = updateParticleParam(context, "shape", SpawningShape.Point)
|
||||
context.source.sendFeedback( { feedback }, false)
|
||||
Command.SINGLE_SUCCESS
|
||||
}
|
||||
@@ -415,19 +415,19 @@ class ArgConfigParticleKeys {
|
||||
}
|
||||
|
||||
|
||||
fun getCurveByString(str: String) : InterpolationCurves {
|
||||
fun getCurveByString(str: String) : LerpCurves {
|
||||
return when (str) {
|
||||
"LINEAR" -> InterpolationCurves.LINEAR
|
||||
"SQRT" -> InterpolationCurves.SQRT
|
||||
"EXPONENT" -> InterpolationCurves.EXPONENT
|
||||
"CUBIC" -> InterpolationCurves.CUBIC
|
||||
"SINE" -> InterpolationCurves.SINE
|
||||
"COSINE" -> InterpolationCurves.COSINE
|
||||
"INVERSE" -> InterpolationCurves.INVERSE
|
||||
"LOG" -> InterpolationCurves.LOG
|
||||
"EXP" -> InterpolationCurves.EXP
|
||||
"BOUNCE" -> InterpolationCurves.BOUNCE
|
||||
else -> InterpolationCurves.LINEAR
|
||||
"LINEAR" -> LerpCurves.Linear
|
||||
"SQRT" -> LerpCurves.Sqrt
|
||||
"EXPONENT" -> LerpCurves.Exponent
|
||||
"CUBIC" -> LerpCurves.Cubic
|
||||
"SINE" -> LerpCurves.Sine
|
||||
"COSINE" -> LerpCurves.Cosine
|
||||
"INVERSE" -> LerpCurves.Inverse
|
||||
"LOG" -> LerpCurves.Log
|
||||
"EXP" -> LerpCurves.Exp
|
||||
"BOUNCE" -> LerpCurves.Bounce
|
||||
else -> LerpCurves.Linear
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +538,7 @@ fun forceFieldAddSphereExec(context: CommandContext<ServerCommandSource>) : Int
|
||||
val minForce = FloatArgumentType.getFloat(context, "Min Force")
|
||||
val maxForce = FloatArgumentType.getFloat(context, "Max Force")
|
||||
|
||||
val shape = ForceFieldShape.SPHERE(radius, Pair(minForce, maxForce))
|
||||
val shape = ForceFieldShape.Sphere(radius, Pair(minForce, maxForce))
|
||||
val forceField = forceFieldGenericParams(context, shape)
|
||||
|
||||
val currentParams = getEmitterParams(emitterIdVal)
|
||||
@@ -567,7 +567,7 @@ fun forceFieldAddCubeExec(context: CommandContext<ServerCommandSource>) : Int {
|
||||
val zForce = FloatArgumentType.getFloat(context, "Z Force")
|
||||
val emitterIdVal = StringArgumentType.getString(context, "Registered Emitter ID")
|
||||
|
||||
val shape = ForceFieldShape.CUBE(Vector3f(xSize, ySize, zSize), Vector3f(xForce, yForce, zForce))
|
||||
val shape = ForceFieldShape.Cube(Vector3f(xSize, ySize, zSize), Vector3f(xForce, yForce, zForce))
|
||||
val forceField = forceFieldGenericParams(context, shape)
|
||||
|
||||
val currentParams = getEmitterParams(emitterIdVal)
|
||||
|
||||
@@ -1,42 +1,60 @@
|
||||
package com.bytedice.bde_particles.particles
|
||||
|
||||
import com.bytedice.bde_particles.LerpCurves
|
||||
import org.joml.Vector3f
|
||||
|
||||
|
||||
/**
|
||||
* EmitterParams defines the parameters for controlling how particles are emitted,
|
||||
* including settings for looping, spawn frequency, and maximum particle count.
|
||||
*
|
||||
* @param maxCount The maximum number of particles that can exist. If set to 0 or below, no particles will spawn.
|
||||
* @param spawnsPerTick The number of particles spawned per tick. If set to 0 or below, no particles will spawn.
|
||||
* @param loopDur The duration for which the loop runs, in ticks. A value 0 or below means the loop is infinite, and `loopDelay` and `loopCount` will be ignored.
|
||||
* @param loopDelay The delay between each loop cycle, in ticks. Negative values are treated as 0, meaning no delay.
|
||||
* @param loopCount The number of times the loop will repeat. 0 means it will shoot a single burst of particles. A value below 0 means it will repeat indefinitely.
|
||||
* @param particle The particle params of the particle that will spawn.
|
||||
* @param maxCount The maximum number of particles that can exist at any time. If set to 0 or below, no particles will spawn.
|
||||
* @param spawnRate The number of particles to spawn each tick. If set to 0 or below, no particles will spawn.
|
||||
* @param spawnChance The chance for a particle to spawn. 0.5 means a particle has a 50% chance of spawning. Values are between 0.0 and 1.0.
|
||||
* @param loopDur The duration, in ticks, that each emission loop lasts. A value of 0 or below makes the loop infinite, ignoring `loopDelay` and `loopCount`.
|
||||
* @param loopDelay The delay, in ticks, between consecutive loops. Negative values are treated as 0 (no delay).
|
||||
* @param loopCount The number of times the loop repeats. A value of 0 results in a single burst of particles. Values below 0 make the loop repeat indefinitely.
|
||||
* @param shape The spawning shape for the particles, such as `SpawningShape.Sphere()`.
|
||||
* @param initRot Specifies the initial random rotation range for the particles, in degrees, for the X, Y, and Z axes.
|
||||
* @param rotVel Specifies the random range for rotational velocity, in degrees per tick, for the X, Y, and Z axes.
|
||||
* @param rotTowardVel If true, particles will face the direction of velocity. It uses `initRot` as an offset rotation and ignores `rotVel`.
|
||||
* @param initVel Specifies the random range for the initial velocity, in units per tick, for the X, Y, and Z axes.
|
||||
* @param initScale Defines the random range for the initial particle size.
|
||||
* @param scaleTowardVel If true, particles will scale to the direction of velocity.
|
||||
* @param forceFields An array of force fields applied to particles, affecting their motion during their lifetime.
|
||||
* @param constVel A constant velocity vector applied to particles each tick, useful for effects like gravity.
|
||||
* @param drag A drag coefficient that slows down particle velocity over time. Calculated as `velocity * (1.0 - drag)`.
|
||||
* @param minVel The minimum speed a particle must maintain. Particles slower than this value are stopped. Values <= 0 disable this check.
|
||||
* @param lifeTime Specifies the range for particle lifetime, in ticks. Values below 1 prevent particles from spawning.
|
||||
* @param rotVelCurve A curve defining how rotational velocity evolves during the particle's lifetime. Multiplies the `rotVel` values.
|
||||
* @param sizeCurve A curve defining how the particle's size evolves over its lifetime. Multiplies the `initScale` values.
|
||||
* @param blockCurve Specifies an array of block names that the particle transitions through during its lifetime, combined with a curve to control transitions. Defaults to "minecraft:air" if empty.
|
||||
*/
|
||||
data class EmitterParams (
|
||||
var maxCount: Int = 200,
|
||||
var spawnsPerTick: Int = 1,
|
||||
var loopDur: Int = 25,
|
||||
var loopDelay: Int = 0,
|
||||
var loopCount: Int = 0,
|
||||
var particle: ParticleParams = ParticleParams.DEFAULT,
|
||||
var maxCount: Int = 200,
|
||||
var spawnRate: Int = 1,
|
||||
var spawnChance: Float = 1.0f,
|
||||
var loopDur: Int = 25,
|
||||
var loopDelay: Int = 0,
|
||||
var loopCount: Int = 0,
|
||||
var shape: SpawningShape = SpawningShape.Circle(3.0f),
|
||||
var initRot: ParamClasses.PairVec3f = ParamClasses.PairVec3f(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f),
|
||||
var rotVel: ParamClasses.PairVec3f = ParamClasses.PairVec3f(-0.2f, -0.2f, -0.2f, 0.2f, 0.2f, 0.2f),
|
||||
var rotTowardVel: Boolean = true,
|
||||
var initVel: ParamClasses.PairVec3f = ParamClasses.PairVec3f(-0.1f, 0.3f, -0.1f, 0.1f, 0.6f, 0.1f),
|
||||
var initScale: ParamClasses.RandScale = ParamClasses.RandScale.Uniform(),
|
||||
var scaleTowardVel: Boolean = true,
|
||||
var forceFields: Array<ForceField> = emptyArray(),
|
||||
var constVel: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
|
||||
var drag: Float = 0.075f,
|
||||
var minVel: Float = 0.0f,
|
||||
var lifeTime: ParamClasses.PairVec2i = ParamClasses.PairVec2i(0, 0, 1, 1),
|
||||
var rotVelCurve: ParamClasses.LerpVal = ParamClasses.LerpVal.LerpUniform(1.0f, 0.0f, LerpCurves.Sqrt),
|
||||
var sizeCurve: ParamClasses.LerpVal = ParamClasses.LerpVal.LerpUniform(1.0f, 0.5f, LerpCurves.Linear),
|
||||
var blockCurve: Pair<Array<String>, LerpCurves> = Pair(arrayOf("minecraft:purple_concrete", "minecraft:purple_stained_glass"), LerpCurves.Sqrt),
|
||||
)
|
||||
{
|
||||
companion object Presets {
|
||||
val DEFAULT = EmitterParams()
|
||||
val FIRE_GEYSER = EmitterParams(
|
||||
200,
|
||||
1,
|
||||
25,
|
||||
0,
|
||||
0,
|
||||
ParticleParams.FIRE_GEYSER
|
||||
)
|
||||
val RING_EXPLOSION = EmitterParams(
|
||||
200,
|
||||
150,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
ParticleParams.RING_EXPLOSION
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,5 @@ import org.joml.Vector3f
|
||||
data class ForceField (
|
||||
val name: String = "DEFAULT",
|
||||
val pos: Vector3f = Vector3f(0.0f, 5.0f, 0.0f),
|
||||
val shape: ForceFieldShape = ForceFieldShape.SPHERE()
|
||||
val shape: ForceFieldShape = ForceFieldShape.Sphere()
|
||||
)
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.bytedice.bde_particles.particles
|
||||
|
||||
import com.bytedice.bde_particles.LerpCurves
|
||||
import com.bytedice.bde_particles.randomFloatBetween
|
||||
import com.bytedice.bde_particles.randomIntBetween
|
||||
import org.joml.Vector3f
|
||||
|
||||
class ParamClasses {
|
||||
class PairVec3f (
|
||||
private val minX: Float = 0.0f,
|
||||
private val minY: Float = 0.0f,
|
||||
private val minZ: Float = 0.0f,
|
||||
private val maxX: Float = 1.0f,
|
||||
private val maxY: Float = 1.0f,
|
||||
private val maxZ: Float = 1.0f,
|
||||
) {
|
||||
fun randomize() : Vector3f {
|
||||
return Vector3f(
|
||||
randomFloatBetween(minX, maxX),
|
||||
randomFloatBetween(minY, maxY),
|
||||
randomFloatBetween(minZ, maxZ),
|
||||
)
|
||||
}
|
||||
}
|
||||
sealed class RandScale {
|
||||
class Uniform (
|
||||
private val min: Float = 0.0f,
|
||||
private val max: Float = 1.0f,
|
||||
) : RandScale() {
|
||||
fun randomize() : Vector3f {
|
||||
val x = randomFloatBetween(min, max)
|
||||
return Vector3f(x, x, x)
|
||||
}
|
||||
}
|
||||
class NonUniform (
|
||||
private val minX: Float = 0.0f,
|
||||
private val minY: Float = 0.0f,
|
||||
private val minZ: Float = 0.0f,
|
||||
private val maxX: Float = 1.0f,
|
||||
private val maxY: Float = 1.0f,
|
||||
private val maxZ: Float = 1.0f
|
||||
) : RandScale() {
|
||||
fun randomize(): Vector3f {
|
||||
return Vector3f(
|
||||
randomFloatBetween(minX, maxX),
|
||||
randomFloatBetween(minY, maxY),
|
||||
randomFloatBetween(minZ, maxZ),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
class PairVec2i (
|
||||
private val minX: Int = 0,
|
||||
private val minY: Int = 0,
|
||||
private val maxX: Int = 1,
|
||||
private val maxY: Int = 1,
|
||||
) {
|
||||
fun randomize() : Pair<Int, Int> {
|
||||
return Pair(
|
||||
randomIntBetween(minX, maxX),
|
||||
randomIntBetween(minY, maxY),
|
||||
)
|
||||
}
|
||||
}
|
||||
sealed class LerpVal {
|
||||
class LerpVec3f(
|
||||
private val fromX: Float = 0.0f,
|
||||
private val fromY: Float = 0.0f,
|
||||
private val fromZ: Float = 0.0f,
|
||||
private val toX: Float = 1.0f,
|
||||
private val toY: Float = 1.0f,
|
||||
private val toZ: Float = 1.0f,
|
||||
private val curve: LerpCurves = LerpCurves.Linear,
|
||||
) : LerpVal() {
|
||||
fun lerp(t: Float): Vector3f {
|
||||
val x = com.bytedice.bde_particles.lerp(fromX, toX, t) * curve.function(t)
|
||||
val y = com.bytedice.bde_particles.lerp(fromY, toY, t) * curve.function(t)
|
||||
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, t) * curve.function(t)
|
||||
return Vector3f(x, y, z)
|
||||
}
|
||||
}
|
||||
class MultiLerpVec3f(
|
||||
private val fromX: Float = 0.0f,
|
||||
private val fromY: Float = 0.0f,
|
||||
private val fromZ: Float = 0.0f,
|
||||
private val toX: Float = 1.0f,
|
||||
private val toY: Float = 1.0f,
|
||||
private val toZ: Float = 1.0f,
|
||||
private val curveX: LerpCurves = LerpCurves.Linear,
|
||||
private val curveY: LerpCurves = LerpCurves.Linear,
|
||||
private val curveZ: LerpCurves = LerpCurves.Linear
|
||||
) : LerpVal() {
|
||||
fun lerp(t: Float): Vector3f {
|
||||
val x = com.bytedice.bde_particles.lerp(fromX, toX, t) * curveX.function(t)
|
||||
val y = com.bytedice.bde_particles.lerp(fromY, toY, t) * curveY.function(t)
|
||||
val z = com.bytedice.bde_particles.lerp(fromZ, toZ, t) * curveZ.function(t)
|
||||
return Vector3f(x, y, z)
|
||||
}
|
||||
}
|
||||
class LerpUniform(
|
||||
private val from: Float = 0.0f,
|
||||
private val to: Float = 1.0f,
|
||||
private val curve: LerpCurves = LerpCurves.Linear,
|
||||
) : LerpVal() {
|
||||
fun lerp(t: Float): Float {
|
||||
return com.bytedice.bde_particles.lerp(from, to, t) * curve.function(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import kotlin.math.*
|
||||
// TODO: consider moving most params to emitter (such as shape, and forceFields) to store less data
|
||||
|
||||
|
||||
class Particle(private val particleParams: ParticleParams) {
|
||||
class Particle(private val emitterParams: EmitterParams) {
|
||||
private val initOffset = Vector3f(-0.5f, -0.5f, -0.5f)
|
||||
private var offset = Vector3f(0.0f, 0.0f, 0.0f)
|
||||
private var pos = Vec3d(0.0, 0.0, 0.0)
|
||||
@@ -44,11 +44,11 @@ class Particle(private val particleParams: ParticleParams) {
|
||||
val newSpawnPos: Vector3f
|
||||
|
||||
when (shape) {
|
||||
is SpawningShape.CIRCLE -> { val posInCircle = randomInCircle(shape.radius); newSpawnPos = Vector3f(posInCircle.x, 0.0f, posInCircle.y) }
|
||||
is SpawningShape.SPHERE -> { newSpawnPos = randomInSphere(shape.radius) }
|
||||
is SpawningShape.RECT -> { val posInRect = randomInRect(shape.size); newSpawnPos = Vector3f(posInRect.x, 0.0f, posInRect.y) }
|
||||
is SpawningShape.CUBE -> { newSpawnPos = randomInCube(shape.size) }
|
||||
is SpawningShape.POINT -> { newSpawnPos = Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
is SpawningShape.Circle -> { val posInCircle = randomInCircle(shape.radius); newSpawnPos = Vector3f(posInCircle.x, 0.0f, posInCircle.y) }
|
||||
is SpawningShape.Sphere -> { newSpawnPos = randomInSphere(shape.radius) }
|
||||
is SpawningShape.Rect -> { val posInRect = randomInRect(shape.size); newSpawnPos = Vector3f(posInRect.x, 0.0f, posInRect.y) }
|
||||
is SpawningShape.Cube -> { newSpawnPos = randomInCube(shape.size) }
|
||||
is SpawningShape.Point -> { newSpawnPos = Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
}
|
||||
|
||||
offset = newSpawnPos
|
||||
@@ -110,7 +110,7 @@ class Particle(private val particleParams: ParticleParams) {
|
||||
}
|
||||
|
||||
fun sphereSdfVel(forceField: ForceField) : Vector3f {
|
||||
if (forceField.shape !is ForceFieldShape.SPHERE) { return Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
if (forceField.shape !is ForceFieldShape.Sphere) { return Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
val shape = forceField.shape
|
||||
|
||||
val sdfVal = sdfSphere(forceField.pos, shape.radius, offset)
|
||||
@@ -123,7 +123,7 @@ class Particle(private val particleParams: ParticleParams) {
|
||||
}
|
||||
|
||||
fun cubeSdfVel(forceField: ForceField) : Vector3f {
|
||||
if (forceField.shape !is ForceFieldShape.CUBE) { return Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
if (forceField.shape !is ForceFieldShape.Cube) { return Vector3f(0.0f, 0.0f, 0.0f) }
|
||||
val shape = forceField.shape
|
||||
|
||||
val sdfVal = sdfCube(forceField.pos, shape.size, offset)
|
||||
@@ -176,8 +176,8 @@ class Particle(private val particleParams: ParticleParams) {
|
||||
rot = newRot
|
||||
|
||||
for (forceField in particleParams.forceFields) {
|
||||
if (forceField.shape is ForceFieldShape.SPHERE) { vel.add(sphereSdfVel(forceField)) }
|
||||
else if (forceField.shape is ForceFieldShape.CUBE) { vel.add(cubeSdfVel(forceField)) }
|
||||
if (forceField.shape is ForceFieldShape.Sphere) { vel.add(sphereSdfVel(forceField)) }
|
||||
else if (forceField.shape is ForceFieldShape.Cube) { vel.add(cubeSdfVel(forceField)) }
|
||||
}
|
||||
|
||||
val (quatRot, transformOffset) = calcTransformOffset(newRot, initOffset, newScale)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
package com.bytedice.bde_particles.particles
|
||||
|
||||
import com.bytedice.bde_particles.InterpolationCurves
|
||||
import com.bytedice.bde_particles.LerpCurves
|
||||
import org.joml.Vector3f
|
||||
|
||||
|
||||
@@ -103,8 +103,8 @@ fun updateSingleParticleParam(params: ParticleParams, paramName: String, paramVa
|
||||
"drag" -> paramValue as Float
|
||||
"minVel" -> paramValue as Float
|
||||
"lifeTime" -> paramValue as Pair<Int, Int>
|
||||
"rotVelCurve" -> paramValue as Triple<Vector3f, Vector3f, InterpolationCurves>
|
||||
"sizeCurve" -> paramValue as Triple<Vector3f, Vector3f, InterpolationCurves>
|
||||
"rotVelCurve" -> paramValue as Triple<Vector3f, Vector3f, LerpCurves>
|
||||
"sizeCurve" -> paramValue as Triple<Vector3f, Vector3f, LerpCurves>
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -125,8 +125,8 @@ fun updateSingleParticleParam(params: ParticleParams, paramName: String, paramVa
|
||||
"drag" -> newParams.drag = value as Float
|
||||
"minVel" -> newParams.minVel = value as Float
|
||||
"lifeTime" -> newParams.lifeTime = value as Pair<Int, Int>
|
||||
"rotVelCurve" -> newParams.rotVelCurve = value as Triple<Vector3f, Vector3f, InterpolationCurves>
|
||||
"sizeCurve" -> newParams.sizeCurve = value as Triple<Vector3f, Vector3f, InterpolationCurves>
|
||||
"rotVelCurve" -> newParams.rotVelCurve = value as Triple<Vector3f, Vector3f, LerpCurves>
|
||||
"sizeCurve" -> newParams.sizeCurve = value as Triple<Vector3f, Vector3f, LerpCurves>
|
||||
else -> return Pair(params, false)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package com.bytedice.bde_particles.particles
|
||||
|
||||
import com.bytedice.bde_particles.InterpolationCurves
|
||||
import org.joml.Vector3f
|
||||
|
||||
/**
|
||||
* ParticleParams defines the parameters for particle behavior, including shape, size, velocity, and other physics properties.
|
||||
*
|
||||
* @param shape The shape of the particle's spawning area, `null` is a single point.
|
||||
* @param blockCurve An array of block names that gets cycled through during the particle's lifetime. Empty defaults to "minecraft:air".
|
||||
* @param rotRandom The random ***initial*** rotation range for the particle's rotation in X, Y, and Z axes.
|
||||
* @param rotVelRandom The random velocity for particle rotation in the X, Y, and Z axes.
|
||||
* @param sizeRandom The random ***initial*** size range for the particle. If `uniformSize` is true, this will be uniform (cubic).
|
||||
* @param uniformSize If true, particles will have a uniform (cubic) size. Otherwise, their sizes on different axis can vary.
|
||||
* @param velRandom The random ***initial*** velocity range for the particle in the X, Y, and Z axes.
|
||||
* @param forceFields An array of force fields applied to the particle.
|
||||
* @param gravity A constant force applied to the particle every tick. It's often used as gravity.
|
||||
* @param drag A drag force that affects the speed overtime. The formula is (velocity * (1.0 - drag))
|
||||
* @param minVel If particles travel slower than this their speed is automatically 0. Values less than or equal to 0 mean the particle can travel at any speed.
|
||||
* @param lifeTime A range for the particle's lifetime in ticks. A value below 1 will result in the particle not spawning.
|
||||
* @param rotVelCurve A curve which the rotation velocity gets multiplied by during the particle's lifetime.
|
||||
* @param sizeCurve A curve which the size gets multiplied by during the particle's lifetime.
|
||||
*/
|
||||
data class ParticleParams (
|
||||
var shape: SpawningShape = SpawningShape.CIRCLE(3.0f),
|
||||
var blockCurve: Array<String> = arrayOf("minecraft:purple_concrete", "minecraft:purple_stained_glass"),
|
||||
var rotRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
|
||||
var rotVelRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
|
||||
var sizeRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
|
||||
var uniformSize: Boolean = true,
|
||||
var velRandom: Pair<Vector3f, Vector3f> = Pair(Vector3f(-0.1f, 0.3f, -0.1f), Vector3f(0.1f, 0.6f, 0.1f)),
|
||||
var forceFields: Array<ForceField> = emptyArray(),
|
||||
var gravity: Vector3f = Vector3f(0.0f, -0.01f, 0.0f),
|
||||
var drag: Float = 0.075f,
|
||||
var minVel: Float = 0.0f,
|
||||
var lifeTime: Pair<Int, Int> = Pair(15, 45),
|
||||
var rotVelCurve: Triple<Vector3f, Vector3f, InterpolationCurves> = Triple(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f), InterpolationCurves.SQRT),
|
||||
var sizeCurve: Triple<Vector3f, Vector3f, InterpolationCurves> = Triple(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f), InterpolationCurves.LINEAR),
|
||||
) {
|
||||
companion object Presets {
|
||||
val DEFAULT = ParticleParams()
|
||||
val FIRE_GEYSER = ParticleParams(
|
||||
SpawningShape.POINT,
|
||||
arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"),
|
||||
Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
|
||||
Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
|
||||
Pair(Vector3f(0.5f, 0.5f, 0.5f), Vector3f(1.0f, 1.0f, 1.0f)),
|
||||
true,
|
||||
Pair(Vector3f(-0.1f, 0.4f, -0.1f), Vector3f(0.1f, 0.8f, 0.1f)),
|
||||
emptyArray(),
|
||||
Vector3f(0.0f, -0.01f, 0.0f),
|
||||
0.075f,
|
||||
0.0f,
|
||||
Pair(15, 45),
|
||||
Triple(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f), InterpolationCurves.SQRT),
|
||||
Triple(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.5f, 0.5f, 0.5f), InterpolationCurves.SQRT)
|
||||
)
|
||||
val RING_EXPLOSION = ParticleParams(
|
||||
SpawningShape.CIRCLE(0.1f),
|
||||
arrayOf("minecraft:shroomlight", "minecraft:orange_concrete", "minecraft:orange_stained_glass", "minecraft:gray_stained_glass", "minecraft:light_gray_stained_glass"),
|
||||
Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(360.0f, 360.0f, 360.0f)),
|
||||
Pair(Vector3f(-0.2f, -0.2f, -0.2f), Vector3f(0.2f, 0.2f, 0.2f)),
|
||||
Pair(Vector3f(10.0f, 10.0f, 10.0f), Vector3f(15.0f, 15.0f, 15.0f)),
|
||||
true,
|
||||
Pair(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(0.0f, 0.0f, 0.0f)),
|
||||
arrayOf(ForceField("init", Vector3f(0.0f, -0.0001f, 0.0f), ForceFieldShape.SPHERE(0.1f, Pair(4.0f, 4.0f)))),
|
||||
Vector3f(0.0f, 0.0f, 0.0f),
|
||||
0.0075f,
|
||||
0.0f,
|
||||
Pair(50, 100),
|
||||
Triple(Vector3f(1.0f, 1.0f, 1.0f), Vector3f(0.0f, 0.0f, 0.0f), InterpolationCurves.SQRT),
|
||||
Triple(Vector3f(0.0f, 0.0f, 0.0f), Vector3f(3.0f, 3.0f, 3.0f), InterpolationCurves.SQRT)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -4,20 +4,31 @@ import org.joml.Vector2f
|
||||
import org.joml.Vector3f
|
||||
|
||||
sealed class SpawningShape {
|
||||
data class CIRCLE(val radius: Float = 1.0f) : SpawningShape()
|
||||
data class RECT (val size: Vector2f = Vector2f(1.0f, 1.0f)) : SpawningShape()
|
||||
data class CUBE (val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f)) : SpawningShape()
|
||||
data class SPHERE(val radius: Float = 1.0f) : SpawningShape()
|
||||
data object POINT : SpawningShape()
|
||||
data class Circle(val radius: Float = 1.0f) : SpawningShape()
|
||||
data class Rect (val size: Vector2f = Vector2f(1.0f, 1.0f)) : SpawningShape()
|
||||
data class Cube (val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f)) : SpawningShape()
|
||||
data class Sphere(val radius: Float = 1.0f) : SpawningShape()
|
||||
data object Point : SpawningShape()
|
||||
}
|
||||
|
||||
sealed class ForceFieldShape {
|
||||
data class SPHERE(
|
||||
data class Sphere(
|
||||
val radius: Float = 3.0f,
|
||||
val force: Pair<Float, Float> = Pair(0.0f, 0.02f),
|
||||
) : ForceFieldShape()
|
||||
data class CUBE(
|
||||
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
||||
val forceDir: Vector3f = Vector3f(0.0f, 0.0f, 0.0f)
|
||||
data class Cube(
|
||||
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
||||
val dir: Vector3f = Vector3f(0.0f, 0.0f, -1.0f),
|
||||
val force: Pair<Float, Float> = Pair(0.0f, 0.02f)
|
||||
) : ForceFieldShape()
|
||||
data class Cone(
|
||||
val size: Vector2f = Vector2f(1.0f, 1.0f),
|
||||
val dir: Vector3f = Vector3f(0.0f, 0.0f, -1.0f),
|
||||
val force: Pair<Float, Float> = Pair(0.0f, 0.02f)
|
||||
)
|
||||
data class Cylinder(
|
||||
val size: Vector3f = Vector3f(1.0f, 1.0f, 1.0f),
|
||||
val dir: Vector3f = Vector3f(0.0f, 0.0f, -1.0f),
|
||||
val force: Pair<Float, Float> = Pair(0.0f, 0.02f)
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user