diff --git a/ode.go b/ode.go index 8a68777..a4cd8a9 100644 --- a/ode.go +++ b/ode.go @@ -40,9 +40,11 @@ type nearCallbackData struct { fn NearCallback } +var nearCallbackDataMap = NewCGOMap() + //export nearCallback func nearCallback(data unsafe.Pointer, obj1, obj2 C.dGeomID) { - cbData := (*nearCallbackData)(data) + cbData := nearCallbackDataMap.Get(int(uintptr(data))).(*nearCallbackData) cbData.fn(cbData.data, cToGeom(obj1), cToGeom(obj2)) } @@ -183,7 +185,7 @@ type VertexList Matrix // NewVertexList returns a new VertexList instance. func NewVertexList(size int, vals ...float64) VertexList { - return VertexList(NewMatrix(size, 3, 1, vals...)) + return VertexList(NewMatrix(size, 3, 4, vals...)) } // PlaneList represents a list of plane definitions. diff --git a/space.go b/space.go index ce6ee4f..a8550c7 100644 --- a/space.go +++ b/space.go @@ -42,6 +42,7 @@ type Space interface { NewCapsule(radius, length float64) Capsule NewCylinder(radius, length float64) Cylinder NewRay(length float64) Ray + NewTriMesh(data TriMeshData) TriMesh NewHeightfield(data HeightfieldData, placeable bool) Heightfield NewSimpleSpace() SimpleSpace NewHashSpace() HashSpace @@ -152,7 +153,9 @@ func (s SpaceBase) Geom(index int) Geom { // Collide tests for collision between contained objects. func (s SpaceBase) Collide(data interface{}, cb NearCallback) { cbData := &nearCallbackData{fn: cb, data: data} - C.dSpaceCollide(s.c(), unsafe.Pointer(cbData), + index := nearCallbackDataMap.Set(cbData) + defer nearCallbackDataMap.Delete(index) + C.dSpaceCollide(s.c(), unsafe.Pointer(uintptr(index)), (*C.dNearCallback)(C.callNearCallback)) } diff --git a/trimesh.go b/trimesh.go index a3ece0c..404dac6 100644 --- a/trimesh.go +++ b/trimesh.go @@ -25,6 +25,11 @@ func (t TriMeshData) c() C.dTriMeshDataID { return C.dTriMeshDataID(unsafe.Pointer(t)) } +var ( + vertexListMap = map[int]VertexList{} + indexListMap = map[int]TriVertexIndexList{} +) + // NewTriMeshData returns a new TriMeshData instance. func NewTriMeshData() TriMeshData { return cToTriMeshData(C.dGeomTriMeshDataCreate()) @@ -32,13 +37,19 @@ func NewTriMeshData() TriMeshData { // Destroy destroys the triangle mesh data. func (t TriMeshData) Destroy() { + delete(vertexListMap, int(t)) + delete(indexListMap, int(t)) C.dGeomTriMeshDataDestroy(t.c()) } // Build builds a triangle mesh from the given data. func (t TriMeshData) Build(verts VertexList, tris TriVertexIndexList) { + delete(vertexListMap, int(t)) + delete(indexListMap, int(t)) C.dGeomTriMeshDataBuildSimple(t.c(), (*C.dReal)(&verts[0][0]), C.int(len(verts)), - (*C.dTriIndex)(&tris[0][0]), C.int(len(tris))) + (*C.dTriIndex)(&tris[0][0]), C.int(len(tris)*3)) + vertexListMap[int(t)] = verts // avoid GC mark and sweep + indexListMap[int(t)] = tris // avoid GC mark and sweep } // Preprocess preprocesses the triangle mesh data. diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..b18a331 --- /dev/null +++ b/utils.go @@ -0,0 +1,30 @@ +package ode + +type CGOMap struct { + index int + pointers map[int]interface{} +} + +func NewCGOMap() CGOMap { + var m CGOMap + m.pointers = make(map[int]interface{}) + return m +} + +func (m CGOMap) Get(index int) interface{} { + p := m.pointers[index] + if p == nil { + panic("couldn't retrieve the pointer") + } + return p +} + +func (m CGOMap) Set(p interface{}) int { + m.index += 1 + m.pointers[m.index] = p + return m.index +} + +func (m CGOMap) Delete(index int) { + delete(m.pointers, index) +}