diff --git a/app/src/components/three/AirflowSystem.tsx b/app/src/components/three/AirflowSystem.tsx index 4cee957..4c31a6b 100644 --- a/app/src/components/three/AirflowSystem.tsx +++ b/app/src/components/three/AirflowSystem.tsx @@ -21,7 +21,7 @@ interface AirflowSystemProps { } export function AirflowSystem({ windAngle, width, length, height, permeabilityCase, wallCpe, roofCpe, cpi }: AirflowSystemProps) { - const count = 1000; + const count = 400; // Quantidade reduzida const meshRef = useRef(null); const particles = useMemo(() => { @@ -33,7 +33,7 @@ export function AirflowSystem({ windAngle, width, length, height, permeabilityCa Math.random() * (height * 3), (Math.random() - 0.5) * (length * 4) ), - baseSpeed: 0.15 + Math.random() * 0.2, + baseSpeed: 0.10 + Math.random() * 0.08, // Velocidade reduzida em ~20% wobbleSpeed: Math.random() * 0.05, wobbleOffset: Math.random() * Math.PI * 2, currentCpe: 0, @@ -61,8 +61,8 @@ export function AirflowSystem({ windAngle, width, length, height, permeabilityCa if (!meshRef.current) return; const time = state.clock.elapsedTime; - // Agora 0° é paralelo à Parede A e bate na Parede C (Eixo X) - // E 90° é paralelo à Parede C e bate na Parede A (Eixo Z) + // 0° = Eixo X + // 90° = Eixo Z const isZAxis = windAngle === 90; const windDir = isZAxis ? new THREE.Vector3(0, 0, 1) : new THREE.Vector3(1, 0, 0); @@ -87,6 +87,46 @@ export function AirflowSystem({ windAngle, width, length, height, permeabilityCa const inY = py >= 0 && py <= height; const aboveRoof = py > height && py <= height + 3 && inX && inZ; + // ====== FLUXO AERODINÂMICO (CONTORNO DO TELHADO) ====== + // Modifica o Y para subir antes do prédio e descer na esteira de sucção + const speedModifier = Math.max(0.2, 1 - (p.currentCpe * 0.5)); + const currentSpeed = p.baseSpeed * speedModifier; + + if (windAngle === 0 && Math.abs(pz) < halfL + margin * 2) { + if (px < -halfW && px > -halfW - height * 2) { + // Subindo antes de bater (Barlavento) + const dist = (-halfW - px); + const lift = Math.max(0, (height - py)) / (dist + 1); + deflectY += lift * currentSpeed * 0.5; + } else if (px >= -halfW && px <= 0 && py > height - 1) { + // Subindo no telhado (1ª Água) + deflectY += currentSpeed * 0.3; + } else if (px > 0 && px <= halfW && py > height - 1) { + // Descendo no telhado (2ª Água) + deflectY -= currentSpeed * 0.2; + } else if (px > halfW && px < halfW + height * 2) { + // Turbilhão de descida (Sotavento) + deflectY -= currentSpeed * 0.3; + } + } else if (windAngle === 90 && Math.abs(px) < halfW + margin * 2) { + if (pz < -halfL && pz > -halfL - height * 2) { + // Subindo antes de bater (Barlavento) + const dist = (-halfL - pz); + const lift = Math.max(0, (height - py)) / (dist + 1); + deflectY += lift * currentSpeed * 0.5; + } else if (pz >= -halfL && pz <= 0 && py > height - 1) { + // Subindo no telhado (1ª Água) + deflectY += currentSpeed * 0.3; + } else if (pz > 0 && pz <= halfL && py > height - 1) { + // Descendo no telhado (2ª Água) + deflectY -= currentSpeed * 0.2; + } else if (pz > halfL && pz < halfL + height * 2) { + // Turbilhão de descida (Sotavento) + deflectY -= currentSpeed * 0.3; + } + } + // ======================================================= + if (inY && inX && inZ) { // Perto das paredes if (Math.abs(pz - (-halfL)) < margin) localCpe = wallCpe.A; @@ -95,32 +135,27 @@ export function AirflowSystem({ windAngle, width, length, height, permeabilityCa else if (Math.abs(px - (halfW)) < margin) localCpe = wallCpe.D; else localCpe = cpi; - // Colisão: Expulsar as partículas do interior com força (Desvio realístico) + // Colisão dura (Impede entrar na parede sólida) const isAirtight = permeabilityCase !== 'four-equally-permeable'; if (isAirtight) { if (windAngle === 90 && pz < -halfL + margin) { - deflectY = p.baseSpeed * 2.0; // Levanta pro telhado - deflectX = px > 0 ? p.baseSpeed * 2.0 : -p.baseSpeed * 2.0; // Contorna laterais - p.position.z -= p.baseSpeed * 1.5; // Impede de avançar + deflectY += p.baseSpeed * 2.0; + deflectX += px > 0 ? p.baseSpeed * 2.0 : -p.baseSpeed * 2.0; + p.position.z -= p.baseSpeed * 1.5; } else if (windAngle === 0 && px < -halfW + margin) { - deflectY = p.baseSpeed * 2.0; // Levanta pro telhado - deflectZ = pz > 0 ? p.baseSpeed * 2.0 : -p.baseSpeed * 2.0; // Contorna laterais - p.position.x -= p.baseSpeed * 1.5; // Impede de avançar + deflectY += p.baseSpeed * 2.0; + deflectZ += pz > 0 ? p.baseSpeed * 2.0 : -p.baseSpeed * 2.0; + p.position.x -= p.baseSpeed * 1.5; } } } else if (aboveRoof) { localCpe = roofAvgCpe; - // Turbulência de vórtice severo no telhado - p.position.y += Math.sin(time * 5 + p.wobbleOffset) * 0.05; + p.position.y += Math.sin(time * 5 + p.wobbleOffset) * 0.05; // Vórtice } // Suaviza a transição de Cpe para a cor fluir p.currentCpe += (localCpe - p.currentCpe) * 0.1; - // Modifica velocidade com base no Cpe (Pressão > 0 diminui, Sucção < 0 aumenta) - const speedModifier = Math.max(0.2, 1 - (p.currentCpe * 0.5)); - const currentSpeed = p.baseSpeed * speedModifier; - // Move a partícula p.position.x += windDir.x * currentSpeed + deflectX; p.position.y += deflectY; @@ -176,11 +211,11 @@ export function AirflowSystem({ windAngle, width, length, height, permeabilityCa return ( - + {/* Partículas ultra finas */}