frontend/src/bin/3dView/BinParts/BinShell.tsx

140 lines
No EOL
4.8 KiB
TypeScript

import Circle, { CircleGeometry } from "3dModels/Shapes/3D/Circle"
import Cone, { ConeGeometry } from "3dModels/Shapes/3D/Cone"
import Cylinder, { CylinderGeometry } from "3dModels/Shapes/3D/Cylinder"
import React from "react"
import { Euler, Vector3 } from "three"
interface Props {
radialSegments: number
binBodyColour: string
binMetalness: number
binRoughness: number
binOpacity: number
diameter: number
sidewallHeight: number
roofHeight: number
hopperHeight?: number
wireframe?: boolean
renderOrder?: number
}
export default function BinShell(props: Props) {
const { radialSegments, binBodyColour, binMetalness, binRoughness, binOpacity, diameter, sidewallHeight, roofHeight, hopperHeight, wireframe, renderOrder } = props
const cylinderGeometry = React.useMemo(() => ({
radiusTop: diameter / 2,
radiusBottom: diameter / 2,
height: sidewallHeight,
radialSegments,
heightSegments: 2,
openEnded: true,
} as CylinderGeometry), [diameter, sidewallHeight, radialSegments]);
const roofGeometry = React.useMemo(() => ({
height: roofHeight,
radius: diameter /2,
radialSegments: radialSegments,
openEnded: true
} as ConeGeometry), [diameter, roofHeight, radialSegments])
const hopperGeometry = React.useMemo(() => ({
height: hopperHeight,
radius: diameter /2,
radialSegments: radialSegments,
openEnded: true
} as ConeGeometry),[hopperHeight, diameter, radialSegments])
const flatBottomGeometry = React.useMemo(() => ({
radius: diameter/2,
radialSegments: radialSegments
} as CircleGeometry),[diameter, radialSegments])
const roofPosition = React.useMemo(
() => new Vector3(0, sidewallHeight/2 + roofHeight/2, 0),
[sidewallHeight, roofHeight]
);
const bottomPosition = React.useMemo(
() => {
if(hopperHeight !== undefined && hopperHeight > 0){
//this returns the position for the center of the cone for the hopper
return new Vector3(0, (sidewallHeight/2 + hopperHeight/2)*-1, 0)
} else {
//this returns the position for the circle for the flat bottom
return new Vector3(0, -sidewallHeight/2, 0)
}
},
[sidewallHeight, hopperHeight]
)
const hopperRotation = React.useMemo(
() => new Euler(Math.PI, 0, 0),
[]
);
const flatBottomRotation = React.useMemo(
() => new Euler(-Math.PI / 2, 0, 0),
[]
);
return (
<React.Fragment>
{/* bin roof - cone */}
<Cone
geometry={roofGeometry}
colour={binBodyColour}
wireframe= {wireframe}
metalness={binMetalness}
position={roofPosition}
roughness={binRoughness}
side={2}
opacity={binOpacity}
depthWrite={false}
depthTest={false}
renderOrder={renderOrder}/>
{/* bin sidewall - cylinder (open ended for the roof and bottom)*/}
<Cylinder
geometry={cylinderGeometry}
colour={binBodyColour}
wireframe= {wireframe}
metalness={binMetalness}
roughness={binRoughness}
opacity={binOpacity}
depthWrite={false}
depthTest={false}
renderOrder={renderOrder}/>
{/* bin bottom - cone -OR- circle depending on the bins shape*/}
{hopperHeight !== undefined && hopperHeight > 0 ?
<Cone
geometry={hopperGeometry}
colour={binBodyColour}
wireframe= {wireframe}
metalness={binMetalness}
position={bottomPosition}
rotation={hopperRotation}
roughness={binRoughness}
opacity={binOpacity}
side={2}
depthWrite={false}
depthTest={false}
renderOrder={renderOrder}
/>
:
<Circle
geometry={flatBottomGeometry}
colour={binBodyColour}
wireframe= {wireframe}
metalness={binMetalness}
position={bottomPosition}
rotation={flatBottomRotation}
roughness={binRoughness}
opacity={binOpacity}
side={2}
depthWrite={false}
depthTest={false}
renderOrder={renderOrder}
/>
}
</React.Fragment>
)
}