github.com/Yeicor/sdf-viewer-go/sdf-viewer-go@v0.0.0-20220827152733-64b36e48c502/lib.go (about) 1 package sdf_viewer_go 2 3 import ( 4 "math" 5 "unsafe" 6 ) 7 8 // SetRootSDF registers the root SDF, overriding any previous value. 9 func SetRootSDF(sdf SDF) { 10 // Reset, in case this is called multiple times 11 nextSDFID = 0 12 availableSDFs = map[uint32]SDF{} 13 // Also register all children, recursively. 14 registerSDFAndChildren(sdf) 15 } 16 17 // SDF provides access to the Signed Distance Function data. Keep in sync with the SDF Viewer app. 18 // Comments may be outdated, so check the original SDF Viewer app for more details. 19 type SDF interface { 20 // AABB is the bounding box of the SDF. Returns the minimum and maximum coordinates of the SDF. 21 // All operations MUST be inside this bounding box. 22 AABB() (aabb [2][3]float32) 23 24 // Sample samples the surface at the given point. It should include the effect of all of its children 25 // and none of its parents. See `SDFSample` for more information. 26 // `distanceOnly` is a hint to the implementation that the caller only needs the distance. 27 Sample(point [3]float32, distanceOnly bool) (sample SDFSample) 28 29 // Children returns the list of sub-SDFs that are directly children of this node. 30 // Note that modifications to the parameters of the returned children MUST affect this node. 31 Children() (children []SDF) 32 33 // Name returns a nice display Name for the SDF, which does not need to be unique in the hierarchy. 34 Name() string 35 36 // Parameters returns the list of parameters (including Values and metadata) that can be modified on this SDF. 37 Parameters() []SDFParam 38 39 // SetParameter modifies the given parameter. The Value must be valid for the reported type (same Kind and within allowed Values) 40 // Implementations will probably need interior mutability to perform this. 41 // Use [`Changed`](#method.Changed) to notify what part of the SDF needs to be updated. 42 SetParameter(paramId uint32, value SDFParamValue) error 43 44 // Changed Returns the bounding box that was modified since [`Changed`](#method.Changed) was last called. 45 // It should also report if the children of this SDF need to be updated. 46 // This may happen due to a parameter change ([`set_parameter`](#method.set_parameter)) or any 47 // other event that may have Changed the SDF. It should delimit as much as possible the part of the 48 // SDF that should be updated to improve performance. 49 // 50 // Multiple changes should be merged into a single bounding box or queued and returned in several 51 // [`Changed`](#method.Changed) calls for a similar effect. 52 // After returning Some(...) the implementation should assume that it was updated and no longer 53 // notify of that change (to avoid infinite loops). 54 // This function is called very frequently, so it should be very fast to avoid delaying frames. 55 Changed() ChangedAABB 56 } 57 58 type SDFSample struct { 59 Distance float32 60 Color [3]float32 61 Metallic, Roughness, Occlusion float32 62 } 63 64 type SDFParam struct { 65 // The ID of the parameter. Must be unique within this SDF (not necessarily within the SDF hierarchy). 66 ID uint32 67 // The Name of the parameter. 68 Name string 69 // The type definition for the parameter. 70 Kind SDFParamKind 71 // The current Value of the parameter. MUST be of the same Kind as the type definition. 72 Value SDFParamValue 73 // The user-facing Description for the parameter. 74 Description string 75 } 76 77 // SDFParamKind is one of the types below 78 type SDFParamKind interface{} 79 80 type SDFParamKindBool struct { 81 } 82 83 type SDFParamKindInt struct { 84 // The minimum Value of the parameter. 85 Min int32 86 // The maximum Value of the parameter. 87 Max int32 88 // The Step size of the parameter. 89 Step int32 90 } 91 92 type SDFParamKindFloat struct { 93 // The minimum Value of the parameter. 94 Min float32 95 // The maximum Value of the parameter. 96 Max float32 97 // The Step size of the parameter. 98 Step float32 99 } 100 101 type SDFParamKindString struct { 102 // The list of possible Values of the parameter. 103 Values []string 104 } 105 106 // SDFParamValue is one of bool, int, float or string 107 type SDFParamValue interface{} 108 109 type ChangedAABB struct { 110 // Has it Changed? 111 Changed bool 112 // The bounding box that was Changed. 113 AABB [2][3]float32 114 } 115 116 // === Private API === 117 118 type pointerLength struct { 119 Pointer uintptr // Always 32 bits on wasm32 120 Length uint32 121 } 122 123 type sdfParamC struct { 124 ID uint32 125 Name pointerLength 126 KindParams sdfParamKindC 127 Value sdfParamValueC 128 Description pointerLength 129 } 130 131 func kindC(k SDFParamKind) sdfParamKindC { 132 switch v := k.(type) { 133 case SDFParamKindBool: 134 return sdfParamKindC{ 135 KindID: 0, 136 Params: [3]uint32{0, 0, 0}, 137 } 138 case SDFParamKindInt: 139 valMin := *(*uint32)(unsafe.Pointer(&v.Min)) // Same as math.Float32bits for int32 -> uint32 140 valMax := *(*uint32)(unsafe.Pointer(&v.Max)) 141 valStep := *(*uint32)(unsafe.Pointer(&v.Step)) 142 return sdfParamKindC{ 143 KindID: 1, 144 Params: [3]uint32{valMin, valMax, valStep}, 145 } 146 case SDFParamKindFloat: 147 return sdfParamKindC{ 148 KindID: 2, 149 Params: [3]uint32{math.Float32bits(v.Min), math.Float32bits(v.Max), math.Float32bits(v.Step)}, 150 } 151 case SDFParamKindString: 152 values := pointerLength{Pointer: 0, Length: 0} 153 if len(v.Values) > 0 { 154 values.Pointer = uintptr(unsafe.Pointer(&v.Values[0])) 155 values.Length = uint32(uintptr(len(v.Values)) * unsafe.Sizeof(v.Values[0])) 156 } 157 return sdfParamKindC{ 158 KindID: 3, 159 Params: [3]uint32{uint32(values.Pointer), values.Length, 0}, 160 } 161 default: 162 panic("unknown kind") 163 } 164 } 165 166 type sdfParamKindC struct { 167 KindID uint32 168 Params [3]uint32 // Interpretation depends on KindID (Go does not support enums with data) 169 } 170 171 func kindValue(v SDFParamValue) sdfParamValueC { 172 switch v := v.(type) { 173 case bool: 174 res := uint32(0) 175 if v { 176 res = 1 177 } 178 return sdfParamValueC{ 179 KindID: 0, 180 Params: [2]uint32{res, 0}, 181 } 182 case int32: 183 return sdfParamValueC{ 184 KindID: 1, 185 Params: [2]uint32{uint32(v), 0}, 186 } 187 case float32: 188 return sdfParamValueC{ 189 KindID: 2, 190 Params: [2]uint32{math.Float32bits(v), 0}, 191 } 192 case string: 193 res := []byte(v) 194 return sdfParamValueC{ 195 KindID: 3, 196 Params: [2]uint32{uint32(uintptr(unsafe.Pointer(&res[0]))), uint32(len(res))}, 197 } 198 default: 199 panic("unknown kind") 200 } 201 } 202 203 type sdfParamValueC struct { 204 KindID uint32 205 Params [2]uint32 // Interpretation depends on KindID (Go does not support enums with data) 206 } 207 208 type setParameterRes struct { 209 Error uint32 // 0 or 1 for success or failure 210 ErrorMsg pointerLength 211 } 212 213 type changedAABBC struct { 214 // Has it Changed? 215 Changed uint32 // 0 or 1 216 // The bounding box that was Changed. 217 AABB [2][3]float32 218 }