Skip to content

Commit

Permalink
add gasket example and symmetry2D
Browse files Browse the repository at this point in the history
  • Loading branch information
soypat committed Aug 31, 2024
1 parent 8e5acea commit b381839
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 1 deletion.
28 changes: 28 additions & 0 deletions cpu_evaluators.go
Original file line number Diff line number Diff line change
Expand Up @@ -825,3 +825,31 @@ func (t *translate2D) Evaluate(pos []ms2.Vec, dist []float32, userData any) erro
}
return sdf.Evaluate(transformed, dist, userData)
}

func (s *symmetry2D) Evaluate(pos []ms2.Vec, dist []float32, userData any) error {
sdf, err := gleval.AssertSDF2(s.s)
if err != nil {
return err
}
vp, err := gleval.GetVecPool(userData)
if err != nil {
return err
}
transformed := vp.V2.Acquire(len(pos))
copy(transformed, pos)
defer vp.V2.Release(transformed)
xb, yb := s.xy.X(), s.xy.Y()
for i, p := range transformed {
if xb {
transformed[i].X = absf(p.X)
}
if yb {
transformed[i].Y = absf(p.Y)
}
}
err = sdf.Evaluate(transformed, dist, userData)
if err != nil {
return err
}
return nil
}
118 changes: 118 additions & 0 deletions examples/gasket/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package main

import (
"flag"
"fmt"
"log"
"runtime"
"time"

"os"

"github.com/soypat/glgl/math/ms2"
"github.com/soypat/gsdf"
"github.com/soypat/gsdf/glbuild"
"github.com/soypat/gsdf/gsdfaux"
)

const (
stl = "gasket.stl"
visualization = "gasket.glsl"
visualization2D = "gasket2D.png"
)

func init() {
runtime.LockOSThread() // In case we wish to use OpenGL.
}

// scene returns the showerhead object.
func scene() (glbuild.Shader3D, error) {
// Sistema Food Storage Container geometry definitions.
// The problem we are trying to solve is how the container is not airtight
// due to the o-ring not sealing against the lid. We can aid the o-ring
// by adding a gasket that sits in the lid so that it fills the empty space
// between lid and o-ring. This particular example is for the common 1 liter tupper.
const (
tupperW = 96.
tupperL = 156.
tupperLStartRound = 154.
channelW = 4.15
round = 10.
extRound = round + 1.2*channelW
channelWall = 0.78
tupperLArcRadius = tupperL * 2.4
extTupperLArcRadius = tupperLArcRadius + channelW
)
// Our gasket constructive geometry definitions.
const (
gasketHeight = 1
tol = 0.8 // remove material from channel walls.
eps = 1 + tol // Prevent from offset from opening symmetry edges.
)

var poly ms2.PolygonBuilder
poly.AddXY(tupperL/2, -eps)
poly.AddXY(tupperLStartRound/2, tupperW/2-round).Arc(tupperLArcRadius, 5)
poly.AddXY(tupperLStartRound/2-round, tupperW/2).Arc(round, 6)
poly.AddXY(-eps, tupperW/2)
poly.AddXY(-eps, tupperW/2+channelW)
poly.AddXY(tupperLStartRound/2-round, tupperW/2+channelW)
poly.AddXY(tupperLStartRound/2+channelW, tupperW/2-2*channelW).Arc(-extRound, 6)
poly.AddXY(tupperL/2+channelW, -eps).Arc(-extTupperLArcRadius, 5)

verts, err := poly.AppendVecs(nil)
if err != nil {
return nil, err
}
poly2, err := gsdf.NewPolygon(verts)
if err != nil {
return nil, err
}
poly2 = gsdf.Symmetry2D(poly2, true, true)
poly2 = gsdf.Offset2D(poly2, tol)
if visualization2D != "" {
start := time.Now()
err = gsdfaux.RenderPNGFile(visualization2D, poly2, 500, false, nil)
if err != nil {
return nil, err
}
fmt.Println("wrote 2D visualization to", visualization2D, "in", time.Since(start))
}
return gsdf.Extrude(poly2, gasketHeight)
}

func run() error {
useGPU := flag.Bool("gpu", false, "Enable GPU usage")
flag.Parse()
object, err := scene()
if err != nil {
return err
}
fpstl, err := os.Create(stl)
if err != nil {
return err
}
defer fpstl.Close()
fpvis, err := os.Create(visualization)
if err != nil {
return err
}
defer fpvis.Close()

err = gsdfaux.Render(object, gsdfaux.RenderConfig{
STLOutput: fpstl,
VisualOutput: fpvis,
Resolution: object.Bounds().Diagonal() / 350,
UseGPU: *useGPU,
})

return err
}

func main() {
err := run()
if err != nil {
log.Fatal(err)
}
fmt.Println("gasket example done")
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.22.1
require (
github.com/chewxy/math32 v1.11.0
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71
github.com/soypat/glgl v0.0.0-20240825222736-8a9aeb4f4a8f
github.com/soypat/glgl v0.0.0-20240831170050-86f4279df7c9
)

require (
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ github.com/soypat/glgl v0.0.0-20240825114214-5f981c176edb h1:pcHDn+P2dG5wf0f65OV
github.com/soypat/glgl v0.0.0-20240825114214-5f981c176edb/go.mod h1:ltzeLFgrGFBm2SBy10lH5IonqEdg9IkL30yam6QHMRs=
github.com/soypat/glgl v0.0.0-20240825222736-8a9aeb4f4a8f h1:TzJXvi/Y8E96YM8ZzTk8gtD5J6EJOOras1q617qoAAQ=
github.com/soypat/glgl v0.0.0-20240825222736-8a9aeb4f4a8f/go.mod h1:ltzeLFgrGFBm2SBy10lH5IonqEdg9IkL30yam6QHMRs=
github.com/soypat/glgl v0.0.0-20240831170050-86f4279df7c9 h1:uEm1bHTWa8mY77k/VVaUcCyKn/ZtpLXMN5Xg4eCrsMw=
github.com/soypat/glgl v0.0.0-20240831170050-86f4279df7c9/go.mod h1:ltzeLFgrGFBm2SBy10lH5IonqEdg9IkL30yam6QHMRs=
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30 h1:m9O6OTJ627iFnN2JIWfdqlZCzneRO6EEBsHXI25P8ws=
golang.org/x/exp v0.0.0-20221230185412-738e83a70c30/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
52 changes: 52 additions & 0 deletions gsdf2d.go
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,11 @@ type offset2D struct {
}

func (u *offset2D) Bounds() ms2.Box {
// TODO: this does not seem right. Removing if statement breaks gasket example STL.
bb := u.s.Bounds()
if u.f > 0 {
return bb
}
bb.Max = ms2.AddScalar(-u.f, bb.Max)
bb.Min = ms2.AddScalar(u.f, bb.Min)
return bb
Expand Down Expand Up @@ -694,3 +698,51 @@ func (s *translate2D) AppendShaderBody(b []byte) []byte {
b = append(b, "(p-t);"...)
return b
}

// Symmetry reflects the SDF around one or more cartesian planes.
func Symmetry2D(s glbuild.Shader2D, mirrorX, mirrorY bool) glbuild.Shader2D {
if !mirrorX && !mirrorY {
panic("ineffective symmetry")
}

return &symmetry2D{s: s, xy: glbuild.NewXYZBits(mirrorX, mirrorY, false)}
}

type symmetry2D struct {
s glbuild.Shader2D
xy glbuild.XYZBits
}

func (u *symmetry2D) Bounds() ms2.Box {
box := u.s.Bounds()
if u.xy.X() {
box.Min.X = minf(box.Min.X, -box.Max.X)
}
if u.xy.Y() {
box.Min.Y = minf(box.Min.Y, -box.Max.Y)
}
return box
}

func (s *symmetry2D) ForEach2DChild(userData any, fn func(userData any, s *glbuild.Shader2D) error) error {
return fn(userData, &s.s)
}

func (s *symmetry2D) AppendShaderName(b []byte) []byte {
b = append(b, "symmetry2D"...)
b = s.xy.AppendMapped_XYZ(b)
b = append(b, '_')
b = s.s.AppendShaderName(b)
return b
}

func (s *symmetry2D) AppendShaderBody(b []byte) []byte {
b = append(b, "p."...)
b = s.xy.AppendMapped_xyz(b)
b = append(b, "=abs(p."...)
b = s.xy.AppendMapped_xyz(b)
b = append(b, ");\n return "...)
b = s.s.AppendShaderName(b)
b = append(b, "(p);"...)
return b
}

0 comments on commit b381839

Please sign in to comment.