Skip to content

Commit

Permalink
pruning implementation finished
Browse files Browse the repository at this point in the history
  • Loading branch information
soypat committed Aug 18, 2024
1 parent afca739 commit 03aad5e
Show file tree
Hide file tree
Showing 8 changed files with 414 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ vendor/
*.hex
# `__debug_bin` Debug binary generated in VSCode when using the built-in debugger.
*bin
*/__debug_bin*

# IDE
.vscode/
Expand Down
2 changes: 2 additions & 0 deletions examples/npt-flange/flange.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ func main() {
fmt.Println("error rendering triangles:", err)
os.Exit(1)
}
evals := sdf.(interface{ Evaluations() uint64 }).Evaluations()
fmt.Println("evaluated sdf", evals, "times")
fp, err := os.Create("nptflange.stl")
if err != nil {
fmt.Println("error creating file:", err)
Expand Down
2 changes: 1 addition & 1 deletion examples/test/glsdf3test.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ var SmoothBinaryOps = []func(a, b glbuild.Shader3D, k float32) glbuild.Shader3D{
}

var OtherUnaryRandomizedOps = []func(a glbuild.Shader3D, rng *rand.Rand) glbuild.Shader3D{
randomRotation,
// randomRotation,
randomShell,
randomElongate,
randomRound,
Expand Down
12 changes: 10 additions & 2 deletions gleval/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func NewCPUSDF3(root bounder3) (*SDF3CPU, error) {
if err != nil {
return nil, err
}

return &sdfcpu, nil
}

Expand All @@ -52,13 +53,16 @@ func AssertSDF2(s bounder2) (SDF2, error) {
}

type SDF3CPU struct {
SDF SDF3
vp VecPool
SDF SDF3
vp VecPool
evals uint64
}

func (sdf *SDF3CPU) Evaluate(pos []ms3.Vec, dist []float32, userData any) error {
if userData == nil {
userData = &sdf.vp
} else if len(pos) != len(dist) {
return errors.New("position and distance buffer length mismatch")
}
err := sdf.SDF.Evaluate(pos, dist, userData)
err2 := sdf.vp.AssertAllReleased()
Expand All @@ -71,13 +75,17 @@ func (sdf *SDF3CPU) Evaluate(pos []ms3.Vec, dist []float32, userData any) error
if err2 != nil {
return err2
}
sdf.evals += uint64(len(pos))
return nil
}

func (sdf *SDF3CPU) Bounds() ms3.Box {
return sdf.SDF.Bounds()
}

// Evaluations returns total evaluations performed succesfully during sdf's lifetime.
func (sdf *SDF3CPU) Evaluations() uint64 { return sdf.evals }

// VecPool method exposes the SDF3CPU's VecPool in case user wishes to use their own userData in evaluations.
func (sdf *SDF3CPU) VecPool() *VecPool { return &sdf.vp }

Expand Down
18 changes: 14 additions & 4 deletions gleval/gpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,18 @@ func NewComputeGPUSDF3(glglSourceCode io.Reader, bb ms3.Box) (*SDF3Compute, erro
}

type SDF3Compute struct {
prog glgl.Program
bb ms3.Box
prog glgl.Program
bb ms3.Box
evals uint64
}

func (sdf *SDF3Compute) Bounds() ms3.Box {
return sdf.bb
}

// Evaluations returns total evaluations performed succesfully during sdf's lifetime.
func (sdf *SDF3Compute) Evaluations() uint64 { return sdf.evals }

func (sdf *SDF3Compute) Evaluate(pos []ms3.Vec, dist []float32, userData any) error {
sdf.prog.Bind()
defer sdf.prog.Unbind()
Expand Down Expand Up @@ -94,6 +98,7 @@ func (sdf *SDF3Compute) Evaluate(pos []ms3.Vec, dist []float32, userData any) er
if err != nil {
return err
}
sdf.evals += uint64(len(pos))
return nil
}

Expand All @@ -115,14 +120,18 @@ func NewComputeGPUSDF2(glglSourceCode io.Reader, bb ms2.Box) (*SDF2Compute, erro
}

type SDF2Compute struct {
prog glgl.Program
bb ms2.Box
prog glgl.Program
bb ms2.Box
evals uint64
}

func (sdf *SDF2Compute) Bounds() ms2.Box {
return sdf.bb
}

// Evaluations returns total evaluations performed succesfully during sdf's lifetime.
func (sdf *SDF2Compute) Evaluations() uint64 { return sdf.evals }

func (sdf *SDF2Compute) Evaluate(pos []ms2.Vec, dist []float32, userData any) error {
sdf.prog.Bind()
defer sdf.prog.Unbind()
Expand Down Expand Up @@ -167,5 +176,6 @@ func (sdf *SDF2Compute) Evaluate(pos []ms2.Vec, dist []float32, userData any) er
if err != nil {
return err
}
sdf.evals += uint64(len(pos))
return nil
}
54 changes: 37 additions & 17 deletions glrender/glrender.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,41 +41,61 @@ type ivec struct {
z int
}

func (a ivec) Add(b ivec) ivec { return ivec{x: a.x + b.x, y: a.y + b.y, z: a.z + b.z} }
func (a ivec) AddScalar(f int) ivec { return ivec{x: a.x + f, y: a.y + f, z: a.z + f} }
func (a ivec) ScaleMul(f int) ivec { return ivec{x: a.x * f, y: a.y * f, z: a.z * f} }
func (a ivec) ScaleDiv(f int) ivec { return ivec{x: a.x / f, y: a.y / f, z: a.z / f} }
func (a ivec) Sub(b ivec) ivec { return ivec{x: a.x - b.x, y: a.y - b.y, z: a.z - b.z} }
func (a ivec) Vec() ms3.Vec { return ms3.Vec{X: float32(a.x), Y: float32(a.y), Z: float32(a.z)} }
func (a ivec) Add(b ivec) ivec { return ivec{x: a.x + b.x, y: a.y + b.y, z: a.z + b.z} }
func (a ivec) AddScalar(f int) ivec { return ivec{x: a.x + f, y: a.y + f, z: a.z + f} }
func (a ivec) ScaleMul(f int) ivec { return ivec{x: a.x * f, y: a.y * f, z: a.z * f} }
func (a ivec) ScaleDiv(f int) ivec { return ivec{x: a.x / f, y: a.y / f, z: a.z / f} }
func (a ivec) ShiftRight(lo int) ivec { return ivec{x: a.x >> lo, y: a.y >> lo, z: a.z >> lo} }
func (a ivec) ShiftLeft(hi int) ivec { return ivec{x: a.x << hi, y: a.y << hi, z: a.z << hi} }
func (a ivec) Sub(b ivec) ivec { return ivec{x: a.x - b.x, y: a.y - b.y, z: a.z - b.z} }
func (a ivec) Vec() ms3.Vec { return ms3.Vec{X: float32(a.x), Y: float32(a.y), Z: float32(a.z)} }

type icube struct {
ivec
lvl int
}

func (c icube) isSmallest() bool { return c.lvl == 1 }

func (c icube) size(baseRes float32) float32 {
dim := 1 << (c.lvl - 1)
return float32(dim) * baseRes
}

func (c icube) box(origin ms3.Vec, size float32) ms3.Box {
origin = c.origin(origin, size) // Replace origin with icube origin.
return ms3.Box{
Min: ms3.Add(origin, ms3.Scale(size, c.ivec.Vec())),
Max: ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{2, 2, 2}).Vec())),
Min: origin,
Max: ms3.AddScalar(size, origin),
}
}

// corners returns the cube corners.
func (c icube) origin(origin ms3.Vec, size float32) ms3.Vec {
idx := c.lvlIdx()
return ms3.Add(origin, ms3.Scale(size, idx.Vec()))
}

func (c icube) lvlIdx() ivec {
return c.ivec.ShiftRight(c.lvl) // icube indices per level in the octree.
}

func (c icube) center(origin ms3.Vec, size float32) ms3.Vec {
return c.box(origin, size).Center()
}

// corners returns the cube corners. Be aware size is NOT the minimum cube resolution but
// can be calculated with the [icube.size] method using resolution. If [icube.lvl]==1 then size is resolution.
func (c icube) corners(origin ms3.Vec, size float32) [8]ms3.Vec {
origin = c.origin(origin, size)
return [8]ms3.Vec{
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{0, 0, 0}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{2, 0, 0}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{2, 2, 0}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{0, 2, 0}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{0, 0, 2}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{2, 0, 2}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{2, 2, 2}).Vec())),
ms3.Add(origin, ms3.Scale(size, c.ivec.Add(ivec{0, 2, 2}).Vec())),
ms3.Add(origin, ms3.Vec{X: 0, Y: 0, Z: 0}),
ms3.Add(origin, ms3.Vec{X: size, Y: 0, Z: 0}),
ms3.Add(origin, ms3.Vec{X: size, Y: size, Z: 0}),
ms3.Add(origin, ms3.Vec{X: 0, Y: size, Z: 0}),
ms3.Add(origin, ms3.Vec{X: 0, Y: 0, Z: size}),
ms3.Add(origin, ms3.Vec{X: size, Y: 0, Z: size}),
ms3.Add(origin, ms3.Vec{X: size, Y: size, Z: size}),
ms3.Add(origin, ms3.Vec{X: 0, Y: size, Z: size}),
}
}

Expand Down
80 changes: 80 additions & 0 deletions glrender/glrender_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package glrender

import (
"os"
"testing"

"github.com/chewxy/math32"
"github.com/soypat/glgl/math/ms3"
"github.com/soypat/gsdf"
"github.com/soypat/gsdf/glbuild"
)

func TestIcube(t *testing.T) {
const tol = 1e-4
const LVLs = 4
const RES = 1.0
const maxdim = RES * (1 << (LVLs - 1))
bb := ms3.Box{Max: ms3.Vec{X: maxdim, Y: maxdim, Z: maxdim}}
topcube, origin, err := makeICube(bb, RES)
if err != nil {
t.Error(err)
}
if origin != (ms3.Vec{}) {
t.Error("expected origin at (0,0,0)")
}
t.Error("truebb", bb)
levelsVisual("levels.glsl", topcube, 3, origin, RES)

subcubes := topcube.octree()
t.Error("top", topcube.lvl, topcube.lvlIdx(), topcube.box(origin, topcube.size(RES)), topcube.size(RES))
for i, subcube := range subcubes {
subsize := subcube.size(RES)
subbox := subcube.box(origin, subsize)
size := subbox.Size()
if math32.Abs(size.Max()-subsize) > tol || math32.Abs(size.Min()-subsize) > tol {
t.Error("size mismatch", size, subsize)
}
t.Error("sub", subcube.lvl, subcube.lvlIdx(), subbox, subsize)
if (i == 0 || i == 1) && subcube.lvl > 1 {
subcube = subcube.octree()[1]
t.Error("subsub", subcube.lvl, subcube.lvlIdx(), subcube.box(origin, subcube.size(RES)), subcube.size(RES))
}
}
levels := topcube.lvl
_ = levels
}

func levelsVisual(filename string, startCube icube, targetLvl int, origin ms3.Vec, res float32) {
topBB := startCube.box(origin, startCube.size(res))
cubes := []icube{startCube}
i := 0
for cubes[i].lvl > targetLvl {
subcubes := cubes[i].octree()
cubes = append(cubes, subcubes[:]...)
i++
}
cubes = cubes[i:]
bb, _ := gsdf.NewBoundsBoxFrame(topBB)
s, _ := gsdf.NewSphere(res)
s = gsdf.Translate(s, origin.X, origin.Y, origin.Z)
s = gsdf.Union(bb, s)
for _, c := range cubes {
bb, err := gsdf.NewBoundsBoxFrame(c.box(origin, c.size(res)))
if err != nil {
panic(err)
}
s = gsdf.Union(s, bb)
}
s = gsdf.Scale(s, 0.5/s.Bounds().Size().Max())
glbuild.RewriteNames3D(&s, 8)
prog := glbuild.NewDefaultProgrammer()
fp, err := os.Create(filename)
if err != nil {
panic(err)
}
_, err = prog.WriteFragVisualizerSDF3(fp, s)
if err != nil {
panic(err)
}
}
Loading

0 comments on commit 03aad5e

Please sign in to comment.