Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
fix sdf top level unkeyed fields
Browse files Browse the repository at this point in the history
  • Loading branch information
soypat committed May 15, 2022
1 parent 65c01cd commit eec0546
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 72 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ Here is a rendered bolt from one of the unit tests under [form3_test.go](./rende
![renderedBolt](./render/testdata/defactoBolt.png)

## Roadmap
- [x] Clean up thread API mess
- [ ] Add a 2D renderer and it's respective `Renderer2` interface.
- [ ] Make 3D renderer multicore
- [ ] Clean up thread API mess


## Comparison

Expand Down
12 changes: 6 additions & 6 deletions examples/atx-bench-supply/atx.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,28 @@ func main() {
var outputs, regOut, regBlock sdf.SDF2
// Outputs banana plugs
outputs = sdf.Array2D(bananaPlugBig, sdf.V2i{4, 2}, r2.Vec{-bananaSpacing, bananaSpacing})
outputs = sdf.Transform2D(outputs, sdf.Translate2d(r2.Vec{atxW/2 - 15, -atxH/2 + 15}))
outputs = sdf.Transform2D(outputs, sdf.Translate2D(r2.Vec{atxW/2 - 15, -atxH/2 + 15}))

panel = sdf.Difference2D(panel, sdf.Transform2D(onButton, sdf.Translate2d(r2.Vec{atxW/2 - 25, atxH/2 - 15})))
panel = sdf.Difference2D(panel, sdf.Transform2D(onButton, sdf.Translate2D(r2.Vec{atxW/2 - 25, atxH/2 - 15})))
panel = sdf.Difference2D(panel, outputs)

// Begin working on regulated step-down block
regOut = sdf.Array2D(bananaPlugSmall, sdf.V2i{2, 1}, r2.Vec{bananaSpacing, bananaSpacing})
bplugX := bbSize(regOut.Bounds()).X
vDisp := sdf.Transform2D(voltageDisplay, sdf.Translate2d(r2.Vec{bplugX / 2, vDispH/2 + bananaSpacing/2}))
vDisp := sdf.Transform2D(voltageDisplay, sdf.Translate2D(r2.Vec{bplugX / 2, vDispH/2 + bananaSpacing/2}))
regOut = sdf.Union2D(regOut, vDisp)
regOut = sdf.Transform2D(regOut, sdf.Translate2d(r2.Vec{-atxW/2 - bplugX/2 + vDispW/2 + 12, atxH/2 - 12 - vDispH/2 - bananaSpacing}))
regOut = sdf.Transform2D(regOut, sdf.Translate2D(r2.Vec{-atxW/2 - bplugX/2 + vDispW/2 + 12, atxH/2 - 12 - vDispH/2 - bananaSpacing}))
// Create mound for step up outputs.
regSz := bbSize(regOut.Bounds())
regBlock = form2.Box(r2.Vec{regSz.X + regBlockMargin, regSz.Y + regBlockMargin}, regBlockMargin/2)
regBlock = sdf.Transform2D(regBlock, sdf.Translate2d(bbCenter(regOut.Bounds())))
regBlock = sdf.Transform2D(regBlock, sdf.Translate2D(bbCenter(regOut.Bounds())))
regBlock = sdf.Difference2D(regBlock, regOut)
regBlock3 := sdf.Extrude3D(regBlock, panelThickness+regBlockDepth) // extrude does it both ways.
regBlock3 = sdf.Transform3D(regBlock3, sdf.Translate3D(r3.Vec{0, 0, regBlockDepth / 2}))
panel = sdf.Difference2D(panel, regOut)

// Speaker clamps
scHole := sdf.Transform2D(speakerClamps, sdf.Translate2d(r2.Vec{-atxW/2 + spkClampW/2 + 12, -atxH/2 + spkClampH/2 + 12}))
scHole := sdf.Transform2D(speakerClamps, sdf.Translate2D(r2.Vec{-atxW/2 + spkClampW/2 + 12, -atxH/2 + spkClampH/2 + 12}))
panel = sdf.Difference2D(panel, scHole)

// Generate model
Expand Down
22 changes: 11 additions & 11 deletions matrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ func Translate3D(v r3.Vec) m44 {
0, 0, 0, 1}
}

// Translate2d returns a 3x3 translation matrix.
func Translate2d(v r2.Vec) m33 {
// Translate2D returns a 3x3 translation matrix.
func Translate2D(v r2.Vec) m33 {
return m33{
1, 0, v.X,
0, 1, v.Y,
Expand Down Expand Up @@ -284,14 +284,14 @@ func (a m22) equals(b m22, tolerance float64) bool {

// MulPosition multiplies a V2 position with a rotate/translate matrix.
func (a m33) MulPosition(b r2.Vec) r2.Vec {
return r2.Vec{a.x00*b.X + a.x01*b.Y + a.x02,
a.x10*b.X + a.x11*b.Y + a.x12}
return r2.Vec{X: a.x00*b.X + a.x01*b.Y + a.x02,
Y: a.x10*b.X + a.x11*b.Y + a.x12}
}

// MulPosition multiplies a V2 position with a rotate matrix.
func (a m22) MulPosition(b r2.Vec) r2.Vec {
return r2.Vec{a.x00*b.X + a.x01*b.Y,
a.x10*b.X + a.x11*b.Y}
return r2.Vec{X: a.x00*b.X + a.x01*b.Y,
Y: a.x10*b.X + a.x11*b.Y}
}

// MulVertices multiples a set of V2 vertices by a rotate/translate matrix.
Expand Down Expand Up @@ -414,14 +414,14 @@ func (a m44) MulBox(box r3.Box) r3.Box {
za, zb = d3.MinElem(za, zb), d3.MaxElem(za, zb)
min := xa.Add(ya).Add(za).Add(t)
max := xb.Add(yb).Add(zb).Add(t)
return r3.Box{min, max}
return r3.Box{Min: min, Max: max}
}

// MulBox rotates/translates a 2d bounding box and resizes for axis-alignment.
func (a m33) MulBox(box r2.Box) r2.Box {
r := r2.Vec{a.x00, a.x10}
u := r2.Vec{a.x01, a.x11}
t := r2.Vec{a.x02, a.x12}
r := r2.Vec{X: a.x00, Y: a.x10}
u := r2.Vec{X: a.x01, Y: a.x11}
t := r2.Vec{X: a.x02, Y: a.x12}
xa := r2.Scale(box.Min.X, r)
xb := r2.Scale(box.Max.X, r)
ya := r2.Scale(box.Min.Y, u)
Expand All @@ -430,7 +430,7 @@ func (a m33) MulBox(box r2.Box) r2.Box {
ya, yb = d2.MinElem(ya, yb), d2.MaxElem(ya, yb)
min := xa.Add(ya).Add(t)
max := xb.Add(yb).Add(t)
return r2.Box{min, max}
return r2.Box{Min: min, Max: max}
}

// Determinant returns the determinant of a 4x4 matrix.
Expand Down
23 changes: 12 additions & 11 deletions sdf2.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func Cut2D(sdf SDF2, a, v r2.Vec) SDF2 {
s.sdf = sdf
s.a = a
v = r2.Unit(v)
s.n = r2.Vec{-v.Y, v.X}
s.n = r2.Vec{X: -v.Y, Y: v.X}
// TODO - cut the bounding box
s.bb = sdf.Bounds()
return &s
Expand Down Expand Up @@ -127,7 +127,7 @@ type ScaleUniformSDF2 struct {
// ScaleUniform2D scales an SDF2 by k on each axis.
// Distance is correct with scaling.
func ScaleUniform2D(sdf SDF2, k float64) SDF2 {
m := Scale2d(r2.Vec{k, k})
m := Scale2d(r2.Vec{X: k, Y: k})
return &ScaleUniformSDF2{
sdf: sdf,
k: k,
Expand All @@ -150,14 +150,14 @@ func (s *ScaleUniformSDF2) Bounds() r2.Box {
// Center2D centers the origin of an SDF2 on it's bounding box.
func Center2D(s SDF2) SDF2 {
ofs := r2.Scale(-1, d2.Box(s.Bounds()).Center())
return Transform2D(s, Translate2d(ofs))
return Transform2D(s, Translate2D(ofs))
}

// CenterAndScale2D centers the origin of an SDF2 on it's bounding box, and then scales it.
// Distance is correct with scaling.
func CenterAndScale2D(s SDF2, k float64) SDF2 {
ofs := r2.Scale(-1, d2.Box(s.Bounds()).Center())
s = Transform2D(s, Translate2d(ofs))
s = Transform2D(s, Translate2D(ofs))
return ScaleUniform2D(s, k)
}

Expand Down Expand Up @@ -201,7 +201,7 @@ func (s *array2) Evaluate(p r2.Vec) float64 {
d := math.MaxFloat64
for j := 0; j < s.num[0]; j++ {
for k := 0; k < s.num[1]; k++ {
x := p.Sub(r2.Vec{float64(j) * s.step.X, float64(k) * s.step.Y})
x := p.Sub(r2.Vec{X: float64(j) * s.step.X, Y: float64(k) * s.step.Y})
d = s.min(d, s.sdf.Evaluate(x))
}
}
Expand Down Expand Up @@ -243,7 +243,7 @@ func RotateUnion2D(sdf SDF2, num int, step m33) SDF2 {
bbMax = d2.MaxElem(bbMax, vset.Max())
MulVertices2(vset, step)
}
s.bb = r2.Box{bbMin, bbMax}
s.bb = r2.Box{Min: bbMin, Max: bbMax}
return &s
}

Expand Down Expand Up @@ -295,7 +295,8 @@ func RotateCopy2D(sdf SDF2, n int) SDF2 {
rmax = l
}
}
s.bb = r2.Box{r2.Vec{-rmax, -rmax}, r2.Vec{rmax, rmax}}
max := r2.Vec{X: rmax, Y: rmax}
s.bb = r2.Box{Min: r2.Scale(-1, max), Max: max}
return &s
}

Expand Down Expand Up @@ -351,9 +352,9 @@ func Slice2D(sdf SDF3, a, n r3.Vec) SDF2 {
va := v.Sub(s.a)
pa := va.Sub(r3.Scale(r3.Dot(n, va), n))
// work out the 3d point in terms of the 2d unit vectors
vec[i] = r2.Vec{pa.Dot(s.u), pa.Dot(s.v)}
vec[i] = r2.Vec{X: pa.Dot(s.u), Y: pa.Dot(s.v)}
}
s.bb = r2.Box{vec.Min(), vec.Max()}
s.bb = r2.Box{Min: vec.Min(), Max: vec.Max()}
return &s
}

Expand Down Expand Up @@ -558,7 +559,7 @@ func LineOf2D(s SDF2, p0, p1 r2.Vec, pattern string) SDF2 {
dx = r2.Scale(1/float64(len(pattern)), dx)
for _, c := range pattern {
if c == 'x' {
objects = append(objects, Transform2D(s, Translate2d(x)))
objects = append(objects, Transform2D(s, Translate2D(x)))
}
x = x.Add(dx)
}
Expand All @@ -579,7 +580,7 @@ func Multi2D(s SDF2, positions d2.Set) SDF2 {
}
objects := make([]SDF2, len(positions))
for i, p := range positions {
objects[i] = Transform2D(s, Translate2d(p))
objects[i] = Transform2D(s, Translate2D(p))
}
return Union2D(objects...)
}
Expand Down
58 changes: 29 additions & 29 deletions sdf3.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,39 +61,39 @@ func Revolve3D(sdf SDF2, theta float64) SDF3 {
sin := math.Sin(s.theta)
cos := math.Cos(s.theta)
// pre-calculate the normal to the theta line
s.norm = r2.Vec{-sin, cos}
s.norm = r2.Vec{X: -sin, Y: cos}
// work out the bounding box
var vset d2.Set
if theta == 0 {
vset = []r2.Vec{{1, 1}, {-1, -1}}
vset = []r2.Vec{{X: 1, Y: 1}, {X: -1, Y: -1}}
} else {
vset = []r2.Vec{{0, 0}, {1, 0}, {cos, sin}}
vset = []r2.Vec{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: cos, Y: sin}}
if s.theta > 0.5*pi {
vset = append(vset, r2.Vec{0, 1})
vset = append(vset, r2.Vec{X: 0, Y: 1})
}
if s.theta > pi {
vset = append(vset, r2.Vec{-1, 0})
vset = append(vset, r2.Vec{X: -1, Y: 0})
}
if s.theta > 1.5*pi {
vset = append(vset, r2.Vec{0, -1})
vset = append(vset, r2.Vec{X: 0, Y: -1})
}
}
bb := s.sdf.Bounds()
l := math.Max(math.Abs(bb.Min.X), math.Abs(bb.Max.X))
vmin := r2.Scale(l, vset.Min())
vmax := r2.Scale(l, vset.Max())
s.bb = r3.Box{r3.Vec{vmin.X, vmin.Y, bb.Min.Y}, r3.Vec{vmax.X, vmax.Y, bb.Max.Y}}
s.bb = r3.Box{Min: r3.Vec{X: vmin.X, Y: vmin.Y, Z: bb.Min.Y}, Max: r3.Vec{X: vmax.X, Y: vmax.Y, Z: bb.Max.Y}}
return &s
}

// Evaluate returns the minimum distance to a solid of revolution.
func (s *revolution3) Evaluate(p r3.Vec) float64 {
x := math.Sqrt(p.X*p.X + p.Y*p.Y)
a := s.sdf.Evaluate(r2.Vec{x, p.Z})
a := s.sdf.Evaluate(r2.Vec{X: x, Y: p.Z})
b := a
if s.theta != 0 {
// combine two vertical planes to give an intersection wedge
d := s.norm.Dot(r2.Vec{p.X, p.Y})
d := s.norm.Dot(r2.Vec{X: p.X, Y: p.Y})
if s.theta < pi {
b = math.Max(-p.Y, d) // intersect
} else {
Expand Down Expand Up @@ -125,7 +125,7 @@ func Extrude3D(sdf SDF2, height float64) SDF3 {
s.extrude = NormalExtrude
// work out the bounding box
bb := sdf.Bounds()
s.bb = r3.Box{r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, r3.Vec{bb.Max.X, bb.Max.Y, s.height}}
s.bb = r3.Box{Min: r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, Max: r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}}
return &s
}

Expand All @@ -138,7 +138,7 @@ func TwistExtrude3D(sdf SDF2, height, twist float64) SDF3 {
// work out the bounding box
bb := sdf.Bounds()
l := r2.Norm(bb.Max)
s.bb = r3.Box{r3.Vec{-l, -l, -s.height}, r3.Vec{l, l, s.height}}
s.bb = r3.Box{Min: r3.Vec{X: -l, Y: -l, Z: -s.height}, Max: r3.Vec{X: l, Y: l, Z: s.height}}
return &s
}

Expand All @@ -150,8 +150,8 @@ func ScaleExtrude3D(sdf SDF2, height float64, scale r2.Vec) SDF3 {
s.extrude = ScaleExtrude(height, scale)
// work out the bounding box
bb := d2.Box(sdf.Bounds())
bb = bb.Extend(d2.Box{d2.MulElem(bb.Min, scale), d2.MulElem(bb.Max, scale)})
s.bb = r3.Box{r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, r3.Vec{bb.Max.X, bb.Max.Y, s.height}}
bb = bb.Extend(d2.Box{Min: d2.MulElem(bb.Min, scale), Max: d2.MulElem(bb.Max, scale)})
s.bb = r3.Box{Min: r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, Max: r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}}
return &s
}

Expand All @@ -163,9 +163,9 @@ func ScaleTwistExtrude3D(sdf SDF2, height, twist float64, scale r2.Vec) SDF3 {
s.extrude = ScaleTwistExtrude(height, twist, scale)
// work out the bounding box
bb := d2.Box(sdf.Bounds())
bb = bb.Extend(d2.Box{d2.MulElem(bb.Min, scale), d2.MulElem(bb.Max, scale)})
bb = bb.Extend(d2.Box{Min: d2.MulElem(bb.Min, scale), Max: d2.MulElem(bb.Max, scale)})
l := r2.Norm(bb.Max)
s.bb = r3.Box{r3.Vec{-l, -l, -s.height}, r3.Vec{l, l, s.height}}
s.bb = r3.Box{Min: r3.Vec{X: -l, Y: -l, Z: -s.height}, Max: r3.Vec{X: l, Y: l, Z: s.height}}
return &s
}

Expand Down Expand Up @@ -223,16 +223,16 @@ func ExtrudeRounded3D(sdf SDF2, height, round float64) SDF3 {
// work out the bounding box
bb := sdf.Bounds()
s.bb = r3.Box{
Min: r3.Sub(r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, d3.Elem(round)),
Max: r3.Add(r3.Vec{bb.Max.X, bb.Max.Y, s.height}, d3.Elem(round)),
Min: r3.Sub(r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, d3.Elem(round)),
Max: r3.Add(r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}, d3.Elem(round)),
}
return &s
}

// Evaluate returns the minimum distance to a rounded extrusion.
func (s *extrudeRounded) Evaluate(p r3.Vec) float64 {
// sdf for the projected 2d surface
a := s.sdf.Evaluate(r2.Vec{p.X, p.Y})
a := s.sdf.Evaluate(r2.Vec{X: p.X, Y: p.Y})
b := math.Abs(p.Z) - s.height
var d float64
if b > 0 {
Expand Down Expand Up @@ -296,8 +296,8 @@ func Loft3D(sdf0, sdf1 SDF2, height, round float64) SDF3 {
bb1 := d2.Box(sdf1.Bounds())
bb := bb0.Extend(bb1)
s.bb = r3.Box{
Min: r3.Sub(r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, d3.Elem(round)),
Max: r3.Add(r3.Vec{bb.Max.X, bb.Max.Y, s.height}, d3.Elem(round))}
Min: r3.Sub(r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, d3.Elem(round)),
Max: r3.Add(r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}, d3.Elem(round))}
return &s
}

Expand All @@ -306,8 +306,8 @@ func (s *loft3) Evaluate(p r3.Vec) float64 {
// work out the mix value as a function of height
k := clamp((0.5*p.Z/s.height)+0.5, 0, 1)
// mix the 2D SDFs
a0 := s.sdf0.Evaluate(r2.Vec{p.X, p.Y})
a1 := s.sdf1.Evaluate(r2.Vec{p.X, p.Y})
a0 := s.sdf0.Evaluate(r2.Vec{X: p.X, Y: p.Y})
a1 := s.sdf1.Evaluate(r2.Vec{X: p.X, Y: p.Y})
a := mix(a0, a1, k)

b := math.Abs(p.Z) - s.height
Expand Down Expand Up @@ -384,7 +384,7 @@ type scaleUniform3 struct {

// ScaleUniform3D uniformly scales an SDF3 on all axes.
func ScaleUniform3D(sdf SDF3, k float64) SDF3 {
m := Scale3d(r3.Vec{k, k, k})
m := Scale3d(r3.Vec{X: k, Y: k, Z: k})
return &scaleUniform3{
sdf: sdf,
k: k,
Expand Down Expand Up @@ -637,7 +637,7 @@ func (s *array3) Evaluate(p r3.Vec) float64 {
for j := 0; j < s.num[0]; j++ {
for k := 0; k < s.num[1]; k++ {
for l := 0; l < s.num[2]; l++ {
x := p.Sub(r3.Vec{float64(j) * s.step.X, float64(k) * s.step.Y, float64(l) * s.step.Z})
x := p.Sub(r3.Vec{X: float64(j) * s.step.X, Y: float64(k) * s.step.Y, Z: float64(l) * s.step.Z})
d = s.min(d, s.sdf.Evaluate(x))
}
}
Expand Down Expand Up @@ -681,7 +681,7 @@ func RotateUnion3D(sdf SDF3, num int, step m44) SDF3Union {
mulVertices3(v, step)
// v.MulVertices(step)
}
s.bb = r3.Box{bbMin, bbMax}
s.bb = r3.Box{Min: bbMin, Max: bbMax}
return &s
}

Expand Down Expand Up @@ -737,16 +737,16 @@ func RotateCopy3D(sdf SDF3, num int) SDF3 {
rmax = l
}
}
s.bb = r3.Box{r3.Vec{-rmax, -rmax, zmin}, r3.Vec{rmax, rmax, zmax}}
s.bb = r3.Box{Min: r3.Vec{X: -rmax, Y: -rmax, Z: zmin}, Max: r3.Vec{X: rmax, Y: rmax, Z: zmax}}
return &s
}

// Evaluate returns the minimum distance to a rotate/copy SDF3.
func (s *rotateCopy3) Evaluate(p r3.Vec) float64 {
// Map p to a point in the first copy sector.
p2 := r2.Vec{p.X, p.Y}
p2 := r2.Vec{X: p.X, Y: p.Y}
p2 = d2.PolarToXY(r2.Norm(p2), sawTooth(math.Atan2(p2.Y, p2.X), s.theta))
return s.sdf.Evaluate(r3.Vec{p2.X, p2.Y, p.Z})
return s.sdf.Evaluate(r3.Vec{X: p2.X, Y: p2.Y, Z: p.Z})
}

// BoundingBox returns the bounding box of a rotate/copy SDF3.
Expand Down Expand Up @@ -842,7 +842,7 @@ func Shell3D(sdf SDF3, thickness float64) SDF3 {
return &shell3{
sdf: sdf,
delta: 0.5 * thickness,
bb: r3.Box(bb.Enlarge(r3.Vec{thickness, thickness, thickness})),
bb: r3.Box(bb.Enlarge(r3.Vec{X: thickness, Y: thickness, Z: thickness})),
}
}

Expand Down
Loading

0 comments on commit eec0546

Please sign in to comment.