From af073a0829c079a54592a038cca7eff07dec8ecd Mon Sep 17 00:00:00 2001 From: soypat Date: Mon, 16 Sep 2024 18:41:28 -0300 Subject: [PATCH] add plant pot and fix revolve operation --- cpu_evaluators.go | 2 +- examples/gasket/main.go | 2 +- examples/plantpot/main.go | 98 +++++++++++++++++++++++++++++++++++++++ glrender/octree.go | 3 +- gsdf2d.go | 17 +++---- 5 files changed, 111 insertions(+), 11 deletions(-) create mode 100644 examples/plantpot/main.go diff --git a/cpu_evaluators.go b/cpu_evaluators.go index ba2845b..2ea8ad3 100644 --- a/cpu_evaluators.go +++ b/cpu_evaluators.go @@ -526,7 +526,7 @@ func (e *revolution) Evaluate(pos []ms3.Vec, dist []float32, userData any) error if err != nil { return err } - sdf, err := gleval.AssertSDF2(e.s) + sdf, err := gleval.AssertSDF2(e.s2d) if err != nil { return err } diff --git a/examples/gasket/main.go b/examples/gasket/main.go index 95f5c1a..3396317 100644 --- a/examples/gasket/main.go +++ b/examples/gasket/main.go @@ -25,7 +25,7 @@ func init() { runtime.LockOSThread() // In case we wish to use OpenGL. } -// scene returns the showerhead object. +// scene returns the gasket 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 diff --git a/examples/plantpot/main.go b/examples/plantpot/main.go new file mode 100644 index 0000000..90b9440 --- /dev/null +++ b/examples/plantpot/main.go @@ -0,0 +1,98 @@ +package main + +import ( + "flag" + "fmt" + "log" + + "runtime" + + "os" + + math "github.com/chewxy/math32" + "github.com/soypat/glgl/math/ms2" + "github.com/soypat/gsdf" + "github.com/soypat/gsdf/glbuild" + "github.com/soypat/gsdf/gsdfaux" +) + +const ( + exampleName = "plantpot" + stl = exampleName + ".stl" + visualization = exampleName + ".glsl" + visualization2D = exampleName + ".png" + potBaseRadius = 40. +) + +func init() { + runtime.LockOSThread() // In case we wish to use OpenGL. +} + +// scenePotBase returns the plant pot base object. +func scenePotBase() (glbuild.Shader3D, error) { + const ( + baseHeight = 10. + baseInclinationDeg = 45. + baseInclination = baseInclinationDeg * math.Pi / 180 //Convert to radians. + baseWallThick = 5. + baseLipRadius = baseWallThick * .54 + ) + + xOff := baseHeight * math.Sin(baseInclination) + var poly ms2.PolygonBuilder + poly.AddXY(0, 0) + poly.AddXY(potBaseRadius, 0) + poly.AddXY(potBaseRadius+xOff, baseHeight) + poly.AddRelativeXY(baseWallThick/3, -baseWallThick).Arc(-baseLipRadius, 20) + poly.AddXY(potBaseRadius+baseWallThick/2, -baseWallThick) + poly.AddXY(0, -baseWallThick) + verts, err := poly.AppendVecs(nil) + if err != nil { + return nil, err + } + poly2, err := gsdf.NewPolygon(verts) + if err != nil { + return nil, err + } + err = gsdfaux.RenderPNGFile(visualization2D, poly2, 1080, false, gsdfaux.ColorConversionInigoQuilez(poly2.Bounds().Diagonal()/3)) + if err != nil { + return nil, err + } + return gsdf.Revolve(poly2, 0) +} + +func run() error { + useGPU := flag.Bool("gpu", false, "Enable GPU usage") + flag.Parse() + object, err := scenePotBase() + 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(exampleName, "example done") +} diff --git a/glrender/octree.go b/glrender/octree.go index b03d59c..673b054 100644 --- a/glrender/octree.go +++ b/glrender/octree.go @@ -90,7 +90,8 @@ func (oc *Octree) Reset(s gleval.SDF3, cubeResolution float32) error { } // Scale the bounding box about the center to make sure the boundaries // aren't on the object surface. - bb := s.Bounds() + scaling := ms3.Vec{X: 1.01, Y: 1.01, Z: 1.01} + bb := s.Bounds().ScaleCentered(scaling) topCube, origin, err := makeICube(bb, cubeResolution) if err != nil { return err diff --git a/gsdf2d.go b/gsdf2d.go index c570cf7..8cc1a80 100644 --- a/gsdf2d.go +++ b/gsdf2d.go @@ -343,24 +343,25 @@ func Revolve(s glbuild.Shader2D, axisOffset float32) (glbuild.Shader3D, error) { } else if axisOffset < 0 { return nil, errors.New("negative axis offset") } - return &revolution{s: s, off: axisOffset}, nil + return &revolution{s2d: s, off: axisOffset}, nil } type revolution struct { - s glbuild.Shader2D + s2d glbuild.Shader2D off float32 } func (r *revolution) Bounds() ms3.Box { - b2 := r.s.Bounds() + b2 := r.s2d.Bounds() + radius := math32.Max(0, b2.Max.X-r.off) return ms3.Box{ - Min: ms3.Vec{X: b2.Min.X, Y: b2.Min.Y, Z: -r.off}, - Max: ms3.Vec{X: b2.Max.X, Y: b2.Max.Y, Z: r.off}, // TODO + Min: ms3.Vec{X: -radius, Y: b2.Min.Y, Z: -radius}, + Max: ms3.Vec{X: radius, Y: b2.Max.Y, Z: radius}, // TODO } } func (r *revolution) ForEach2DChild(userData any, fn func(userData any, s *glbuild.Shader2D) error) error { - return fn(userData, &r.s) + return fn(userData, &r.s2d) } func (r *revolution) ForEachChild(userData any, fn func(userData any, s *glbuild.Shader3D) error) error { return nil @@ -368,14 +369,14 @@ func (r *revolution) ForEachChild(userData any, fn func(userData any, s *glbuild func (r *revolution) AppendShaderName(b []byte) []byte { b = append(b, "revolution_"...) - b = r.s.AppendShaderName(b) + b = r.s2d.AppendShaderName(b) return b } func (r *revolution) AppendShaderBody(b []byte) []byte { b = glbuild.AppendFloatDecl(b, "w", r.off) b = append(b, "vec2 q = vec2( length(p.xz) - w, p.y );\n"...) - b = glbuild.AppendDistanceDecl(b, "d", "q", r.s) + b = glbuild.AppendDistanceDecl(b, "d", "q", r.s2d) b = append(b, "return d;"...) return b }