func Close() {
	C.dCloseODE()
}
Close releases ODE resources.
package ode
import "C"
import (
	"unsafe"
)
const (
	ManualThreadCleanupIFlag = C.dInitFlagManualThreadCleanup
)
const (
	BasicDataAFlag     = C.dAllocateFlagBasicData
	CollisionDataAFlag = C.dAllocateFlagCollisionData
	AllAFlag           = C.dAllocateMaskAll
)
var (
	V3 = NewVector3
	V4 = NewVector4
	M3 = NewMatrix3
	M4 = NewMatrix4
	Q  = NewQuaternion
	BB = NewAABB
)
type NearCallback func(data interface{}, obj1, obj2 Geom)
type nearCallbackData struct {
	data interface{}
	fn   NearCallback
}
func nearCallback(data unsafe.Pointer, obj1, obj2 C.dGeomID) {
	cbData := (*nearCallbackData)(data)
	cbData.fn(cbData.data, cToGeom(obj1), cToGeom(obj2))
}
func alignNum(num, align int) int {
	return (num + (align - 1)) &^ (align - 1)
}
type Vector []float64
func NewVector(size, align int, vals ...float64) Vector {
	alignSize := alignNum(size, align)
	v := make(Vector, size, alignSize)
	copy(v, vals)
	return v
}
func (v Vector) convertC(c *C.dReal, toC bool) {
	for i := range v {
		if toC {
			*c = C.dReal(v[i])
		} else {
			v[i] = float64(*c)
		}
		c = (*C.dReal)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + unsafe.Sizeof(*c)))
	}
}
func (v Vector) toC(c *C.dReal) {
	v.convertC(c, true)
}
func (v Vector) fromC(c *C.dReal) {
	v.convertC(c, false)
}
type Vector3 Vector
func cToVector3(a *C.dReal) Vector3 {
	vec := NewVector3()
	Vector(vec).fromC(a)
	return vec
}
func NewVector3(vals ...float64) Vector3 {
	return Vector3(NewVector(3, 4, vals...))
}
type Vector4 Vector
func NewVector4(vals ...float64) Vector4 {
	return Vector4(NewVector(4, 4, vals...))
}
type Quaternion Vector
func NewQuaternion(vals ...float64) Quaternion {
	return Quaternion(NewVector(4, 1, vals...))
}
type AABB Vector
func NewAABB(vals ...float64) AABB {
	return AABB(NewVector(6, 1, vals...))
}
type Matrix [][]float64
func NewMatrix(numRows, numCols, align int, vals ...float64) Matrix {
	mat := make(Matrix, numRows)
	numAlignCols := alignNum(numCols, align)
	elts := make([]float64, numAlignCols*numRows)
	for i := range mat {
		mat[i], elts = elts[:numCols:numAlignCols], elts[numAlignCols:]
		n := numCols
		if len(vals) < numCols {
			n = len(vals)
		}
		copy(mat[i], vals[:n])
		vals = vals[n:]
	}
	return mat
}
func (m Matrix) convertC(c *C.dReal, toC bool) {
	for i := range m {
		for j := 0; j < cap(m[i]); j++ {
			if j < len(m[i]) {
				if toC {
					*c = C.dReal(m[i][j])
				} else {
					m[i][j] = float64(*c)
				}
			}
			c = (*C.dReal)(unsafe.Pointer(uintptr(unsafe.Pointer(c)) + unsafe.Sizeof(*c)))
		}
	}
}
func (m Matrix) toC(c *C.dReal) {
	m.convertC(c, true)
}
func (m Matrix) fromC(c *C.dReal) {
	m.convertC(c, false)
}
type Matrix3 Matrix
func NewMatrix3(vals ...float64) Matrix3 {
	return Matrix3(NewMatrix(3, 3, 4, vals...))
}
type Matrix4 Matrix
func NewMatrix4(vals ...float64) Matrix4 {
	return Matrix4(NewMatrix(4, 4, 4, vals...))
}
type VertexList Matrix
func NewVertexList(size int, vals ...float64) VertexList {
	return VertexList(NewMatrix(size, 3, 1, vals...))
}
type PlaneList Matrix
func NewPlaneList(size int, vals ...float64) PlaneList {
	return PlaneList(NewMatrix(size, 4, 1, vals...))
}
type TriVertexIndexList [][]uint32
func NewTriVertexIndexList(size int, indices ...uint32) TriVertexIndexList {
	list := make(TriVertexIndexList, size)
	elts := make([]uint32, 3*size)
	for i := range list {
		list[i], elts = elts[:3], elts[3:]
		n := 3
		if len(indices) < 3 {
			n = len(indices)
		}
		copy(list[i], indices[:n])
		indices = indices[n:]
	}
	return list
}
type PolygonList []C.uint
func Init(initFlags, allocFlags int) {
	C.dInitODE2(C.uint(initFlags))
	C.dAllocateODEDataForThread(C.uint(allocFlags))
}