🚀 Auto-deploy: BrainWind atualizado em 14/07/2026 15:18:53

This commit is contained in:
2026-07-14 15:18:53 +00:00
parent c07016ab82
commit 4e0b26f1c4
14 changed files with 1580 additions and 158 deletions
+36 -32
View File
@@ -55,48 +55,52 @@ function PiperackModel({
);
}
// Viga Longitudinal da fileira
// Viga Longitudinal da fileira (representando a face reticulada do pórtico)
frames.push(
<mesh key={`beam-${i}`} position={[0, elevation, z]} receiveShadow castShadow>
<boxGeometry args={[width, height, 0.3]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
{/* Opacidade ajustada para atingir 90% quando a solidez for 1.0 */}
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={Math.max(0.1, Math.min(0.9, phiTotal * 0.9))} depthWrite={false} />
</mesh>
);
}
// Vigas transversais conectando as fileiras nas pontas
if (numFrames > 1) {
frames.push(
<mesh key={`cross-1`} position={[-halfW, elevation, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, height, totalSpacing]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
);
frames.push(
<mesh key={`cross-2`} position={[halfW, elevation, 0]} receiveShadow castShadow>
<boxGeometry args={[0.3, height, totalSpacing]} />
<meshStandardMaterial color={steelColor} metalness={0.6} roughness={0.4} transparent opacity={phiTotal} />
</mesh>
);
}
// Gera as tubulações correndo longitudinalmente (ao longo de X)
const pipeMeshes = pipes.map((pipe, idx) => {
// Distribui os tubos ao longo do espaçamento transversal (Z)
const zPos = numFrames > 1
? -zOffset + 0.5 + (idx % Math.max(pipes.length, 1)) * (totalSpacing - 1) / Math.max(pipes.length - 1, 1) || 0
: 0;
// elevationOffset varia de 0 (base da estrutura reticulada) a height (topo da estrutura)
// A base da estrutura fica em: rackTop - height, que é elevation - height/2
const yPos = (elevation - height/2) + pipe.elevationOffset + pipe.diameter/2;
const color = pipeColors[idx % pipeColors.length];
// Agrupa tubos pela mesma elevação para evitar colisões e distribuí-los lado a lado (ao longo de Z)
const pipeMeshes: any[] = [];
const groups: Record<number, {pipe: PipeDef, idx: number}[]> = {};
pipes.forEach((pipe, idx) => {
// Arredondamos a elevação para agrupar valores muito próximos
const key = Math.round(pipe.elevationOffset * 100) / 100;
if (!groups[key]) groups[key] = [];
groups[key].push({pipe, idx});
});
return (
<mesh key={`pipe-${pipe.id}`} position={[0, yPos, zPos]} rotation={[0, 0, Math.PI / 2]} receiveShadow castShadow>
<cylinderGeometry args={[pipe.diameter / 2, pipe.diameter / 2, width + 1, 16]} />
<meshStandardMaterial color={color} metalness={0.3} roughness={0.2} />
</mesh>
);
Object.values(groups).forEach(group => {
const gap = 0.2; // 20cm de espaçamento entre tubos na mesma elevação
const totalDiam = group.reduce((sum, item) => sum + item.pipe.diameter, 0);
const totalGroupWidth = totalDiam + gap * (group.length - 1);
// Inicia a distribuição centralizada em Z=0
let currentZ = -totalGroupWidth / 2;
group.forEach((item) => {
const { pipe, idx } = item;
const zPos = currentZ + pipe.diameter / 2;
currentZ += pipe.diameter + gap;
const yPos = (elevation - height/2) + pipe.elevationOffset + pipe.diameter/2;
const color = pipeColors[idx % pipeColors.length];
pipeMeshes.push(
<mesh key={`pipe-${pipe.id}`} position={[0, yPos, zPos]} rotation={[0, 0, Math.PI / 2]} receiveShadow castShadow>
<cylinderGeometry args={[pipe.diameter / 2, pipe.diameter / 2, width + 1, 16]} />
<meshStandardMaterial color={color} metalness={0.3} roughness={0.2} />
</mesh>
);
});
});
return (