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

Commit eec0546

Browse files
committed
fix sdf top level unkeyed fields
1 parent 65c01cd commit eec0546

File tree

7 files changed

+74
-72
lines changed

7 files changed

+74
-72
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@ Here is a rendered bolt from one of the unit tests under [form3_test.go](./rende
2626
![renderedBolt](./render/testdata/defactoBolt.png)
2727

2828
## Roadmap
29+
- [x] Clean up thread API mess
2930
- [ ] Add a 2D renderer and it's respective `Renderer2` interface.
3031
- [ ] Make 3D renderer multicore
31-
- [ ] Clean up thread API mess
32+
3233

3334
## Comparison
3435

examples/atx-bench-supply/atx.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,28 +52,28 @@ func main() {
5252
var outputs, regOut, regBlock sdf.SDF2
5353
// Outputs banana plugs
5454
outputs = sdf.Array2D(bananaPlugBig, sdf.V2i{4, 2}, r2.Vec{-bananaSpacing, bananaSpacing})
55-
outputs = sdf.Transform2D(outputs, sdf.Translate2d(r2.Vec{atxW/2 - 15, -atxH/2 + 15}))
55+
outputs = sdf.Transform2D(outputs, sdf.Translate2D(r2.Vec{atxW/2 - 15, -atxH/2 + 15}))
5656

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

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

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

7979
// Generate model

matrix.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ func Translate3D(v r3.Vec) m44 {
114114
0, 0, 0, 1}
115115
}
116116

117-
// Translate2d returns a 3x3 translation matrix.
118-
func Translate2d(v r2.Vec) m33 {
117+
// Translate2D returns a 3x3 translation matrix.
118+
func Translate2D(v r2.Vec) m33 {
119119
return m33{
120120
1, 0, v.X,
121121
0, 1, v.Y,
@@ -284,14 +284,14 @@ func (a m22) equals(b m22, tolerance float64) bool {
284284

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

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

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

420420
// MulBox rotates/translates a 2d bounding box and resizes for axis-alignment.
421421
func (a m33) MulBox(box r2.Box) r2.Box {
422-
r := r2.Vec{a.x00, a.x10}
423-
u := r2.Vec{a.x01, a.x11}
424-
t := r2.Vec{a.x02, a.x12}
422+
r := r2.Vec{X: a.x00, Y: a.x10}
423+
u := r2.Vec{X: a.x01, Y: a.x11}
424+
t := r2.Vec{X: a.x02, Y: a.x12}
425425
xa := r2.Scale(box.Min.X, r)
426426
xb := r2.Scale(box.Max.X, r)
427427
ya := r2.Scale(box.Min.Y, u)
@@ -430,7 +430,7 @@ func (a m33) MulBox(box r2.Box) r2.Box {
430430
ya, yb = d2.MinElem(ya, yb), d2.MaxElem(ya, yb)
431431
min := xa.Add(ya).Add(t)
432432
max := xb.Add(yb).Add(t)
433-
return r2.Box{min, max}
433+
return r2.Box{Min: min, Max: max}
434434
}
435435

436436
// Determinant returns the determinant of a 4x4 matrix.

sdf2.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func Cut2D(sdf SDF2, a, v r2.Vec) SDF2 {
6868
s.sdf = sdf
6969
s.a = a
7070
v = r2.Unit(v)
71-
s.n = r2.Vec{-v.Y, v.X}
71+
s.n = r2.Vec{X: -v.Y, Y: v.X}
7272
// TODO - cut the bounding box
7373
s.bb = sdf.Bounds()
7474
return &s
@@ -127,7 +127,7 @@ type ScaleUniformSDF2 struct {
127127
// ScaleUniform2D scales an SDF2 by k on each axis.
128128
// Distance is correct with scaling.
129129
func ScaleUniform2D(sdf SDF2, k float64) SDF2 {
130-
m := Scale2d(r2.Vec{k, k})
130+
m := Scale2d(r2.Vec{X: k, Y: k})
131131
return &ScaleUniformSDF2{
132132
sdf: sdf,
133133
k: k,
@@ -150,14 +150,14 @@ func (s *ScaleUniformSDF2) Bounds() r2.Box {
150150
// Center2D centers the origin of an SDF2 on it's bounding box.
151151
func Center2D(s SDF2) SDF2 {
152152
ofs := r2.Scale(-1, d2.Box(s.Bounds()).Center())
153-
return Transform2D(s, Translate2d(ofs))
153+
return Transform2D(s, Translate2D(ofs))
154154
}
155155

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

@@ -201,7 +201,7 @@ func (s *array2) Evaluate(p r2.Vec) float64 {
201201
d := math.MaxFloat64
202202
for j := 0; j < s.num[0]; j++ {
203203
for k := 0; k < s.num[1]; k++ {
204-
x := p.Sub(r2.Vec{float64(j) * s.step.X, float64(k) * s.step.Y})
204+
x := p.Sub(r2.Vec{X: float64(j) * s.step.X, Y: float64(k) * s.step.Y})
205205
d = s.min(d, s.sdf.Evaluate(x))
206206
}
207207
}
@@ -243,7 +243,7 @@ func RotateUnion2D(sdf SDF2, num int, step m33) SDF2 {
243243
bbMax = d2.MaxElem(bbMax, vset.Max())
244244
MulVertices2(vset, step)
245245
}
246-
s.bb = r2.Box{bbMin, bbMax}
246+
s.bb = r2.Box{Min: bbMin, Max: bbMax}
247247
return &s
248248
}
249249

@@ -295,7 +295,8 @@ func RotateCopy2D(sdf SDF2, n int) SDF2 {
295295
rmax = l
296296
}
297297
}
298-
s.bb = r2.Box{r2.Vec{-rmax, -rmax}, r2.Vec{rmax, rmax}}
298+
max := r2.Vec{X: rmax, Y: rmax}
299+
s.bb = r2.Box{Min: r2.Scale(-1, max), Max: max}
299300
return &s
300301
}
301302

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

@@ -558,7 +559,7 @@ func LineOf2D(s SDF2, p0, p1 r2.Vec, pattern string) SDF2 {
558559
dx = r2.Scale(1/float64(len(pattern)), dx)
559560
for _, c := range pattern {
560561
if c == 'x' {
561-
objects = append(objects, Transform2D(s, Translate2d(x)))
562+
objects = append(objects, Transform2D(s, Translate2D(x)))
562563
}
563564
x = x.Add(dx)
564565
}
@@ -579,7 +580,7 @@ func Multi2D(s SDF2, positions d2.Set) SDF2 {
579580
}
580581
objects := make([]SDF2, len(positions))
581582
for i, p := range positions {
582-
objects[i] = Transform2D(s, Translate2d(p))
583+
objects[i] = Transform2D(s, Translate2D(p))
583584
}
584585
return Union2D(objects...)
585586
}

sdf3.go

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,39 +61,39 @@ func Revolve3D(sdf SDF2, theta float64) SDF3 {
6161
sin := math.Sin(s.theta)
6262
cos := math.Cos(s.theta)
6363
// pre-calculate the normal to the theta line
64-
s.norm = r2.Vec{-sin, cos}
64+
s.norm = r2.Vec{X: -sin, Y: cos}
6565
// work out the bounding box
6666
var vset d2.Set
6767
if theta == 0 {
68-
vset = []r2.Vec{{1, 1}, {-1, -1}}
68+
vset = []r2.Vec{{X: 1, Y: 1}, {X: -1, Y: -1}}
6969
} else {
70-
vset = []r2.Vec{{0, 0}, {1, 0}, {cos, sin}}
70+
vset = []r2.Vec{{X: 0, Y: 0}, {X: 1, Y: 0}, {X: cos, Y: sin}}
7171
if s.theta > 0.5*pi {
72-
vset = append(vset, r2.Vec{0, 1})
72+
vset = append(vset, r2.Vec{X: 0, Y: 1})
7373
}
7474
if s.theta > pi {
75-
vset = append(vset, r2.Vec{-1, 0})
75+
vset = append(vset, r2.Vec{X: -1, Y: 0})
7676
}
7777
if s.theta > 1.5*pi {
78-
vset = append(vset, r2.Vec{0, -1})
78+
vset = append(vset, r2.Vec{X: 0, Y: -1})
7979
}
8080
}
8181
bb := s.sdf.Bounds()
8282
l := math.Max(math.Abs(bb.Min.X), math.Abs(bb.Max.X))
8383
vmin := r2.Scale(l, vset.Min())
8484
vmax := r2.Scale(l, vset.Max())
85-
s.bb = r3.Box{r3.Vec{vmin.X, vmin.Y, bb.Min.Y}, r3.Vec{vmax.X, vmax.Y, bb.Max.Y}}
85+
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}}
8686
return &s
8787
}
8888

8989
// Evaluate returns the minimum distance to a solid of revolution.
9090
func (s *revolution3) Evaluate(p r3.Vec) float64 {
9191
x := math.Sqrt(p.X*p.X + p.Y*p.Y)
92-
a := s.sdf.Evaluate(r2.Vec{x, p.Z})
92+
a := s.sdf.Evaluate(r2.Vec{X: x, Y: p.Z})
9393
b := a
9494
if s.theta != 0 {
9595
// combine two vertical planes to give an intersection wedge
96-
d := s.norm.Dot(r2.Vec{p.X, p.Y})
96+
d := s.norm.Dot(r2.Vec{X: p.X, Y: p.Y})
9797
if s.theta < pi {
9898
b = math.Max(-p.Y, d) // intersect
9999
} else {
@@ -125,7 +125,7 @@ func Extrude3D(sdf SDF2, height float64) SDF3 {
125125
s.extrude = NormalExtrude
126126
// work out the bounding box
127127
bb := sdf.Bounds()
128-
s.bb = r3.Box{r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, r3.Vec{bb.Max.X, bb.Max.Y, s.height}}
128+
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}}
129129
return &s
130130
}
131131

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

@@ -150,8 +150,8 @@ func ScaleExtrude3D(sdf SDF2, height float64, scale r2.Vec) SDF3 {
150150
s.extrude = ScaleExtrude(height, scale)
151151
// work out the bounding box
152152
bb := d2.Box(sdf.Bounds())
153-
bb = bb.Extend(d2.Box{d2.MulElem(bb.Min, scale), d2.MulElem(bb.Max, scale)})
154-
s.bb = r3.Box{r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, r3.Vec{bb.Max.X, bb.Max.Y, s.height}}
153+
bb = bb.Extend(d2.Box{Min: d2.MulElem(bb.Min, scale), Max: d2.MulElem(bb.Max, scale)})
154+
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}}
155155
return &s
156156
}
157157

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

@@ -223,16 +223,16 @@ func ExtrudeRounded3D(sdf SDF2, height, round float64) SDF3 {
223223
// work out the bounding box
224224
bb := sdf.Bounds()
225225
s.bb = r3.Box{
226-
Min: r3.Sub(r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, d3.Elem(round)),
227-
Max: r3.Add(r3.Vec{bb.Max.X, bb.Max.Y, s.height}, d3.Elem(round)),
226+
Min: r3.Sub(r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, d3.Elem(round)),
227+
Max: r3.Add(r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}, d3.Elem(round)),
228228
}
229229
return &s
230230
}
231231

232232
// Evaluate returns the minimum distance to a rounded extrusion.
233233
func (s *extrudeRounded) Evaluate(p r3.Vec) float64 {
234234
// sdf for the projected 2d surface
235-
a := s.sdf.Evaluate(r2.Vec{p.X, p.Y})
235+
a := s.sdf.Evaluate(r2.Vec{X: p.X, Y: p.Y})
236236
b := math.Abs(p.Z) - s.height
237237
var d float64
238238
if b > 0 {
@@ -296,8 +296,8 @@ func Loft3D(sdf0, sdf1 SDF2, height, round float64) SDF3 {
296296
bb1 := d2.Box(sdf1.Bounds())
297297
bb := bb0.Extend(bb1)
298298
s.bb = r3.Box{
299-
Min: r3.Sub(r3.Vec{bb.Min.X, bb.Min.Y, -s.height}, d3.Elem(round)),
300-
Max: r3.Add(r3.Vec{bb.Max.X, bb.Max.Y, s.height}, d3.Elem(round))}
299+
Min: r3.Sub(r3.Vec{X: bb.Min.X, Y: bb.Min.Y, Z: -s.height}, d3.Elem(round)),
300+
Max: r3.Add(r3.Vec{X: bb.Max.X, Y: bb.Max.Y, Z: s.height}, d3.Elem(round))}
301301
return &s
302302
}
303303

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

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

385385
// ScaleUniform3D uniformly scales an SDF3 on all axes.
386386
func ScaleUniform3D(sdf SDF3, k float64) SDF3 {
387-
m := Scale3d(r3.Vec{k, k, k})
387+
m := Scale3d(r3.Vec{X: k, Y: k, Z: k})
388388
return &scaleUniform3{
389389
sdf: sdf,
390390
k: k,
@@ -637,7 +637,7 @@ func (s *array3) Evaluate(p r3.Vec) float64 {
637637
for j := 0; j < s.num[0]; j++ {
638638
for k := 0; k < s.num[1]; k++ {
639639
for l := 0; l < s.num[2]; l++ {
640-
x := p.Sub(r3.Vec{float64(j) * s.step.X, float64(k) * s.step.Y, float64(l) * s.step.Z})
640+
x := p.Sub(r3.Vec{X: float64(j) * s.step.X, Y: float64(k) * s.step.Y, Z: float64(l) * s.step.Z})
641641
d = s.min(d, s.sdf.Evaluate(x))
642642
}
643643
}
@@ -681,7 +681,7 @@ func RotateUnion3D(sdf SDF3, num int, step m44) SDF3Union {
681681
mulVertices3(v, step)
682682
// v.MulVertices(step)
683683
}
684-
s.bb = r3.Box{bbMin, bbMax}
684+
s.bb = r3.Box{Min: bbMin, Max: bbMax}
685685
return &s
686686
}
687687

@@ -737,16 +737,16 @@ func RotateCopy3D(sdf SDF3, num int) SDF3 {
737737
rmax = l
738738
}
739739
}
740-
s.bb = r3.Box{r3.Vec{-rmax, -rmax, zmin}, r3.Vec{rmax, rmax, zmax}}
740+
s.bb = r3.Box{Min: r3.Vec{X: -rmax, Y: -rmax, Z: zmin}, Max: r3.Vec{X: rmax, Y: rmax, Z: zmax}}
741741
return &s
742742
}
743743

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

752752
// BoundingBox returns the bounding box of a rotate/copy SDF3.
@@ -842,7 +842,7 @@ func Shell3D(sdf SDF3, thickness float64) SDF3 {
842842
return &shell3{
843843
sdf: sdf,
844844
delta: 0.5 * thickness,
845-
bb: r3.Box(bb.Enlarge(r3.Vec{thickness, thickness, thickness})),
845+
bb: r3.Box(bb.Enlarge(r3.Vec{X: thickness, Y: thickness, Z: thickness})),
846846
}
847847
}
848848

0 commit comments

Comments
 (0)