Class ODE::Space
In: ext/body.c  (CVS)
lib/ode/space.rb  (CVS)
Parent: ODE::Geometry

Instance of this class are collision spaces..

Methods

Public Class methods

ODE::Space Singleton allocator

[Source]

/*
 * ODE::Space Singleton allocator
 */
static VALUE
ode_space_s_alloc( klass )
	 VALUE klass;
{
	debugMsg(( "Wrapping an uninitialized ODE::Space ptr." ));
	return Data_Wrap_Struct( klass, ode_space_gc_mark, ode_space_gc_free, 0 );
}

Base initializer.

[Source]

/* 
 * Base initializer.
 */
static VALUE
ode_space_init( argc, argv, self )
	 int	argc;
	 VALUE	*argv, self;
{
	debugMsg(( "ODE::Space init." ));

	/* Create the underlying dSpaceID object if it hasn't been already */
	if ( !check_space(self) ) {
		ode_GEOMETRY	*ptr;
		dSpaceID		containerSpace = 0;
		VALUE			container = Qnil;

		debugMsg(( "Space::initialize: Fetching new data object." ));

		/* If they gave a container space, fetch it */
		if ( rb_scan_args(argc, argv, "01", &container) ) {
			ode_GEOMETRY	*containerPtr;

			containerPtr = get_space( container );
			debugMsg(( "Got container space <%p>", containerPtr ));
			containerSpace = (dSpaceID)containerPtr->id;
		}

		/* Allocate the ode_GEOMETRY struct for this space */
		DATA_PTR(self) = ptr = ode_space_alloc();
		ptr->object		= self;
		ptr->container	= container;
		debugMsg(( "New space = <%p>", ptr ));

		/* Create the ODE space object according to which class is being initialized */
		if ( CLASS_OF(self) == ode_cOdeSpace )
			ptr->id = (dGeomID)dSimpleSpaceCreate( containerSpace );
		else if ( CLASS_OF(self) == ode_cOdeHashSpace )
			ptr->id = (dGeomID)dHashSpaceCreate( containerSpace );
		else
			rb_raise( rb_eTypeError, "No allocator defined for a %s.",
					  rb_class2name(CLASS_OF( self )) );

		/* Tell ODE not to clean up its spaces itself to prevent running around
		   pointing to freed memory */
		debugMsg(( "Turning off cleanup flag." ));
		dSpaceSetCleanup( (dSpaceID)ptr->id, 0 );

		/* Set the ode_GEOMETRY struct as the space's data pointer so we can get
		   the object from the dSpaceID */
		dGeomSetData( ptr->id, ptr );
	}

	/* Call our parent's initializer */
	debugMsg(( "Calling super()" ));
	rb_call_super( 0, 0 );
	debugMsg(( "Back from super()" ));

	return self;
}

Public Instance methods

addGeometries( *geometries ) — Add the specified geometries (ODE::Geometry objects) to the receiving space and return the space itself.

[Source]

/*
 * addGeometries( *geometries )
 * --
 * Add the specified geometries (ODE::Geometry objects) to the receiving
 * space and return the space itself.
 */
static VALUE
ode_space_insert( self, args )
	 VALUE self, args;
{
	ode_GEOMETRY	*ptr = get_space( self );
	int				i = 0;

	if ( TYPE(args) != T_ARRAY )
		rb_bug( "Expected array, got a %s.", rb_class2name(CLASS_OF(args)) );

	for ( i = 0; i < RARRAY(args)->len; i++ ) {
		ode_GEOMETRY	*cptr = ode_get_geom( *(RARRAY(args)->ptr + i) );
		dSpaceAdd( (dSpaceID)ptr->id, (dGeomID)cptr->id );
	}

	return self;
}

contains?( geom ) — Returns true if the receiving space, or any of the spaces it contains (recursively), contains the specified geom (an ODE::Geometry object).

[Source]

/*
 * contains?( geom )
 * --
 * Returns true if the receiving space, or any of the spaces it contains
 * (recursively), contains the specified <tt>geom</tt> (an ODE::Geometry
 * object).
 */
static VALUE
ode_space_contains_p( self, geom )
	 VALUE self, geom;
{
	ode_GEOMETRY	*ptr = get_space( self );
	ode_GEOMETRY	*targetPtr = ode_get_geom( geom );

	if ( ode_spaceId_contains((dSpaceID)ptr->id, targetPtr->id) )
		return Qtrue;
	else
		return Qfalse;
}

directlyContains?( geom ) — Returns true if the receiving space contains the geom (an ODE::Geometry object) specified. This, unlike contains?, does not recurse into contained subspaces.

[Source]

/*
 * directlyContains?( geom )
 * --
 * Returns true if the receiving space contains the geom (an ODE::Geometry
 * object) specified. This, unlike contains?, does not recurse into contained
 * subspaces.
 */
static VALUE
ode_space_directly_contains_p( self, geom )
	 VALUE self, geom;
{
	ode_GEOMETRY	*ptr = get_space( self );
	ode_GEOMETRY	*otherptr = ode_get_geom( geom );

	if ( dSpaceQuery((dSpaceID)ptr->id, otherptr->id) )
		return Qtrue;
	else
		return Qfalse;
}

each( &block ) — Iterate over the geometries in the space, passing each to the given block.

[Source]

/*
 * each( &block )
 * --
 * Iterate over the geometries in the space, passing each to the given block.
 */
static VALUE
ode_space_each( self )
	 VALUE self;
{
	ode_GEOMETRY *ptr = get_space( self );
	VALUE		 rary = rb_ary_new();
	int			 i, geomCount = dSpaceGetNumGeoms( (dSpaceID)ptr->id );

	if ( !rb_block_given_p() )
		rb_raise( ruby_eLocalJumpError, "no block given" );

	for ( i = 0 ; i < geomCount ; i++ ) {
		dGeomID subgeom = dSpaceGetGeom( (dSpaceID)ptr->id, i );
		ode_GEOMETRY *subgeomPtr = dGeomGetData(subgeom);

		rb_ary_push( rary, rb_yield(subgeomPtr->object) );
	}

	return rary;
}

eachAdjacentPair( *data ) {|geom1, geom2, *data| block } — Call the specified block once for each adjacent pair of ODE::Geometry objects in the receiving space. The block must accept three arguments: the two geometries and a data Array.

[Source]

/*
 * eachAdjacentPair( *data ) {|geom1, geom2, *data| block }
 * --
 * Call the specified <tt>block</tt> once for each adjacent pair of
 * ODE::Geometry objects in the receiving space. The block must accept three
 * arguments: the two geometries and a <tt>data</tt> Array.
 */
static VALUE
ode_space_each_adjacent_pair( argc, argv, self )
	 int	argc;
	 VALUE	*argv, self;
{
	ode_GEOMETRY	*ptr = get_space( self );
	ode_CALLBACK	*callback;
	VALUE			data, block;

	rb_scan_args( argc, argv, "0*&", &data, &block );

	ode_check_arity( block, 3 );

	callback = ALLOCA_N( ode_CALLBACK, 1 );
	callback->callback = block;
	callback->args = data;

	dSpaceCollide( (dSpaceID)ptr->id, callback,
				   (dNearCallback *)(ode_near_callback) );

	return Qtrue;
}

geometries — Returns an Array of all the geometries (ODE::Geometry objects) contained in this space.

[Source]

/*
 * geometries
 * --
 * Returns an Array of all the geometries (ODE::Geometry objects) contained in
 * this space.
 */
static VALUE
ode_space_geometries( self )
	 VALUE self;
{
	ode_GEOMETRY *ptr = get_space( self );
	VALUE		 rary = rb_ary_new();
	int			 i, geomCount = dSpaceGetNumGeoms( (dSpaceID)ptr->id );

	for ( i = 0 ; i < geomCount ; i++ ) {
		dGeomID geom = dSpaceGetGeom( (dSpaceID)ptr->id, i );
		rb_ary_push( rary, ((ode_GEOMETRY *)dGeomGetData(geom))->object );
	}

	return rary;
}

geometries=( geometryArray ) — Set the geometries in the receiving space to the given Array of geometries (ODE::Geometry objects).

[Source]

/*
 * geometries=( geometryArray )
 * --
 * Set the geometries in the receiving space to the given Array of geometries
 * (ODE::Geometry objects).
 */
static VALUE
ode_space_geometries_eq( self, geometryArray )
	 VALUE self, geometryArray;
{
	ode_GEOMETRY	*ptr = get_space( self );
	dSpaceID		thisSpace = (dSpaceID)( ptr->id );
	int				i, geomCount = dSpaceGetNumGeoms( (dSpaceID)ptr->id );
	VALUE			removeGeoms = rb_ary_new(),
					addGeoms = rb_ary_new();

	Check_Type( geometryArray, T_ARRAY );

	/* First remove any geometries that aren't in the new array -- Build an
	   array of all geometries that are currently in the space but aren't in the
	   new array. */
	for ( i = 0 ; i < geomCount ; i++ ) {
		dGeomID			geom = dSpaceGetGeom( thisSpace, i );
		ode_GEOMETRY	*gptr = dGeomGetData( geom );

		if ( !RTEST(rb_ary_includes( geometryArray, gptr->object )) )
			rb_ary_push( removeGeoms, gptr->object );
	}

	/* If there are any geometries to remove, remove them via #removeGeometries to give
	   derivatives a chance to act on the removals. */
	if ( RARRAY(removeGeoms)->len )
		rb_funcall( self, rb_intern("removeGeometries"), 1, &removeGeoms );

	/* Now make an array of geometries which are in the new array, but aren't in
	   the space currently. */
	for ( i = 0 ; i < RARRAY(geometryArray)->len ; i++ ) {
		ode_GEOMETRY *geom = ode_get_geom( *(RARRAY(geometryArray)->ptr + i) );

		if ( !dSpaceQuery(thisSpace, geom->id) )
			rb_ary_push( addGeoms, geom->object );
	}

	/* If there are any geometries to add, add them via #addGeometries to give
	   derivatives a chance to act on the additions. */
	if ( RARRAY(addGeoms)->len )
		rb_funcall( self, rb_intern("addGeometries"), 1, &addGeoms );

	/* It doesn't really matter what we return here, as Matz decided assignment
	   methods always return what was assigned, so... */
	return Qnil;
}

Returns a human-readable string containing a representation of the Space suitable for debugging or tracing.

[Source]

# File lib/ode/space.rb, line 44
        def inspect
            return "<%s 0x%x: geometries=[%s]>" % [
                self.class.name,
                self.respond_to?( :object_id ) ? self.object_id * 2 : self.id * 2,
                self.geometries.collect {|geom| geom.inspect}.join(", "),
            ]
        end

removeGeometries( *geometries ) — Remove the specified geometries (ODE::Geometry objects) from the receiving space if they are there and return the ones that were removed.

[Source]

/*
 * removeGeometries( *geometries )
 * --
 * Remove the specified <tt>geometries</tt> (ODE::Geometry objects) from the
 * receiving space if they are there and return the ones that were removed.
 */
static VALUE
ode_space_remove( self, args )
	 VALUE self, args;
{
	ode_GEOMETRY	*ptr = get_space( self );
	int				i = 0;
	VALUE			rary = rb_ary_new();

	if ( TYPE(args) != T_ARRAY )
		rb_bug( "Expected array, got a %s.", rb_class2name(CLASS_OF(args)) );

	for ( i = 0; i < RARRAY(args)->len; i++ ) {
		ode_GEOMETRY	*cptr = ode_get_geom( *(RARRAY(args)->ptr + i) );
		if ( dSpaceQuery((dSpaceID)ptr->id, (dGeomID)cptr->id) ) {
			rb_ary_push( rary, *(RARRAY(args)->ptr + i) );
			dSpaceRemove( (dSpaceID)ptr->id, (dGeomID)cptr->id );
		}
	}

	return rary;
}

[Validate]