github.com/Yeicor/sdf-viewer-go/sdf-viewer-go@v0.0.0-20220827152733-64b36e48c502/exports.go (about)

     1  package sdf_viewer_go
     2  
     3  import (
     4  	"math"
     5  	"unsafe"
     6  )
     7  
     8  // availableSDFs is the exported SDF hierarchy implementations.
     9  var availableSDFs map[uint32]SDF
    10  var nextSDFID uint32
    11  
    12  func registerSDFAndChildren(s SDF) {
    13  	//fmt.Printf("registerSDFAndChildren(%d)\n", nextSDFID)
    14  	availableSDFs[nextSDFID] = s
    15  	nextSDFID++
    16  	for _, child := range s.Children() {
    17  		registerSDFAndChildren(child)
    18  	}
    19  }
    20  
    21  func getSDFOrPanic(sdfID uint32) SDF {
    22  	if sdf, ok := availableSDFs[sdfID]; ok {
    23  		return sdf
    24  	}
    25  	panic("SDF not found")
    26  }
    27  
    28  //export bounding_box
    29  //goland:noinspection GoSnakeCaseUsage
    30  func bounding_box(sdfID uint32) *[2][3]float32 {
    31  	//fmt.Printf("-> AABB(%d)\n", sdfID)
    32  	minMax := getSDFOrPanic(sdfID).AABB()
    33  	//fmt.Printf("<- AABB(%d) <- (%v, %v)\n", sdfID, minMax[0], minMax[1])
    34  	return &minMax
    35  }
    36  
    37  //export sample
    38  func sample(sdfID uint32, point [3]float32, distanceOnly bool) *SDFSample {
    39  	//fmt.Printf("Sample(%d, %v, %v)\n", sdfID, point, distanceOnly)
    40  	sample := getSDFOrPanic(sdfID).Sample(point, distanceOnly)
    41  	//fmt.Printf("Sample(%d, %v, %v) <- (%v)\n", sdfID, point, distanceOnly, sample)
    42  	return &sample
    43  }
    44  
    45  //export children
    46  func children(sdfID uint32) *pointerLength {
    47  	//fmt.Printf("-> Children(%d)\n", sdfID)
    48  	children := getSDFOrPanic(sdfID).Children()
    49  	if len(children) == 0 {
    50  		res := pointerLength{Pointer: 0, Length: 0}
    51  		return &res
    52  	}
    53  	childrenIDs := make([]uint32, len(children))
    54  	for i, child := range children {
    55  		var childID uint32
    56  		var ok bool
    57  		for id, s := range availableSDFs { // Too slow?
    58  			if s == child {
    59  				childID = id
    60  				ok = true
    61  				break
    62  			}
    63  		}
    64  		if !ok {
    65  			// NOTE: Children may change after a parameter update (or at any point in time),
    66  			// so register them again (with new IDs) if not found
    67  			// WARNING: A new struct instance on every Children call would cause a memory leak
    68  			registerSDFAndChildren(child)
    69  			childID = nextSDFID - 1
    70  		}
    71  		childrenIDs[i] = childID
    72  	}
    73  	res := pointerLength{Pointer: uintptr(unsafe.Pointer(&(childrenIDs[0]))), Length: uint32(uintptr(len(childrenIDs)) * unsafe.Sizeof(childrenIDs[0]))}
    74  	//fmt.Printf("<- Children(%d) <- (%v, %v)\n", sdfID, children.Pointer, children.Length)
    75  	return &res
    76  }
    77  
    78  //export name
    79  func name(sdfID uint32) *pointerLength {
    80  	//fmt.Printf("-> Children(%d)\n", sdfID)
    81  	res := stringToPointerLength(getSDFOrPanic(sdfID).Name())
    82  	//fmt.Printf("<- Children(%d) <- (%v, %v)\n", sdfID, children.Pointer, children.Length)
    83  	return &res
    84  }
    85  
    86  func stringToPointerLength(str string) pointerLength {
    87  	name := []byte(str)
    88  	res := pointerLength{Pointer: uintptr(unsafe.Pointer(&(name[0]))), Length: uint32(uintptr(len(name)) * unsafe.Sizeof(name[0]))}
    89  	return res
    90  }
    91  
    92  //export parameters
    93  func parameters(sdfID uint32) *pointerLength {
    94  	//fmt.Printf("-> Parameters(%d)\n", sdfID)
    95  	params := getSDFOrPanic(sdfID).Parameters()
    96  	if len(params) == 0 {
    97  		res := pointerLength{Pointer: 0, Length: 0}
    98  		return &res
    99  	}
   100  	paramsC := make([]sdfParamC, len(params))
   101  	for i, param := range params {
   102  		paramsC[i] = sdfParamC{
   103  			ID:          param.ID,
   104  			Name:        stringToPointerLength(param.Name),
   105  			KindParams:  kindC(param.Kind),
   106  			Value:       kindValue(param.Value),
   107  			Description: stringToPointerLength(param.Description),
   108  		}
   109  	}
   110  	res := pointerLength{Pointer: uintptr(unsafe.Pointer(&(paramsC[0]))), Length: uint32(uintptr(len(paramsC)) * unsafe.Sizeof(paramsC[0]))}
   111  	//fmt.Printf("<- Parameters(%d) <- (%v, %v)\n", sdfID, res.Pointer, res.Length)
   112  	return &res
   113  }
   114  
   115  //export set_parameter
   116  //goland:noinspection GoSnakeCaseUsage
   117  func set_parameter(sdfID, paramID, paramKindID, paramArg1, paramArg2 uint32) *setParameterRes {
   118  	//fmt.Printf("-> SetParameter(%d, %d, %d, %d, %d)\n", sdfID, paramID, paramKindID, paramArg1, paramArg2)
   119  	var paramVal SDFParamValue
   120  	switch paramKindID {
   121  	case 0: // bool
   122  		paramVal = paramArg1 != 0
   123  	case 1: // int
   124  		paramVal = *(*int32)(unsafe.Pointer(&paramArg1))
   125  	case 2: // float
   126  		paramVal = math.Float32frombits(paramArg1)
   127  	case 3: // string
   128  		//goland:noinspection GoVetUnsafePointer
   129  		memPtr := unsafe.Pointer(uintptr(paramArg1))
   130  		memLen := paramArg2
   131  		var bytes = unsafe.Slice((*byte)(memPtr), memLen)
   132  		paramVal = string(bytes)
   133  	default:
   134  		panic("Invalid paramKindID")
   135  	}
   136  	err := getSDFOrPanic(sdfID).SetParameter(paramID, paramVal)
   137  	res := setParameterRes{Error: 0, ErrorMsg: pointerLength{Pointer: 0, Length: 0}}
   138  	//err = errors.New("testing error on set_parameter")
   139  	if err != nil {
   140  		name := []byte(err.Error())
   141  		res.Error = 1
   142  		res.ErrorMsg.Pointer = uintptr(unsafe.Pointer(&(name[0])))
   143  		res.ErrorMsg.Length = uint32(uintptr(len(name)) * unsafe.Sizeof(name[0]))
   144  	}
   145  	//fmt.Printf("<- SetParameter(%d) <- (%v, %v)\n", sdfID, res.Pointer, res.Length)
   146  	return &res
   147  }
   148  
   149  //export changed
   150  func changed(sdfID uint32) *ChangedAABB {
   151  	//fmt.Printf("-> Changed(%d)\n", sdfID)
   152  	changed := getSDFOrPanic(sdfID).Changed()
   153  	res := changedAABBC{
   154  		Changed: 0,
   155  		AABB:    changed.AABB,
   156  	}
   157  	if changed.Changed {
   158  		res.Changed = 1
   159  	}
   160  	//fmt.Printf("<- Changed(%d) <- (%v)\n", sdfID, Changed)
   161  	return &changed
   162  }