demos
This commit is contained in:
@@ -278,6 +278,130 @@ export function useParticleSystem() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建增强型火焰发射器 - 用于大型中心火焰效果
|
||||
*/
|
||||
function createIntenseFireEmitter(
|
||||
scene: THREE.Scene,
|
||||
position: THREE.Vector3,
|
||||
emissionRate = 50,
|
||||
spreadRadius = 2,
|
||||
) {
|
||||
const texture = createFlameTexture()
|
||||
const particles: Particle[] = []
|
||||
let emissionCounter = 0
|
||||
|
||||
function emit() {
|
||||
for (let i = 0; i < emissionRate; i++) {
|
||||
const particlePos = position.clone()
|
||||
|
||||
// 在圆形区域内随机分布
|
||||
const angle = Math.random() * Math.PI * 2
|
||||
const radius = Math.random() * spreadRadius
|
||||
particlePos.x += Math.cos(angle) * radius
|
||||
particlePos.z += Math.sin(angle) * radius
|
||||
|
||||
// 多样化的火焰颜色
|
||||
const colorVariation = Math.random()
|
||||
let color: number
|
||||
if (colorVariation < 0.3) {
|
||||
color = 0xFFFFFF // 白色(最热)
|
||||
}
|
||||
else if (colorVariation < 0.6) {
|
||||
color = 0xFFDD00 // 黄色
|
||||
}
|
||||
else if (colorVariation < 0.85) {
|
||||
color = 0xFF8800 // 橙色
|
||||
}
|
||||
else {
|
||||
color = 0xFF2200 // 红色
|
||||
}
|
||||
|
||||
// 粒子大小和速度变化
|
||||
const sizeVariation = 0.3 + Math.random() * 0.5
|
||||
const speedVariation = 0.05 + Math.random() * 0.1
|
||||
|
||||
const particle = createParticle(texture, particlePos, {
|
||||
color,
|
||||
opacity: 0.6 + Math.random() * 0.3,
|
||||
size: sizeVariation,
|
||||
velocity: new THREE.Vector3(
|
||||
(Math.random() - 0.5) * 0.08,
|
||||
speedVariation,
|
||||
(Math.random() - 0.5) * 0.08,
|
||||
),
|
||||
maxAge: 40 + Math.floor(Math.random() * 30),
|
||||
})
|
||||
scene.add(particle.sprite)
|
||||
particles.push(particle)
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
// 更新现有粒子
|
||||
for (let i = particles.length - 1; i >= 0; i--) {
|
||||
const particle = particles[i]
|
||||
if (!particle)
|
||||
continue
|
||||
|
||||
// 自定义更新逻辑以增强视觉效果
|
||||
particle.sprite.position.add(particle.velocity)
|
||||
|
||||
// 添加轻微的湍流效果
|
||||
particle.velocity.x += (Math.random() - 0.5) * 0.002
|
||||
particle.velocity.z += (Math.random() - 0.5) * 0.002
|
||||
|
||||
particle.age++
|
||||
|
||||
// 更新大小和透明度
|
||||
const lifeRatio = particle.age / particle.maxAge
|
||||
const initialSize = 0.3
|
||||
// 火焰先变大后缩小
|
||||
const sizeFactor = Math.sin(lifeRatio * Math.PI) * 2 + 1
|
||||
particle.sprite.scale.setScalar(initialSize * sizeFactor)
|
||||
|
||||
// 透明度渐变
|
||||
particle.sprite.material.opacity = 0.8 * (1 - lifeRatio * lifeRatio)
|
||||
|
||||
// 颜色渐变(从亮到暗)
|
||||
const material = particle.sprite.material as THREE.SpriteMaterial
|
||||
if (lifeRatio > 0.5) {
|
||||
const darkening = (lifeRatio - 0.5) * 2
|
||||
material.color.lerp(new THREE.Color(0x440000), darkening * 0.5)
|
||||
}
|
||||
|
||||
const shouldRemove = particle.age >= particle.maxAge
|
||||
|
||||
if (shouldRemove) {
|
||||
scene.remove(particle.sprite)
|
||||
particle.sprite.material.dispose()
|
||||
particles.splice(i, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 控制发射频率
|
||||
emissionCounter++
|
||||
if (emissionCounter >= 1) {
|
||||
emit()
|
||||
emissionCounter = 0
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
particles.forEach((particle) => {
|
||||
scene.remove(particle.sprite)
|
||||
particle.sprite.material.dispose()
|
||||
})
|
||||
particles.length = 0
|
||||
}
|
||||
|
||||
return {
|
||||
update,
|
||||
stop,
|
||||
particles,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
createSmokeTexture,
|
||||
createFlameTexture,
|
||||
@@ -285,5 +409,6 @@ export function useParticleSystem() {
|
||||
updateParticle,
|
||||
createEmitter,
|
||||
createFlameEmitter,
|
||||
createIntenseFireEmitter,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,6 +304,19 @@ function spreadFire() {
|
||||
}
|
||||
}
|
||||
|
||||
// 移除初始着火点的火焰
|
||||
function removeInitialFire() {
|
||||
// 找到并移除 pingt01_0019_pCylinder10001 的火焰发射器
|
||||
for (let i = flameEmitters.length - 1; i >= 0; i--) {
|
||||
const { emitter, mesh } = flameEmitters[i]
|
||||
if (mesh && mesh.name === 'pingt01_0019_pCylinder10001') {
|
||||
emitter.stop()
|
||||
flameEmitters.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建中心大火效果
|
||||
function createCenterFire() {
|
||||
if (!model)
|
||||
@@ -311,6 +324,9 @@ function createCenterFire() {
|
||||
|
||||
const particleUtils = useParticleSystem()
|
||||
|
||||
// 先移除初始着火点
|
||||
removeInitialFire()
|
||||
|
||||
// 移除所有小火焰发射器
|
||||
flameEmitters.forEach(({ emitter }) => {
|
||||
emitter.stop()
|
||||
@@ -323,23 +339,41 @@ function createCenterFire() {
|
||||
const modelCenter = modelBox.getCenter(new THREE.Vector3())
|
||||
const modelSize = modelBox.getSize(new THREE.Vector3())
|
||||
|
||||
// 在中心创建大型火焰发射器
|
||||
centerFireEmitter = particleUtils.createFlameEmitter(
|
||||
// 在中心创建大型火焰发射器 - 使用增强版
|
||||
centerFireEmitter = particleUtils.createIntenseFireEmitter(
|
||||
scene,
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y + modelSize.y * 0.3, modelCenter.z),
|
||||
30, // 大量粒子
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y, modelCenter.z),
|
||||
80, // 更多粒子
|
||||
modelSize.x * 0.5, // 扩散范围
|
||||
)
|
||||
|
||||
// 添加多个位置的火焰,模拟整体燃烧
|
||||
// 添加多层火焰效果,模拟整体燃烧
|
||||
const layers = [
|
||||
{ y: modelBox.min.y, count: 60, spread: modelSize.x * 0.4 },
|
||||
{ y: modelBox.min.y + modelSize.y * 0.3, count: 50, spread: modelSize.x * 0.3 },
|
||||
{ y: modelBox.min.y + modelSize.y * 0.6, count: 40, spread: modelSize.x * 0.2 },
|
||||
]
|
||||
|
||||
layers.forEach((layer) => {
|
||||
const emitter = particleUtils.createIntenseFireEmitter(
|
||||
scene,
|
||||
new THREE.Vector3(modelCenter.x, layer.y, modelCenter.z),
|
||||
layer.count,
|
||||
layer.spread,
|
||||
)
|
||||
flameEmitters.push({ emitter, mesh: null })
|
||||
})
|
||||
|
||||
// 四周添加火焰柱
|
||||
const positions = [
|
||||
new THREE.Vector3(modelBox.min.x, modelBox.min.y + 1, modelCenter.z),
|
||||
new THREE.Vector3(modelBox.max.x, modelBox.min.y + 1, modelCenter.z),
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y + 1, modelBox.min.z),
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y + 1, modelBox.max.z),
|
||||
new THREE.Vector3(modelBox.min.x, modelBox.min.y, modelCenter.z),
|
||||
new THREE.Vector3(modelBox.max.x, modelBox.min.y, modelCenter.z),
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y, modelBox.min.z),
|
||||
new THREE.Vector3(modelCenter.x, modelBox.min.y, modelBox.max.z),
|
||||
]
|
||||
|
||||
positions.forEach((pos) => {
|
||||
const emitter = particleUtils.createFlameEmitter(scene, pos, 20)
|
||||
const emitter = particleUtils.createIntenseFireEmitter(scene, pos, 40, modelSize.x * 0.15)
|
||||
flameEmitters.push({ emitter, mesh: null })
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user