Skip to content

Commit 1c35a77

Browse files
committed
# 修复
修复了Math3DUtil的 rotatePointsToPoint方法中 会出现多余的滚动角的问题 # 示例 更改了火焰粒子发射器的示例
1 parent 85a125d commit 1c35a77

8 files changed

Lines changed: 103 additions & 107 deletions

File tree

src/main/kotlin/cn/coostack/cooparticlesapi/items/TestParticleItem.kt

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import cn.coostack.cooparticlesapi.particles.impl.ControlableCloudEffect
1616
import cn.coostack.cooparticlesapi.particles.impl.TestEndRodEffect
1717
import cn.coostack.cooparticlesapi.test.particle.style.RomaMagicTestStyle
1818
import cn.coostack.cooparticlesapi.test.particle.style.RotateTestStyle
19-
import cn.coostack.cooparticlesapi.utils.CameraUtil
2019
import cn.coostack.cooparticlesapi.utils.Math3DUtil
2120
import net.minecraft.client.particle.ParticleTextureSheet
2221
import net.minecraft.entity.player.PlayerEntity
@@ -26,7 +25,6 @@ import net.minecraft.server.world.ServerWorld
2625
import net.minecraft.util.Hand
2726
import net.minecraft.util.TypedActionResult
2827
import net.minecraft.world.World
29-
import kotlin.math.PI
3028

3129
class TestParticleItem(settings: Settings) : Item(settings) {
3230

@@ -36,7 +34,8 @@ class TestParticleItem(settings: Settings) : Item(settings) {
3634
}
3735
testRotate(world, user)
3836
// CameraUtil.startShakeCamera(240, 0.25)
39-
// testFire(world, user)
37+
// testRomaCircle(world, user)
38+
4039
// 线性阻力
4140
return super.use(world, user, hand)
4241
}
@@ -112,20 +111,20 @@ class TestParticleItem(settings: Settings) : Item(settings) {
112111
}
113112

114113
private fun testFire(world: World, user: PlayerEntity) {
115-
val example = FireClassParticleEmitters(
116-
user.uuid, user.eyePos, world
114+
val part1 = FireClassParticleEmitters(
115+
user.uuid, user.eyePos.add(0.0, -0.5, 0.0), world
117116
).also {
118-
it.maxTick = 120
119-
it.fireSize = 0.4
120-
it.fireForce = 0.01
117+
it.maxTick = -1
121118
it.templateData.apply {
122-
maxAge = 20
119+
maxAge = 30
123120
textureSheet = ParticleTextureSheet.PARTICLE_SHEET_TRANSLUCENT
124121
color = Math3DUtil.colorOf(255, 255, 255)
125122
effect = TestEndRodEffect(uuid)
126123
}
127124
}
128-
ParticleEmittersManager.spawnEmitters(example)
125+
// ParticleEmittersManager.spawnEmitters(example)
126+
127+
ParticleEmittersManager.spawnEmitters(part1)
129128
}
130129

131130

src/main/kotlin/cn/coostack/cooparticlesapi/network/particle/emitters/ParticleEmittersManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,11 @@ object ParticleEmittersManager {
176176
register(PhysicsParticleEmitters.ID, PhysicsParticleEmitters.CODEC)
177177
register(SimpleParticleEmitters.ID, SimpleParticleEmitters.CODEC)
178178
register(ExampleClassParticleEmitters.ID, ExampleClassParticleEmitters.CODEC)
179-
register(FireClassParticleEmitters.ID, FireClassParticleEmitters.CODEC)
180179
register(ExplodeClassParticleEmitters.ID, ExplodeClassParticleEmitters.CODEC)
181180
register(LightningClassParticleEmitters.ID, LightningClassParticleEmitters.CODEC)
182181
register(DefendClassParticleEmitters.ID, DefendClassParticleEmitters.CODEC)
183182
register(PresetTestEmitters.ID, PresetTestEmitters.CODEC)
183+
register(FireClassParticleEmitters.ID, FireClassParticleEmitters.CODEC)
184184
}
185185

186186
}

src/main/kotlin/cn/coostack/cooparticlesapi/network/particle/emitters/impl/FireClassParticleEmitters.kt

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import cn.coostack.cooparticlesapi.network.particle.emitters.ControlableParticle
55
import cn.coostack.cooparticlesapi.network.particle.emitters.ParticleEmitters
66
import cn.coostack.cooparticlesapi.network.particle.emitters.PhysicConstant
77
import cn.coostack.cooparticlesapi.network.particle.emitters.environment.wind.GlobalWindDirection
8-
import cn.coostack.cooparticlesapi.network.particle.emitters.environment.wind.WindDirections
98
import cn.coostack.cooparticlesapi.particles.control.ParticleControler
109
import cn.coostack.cooparticlesapi.utils.Math3DUtil
1110
import cn.coostack.cooparticlesapi.utils.RelativeLocation
@@ -15,21 +14,19 @@ import net.minecraft.network.codec.PacketCodec
1514
import net.minecraft.util.math.Vec3d
1615
import net.minecraft.world.World
1716
import java.util.UUID
18-
import kotlin.math.abs
1917
import kotlin.math.roundToInt
2018
import kotlin.random.Random
21-
import kotlin.random.nextInt
2219

2320
class FireClassParticleEmitters(var player: UUID, pos: Vec3d, world: World?) : ClassParticleEmitters(pos, world) {
2421
var templateData = ControlableParticleData()
2522
var fireSize = 0.5
26-
var fireForce = 1.0
23+
var fireForce = 0.6
2724

2825
init {
2926
airDensity = PhysicConstant.SEA_AIR_DENSITY
3027
// mass = 1000.0
3128
wind = GlobalWindDirection(
32-
Vec3d(0.0, fireForce * 6, 0.0)
29+
Vec3d(0.0, fireForce * 30, 0.0)
3330
)
3431
.loadEmitters(this)
3532
}
@@ -68,6 +65,7 @@ class FireClassParticleEmitters(var player: UUID, pos: Vec3d, world: World?) : C
6865
override fun genParticles(): Map<ControlableParticleData, RelativeLocation> {
6966
val velocityList = PointsBuilder()
7067
.addRoundShape(fireSize, 0.25, 10, (120 * fireSize).roundToInt())
68+
.rotateTo(Vec3d(0.0, 0.0, 1.0))
7169
.pointsOnEach { it.y += 6.0 }
7270
// .rotateTo(
7371
// world!!.getPlayerByUuid(player)!!.rotationVector
@@ -78,17 +76,11 @@ class FireClassParticleEmitters(var player: UUID, pos: Vec3d, world: World?) : C
7876
// 0.0 - 2.0
7977
val step = 1.0
8078
var current = step
81-
while (current < 5.0) {
82-
val minCount = (5 * current).roundToInt()
83-
val maxCount = (10 * current).roundToInt()
84-
val count = random.nextInt(minCount, maxCount)
85-
for (i in 0 until count) {
86-
val it = velocityList.random()
87-
res[templateData.clone().apply {
88-
this.velocity = it.normalize().multiply(fireForce).toVector()
89-
}] = RelativeLocation(0.0, current, 0.0)
90-
}
91-
current += step
79+
for (i in 0 until 60) {
80+
val it = velocityList.random()
81+
res[templateData.clone().apply {
82+
this.velocity = it.normalize().multiply(fireForce).toVector()
83+
}] = RelativeLocation(0.0, current, 0.0)
9284
}
9385
return res
9486
}
@@ -102,27 +94,40 @@ class FireClassParticleEmitters(var player: UUID, pos: Vec3d, world: World?) : C
10294
) {
10395
data.velocity = data.velocity.add(
10496
Vec3d(
105-
random.nextDouble(-fireForce, fireForce),
106-
random.nextDouble(-fireForce, fireForce),
107-
random.nextDouble(-fireForce, fireForce)
108-
).normalize().multiply(0.25)
97+
random.nextDouble(-fireForce * 10, fireForce * 10),
98+
random.nextDouble(-10.0, 10.0),
99+
random.nextDouble(-fireForce * 10, fireForce * 10)
100+
).normalize().multiply(0.125)
109101
)
110102
// data.alpha = 0f
111103
data.color = Math3DUtil.colorOf(
112-
random.nextInt(210, 255),
113-
random.nextInt(100, 120),
114-
random.nextInt(100, 120),
104+
random.nextInt(240, 255),
105+
random.nextInt(160, 180),
106+
random.nextInt(40, 80),
115107
)
116108
val alphaBezier = Math3DUtil.generateBezierCurve(
117109
RelativeLocation(data.maxAge.toDouble(), 0.0, 0.0),
118110
RelativeLocation(0.0, 1.0, 0.0),
119111
RelativeLocation(-data.maxAge.toDouble(), 1.0, 0.0),
120112
data.maxAge
121-
122113
)
123114
val size = alphaBezier.size
115+
val maxY = random.nextDouble(0.6, 0.8)
124116
controler.addPreTickAction {
125-
updatePhysics(controler.particle.pos, data)
117+
// updatePhysics(controler.particle.pos, data)
118+
data.velocity = data.velocity.add(0.0, 0.05, 0.0)
119+
if (data.velocity.y >= maxY) {
120+
data.velocity = Vec3d(data.velocity.x, maxY, data.velocity.z)
121+
}
122+
this.size = 0.3f
123+
// color.x = ((color.x * 255 + currentAge * 10).coerceIn(0.0f, 255.0f))
124+
// color.y = ((color.y * 255 - currentAge * 10).coerceIn(0.0f, 255.0f) / 255f)
125+
// color.z = ((color.z * 255 - currentAge * 10).coerceIn(0.0f, 255.0f) / 255f)
126+
colorOfRGB(
127+
(color.x * 255).coerceIn(0.0f, 255.0f).roundToInt(),
128+
(color.y * 255 - currentAge * 1).coerceIn(0.0f, 255.0f).roundToInt(),
129+
(color.z * 255 - currentAge * 1).coerceIn(0.0f, 255.0f).roundToInt()
130+
)
126131
// val index = currentAge.coerceIn(0, size - 1)
127132
// particleAlpha = alphaBezier[index].y.toFloat()
128133
}

src/main/kotlin/cn/coostack/cooparticlesapi/test/particle/style/RomaMagicTestStyle.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class RomaMagicTestStyle(uuid: UUID = UUID.randomUUID()) :
8787
.addCircle(0.5, 120)
8888
.pointsOnEach {
8989
it.x += 1.5
90-
it.z += 1.5
90+
// it.z += 1.5
9191
}
9292
) {
9393
StyleData {
@@ -98,7 +98,7 @@ class RomaMagicTestStyle(uuid: UUID = UUID.randomUUID()) :
9898
.addCircle(0.5, 120)
9999
.pointsOnEach {
100100
it.x -= 1.5
101-
it.z -= 1.5
101+
// it.z -= 1.5
102102
}
103103
) {
104104
StyleData {
@@ -108,8 +108,8 @@ class RomaMagicTestStyle(uuid: UUID = UUID.randomUUID()) :
108108
PointsBuilder()
109109
.addBezierCurve(
110110
RelativeLocation(6.0, 0.0, 0.0),
111-
RelativeLocation(3.0, 3.0, 0.0),
112-
RelativeLocation(-3.0, -3.0, 0.0),
111+
RelativeLocation(3.0, 3.5, 0.0),
112+
RelativeLocation(-3.0, -3.5, 0.0),
113113
120
114114
)
115115
.pointsOnEach { p -> p.x -= 3.0 }

src/main/kotlin/cn/coostack/cooparticlesapi/test/particle/style/RotateTestStyle.kt

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class RotateTestStyle(val player: UUID, uuid: UUID = UUID.randomUUID()) :
6262
}
6363

6464
override fun onDisplay() {
65+
axis = RelativeLocation.yAxis()
6566
// var x = -PI
6667
// var y = -PI
6768
addPreTickAction {
@@ -82,18 +83,11 @@ class RotateTestStyle(val player: UUID, uuid: UUID = UUID.randomUUID()) :
8283
val loc = player.pos
8384
val relativize = pos.relativize(loc)
8485
rotateParticlesToPoint(
85-
RelativeLocation.of(player.rotationVector)
86+
RelativeLocation.of(relativize)
8687
)
8788
}
8889
}
8990

90-
override fun rotateParticlesToPoint(to: RelativeLocation) {
91-
Math3DUtil.rotatePointsToWithAngle(
92-
particleLocations.values.toList(), to, axis
93-
)
94-
axis = to
95-
toggleRelative()
96-
}
9791

9892
fun rotateParticlesToPoint(yaw: Double, pitch: Double) {
9993
Math3DUtil.rotatePointsToWithAngle(

src/main/kotlin/cn/coostack/cooparticlesapi/utils/Math3DUtil.kt

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package cn.coostack.cooparticlesapi.utils
22

33
import net.minecraft.util.math.Vec3d
4+
import org.joml.Matrix4d
5+
import org.joml.Matrix4f
46
import org.joml.Quaterniond
5-
import org.joml.Quaternionf
67
import org.joml.Vector3d
78
import org.joml.Vector3f
9+
import org.joml.Vector4d
810
import java.util.ArrayList
911
import kotlin.math.*
1012
import kotlin.random.Random
@@ -19,6 +21,7 @@ object Math3DUtil {
1921
return Vector3f(r.toFloat() / 255, g.toFloat() / 255, b.toFloat() / 255)
2022
}
2123

24+
2225
/**
2326
* 闪电
2427
*/
@@ -376,28 +379,41 @@ object Math3DUtil {
376379
* 让图形的对称轴指向某个点(图形跟着转变)
377380
*/
378381
fun rotatePointsToPoint(
379-
locList: List<RelativeLocation>,
382+
shape: List<RelativeLocation>,
380383
toPoint: RelativeLocation,
381384
axis: RelativeLocation
382385
): List<RelativeLocation> {
383386
// 同向共线
384387
if (axis.cross(toPoint).length() in -1e-5..1e-5 && axis.dot(toPoint) > 0) {
385-
return locList
388+
return shape
389+
}
390+
val q = Quaterniond()
391+
// 差值
392+
val na = axis.normalize()
393+
val axisYaw = getYawFromLocation(na)
394+
val axisPitch = getPitchFromLocation(na)
395+
396+
val toa = toPoint.normalize()
397+
val toYaw = getYawFromLocation(toa)
398+
val toPitch = getPitchFromLocation(toa)
399+
// return shape
400+
// 先给点转回去
401+
q.rotateY(axisYaw)
402+
.rotateLocalX(axisPitch)
403+
val toQ = Quaterniond()
404+
.rotateY(-toYaw)
405+
.rotateX(-toPitch)
406+
return shape.onEach {
407+
val vector = Vector3d(it.x, it.y, it.z)
408+
vector.rotate(q)
409+
vector.rotate(toQ)
410+
it.x = vector.x
411+
it.y = vector.y
412+
it.z = vector.z
386413
}
387-
// 计算旋转角度
388-
// 首先,将目标点(toPoint)和当前轴(axis)都归一化
389-
val normalizedAxis = axis.normalize()
390-
val normalizedToPoint = toPoint.normalize()
391-
392-
// 计算两个向量之间的夹角
393-
val angle = acos(normalizedAxis.dot(normalizedToPoint))
394-
395-
// 计算旋转轴,它是当前轴和目标点的叉乘
396-
val rotationAxis = normalizedAxis.cross(normalizedToPoint).normalize()
397-
// 使用rotateAsAxis函数旋转locList
398-
return rotateAsAxis(locList, rotationAxis, angle)
399414
}
400415

416+
401417
/**
402418
* 旋转到对应的yaw和pitch 上
403419
*
@@ -410,42 +426,25 @@ object Math3DUtil {
410426
pitch: Double,
411427
axis: RelativeLocation
412428
): List<RelativeLocation> {
413-
val axisYaw = getYawFromLocation(axis)
414-
val axisPitch = getPitchFromLocation(axis)
415-
val yawDelta = (yaw - axisYaw)
416-
val pitchDelta = -(pitch - axisPitch).coerceIn(
417-
-PI / 2, PI / 2
418-
)
429+
val axisYaw = getYawFromLocation(axis.normalize())
430+
val axisPitch = getPitchFromLocation(axis.normalize())
431+
//
432+
val deltaYaw = yaw - axisYaw
433+
val deltaPitch = pitch - axisPitch
434+
435+
Vector3d(axis.x, axis.y, axis.z)
419436
val q = Quaterniond()
420-
q.rotationXYZ(
421-
-pitchDelta,
422-
yawDelta,
423-
0.0
424-
)
425-
shape.onEach {
426-
val v = Vector3d(it.x,it.y,it.z)
427-
v.rotate(q)
428-
it.x = v.x
429-
it.y = v.y
430-
it.z = v.z
437+
.rotateY(-deltaYaw)
438+
.rotateLocalX(deltaPitch)
439+
return shape.onEach {
440+
val vector = Vector3d(it.x, it.y, it.z)
441+
q.transform(vector)
442+
it.x = vector.x
443+
it.y = vector.y
444+
it.z = vector.z
431445
}
432-
return shape
433-
}
434-
435-
/**
436-
* 旋转到对应的yaw和pitch 上
437-
*/
438-
fun rotatePointsToWithAngle(
439-
shape: List<RelativeLocation>,
440-
to: RelativeLocation,
441-
axis: RelativeLocation
442-
): List<RelativeLocation> {
443-
val toYaw = getYawFromLocation(to)
444-
val toPitch = getPitchFromLocation(to)
445-
return rotatePointsToWithAngle(shape, toYaw, toPitch, axis)
446446
}
447447

448-
449448
/**
450449
* 让图形的对称轴指向某个点(图形跟着转变)
451450
*/
@@ -489,13 +488,13 @@ object Math3DUtil {
489488
}
490489

491490
fun getYawFromLocation(loc: RelativeLocation): Double {
492-
return atan2(loc.z, loc.x)
491+
return atan2(-loc.x, loc.z)
493492
}
494493

495494
fun getPitchFromLocation(v: RelativeLocation): Double {
496-
val length = v.length()
497-
if (length == 0.0) return 0.0
498-
return asin(v.y / length)
495+
// val length = v.length()
496+
// if (length == 0.0) return 0.0
497+
return atan2(v.y, sqrt(v.x.pow(2) + v.z.pow(2)))
499498
}
500499

501500
fun getPitchFromLocation(v: Vec3d): Double {

0 commit comments

Comments
 (0)