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  }