"use client" import { Canvas } from '@react-three/fiber' import { OrbitControls } from '@react-three/drei' import { Leva, useControls } from 'leva' import { useMemo, StrictMode } from 'react' import * as THREE from 'three' export const BasementWall = ({ width, wallThk, slabThk, slabElevs }) => { const tw = wallThk / 12 const wallHeight = Math.max(...slabElevs) - Math.min(...slabElevs) const slabWidth = 6 + tw const ftgThk = 1 + tw const ftgWidth = 2 * ftgThk return ( <group> {/* Main wall */} <mesh position={[0, (wallHeight - slabThk) / 2, 0]}> <boxGeometry args={[width, wallHeight - slabThk, tw]} /> <meshStandardMaterial color="#8b8c89" /> </mesh> {/* Footing */} <mesh position={[0, -ftgThk / 2, (tw - ftgWidth) / 2]}> <boxGeometry args={[width, ftgThk, ftgWidth]} /> <meshStandardMaterial color="#a8a9ad" /> </mesh> {/* Slabs */} {slabElevs .filter((e) => e != 0) .map((elev) => ( <mesh key={elev} position={[0, elev - slabThk / 2, -slabWidth / 2 + tw / 2]}> <boxGeometry args={[width * 1.01, slabThk, slabWidth * 1.01]} /> <meshStandardMaterial color="#a8a9ad" /> </mesh> ))} </group> ) } export const Triangle = ({ vertices, color = '#5243aa' }) => { let convertedVertices = vertices.map((v) => new THREE.Vector3(...v)) const f32array = useMemo(() => Float32Array.from(new Array(convertedVertices.length).fill().flatMap((item, index) => convertedVertices[index].toArray())), [vertices]) return ( <mesh position={[0, 0, 0]}> <bufferGeometry attach="geometry"> <bufferAttribute attachObject={['attributes', 'position']} args={[f32array, 3]} /> </bufferGeometry> <meshBasicMaterial attach="material" color={color} wireframe={false} side={THREE.DoubleSide} /> </mesh> ) } export const LateralEarthPressure = ({ qH, qE, slabElevs, wallThk }) => { //make qh ~ 1/3 of H for visibility const SF = 10 / Math.max(qH, qE) const H = Math.max(...slabElevs) const offset = wallThk / 12 const vertices1 = [ [-2, 0, offset], [-2, H, offset], [-2, 0, SF * qH + offset] ] const vertices2 = [ [2, 0, offset], [2, H, offset], [2, H, SF * qE + offset] ] return ( <> <Triangle vertices={vertices2} color="red" /> <Triangle vertices={vertices1} color="blue" /> </> ) } export function Experience() { const { width, wallThk, numFloors, floorHeight, slabThk, qH, qE } = useControls({ slabThk: 1, width: { value: 10, min: 1, max: 50, step: 1 }, wallThk: { value: 12, min: 6, max: 60, step: 1 }, numFloors: { options: [1, 2, 3, 4, 5, 6, 7, 8], value: 3 }, floorHeight: { value: 10, min: 1, max: 50, step: 1 / 12 }, qH: { value: 10, min: 0, max: 50, step: 1 }, qE: { value: 5, min: 0, max: 50, step: 1 } }) let slabElevs = [] for (let aa = 0; aa < numFloors + 1; aa++) { slabElevs.push(aa * floorHeight) } const Hw = Math.max(...slabElevs) const midpoint = [0, Hw / 2, 0] const position = [100, 50, 25] const props = { width, wallThk, numFloors, floorHeight, slabThk, slabElevs, qH, qE } return <> <color attach="background" args={['#2a2b2d']} /> <ambientLight intensity={Math.PI / 2} /> <BasementWall {...props} /> <LateralEarthPressure {...props} /> <OrbitControls enableDamping dampingFactor={0.25} target={midpoint} /> <gridHelper args={[width + 10, width + 10, '#888888', '#444444']} /> <axesHelper args={[5]} /> </> } export default function App() { return ( <StrictMode> <Leva flat /> <Canvas camera={{ fov: 45, near: 0.1, far: 200, position: [100, 50, 25] }}> <Experience /> </Canvas> </StrictMode> ) }
Comments (0)
Loading comments...