@@ -4,15 +4,17 @@ import (
44 "errors"
55
66 "github.com/chewxy/math32"
7+ "github.com/soypat/geometry/i3"
78 "github.com/soypat/geometry/ms3"
89 "github.com/soypat/gsdf/gleval"
910)
1011
1112type DualContourRenderer struct {
1213 sdf gleval.SDF3
14+ oct ms3.Octree
1315 contourer DualContourer
14- cubeMap map [ivec ]int
15- cubebuf []icube
16+ cubeMap map [i3. Vec ]int
17+ cubebuf []i3. Cube
1618 posbuf []ms3.Vec
1719 distbuf []float32
1820 // cubeinfo stores both cube and edge information for dual contouring algorithm.
@@ -33,15 +35,16 @@ func (dcr *DualContourRenderer) Reset(sdf gleval.SDF3, res float32, vertexPlacer
3335 if err != nil {
3436 return err
3537 }
36- nCubes := int (topCube .decomposesTo (1 ))
38+ nCubes := int (topCube .DecomposesTo (1 ))
3739 if cap (dcr .cubebuf ) < nCubes * 2 {
38- dcr .cubebuf = make ([]icube , 0 , nCubes * 2 ) // Want to fully decompose cube.
40+ dcr .cubebuf = make ([]i3. Cube , 0 , nCubes * 2 ) // Want to fully decompose cube.
3941 }
4042 var ok bool
41- dcr .cubebuf , ok = octreeDecomposeBFS (dcr .cubebuf [:0 ], topCube , 1 )
43+ dcr .oct = ms3.Octree {Resolution : res , Origin : origin }
44+ dcr .cubebuf , ok = dcr .oct .DecomposeBFS (dcr .cubebuf [:0 ], topCube , 1 )
4245 if ! ok {
4346 return errors .New ("unable to decompose top level cube" )
44- } else if dcr .cubebuf [0 ].lvl != 1 {
47+ } else if dcr .cubebuf [0 ].Level != 1 {
4548 return errors .New ("short buffer decomposing all cubes" )
4649 } else if len (dcr .cubebuf ) != nCubes {
4750 panic ("failed to decompose all edges?" )
@@ -54,7 +57,7 @@ func (dcr *DualContourRenderer) Reset(sdf gleval.SDF3, res float32, vertexPlacer
5457 posbuf := dcr .posbuf [:cap (dcr .posbuf )]
5558
5659 // Keep cubes that contain a surface and their neighbors.
57- dcr .cubebuf , _ , err = octreePrune (sdf , dcr .cubebuf , origin , res , posbuf , dcr .distbuf [:len (posbuf )], userData , 2 , true )
60+ dcr .cubebuf , _ , err = octreePrunea (sdf , dcr .cubebuf , origin , res , posbuf , dcr .distbuf [:len (posbuf )], userData , 2 , true )
5861 if err != nil {
5962 return err
6063 }
@@ -64,7 +67,7 @@ func (dcr *DualContourRenderer) Reset(sdf gleval.SDF3, res float32, vertexPlacer
6467 dcr .cubeinfo = make ([]DualCube , nCubes )
6568 }
6669 if dcr .cubeMap == nil {
67- dcr .cubeMap = make (map [ivec ]int )
70+ dcr .cubeMap = make (map [i3. Vec ]int )
6871 }
6972 clear (dcr .cubeMap )
7073 dcr .res = res
@@ -84,8 +87,9 @@ func (dcr *DualContourRenderer) RenderAll(dst []ms3.Triangle, userData any) ([]m
8487 cubes := dcr .cubeinfo [:len (edges )]
8588
8689 for e , edge := range edges {
87- sz := edge .size (res )
88- edgeOrig := edge .origin (origin , sz )
90+
91+ sz := dcr .oct .CubeSize (edge )
92+ edgeOrig := dcr .oct .CubeOrigin (edge , sz )
8993 // posbuf has edge origin, edge extremes in x,y,z and the center of the voxel.
9094 posbuf = append (posbuf ,
9195 edgeOrig ,
@@ -94,7 +98,7 @@ func (dcr *DualContourRenderer) RenderAll(dst []ms3.Triangle, userData any) ([]m
9498 ms3 .Add (edgeOrig , ms3.Vec {Z : sz }),
9599 )
96100 cubes [e ].FinalVertex = edgeOrig // By default set to center.
97- cubeMap [edge .ivec ] = e
101+ cubeMap [edge .Vec ] = e
98102 }
99103
100104 lenPos := len (posbuf )
@@ -108,7 +112,7 @@ func (dcr *DualContourRenderer) RenderAll(dst []ms3.Triangle, userData any) ([]m
108112 posbuf = posbuf [:0 ]
109113 for e , edge := range edges {
110114 // First for loop accumulates edge biases into voxels/cubes.
111- cube := makeDualCube (edge .ivec , distbuf [e * 4 :])
115+ cube := makeDualCube (edge .Vec , distbuf [e * 4 :])
112116 cubes [e ] = cube
113117 if ! cube .IsActive () {
114118 continue
@@ -180,7 +184,7 @@ func (dcr *DualContourRenderer) RenderAll(dst []ms3.Triangle, userData any) ([]m
180184 return dst , nil
181185}
182186
183- func makeDualCube (ivec ivec , data []float32 ) DualCube {
187+ func makeDualCube (ivec i3. Vec , data []float32 ) DualCube {
184188 if len (data ) < 4 {
185189 panic ("short dual cube info buffer" )
186190 }
@@ -196,7 +200,7 @@ func makeDualCube(ivec ivec, data []float32) DualCube {
196200// DualCube corresponds to a voxel anmd contains both cube and edge data.
197201type DualCube struct {
198202 // ivec stores the octree index of the cube, used to find neighboring cube ivec indices and the absolute position of the cube.
199- ivec ivec
203+ ivec i3. Vec
200204 // Neighbors contains neighboring index into dualCube buffer and contributing edge intersect axis.
201205 // - Neighbors[0]: Index into dualCube buffer to cube neighbor with edge.
202206 // - Neighbors[1]: Intersecting axis. 0 is x; 1 is y; 2 is z.
@@ -212,7 +216,9 @@ type DualCube struct {
212216}
213217
214218func (dc * DualCube ) SizeAndOrigin (res float32 , octreeOrigin ms3.Vec ) (float32 , ms3.Vec ) {
215- return res , icube {ivec : dc .ivec , lvl : 1 }.origin (octreeOrigin , res )
219+ cb := i3.Cube {Vec : dc .ivec , Level : 1 }
220+ oct := ms3.Octree {Resolution : res , Origin : octreeOrigin }
221+ return res , oct .CubeOrigin (cb , oct .CubeSize (cb ))
216222}
217223
218224func (dc * DualCube ) IsActive () bool {
@@ -235,22 +241,22 @@ func (dc *DualCube) FlipX() bool { return dc.XDist-dc.OrigDist < 0 }
235241func (dc * DualCube ) FlipY () bool { return dc .YDist - dc .OrigDist < 0 }
236242func (dc * DualCube ) FlipZ () bool { return dc .ZDist - dc .OrigDist < 0 }
237243
238- func (dc * DualCube ) EdgeNeighborsX () [4 ]ivec {
244+ func (dc * DualCube ) EdgeNeighborsX () [4 ]i3. Vec {
239245 const sub = - (1 << minIcubeLvl )
240246 v := dc .ivec
241- return [4 ]ivec {v .Add (ivec { y : sub , z : sub }), v .Add (ivec { z : sub }), v , v .Add (ivec { y : sub })}
247+ return [4 ]i3. Vec {v .Add (i3. Vec { Y : sub , Z : sub }), v .Add (i3. Vec { Z : sub }), v , v .Add (i3. Vec { Y : sub })}
242248}
243249
244- func (dc * DualCube ) EdgeNeighborsY () [4 ]ivec {
250+ func (dc * DualCube ) EdgeNeighborsY () [4 ]i3. Vec {
245251 const sub = - (1 << minIcubeLvl )
246252 v := dc .ivec
247- return [4 ]ivec {v .Add (ivec { x : sub , z : sub }), v .Add (ivec { x : sub }), v , v .Add (ivec { z : sub })}
253+ return [4 ]i3. Vec {v .Add (i3. Vec { X : sub , Z : sub }), v .Add (i3. Vec { X : sub }), v , v .Add (i3. Vec { Z : sub })}
248254}
249255
250- func (dc * DualCube ) EdgeNeighborsZ () [4 ]ivec {
256+ func (dc * DualCube ) EdgeNeighborsZ () [4 ]i3. Vec {
251257 const sub = - (1 << minIcubeLvl )
252258 v := dc .ivec
253- return [4 ]ivec {v .Add (ivec { x : sub , y : sub }), v .Add (ivec { y : sub }), v , v .Add (ivec { x : sub })}
259+ return [4 ]i3. Vec {v .Add (i3. Vec { X : sub , Y : sub }), v .Add (i3. Vec { Y : sub }), v , v .Add (i3. Vec { X : sub })}
254260}
255261
256262// minecraftRender performs a minecraft-like render of the SDF using a dual contour method.
@@ -261,21 +267,27 @@ func minecraftRender(dst []ms3.Triangle, sdf gleval.SDF3, res float32) ([]ms3.Tr
261267 if err != nil {
262268 return dst , err
263269 }
264- decomp := topCube .decomposesTo (1 )
265- cubes := make ([]icube , 0 , decomp * 2 )
266- cubes , ok := octreeDecomposeBFS (cubes , topCube , 1 )
270+ oct := ms3.Octree {
271+ Resolution : res ,
272+ Origin : origin ,
273+ }
274+
275+ decomp := topCube .DecomposesTo (1 )
276+ cubes := make ([]i3.Cube , 0 , decomp * 2 )
277+
278+ cubes , ok := oct .DecomposeBFS (cubes , topCube , 1 )
267279 if ! ok {
268280 return dst , errors .New ("unable to decompose top level cube" )
269- } else if cubes [0 ].lvl != 1 {
281+ } else if cubes [0 ].Level != 1 {
270282 return dst , errors .New ("short buffer decomposing all cubes" )
271283 }
272284
273285 var posbuf []ms3.Vec
274286 iCubes := 0
275287 for ; iCubes < len (cubes ); iCubes ++ {
276288 cube := cubes [iCubes ]
277- sz := cube . size ( res )
278- cubeOrig := cube . origin ( origin , sz )
289+ sz := oct . CubeSize ( cube )
290+ cubeOrig := oct . CubeOrigin ( cube , sz )
279291 // Append origin and edge-end vertices.
280292 posbuf = append (posbuf ,
281293 cubeOrig ,
@@ -292,9 +304,9 @@ func minecraftRender(dst []ms3.Triangle, sdf gleval.SDF3, res float32) ([]ms3.Tr
292304 }
293305 for j := 0 ; j < iCubes ; j ++ {
294306 cube := cubes [j ]
295- sz := cube . size ( res )
296- srcOrig := cube . origin ( origin , sz )
297- dci := makeDualCube (cube .ivec , distbuf [j * 4 :])
307+ sz := oct . CubeSize ( cube )
308+ srcOrig := oct . CubeOrigin ( cube , sz )
309+ dci := makeDualCube (cube .Vec , distbuf [j * 4 :])
298310 origOff := sz
299311 if dci .ActiveX () {
300312 xOrig := ms3 .Add (srcOrig , ms3.Vec {X : origOff })
0 commit comments