# -*- indent-tabs-mode: t -*- #cdef class _TriMesh(_Geom) # _Space cdef class _Space(_Geom): """Space class (container for geometry objects). A Space object is a container for geometry objects which are used to do collision detection. The space does high level collision culling, which means that it can identify which pairs of geometry objects are potentially touching. """ # The world this space belongs to, for the default collision callback #cdef _World _world ## Group for contact joints generated by this space #cdef JointGroup contactgroup def __init__(self, _World world): cdef _World parent cdef _Geom geom cdef _Space former parent = world._parent if (not world._option & WORLD_HAS_ODE) and parent is not None: if parent._space is None: self.__class__(world= parent) space = parent._space else: space = None self.geoms = [] _Geom.__init__(self,space) dSpaceSetCleanup(self._OdeGeomID, 0) if world._space is not None: former = world._space for geom in former.geoms: dSpaceRemove(former._OdeGeomID, geom._OdeGeomID) dSpaceAdd(self._OdeGeomID, geom._OdeGeomID) geom._space = self self.geoms= former.geoms former.geoms = [] former._world = None world._space = self self._world = world #property world: # def __set__(self, _Body world): # if self._world is not world: # if self._world is not None: # self._world.space = None # self._world = world # if world is None: # dGeomSetBody(self._OdeGeomID,NULL) # else: # if not world._option & BODY_HAS_ODE: # world._activate_ode_world() # dGeomSetBody(self._OdeGeomID,world._OdeBodyID) # world.space = self cdef _create(self): raise NotImplementedError("Space classe can not be used directly") def __dealloc__(self): if self._OdeGeomID != NULL: #self._OdeGeomID = NULL dSpaceDestroy(self._OdeGeomID) self._OdeGeomID = NULL def __contains__(self, _Geom geom): """query(geom) -> bool Return True if the given geom is in the space. @param geom: Geom object to check @type geom: _Geom """ return dSpaceQuery(self._OdeGeomID, geom._OdeGeomID) #def _id(self): # cdef long id # id = self._OdeGeomID # return id def add(self, _Geom geom): """add(geom) Add a geom to a space. This does nothing if the geom is already in the space. @param geom: Geom object to add @type geom: _Geom """ if geom not in self.geoms: self.geoms.append(geom) self.space = self # ZZZ warning dSpaceAdd(self._OdeGeomID, geom._OdeGeomID) def remove(self, _Geom geom): """remove(geom) Remove a geom from a space. @param geom: Geom object to remove @type geom: _Geom """ self.geoms.remove(geom) geom._space = None dSpaceRemove(self._OdeGeomID, geom._OdeGeomID) #def set_last_transformations(self): # """Set the last transformation for each TriMesh geom in the space. # This must be called before the geoms are moved but after the # previous collisions.""" # # cdef _Geom geom # cdef _TriMesh trimesh # # for geom in self.geoms: # if isinstance(geom, _TriMesh): # trimesh = <_TriMesh>geom # trimesh._set_last_transformation() def __len__(self): """getNumGeoms() -> int Return the number of geoms contained within the space. """ return dSpaceGetNumGeoms(self._OdeGeomID) def __getitem__(self, int idx): """getGeom(idx) -> _Geom Return the geom with the given index contained within the space. @param idx: Geom index (0,1,...,getNumGeoms()-1) @type idx: int """ cdef dGeomID _OdeGeomID cdef void *data # Check the index if 0<=idxself._OdeGeomID): raise IndexError, "geom index out of range" _OdeGeomID = dSpaceGetGeom(self._OdeGeomID, idx) #if _OdeGeomID not in _geom_c2py_lut: # raise RuntimeError, "geom id cannot be translated to a Python object" #return _geom_c2py_lut[_OdeGeomID] data = dGeomGetData(_OdeGeomID) return data#return the python object #def near_callback(self, g1, g2): # """Called for each pair of geoms that might be intersecting. # Meant to be overridden in subclasses""" # # cdef Contact c # cdef Joint j # # for c in collide(g1, g2): # j = ContactJoint(self.world, self.contactgroup, c) # j.attach(g1.body, g2.body) def collide(self): """Do collision detection. Call a callback function one or more times, for all potentially intersecting objects in the space. The callback function takes 3 arguments: def NearCallback(arg, geom1, geom2): The arg parameter is just passed on to the callback function. Its meaning is user defined. The geom1 and geom2 arguments are the geometry objects that may be near each other. The callback function can call the function collide() (not the Space method) on geom1 and geom2, perhaps first determining whether to collide them at all based on other information. """ # # Empty out our contact group # self.contactgroup.empty() #print "I'm a Space, I will call collide" dSpaceCollide(self._OdeGeomID, self, collide_callback) cdef class SimpleSpace(_Space): """Simple space. This does not do any collision culling - it simply checks every possible pair of geoms for intersection, and reports the pairs whose AABBs overlap. The time required to do intersection testing for n objects is O(n**2). This should not be used for large numbers of objects, but it can be the preferred algorithm for a small number of objects. This is also useful for debugging potential problems with the collision system. """ cdef _create(self): cdef dSpaceID parent_id if self._space is None: parent_id = NULL else: parent_id = self._space._OdeGeomID self._OdeGeomID = dSimpleSpaceCreate(parent_id)