Force effects

From H3D.org

Jump to: navigation, search

One of the plus points of H3D is that developers can work on one scenegraph that integrates both graphics and haptics. These examples with various types of force effects demonstrate exactly that. When programming with X3D, force effects haptics can be added to the scenegraph just like any other node.

H3DAPI implements six types of force effects:

  • Force field
  • Spring effect
  • Magnetic geometry effect
  • Position function effect
  • Time function effect
  • Viscosity effect

All the force effects nodes in H3DAPI inherit from H3DForceEffect which only contains the metadata field, and thus is the only field common to all force effects node. We will go through examples for the first five effects here.

Image:Note-tip.pngThis tutorial refers to the source code. You can download it from SVN at H3D release branch, or find it at H3D/H3DAPI/examples/ForceEffects/.

Contents

Force field

A force field adds a constant force to the scene. Force fields are added with the ForceField node, which has only one field of its own: force, an SFVec3f typed field that specifies the force to render.

 
<!!-- forcefield.x3d -->
<ForceField force = "0.5 0 0"/>
 

The one line of code above generates a force field of 0.5N in the positive x-direction.


Spring effect

The spring effect models force by spring and is added to a scene with the SpringEffect node. The example below demonstrates this and the concept of the startDistance, escapeDistance and active fields.

 
<!!-- springs.x3d -->
<Group>
  <Shape>
    <Appearance>
      <Material diffuseColor="1 0 0" transparency="0.5"/>
    </Appearance>
    <Sphere DEF="SPHERE" radius = "0.01" />
  </Shape>
  <SpringEffect DEF="SPRING" escapeDistance="0.03"/>
 

A red-coloured transparent Sphere is added to the scene, followed by a SpringEffect. By the default, the position of the SpringEffect is at the origin, which is also the center of the sphere. The position of the SpringEffect can be changed by changing the value of its position field, which we do not do here.

 
<!!-- springs.x3d -->
  <PythonScript DEF="PS" url="springs.py" />
  <ROUTE fromNode="SPRING" fromField="active" toNode="PS" toField="sphereRadius"/>
  <ROUTE fromNode="SPRING" fromField="startDistance" toNode="PS" toField="sphereRadius"/>
  <ROUTE fromNode="SPRING" fromField="escapeDistance" toNode="PS" toField="sphereRadius"/>
  <ROUTE fromNode="PS" fromField="sphereRadius" toNode="SPHERE" toField="radius"/>
</Group>
 

Then a PythonScript with a sphereRadius field is added, routed to by the fields active, startDistance and escapeDistance of SpringEffect. The active field is an outputOnly field whose value is True when the SpringEffect is acting on a haptics device, and False when it is not. The startDistance field is an SFFloat indicating the distance from the SpringEffect position where force starts to act on the haptics device. escapeDistance is the distance from the geometry that when exceeded while the SpringEffect is active, the SpringEffect will no longer generate any force on the haptics device.

Since this is an X3D tutorial for H3DAPI beginners we will not discuss the details of the Python script. The keen reader may find the script below. It suffices to know for now that the sphereRadius field is just like any other field. It is an inputOutput field of type SFFloat whose value is determined by the following:

  • if SpringEffect is active i.e. active is True, the value is the same as escapeDistance.
  • if SpringEffect is inactive i.e. active is False, the value is the same as startDistance.

sphereRadius is then routed to the radius of the Sphere, which means that when there is a change in value of sphereRadius, radius will be updated to the same value.

 
#springs.py
from H3DInterface import *
 
class SphereRadius( TypedField( SFFloat, ( SFBool, SFFloat, SFFloat )  ) ):
  def update( self, event ):
    routes_in = self.getRoutesIn()
    active = routes_in[0].getValue()
    start_dist = routes_in[1].getValue()
    escape_dist = routes_in[2].getValue()
    if( active ):
      return escape_dist
    else:
      return start_dist
 
sphereRadius = SphereRadius()
 


Magnetic geometry effect

The magnetic geometry effect models a magnetic force and is implemented in the MagneticGeometryEffect node. The following code shows the magnetic geometry effect in action. The MagneticGeometryEffect is akin to MagneticSurface. While MagneticSurface is an H3DSurface node and is a child of the Appearance node that defines the appearance of an X3DGeometryNode, MagneticGeometryEffect is an H3DForceEffect that uses the X3DGeometryNode to specify the geometry of its source object.

 
<!!-- magneticGeometryEffect.x3d -->
<Transform translation="0 -0.05 0">
  <Transform translation="0.1 0 0">
    <Shape>
      <Appearance>
        <Material diffuseColor="1 0 0" transparency="0.5"/>
      </Appearance>
      <Box size="0.1 0.1 0.1" DEF="BOX"/>
    </Shape>
 

First the graphical representation of a Box is created, DEF-ed BOX

 
<!!-- magneticGeometryEffect.x3d -->
    <MagneticGeometryEffect DEF="MGE" startDistance="0.03" escapeDistance="0.03">
      <Box USE="BOX"/>
    </MagneticGeometryEffect>
  </Transform>
 

MagneticGeometryEffect is added to the scene, and uses BOX as its geometry. The startDistance field is an SFFloat indicating the distance from the geometry where force starts to act on the haptics device. escapeDistance is the distance from the geometry that when exceeded while the effect is active, will no longer generate any force effect on the haptics device.

 
<!!-- magneticGeometryEffect.x3d -->
  <Transform translation="-0.1 0 0">
    <MagneticGeometryEffect DEF="MGE" startDistance="0.01" escapeDistance="0.01" springConstant="400">
      <Extrusion spine="-0.05 -0.05 -0.05, 0 -0.05 0, 0 0.05 0, 0.05 0.05 0"
                 crossSection="0.01 0.01, 0.01 -0.01, -0.01 -0.01, -0.01 0.01, 0.01 0.01" 
                 DEF="EXT"/>
    </MagneticGeometryEffect>
 

Another MagneticGeometryEffect is created and translated 0.1m to the left of the origin. The springConstant of this MagneticGeometryEffect is set to 400. The springConstant is used to calculate the force of this effect. The larger the value of springConstant the larger the force. This MagneticGeometryEffect uses an Extrusion as its geometry. Note that if left on its own, the code above would create a magnetic field that seems to surround an invisible object.

 
<!!-- magneticGeometryEffect.x3d -->
    <ToggleGroup DEF="TG" graphicsOn="false" hapticsOn="false">
      <Shape>
        <Appearance>
          <Material/>
        </Appearance>
        <Extrusion USE="EXT"/>
      </Shape>
    </ToggleGroup>
  </Transform>
 

A shape with the same Extrusion geometry is added. It is enclosed by a ToggleGroup. The ToggleGroup node is an H3DAPI implementation that inherits from the X3DGroupingNode. It has two fields, graphicsOn and hapticsOn that determines whether the graphics or haptics are of its children nodes are rendered.

 
<!!-- magneticGeometryEffect.x3d -->
  <MouseSensor DEF="MS"/>
 
  <ROUTE fromNode='MS' fromField='rightButton'
         toNode='TG' toField='graphicsOn'/>
</Transform>
 

A MouseSensor is added, and its rightButton routed to the graphicsOn field of ToggleGroup. Hence when right button of the mouse is click, the children of the ToggleGroup, in this case the Shape with Extrusion geometry will be graphically rendered.

Position function effect

As its name suggests, the position function effect creates a force in the scene controlled by a position function. The node has fields xFunction, yFunction and zFunction that controls the force in the x, y and z directions respectively. The generated force is F = <xFunction, yFunction, zFunction>

 
<!!-- positionFunctionEffect.x3d -->
    <PositionFunctionEffect>
      <GeneralFunction containerField="xFunction" function="10*y" params="x,y,z"/>
      <GeneralFunction containerField="yFunction" function="0" params="x,y,z"/>
      <GeneralFunction containerField="zFunction" function="0" params="x,y,z"/>
    </PositionFunctionEffect>
 

xFunction, yFunction and zFunction are of type SFFunctionNode. In this example GeneralFunction is used as the value to each field. GeneralFunction takes a string of needed function in its function field and a string indicating the parameters on the function. In this case we specify the functions f1=10y, f2=0 and f3=0, which eventually determines the force of the effect to be F = <10y, 0, 0>.

Image:Note-info.pngThe source code for this example contains additional interfacing with ToggleGroup. ToggleGroup is discussed in Magnetic geometry effect above and will not be repeated here for purpose of brevity.


Time function effect

The time function effect creates a force in the scene controlled by a time function. The node has fields xFunction, yFunction and zFunction that controls the force in the x, y and z directions with respect to time. The generated force is F = <xFunction, yFunction, zFunction>

 
<!!-- timeFunctionEffect.x3d -->
    <TimeFunctionEffect>
      <GeneralFunction containerField="xFunction" function="sin(2*t)" params="t"/>
      <GeneralFunction containerField="yFunction" function="0" params="t"/>
      <GeneralFunction containerField="zFunction" function="0" params="t"/>
    </TimeFunctionEffect>
 

Like the position function effect example, GeneralFunction is used to specify the functions. Functions to TimeFucntionEffect must take only one variable (representing time). In this case we specify the functions f1=sin(2t), f2=0 and f3=0, which eventually determines the force of the effect to be F = <sin(2t), 0, 0>.


References

Personal tools
go to