package objects import ( "github.com/deadsy/sdfx/sdf" "math" ) type BoxParams struct { Size sdf.V3 // internal box size Wall float64 // wall thickness BottomTopRatio float64 // ratio between the height of the top and the bottom CornerRadius float64 // radius of rounded corners Taper float64 // angle of split ClosingHeight float64 // height of the closing Margin float64 // Margin for closing Text string } func Box3D(k *BoxParams) (top sdf.SDF3, bottom sdf.SDF3, err error) { top, err = TopBox3D(k) bottom, err = TopBox3D(k) if err != nil { return } return } func baseBox3D(k *BoxParams) (sdf.SDF3, error) { box, err := sdf.Box3D(k.Size.AddScalar(k.Wall*2), k.CornerRadius) if err != nil { return nil, err } return box, nil } func TopBox3D(k *BoxParams) (top sdf.SDF3, err error) { box, err := baseBox3D(k) if err != nil { return } a := sdf.V3{X: 0, Y: 0, Z: 0.5 - k.BottomTopRatio}.Mul(k.Size).Add(sdf.V3{X: 0, Y: 0, Z: k.ClosingHeight / 2}) n := sdf.V3{X: 0, Y: 0, Z: 1} top = sdf.Cut3D(box, a, n) closing, err := InnerClosing(k) if err != nil { return } top = sdf.Union3D(top,closing) return } func BottomBox3D(k *BoxParams) (bottom sdf.SDF3, err error) { box, err := baseBox3D(k) if err != nil { return } a := sdf.V3{X: 0, Y: 0, Z: 0.5 - k.BottomTopRatio}.Mul(k.Size).Add(sdf.V3{X: 0, Y: 0, Z: k.ClosingHeight / 2}) n := sdf.V3{X: 0, Y: 0, Z: -1} bottom = sdf.Cut3D(box, a, n) closing, err := InnerClosing(k) scale := k.Size.Add(sdf.V3{X: k.Margin, Y: k.Margin, Z: 0}).Div(k.Size) closing = sdf.Transform3D(closing, sdf.Scale3d(scale)) if err != nil { return } bottom = sdf.Difference3D(bottom,closing) return } func InnerClosing(k *BoxParams) (closing sdf.SDF3, err error) { offset := math.Tan(k.Taper) * k.ClosingHeight / 2 size := sdf.V2{X: k.Size.X, Y: k.Size.Y} s1 := sdf.Box2D(size.AddScalar(k.Wall-offset), k.CornerRadius) s2 := sdf.Box2D(size.AddScalar(k.Wall+offset), k.CornerRadius) closing, err = sdf.Loft3D(s1, s2, k.ClosingHeight, 0) if err != nil { return } closing = sdf.Transform3D(closing, sdf.Translate3d(sdf.V3{0,0,0.5-k.BottomTopRatio}.Mul(k.Size))) return } func OuterClosing(k *BoxParams) (closing sdf.SDF3, err error) { s0, err := InnerClosing(k) if err != nil { return } s1, err := baseBox3D(k) if err != nil { return } a := sdf.V3{0, 0, k.ClosingHeight / 2} n := sdf.V3{0, 0, -1} s1 = sdf.Cut3D(s1, a, n) s1 = sdf.Cut3D(s1, a.Neg(), n.Neg()) closing = sdf.Difference3D(s1, s0) return }