Class ODE::Surface
In: ext/body.c  (CVS)
Parent: Object

Methods

Public Class methods

allocate() — Allocate a new ODE::Surface object.

[Source]

/*
 * allocate()
 * --
 * Allocate a new ODE::Surface object.
 */
static VALUE
ode_surface_s_alloc( klass )
{
	debugMsg(( "Wrapping an uninitialized ODE::Surface pointer." ));
	return Data_Wrap_Struct( klass, 0, xfree, 0 );
}

     Instance Methods

[Source]

/* --------------------------------------------------
 *	Instance Methods
 * -------------------------------------------------- */

static VALUE
ode_surface_init( argc, argv, self )
	 int	argc;
	 VALUE	*argv, self;
{
	dSurfaceParameters	*surface;
	VALUE				mu;

	DATA_PTR(self) = surface = ode_surface_alloc();

	/* Set the mode if it was specified. */
	if ( rb_scan_args(argc, argv, "01", &mu) ) {
		CheckPositiveNumber( NUM2DBL(mu), "mu" );
		surface->mu = (dReal)NUM2DBL( mu );
	}

	rb_call_super( 0, 0 );

	return self;
}

Public Instance methods

bounce() — Get the surface’s elasticity as the coefficient of restitution, which will be a value between 0 and 1, inclusive. 0 means the surfaces are not elastic at all; 1 is perfect elasticity.

[Source]

/*
 * bounce()
 * --
 * Get the surface's elasticity as the coefficient of restitution, which will be
 * a value between 0 and 1, inclusive. 0 means the surfaces are not elastic at
 * all; 1 is perfect elasticity.
 */
static VALUE
ode_surface_get_bounce( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactBounce )
		return rb_float_new( surface->bounce );
	else
		return Qnil;
}

bounce=( Float ) — Set the surface’s elasticity as the coefficient of restitution; the value must be between 0 and 1, inclusive. 0 means the surfaces are not elastic at all; 1 is perfect elasticity.

[Source]

/*
 * bounce=( Float )
 * --
 * Set the surface's elasticity as the coefficient of restitution; the value
 * must be between 0 and 1, inclusive. 0 means the surfaces are not elastic at
 * all; 1 is perfect elasticity.
 */
static VALUE
ode_surface_set_bounce( self, newBounce )
	 VALUE self, newBounce;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newBounce )) {
		dReal bounce = NUM2DBL( newBounce );

		if ( bounce < 0 || bounce > 1 )
			rb_raise( rb_eRangeError,
					  "Value (%0.2f) out of bounds; must be between 0 and 1, inclusive.",
					  bounce );

		surface->bounce = bounce;
		surface->mode |= dContactBounce;

		return rb_float_new( surface->bounce );
	} else {
		surface->mode ^= (surface->mode & dContactBounce);
		surface->bounce = 0.f;

		return Qnil;
	}
}

bounce?() — Predicate method to test if the elasticity (bounciness) of the surface has been set.

[Source]

/*
 * bounce?()
 * --
 * Predicate method to test if the elasticity (bounciness) of the surface has
 * been set.
 */
static VALUE
ode_surface_bounce_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactBounce )
		return Qtrue;
	else
		return Qfalse;
}

bounce_vel() — Get the minimum incoming velocity necessary for bounce (in m/s). Incoming velocities below this will effectively have a bounce parameter of 0.

[Source]

/*
 * bounce_vel()
 * --
 * Get the minimum incoming velocity necessary for bounce (in m/s). Incoming
 * velocities below this will effectively have a bounce parameter of 0.
 */
static VALUE
ode_surface_get_bounce_vel( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactBounce )
		return rb_float_new( surface->bounce_vel );
	else
		return Qnil;
}

bounce_vel=( Float ) — Set the minimum incoming velocity necessary for bounce (in m/s). Incoming velocities below this will effectively have a bounce parameter of 0.

[Source]

/*
 * bounce_vel=( Float )
 * --
 * Set the minimum incoming velocity necessary for bounce (in m/s). Incoming
 * velocities below this will effectively have a bounce parameter of 0.
 */
static VALUE
ode_surface_set_bounce_vel( self, velocity )
	 VALUE self, velocity;
{
	dSurfaceParameters	*surface = get_surface(self);
	dReal vel = NUM2DBL( velocity );

	if ( vel < 0 )
		rb_raise( rb_eRangeError, "Value (%0.2f) out of bounds; must be "
				  "a positive value.", vel );

	surface->bounce_vel = vel;

	return rb_float_new( surface->bounce_vel );
}

frictionModel=( flags ) — Set the friction model to be used for either or both friction directions. The flags argument can be one of ODE::Contact::PyramidFriction{Neither,1,2,Both}. Any friction direction which does not use the pyramid friction approximation will use normal "box friction". ODE::Contact::PyramidFrictionNeither is the default.

[Source]

/*
 * frictionModel=( flags )
 * --
 * Set the friction model to be used for either or both friction directions. The
 * <tt>flags</tt> argument can be one of
 * ODE::Contact::PyramidFriction{Neither,1,2,Both}. Any friction direction which
 * does not use the pyramid friction approximation will use normal "box
 * friction". ODE::Contact::PyramidFrictionNeither is the default.
 */
static VALUE
ode_surface_set_friction_model( self, setting )
	VALUE self, setting;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	surface->mode ^= (surface->mode & dContactApprox1);
	surface->mode |= (FIX2INT(setting) & (dContactApprox1));

	return INT2FIX( surface->mode & dContactApprox1 );
}

mode() — Get the surface’s contact flags. See the constants in the ODE::Contact class for possible legal values.

[Source]

/*
 * mode()
 * --
 * Get the surface's contact flags. See the constants in the ODE::Contact class
 * for possible legal values.
 */
static VALUE
ode_surface_get_mode( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	return INT2FIX( surface->mode );
}

mode=( Integer ) — Set the surface’s contact flags. See the constants in the ODE::Contact class for possible legal values. Note that the mode value may also be altered by setting the corresponding values for the given contact flags. Eg., calling ODE::Contact#mu2= with a non-nil value will automatically add ODE::Contact::Mu2 to the surface’s contact mode, while calling it with nil or false will remove the flag. Setting this to a value inconsistant with the contact values may have undesired results.

[Source]

/*
 * mode=( Integer )
 * --
 * Set the surface's contact flags. See the constants in the ODE::Contact class
 * for possible legal values. Note that the mode value may also be altered by
 * setting the corresponding values for the given contact flags. Eg., calling
 * ODE::Contact#mu2= with a non-nil value will automatically add
 * ODE::Contact::Mu2 to the surface's contact mode, while calling it with nil or
 * false will remove the flag. Setting this to a value inconsistant with the
 * contact values may have undesired results.
 */
static VALUE
ode_surface_set_mode( self, newMode )
	 VALUE self, newMode;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	CheckPositiveNumber( NUM2INT(newMode), "mode" );
	surface->mode = NUM2INT( newMode );

	return INT2FIX( surface->mode );
}

motion1() — Get the surface’s velocity (m/s) in friction direction 1.

[Source]

/*
 * motion1()
 * --
 * Get the surface's velocity (m/s) in friction direction 1.
 */
static VALUE
ode_surface_get_motion1( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMotion1 )
		return rb_float_new( surface->motion1 );
	else
		return Qnil;
}

motion1=( Float ) — Set the surface’s velocity (m/s) in friction direction 1 to the given value.

[Source]

/*
 * motion1=( Float )
 * --
 * Set the surface's velocity (m/s) in friction direction 1 to the given value.
 */
static VALUE
ode_surface_set_motion1( self, newMotion1 )
	 VALUE self, newMotion1;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newMotion1 )) {
		dReal velocity = NUM2DBL( newMotion1 );

		surface->motion1 = velocity;
		surface->mode |= dContactMotion1;

		return rb_float_new( surface->motion1 );
	} else {
		surface->mode ^= (surface->mode & dContactMotion1);
		surface->motion1 = 0.f;

		return Qnil;
	}
}

motion1?() — Predicate method to test if the surface has a velocity in friction direction

  1. If true, the contact surface is assumed to be moving

independently of the motion of the bodies — like a conveyor belt running over the surface.

[Source]

/*
 * motion1?()
 * --
 * Predicate method to test if the surface has a velocity in friction direction
 * 1. If <tt>true</tt>, the contact surface is assumed to be moving
 * independently of the motion of the bodies -- like a conveyor belt running
 * over the surface.
 */
static VALUE
ode_surface_motion1_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMotion1 )
		return Qtrue;
	else
		return Qfalse;
}

motion2() — Get the surface’s velocity (m/s) in friction direction 2.

[Source]

/*
 * motion2()
 * --
 * Get the surface's velocity (m/s) in friction direction 2.
 */
static VALUE
ode_surface_get_motion2( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMotion2 )
		return rb_float_new( surface->motion2 );
	else
		return Qnil;
}

motion2=( Float ) — Set the surface’s velocity (m/s) in friction direction 2 to the given value.

[Source]

/*
 * motion2=( Float )
 * --
 * Set the surface's velocity (m/s) in friction direction 2 to the given value.
 */
static VALUE
ode_surface_set_motion2( self, newMotion2 )
	 VALUE self, newMotion2;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newMotion2 )) {
		dReal velocity = NUM2DBL( newMotion2 );

		surface->motion2 = velocity;
		surface->mode |= dContactMotion2;

		return rb_float_new( surface->motion2 );
	} else {
		surface->mode ^= (surface->mode & dContactMotion2);
		surface->motion2 = 0.f;

		return Qnil;
	}
}

motion2?() — Predicate method to test if the surface has a velocity in friction direction

  1. If true, the contact surface is assumed to be moving

independently of the motion of the bodies — like a conveyor belt running over the surface.

[Source]

/*
 * motion2?()
 * --
 * Predicate method to test if the surface has a velocity in friction direction
 * 2. If <tt>true</tt>, the contact surface is assumed to be moving
 * independently of the motion of the bodies -- like a conveyor belt running
 * over the surface.
 */
static VALUE
ode_surface_motion2_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMotion2 )
		return Qtrue;
	else
		return Qfalse;
}

mu() — Get the surface’s Coulomb friction coefficient.

[Source]

/*
 * mu()
 * --
 * Get the surface's Coulomb friction coefficient.
 */
static VALUE
ode_surface_get_mu( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	return rb_float_new( surface->mu );
}

mu2() — Get the surface’s Coulomb friction coefficient for friction direction 2. This must be in the range 0.0 to ODE::Infinity. If not set, the surface’s first coefficient will be used for both directions.

[Source]

/*
 * mu2()
 * --
 * Get the surface's Coulomb friction coefficient for friction direction 2. This
 * must be in the range 0.0 to ODE::Infinity. If not set, the surface's first
 * coefficient will be used for both directions.
 */
static VALUE
ode_surface_get_mu2( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMu2 )
		return rb_float_new( surface->mu2 );
	else
		return Qnil;
}

mu2=( Float ) — Set the surface’s Coulomb friction coefficient for friction direction 2. This must be in the range 0.0 to ODE::Infinity. If not set, the surface’s first coefficient will be used for both directions.

[Source]

/*
 * mu2=( Float )
 * --
 * Set the surface's Coulomb friction coefficient for friction direction 2. This
 * must be in the range 0.0 to ODE::Infinity. If not set, the surface's first
 * coefficient will be used for both directions.
 */
static VALUE
ode_surface_set_mu2( self, newMu2 )
	 VALUE self, newMu2;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newMu2 )) {
		dReal mu2 = NUM2DBL( newMu2 );

		if ( mu2 != dInfinity && mu2 < 0 )
			rb_raise( rb_eRangeError,
					  "Illegal value (%0.2f); must be between 0 and ODE::Infinity",
					  mu2 );
	
		surface->mu2 = mu2;
		surface->mode |= dContactMu2;

		return rb_float_new( surface->mu2 );
	} else {
		surface->mode ^= (surface->mode & dContactMu2);
		surface->mu2 = 0.f;

		return Qnil;
	}
}

mu2?() — Predicate method to test if the Coulomb friction coefficient for friction direction 2 is set for this surface.

[Source]

/*
 * mu2?()
 * --
 * Predicate method to test if the Coulomb friction coefficient for friction
 * direction 2 is set for this surface.
 */
static VALUE
ode_surface_mu2_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactMu2 )
		return Qtrue;
	else
		return Qfalse;
}

mu=( Float ) — Set the surface’s Coulomb friction coefficient. This must be in the range 0.0 to ODE::Infinity. 0.0 results in a frictionless contact, and ODE::Infinity results in a contact that never slips. Note that frictionless contacts are less time consuming to compute than ones with friction, and infinite friction contacts can be cheaper than contacts with finite friction.

[Source]

/*
 * mu=( Float )
 * --
 * Set the surface's Coulomb friction coefficient. This must be in the range 0.0
 * to ODE::Infinity. 0.0 results in a frictionless contact, and ODE::Infinity
 * results in a contact that never slips. Note that frictionless contacts are
 * less time consuming to compute than ones with friction, and infinite friction
 * contacts can be cheaper than contacts with finite friction.
 */
static VALUE
ode_surface_set_mu( self, newMu )
	 VALUE self, newMu;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	CheckPositiveNumber( NUM2DBL(newMu), "mu" );
	surface->mu = (dReal)NUM2DBL( newMu );

	return rb_float_new( surface->mu );
}

pyramidFriction1=( trueOrFalse ) — Turn the pyramid friction approximation on or off for friction direction 1.

[Source]

/*
 * pyramidFriction1=( trueOrFalse )
 * --
 * Turn the pyramid friction approximation on or off for friction direction 1.
 */
static VALUE
ode_surface_set_friction_model1( self, setting )
	VALUE self, setting;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( setting )) 
		surface->mode |= dContactApprox1_1;

	return (surface->mode & dContactApprox1_1) ? Qtrue : Qfalse;
}

pyramidFriction1? — Returns true if friction direction 1 of the surface will use the friction pyramid approximation.

[Source]

/*
 * pyramidFriction1?
 * --
 * Returns <tt>true</tt> if friction direction 1 of the surface will use the
 * friction pyramid approximation.
 */
static VALUE
ode_surface_friction_model1_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactApprox1_1 )
		return Qtrue;
	else
		return Qfalse;
}

pyramidFriction1=( trueOrFalse ) — Turn the pyramid friction approximation on or off for friction direction 1.

[Source]

/*
 * pyramidFriction1=( trueOrFalse )
 * --
 * Turn the pyramid friction approximation on or off for friction direction 1.
 */
static VALUE
ode_surface_set_friction_model2( self, setting )
	VALUE self, setting;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( setting )) 
		surface->mode |= dContactApprox1_2;

	return (surface->mode & dContactApprox1_2) ? Qtrue : Qfalse;
}

pyramidFriction2? — Returns true if friction direction 2 of the surface will use the friction pyramid approximation.

[Source]

/*
 * pyramidFriction2?
 * --
 * Returns <tt>true</tt> if friction direction 2 of the surface will use the
 * friction pyramid approximation.
 */
static VALUE
ode_surface_friction_model2_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactApprox1_2 )
		return Qtrue;
	else
		return Qfalse;
}

slip1() — Get the surface’s first-order slip in friction direction 1.

[Source]

/*
 * slip1()
 * --
 * Get the surface's first-order slip in friction direction 1.
 */
static VALUE
ode_surface_get_slip1( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSlip1 )
		return rb_float_new( surface->slip1 );
	else
		return Qnil;
}

slip1=( Float ) — Set the surface’s first-order slip in friction direction 1 to the given value.

[Source]

/*
 * slip1=( Float )
 * --
 * Set the surface's first-order slip in friction direction 1 to the given value.
 */
static VALUE
ode_surface_set_slip1( self, newSlip1 )
	 VALUE self, newSlip1;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newSlip1 )) {
		dReal coefficient = NUM2DBL( newSlip1 );

		if ( coefficient < 0 || coefficient > 1 )
			rb_raise( rb_eRangeError,
					  "Value (%0.2f) out of bounds; must be between 0 and 1, inclusive.",
					  coefficient );

		surface->slip1 = coefficient;
		surface->mode |= dContactSlip1;

		return rb_float_new( surface->slip1 );
	} else {
		surface->mode ^= (surface->mode & dContactSlip1);
		surface->slip1 = 0.f;

		return Qnil;
	}
}

slip1?() — Predicate method to test if the surface defines a first-order slip for friction direction 1.

[Source]

/*
 * slip1?()
 * --
 * Predicate method to test if the surface defines a first-order slip for
 * friction direction 1.
 */
static VALUE
ode_surface_slip1_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSlip1 )
		return Qtrue;
	else
		return Qfalse;
}

slip2() — Get the surface’s first-order slip in friction direction 2.

[Source]

/*
 * slip2()
 * --
 * Get the surface's first-order slip in friction direction 2.
 */
static VALUE
ode_surface_get_slip2( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSlip2 )
		return rb_float_new( surface->slip2 );
	else
		return Qnil;
}

slip2=( Float ) — Set the surface’s first-order slip in friction direction 2 to the given value.

[Source]

/*
 * slip2=( Float )
 * --
 * Set the surface's first-order slip in friction direction 2 to the given value.
 */
static VALUE
ode_surface_set_slip2( self, newSlip2 )
	 VALUE self, newSlip2;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newSlip2 )) {
		dReal coefficient = NUM2DBL( newSlip2 );

		if ( coefficient < 0 || coefficient > 1 )
			rb_raise( rb_eRangeError,
					  "Value (%0.2f) out of bounds; must be between 0 and 1, inclusive.",
					  coefficient );

		surface->slip2 = coefficient;
		surface->mode |= dContactSlip2;

		return rb_float_new( surface->slip2 );
	} else {
		surface->mode ^= (surface->mode & dContactSlip2);
		surface->slip2 = 0.f;

		return Qnil;
	}
}

slip2?() — Predicate method to test if the surface defines a first-order slip for friction direction 2.

[Source]

/*
 * slip2?()
 * --
 * Predicate method to test if the surface defines a first-order slip for
 * friction direction 2.
 */
static VALUE
ode_surface_slip2_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSlip2 )
		return Qtrue;
	else
		return Qfalse;
}

softCFM() — Get the surface’s contact normal "softness" constraint force mixing parameter.

[Source]

/*
 * softCFM()
 * --
 * Get the surface's contact normal "softness" constraint force mixing
 * parameter.
 */
static VALUE
ode_surface_get_soft_cfm( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSoftCFM )
		return rb_float_new( surface->soft_cfm );
	else
		return Qnil;
}

softCFM=( Float ) — Set the surface’s contact normal "softness" constraint force mixing parameter. Typical values are in the range 1e-9 to 1.

[Source]

/*
 * softCFM=( Float )
 * --
 * Set the surface's contact normal "softness" constraint force mixing
 * parameter. Typical values are in the range 1e-9 to 1.
 */
static VALUE
ode_surface_set_soft_cfm( self, newSoftCFM )
	 VALUE self, newSoftCFM;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newSoftCFM )) {
		dReal cfm = NUM2DBL( newSoftCFM );

		if ( cfm < 0 || cfm > 1 )
			rb_raise( rb_eRangeError,
					  "Value (%0.2f) out of bounds; must be between 0 and 1, inclusive.",
					  cfm );

		surface->soft_cfm = cfm;
		surface->mode |= dContactSoftCFM;

		return rb_float_new( surface->soft_cfm );
	} else {
		surface->mode ^= (surface->mode & dContactSoftCFM);
		surface->soft_cfm = 0.f;

		return Qnil;
	}
}

softCFM?() — Predicate method to test if the surface’s contact normal "softness" constraint force mixing parameter is enabled.

[Source]

/*
 * softCFM?()
 * --
 * Predicate method to test if the surface's contact normal "softness"
 * constraint force mixing parameter is enabled.
 */
static VALUE
ode_surface_soft_cfm_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSoftCFM )
		return Qtrue;
	else
		return Qfalse;
}

softERP() — Get the surface’s contact normal "softness" error reduction parameter.

[Source]

/*
 * softERP()
 * --
 * Get the surface's contact normal "softness" error reduction parameter.
 */
static VALUE
ode_surface_get_soft_erp( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSoftERP )
		return rb_float_new( surface->soft_erp );
	else
		return Qnil;
}

softERP=( Float ) — Set the surface’s contact normal "softness" error reduction parameter. Typical values are in the range 0.1 to 0.8.

[Source]

/*
 * softERP=( Float )
 * --
 * Set the surface's contact normal "softness" error reduction
 * parameter. Typical values are in the range 0.1 to 0.8.
 */
static VALUE
ode_surface_set_soft_erp( self, newSoftERP )
	 VALUE self, newSoftERP;
{
	dSurfaceParameters	*surface = get_surface(self);

	if (RTEST( newSoftERP )) {
		dReal erp = NUM2DBL( newSoftERP );

		if ( erp < 0 || erp > 1 )
			rb_raise( rb_eRangeError,
					  "Value (%0.2f) out of bounds; must be between 0 and 1, inclusive.",
					  erp );

		surface->soft_erp = erp;
		surface->mode |= dContactSoftERP;

		return rb_float_new( surface->soft_erp );
	} else {
		surface->mode ^= (surface->mode & dContactSoftERP);
		surface->soft_erp = 0.f;

		return Qnil;
	}
}

softERP?() — Predicate method to test if the surface’s contact normal "softness" error reduction parameter is enabled.

[Source]

/*
 * softERP?()
 * --
 * Predicate method to test if the surface's contact normal "softness" error
 * reduction parameter is enabled.
 */
static VALUE
ode_surface_soft_erp_p( self )
	 VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactSoftERP )
		return Qtrue;
	else
		return Qfalse;
}

useFrictionDirection=( trueOrFalse ) — If set to a true value, the ‘frictionDirection’ vector of any ODE::Contact this surface is applied to will be used as friction direction 1; otherwise direction 1 will be computed to be perpendicular to the contact normal (in which case its resulting orientation is not defined).

[Source]

/*
 * useFrictionDirection=( trueOrFalse )
 * --
 * If set to a true value, the 'frictionDirection' vector of any ODE::Contact
 * this surface is applied to will be used as friction direction 1; otherwise
 * direction 1 will be computed to be perpendicular to the contact normal (in
 * which case its resulting orientation is not defined).
 */
static VALUE
ode_surface_set_fdir1_mode( self, setting )
	VALUE self, setting;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if (RTEST( setting ))
		surface->mode |= dContactFDir1;
	else
		surface->mode ^= (surface->mode & dContactFDir1);

	return RTEST(setting) ? Qtrue : Qfalse;
}

useFrictionDirection? — Returns true if the ‘frictionDirection’ vector of any ODE::Contact this surface is applied to will be used as friction direction 1.

[Source]

/*
 * useFrictionDirection?
 * --
 * Returns true if the 'frictionDirection' vector of any ODE::Contact this
 * surface is applied to will be used as friction direction 1.
 */
static VALUE
ode_surface_fdir1_mode_p( self )
	VALUE self;
{
	dSurfaceParameters	*surface = get_surface(self);
	
	if ( surface->mode & dContactFDir1 )
		return Qtrue;
	else 
		return Qfalse;
}

|( otherSurface ) — Combine the receiver with the otherSurface and return the new surface.

[Source]

/*
 * |( otherSurface )
 * --
 * Combine the receiver with the <tt>otherSurface</tt> and return the new
 * surface.
 */
static VALUE
ode_surface_combine( self, otherSurface )
	 VALUE self, otherSurface;
{
	dSurfaceParameters *surface	= get_surface( self );
	dSurfaceParameters *other	= get_surface( otherSurface );

	VALUE newSurface = rb_class_new_instance( 0, 0, CLASS_OF(self) );
	dSurfaceParameters *ptr = get_surface( newSurface );

	/* This is by no means perfect, and probably not even mathematically or
	   physically correct, but it does the job for now. Suggestions for a better
	   way to do this welcomed. */
	ptr->mode		= surface->mode | other->mode;
	ptr->mu			= average( surface->mu, other->mu );
	ptr->mu2		= average( surface->mu2, other->mu2 );

	ptr->bounce		= average( surface->bounce, other->bounce );
	ptr->bounce_vel	= average( surface->bounce_vel, other->bounce_vel );
	ptr->soft_erp	= average( surface->soft_erp, other->soft_erp );
	ptr->soft_cfm	= average( surface->soft_cfm, other->soft_cfm );
	ptr->motion1	= average( surface->motion1, other->motion1 );
	ptr->motion2	= average( surface->motion2, other->motion2 );
	ptr->slip1		= average( surface->slip1, other->slip1 );
	ptr->slip2		= average( surface->slip2, other->slip2 );

	return newSurface;
}

[Validate]