github.com/Yeicor/sdf-viewer-go/sdf-viewer-go@v0.0.0-20220827152733-64b36e48c502/example/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 sdfviewergo "github.com/Yeicor/sdf-viewer-go/sdf-viewer-go" 6 "math" 7 ) 8 9 //export init 10 func init() { 11 // This is the only function you need to call to initialize the SDF Viewer. 12 sdfviewergo.SetRootSDF(sceneSDF()) 13 } 14 15 func main() { 16 fmt.Println("This is not an executable. Compile this with `" + 17 "tinygo build -o example.wasm -target wasi -opt 2 -x -no-debug ." + 18 "` and use the SDF Viewer app (github.com/Yeicor/sdf-viewer) to visualize the SDF.") 19 } 20 21 // sceneSDF returns the root SDF of the scene. 22 func sceneSDF() sdfviewergo.SDF { 23 return &SampleSDF{isRoot: true, name: "test-root-cube", cubeHalfSide: 0.99, changed: false, 24 child: &SampleSDF{isRoot: false, name: "test-fake-child", cubeHalfSide: 0.51, changed: false}} 25 } 26 27 // ######################## START OF EXAMPLE MANUAL SDF IMPLEMENTATION ######################## 28 // NOTE: Other modules of this repo have better examples of how to implement SDFs. 29 30 type SampleSDF struct { 31 isRoot bool 32 child *SampleSDF // May be nil 33 name string 34 cubeHalfSide float32 // Cube side length 35 changed bool // Whether any param changed, affecting the whole SDF 36 } 37 38 func (s *SampleSDF) AABB() [2][3]float32 { 39 return [2][3]float32{{-1, -1, -1}, {1, 1, 1}} 40 } 41 42 func (s *SampleSDF) Sample(point [3]float32, distanceOnly bool) (sample sdfviewergo.SDFSample) { 43 // Cube SDF 44 sample.Distance = maxF32(maxF32(absF32(point[0]), absF32(point[1])), absF32(point[2])) - s.cubeHalfSide 45 if !distanceOnly { 46 sample.Color = [3]float32{sinF32(point[0] * 2.0), (point[1] + 1.0) / 2.0, (point[2] + 1.0) / 2.0} 47 sample.Metallic = modF32(point[0], 1.0) 48 sample.Roughness = modF32(point[1], 1.0) 49 sample.Occlusion = modF32(point[2], 1.0) 50 } 51 return 52 } 53 54 func (s *SampleSDF) Children() []sdfviewergo.SDF { 55 if s.child != nil { // Fake, just for testing... 56 return []sdfviewergo.SDF{s.child} 57 } 58 return []sdfviewergo.SDF{} 59 } 60 61 func (s *SampleSDF) Name() string { 62 return s.name 63 } 64 65 func (s *SampleSDF) Parameters() []sdfviewergo.SDFParam { 66 if !s.isRoot { 67 return []sdfviewergo.SDFParam{} 68 } 69 return []sdfviewergo.SDFParam{ 70 { 71 ID: 0, 72 Name: "Cube half side", 73 Kind: sdfviewergo.SDFParamKindFloat{ 74 Min: 0.01, 75 Max: 0.99, 76 Step: 0.01, 77 }, 78 Value: s.cubeHalfSide, // float32, as described 79 Description: "Half side length of the cube", 80 }, 81 } 82 } 83 84 func (s *SampleSDF) SetParameter(paramId uint32, value sdfviewergo.SDFParamValue) error { 85 if paramId == 0 { 86 s.cubeHalfSide = value.(float32) 87 s.changed = true 88 return nil 89 } 90 return fmt.Errorf("unknown parameter id: %d", paramId) 91 } 92 93 func (s *SampleSDF) Changed() sdfviewergo.ChangedAABB { 94 changed := s.changed 95 s.changed = false 96 return sdfviewergo.ChangedAABB{ 97 Changed: changed, 98 AABB: s.AABB(), 99 } 100 } 101 102 // ######################## END OF EXAMPLE MANUAL SDF IMPLEMENTATION ######################## 103 104 func sinF32(f float32) float32 { 105 return float32(math.Sin(float64(f))) 106 } 107 108 func modF32(f float32, f2 float32) float32 { 109 res := float32(math.Mod(float64(f), float64(f2))) 110 if res < 0 { 111 return res + f2 112 } 113 return res 114 } 115 116 func maxF32(v1 float32, v2 float32) float32 { 117 if v1 > v2 { 118 return v1 119 } 120 return v2 121 } 122 123 func absF32(v float32) float32 { 124 if v < 0 { 125 return -v 126 } 127 return v 128 }