[ODE] Hydrodynamic Forces Demo

Ander Taylor ander_taylor at hotmail.com
Fri Nov 14 03:31:45 MST 2003


Hi Artur,

I am a bit lazy : )

So here is the source.

Module Demo

  'TV Mesh Objects
  Public SubBodyMesh As New TrueVision3D.TVMesh()
  Public SubRightWingMesh As New TrueVision3D.TVMesh()
  Public SubLeftWingMesh As New TrueVision3D.TVMesh()
  Public SubRudderMesh As New TrueVision3D.TVMesh()
  Public SubPropSpindleMesh As New TrueVision3D.TVMesh()
  Public SubPropBladesMesh(3) As TrueVision3D.TVMesh
  Public GroundMesh As New TrueVision3D.TVMesh()

  'ODEDotNet Objects
  Public gWorld As ManagedODE.World
  Public gSpace As ManagedODE.SimpleSpace
  Public gPlane As ManagedODE.PlaneGeom

  Public gCallBack As New ManagedODE.CollisionHandler(AddressOf MyCallBack)
  Public gCallCollide As New ManagedODE.CollisionManager()
  Public gContact As ManagedODE.Contact
  Public gContactGroup As New ManagedODE.JointGroup(1000)

  Public SubBody As ManagedODE.Body
  Public SubBodyGeom As ManagedODE.BoxGeom
  Public SubBodySize As New ManagedODE.Vector3(300, 30, 100)

  Public SubRightWing As ManagedODE.Body
  Public SubRightWingGeom As ManagedODE.BoxGeom
  Public SubRightWingHinge As ManagedODE.JointHinge
  Public SubLeftWing As ManagedODE.Body
  Public SubLeftWingGeom As ManagedODE.BoxGeom
  Public SubLeftWingHinge As ManagedODE.JointHinge
  Public SubWingSize As New ManagedODE.Vector3(50, 5, 75)

  Public SubRudder As ManagedODE.Body
  Public SubRudderGeom As ManagedODE.BoxGeom
  Public SubRudderHinge As ManagedODE.JointHinge
  Public SubRudderSize As New ManagedODE.Vector3(50, 50, 5)

  Public SubPropSpindle As ManagedODE.Body
  Public SubPropSpindleHinge As ManagedODE.JointHinge

  Public Mass As ManagedODE.Mass

  Public Mat As New ManagedODE.Matrix3()
  Public Vec As New ManagedODE.Vector3()
  Public Flow As New ManagedODE.Vector3()

  Public Gravity As Double = -9.8

  Public GravityOn As Boolean = True
  Public HydrodynamicsOn As Boolean = True
  Public LinearViscosity As Double = 0.1
  Public AngularViscosity As Double = 50
  Public Density As Double = 0.001

  Public Sub InitializeMesh()

    'Create meshs to represent our Bodys
    SubBodyMesh = BoxMesh("Box", Globals.GetTex("Gray"), SubBodySize.x, 
SubBodySize.y, SubBodySize.z)
    SubRightWingMesh = BoxMesh("Box", Globals.GetTex("Gray"), SubWingSize.x, 
SubWingSize.y, SubWingSize.z)
    SubLeftWingMesh = BoxMesh("Box", Globals.GetTex("Gray"), SubWingSize.x, 
SubWingSize.y, SubWingSize.z)
    SubRudderMesh = BoxMesh("Box", Globals.GetTex("Gray"), SubRudderSize.x, 
SubRudderSize.y, SubRudderSize.z)
    SubPropSpindleMesh = CCylinderMesh("Spindle", Globals.GetTex("Gray"), 
10, 20, 10)

  End Sub

  Public Sub InitializeODE()

    Dim I As Long

    'New-up a world
    gWorld = New ManagedODE.World()

    'set cfm for world (0=rigid, greater than 0 = more springy)
    gWorld.CFM = 0.000000005
    gWorld.ERP = 0.4

    'Set gravity for world
    If GravityOn Then

      gWorld.SetGravity(0, Gravity, 0)

    End If

    'New-up a space
    gSpace = New ManagedODE.SimpleSpace()

    'New-up a plane for the ground
    gPlane = New ManagedODE.PlaneGeom(gSpace, 0, 1, 0, 0)

    'New-up our body's passing them our world
    SubBody = New ManagedODE.Body(gWorld)
    SubRightWing = New ManagedODE.Body(gWorld)
    SubLeftWing = New ManagedODE.Body(gWorld)
    SubRudder = New ManagedODE.Body(gWorld)
    SubPropSpindle = New ManagedODE.Body(gWorld)

    'New-up Geom's for bodys that we want to collide and add them to our 
collision space
    SubBodyGeom = New ManagedODE.BoxGeom(gSpace, SubBodySize.x, 
SubBodySize.y, SubBodySize.z)
    SubRightWingGeom = New ManagedODE.BoxGeom(gSpace, SubWingSize.x, 
SubWingSize.y, SubWingSize.z)
    SubLeftWingGeom = New ManagedODE.BoxGeom(gSpace, SubWingSize.x, 
SubWingSize.y, SubWingSize.z)
    SubRudderGeom = New ManagedODE.BoxGeom(gSpace, SubRudderSize.x, 
SubRudderSize.y, SubRudderSize.z)

    'Now attach the Geoms to their bodies
    SubBody.GeomList.Add(SubBodyGeom)
    SubRightWing.GeomList.Add(SubRightWingGeom)
    SubLeftWing.GeomList.Add(SubLeftWingGeom)
    SubRudder.GeomList.Add(SubRudderGeom)

    'New-up a mass to pass to our body's
    Mass = New ManagedODE.Mass()
    'TODO fix mass
    Mass.SetZero()
    'Set its size and density
    Mass.SetBox(0.005, SubBodySize.x, SubBodySize.y, SubBodySize.z)
    'Pass our mass to the body
    SubBody.SetMass(Mass)

    Mass.SetBox(0.005, SubWingSize.x, SubWingSize.y, SubWingSize.z)
    SubRightWing.SetMass(Mass)
    SubLeftWing.SetMass(Mass)

    Mass.SetBox(0.005, SubRudderSize.x, SubRudderSize.y, SubRudderSize.z)
    SubRudder.SetMass(Mass)

    Mass.SetCappedCylinder(0.005, 1, 10, 20)
    SubPropSpindle.SetMass(Mass)

    'Now set the position of each of our bodies
    SubBody.SetPosition(0, 500, 0)
    SubRightWing.SetPosition(80, 500, 90)
    SubLeftWing.SetPosition(80, 500, -90)
    SubRudder.SetPosition(125, 545, 0)
    SubPropSpindle.SetPosition(155, 500, 0)
    SubPropSpindle.SetEulerAnglesDeg(0, 0, 90)

    'New-up, place and attach the joints
    SubRightWingHinge = New ManagedODE.JointHinge(gWorld)
    SubRightWingHinge.Attach(SubRightWing, SubBody)
    SubRightWingHinge.SetAxis(0, 0, 1)
    SubRightWingHinge.SetAnchor(60, 500, 90)
    SubRightWingHinge.SetAllMovParams(-1, 1, 0, 500000, 1, 0.2, 0.0000001, 
0.0000001, 0.0000001)

    SubLeftWingHinge = New ManagedODE.JointHinge(gWorld)
    SubLeftWingHinge.Attach(SubBody, SubLeftWing)
    SubLeftWingHinge.SetAxis(0, 0, -1)
    SubLeftWingHinge.SetAnchor(60, 500, -90)
    SubLeftWingHinge.SetAllMovParams(-1, 1, 0, 500000, 1, 0.2, 0.0000001, 
0.0000001, 0.0000001)

    SubRudderHinge = New ManagedODE.JointHinge(gWorld)
    SubRudderHinge.Attach(SubBody, SubRudder)
    SubRudderHinge.SetAxis(0, 1, 0)
    SubRudderHinge.SetAnchor(100, 500, 0)
    SubRudderHinge.SetAllMovParams(-3, 3, 0, 500000, 1, 0.2, 0.0000001, 
0.0000001, 0.0000001)

    SubPropSpindleHinge = New ManagedODE.JointHinge(gWorld)
    SubPropSpindleHinge.Attach(SubBody, SubPropSpindle)
    SubPropSpindleHinge.SetAxis(1, 0, 0)
    SubPropSpindleHinge.SetAnchor(155, 500, 0)
    SubPropSpindleHinge.SetAllMovParams(1, -1, 0, 500000, 1, 0.2, 0.00001, 
0.00001, 0.00001)

    'Put the meshes in the right place to
    SubBodyMesh.SetPosition(0, 500, 0)
    SubRightWingMesh.SetPosition(80, 500, 90)
    SubLeftWingMesh.SetPosition(80, 500, -90)
    SubRudderMesh.SetPosition(125, 545, 0)
    SubPropSpindleMesh.SetPosition(155, 500, 0)
    SubPropSpindleMesh.RotateZ(DegToRad(90))

  End Sub

  Public Sub StepODE()

    'Used for updating mesh position
    Dim pos As ManagedODE.Vector3
    'Used for updating mesh rotation(orientation)
    Dim rot As ManagedODE.Matrix3
    'Used because we need to convert the matrix
    'returned from "GetRotation" to a d3dmatrix
    Dim rot_DX As DxVBLibA.D3DMATRIX

    'This holds all our contact points and needs to be emptied each before 
we call spacecollide
    gContactGroup.Empty()
    'SpaceCollide sends pairs of possibly colliding Geoms to MyCallBack
    gCallCollide.SpaceCollide(gSpace, gCallBack)
    'Step the world ahead a time unit
    gWorld.Step(0.05)

    'puts the position and rotation of each body into pos and rot
    pos = SubBody.Position
    rot = SubBody.Rotation
    'convert the ODEManaged.Matrix3 to an D3DMatrix
    'so the SetRotationMatrix of the mesh can use it.
    rot_DX = MatrixConvertToDX(rot)
    'Use pos and rot_DX to place our meshes
    SubBodyMesh.SetPosition(pos.x, pos.y, pos.z)
    SubBodyMesh.SetRotationMatrix(rot_DX)

    pos = SubRightWing.Position
    rot = SubRightWing.Rotation
    rot_DX = MatrixConvertToDX(rot)
    SubRightWingMesh.SetPosition(pos.x, pos.y, pos.z)
    SubRightWingMesh.SetRotationMatrix(rot_DX)

    pos = SubLeftWing.Position
    rot = SubLeftWing.Rotation
    rot_DX = MatrixConvertToDX(rot)
    SubLeftWingMesh.SetPosition(pos.x, pos.y, pos.z)
    SubLeftWingMesh.SetRotationMatrix(rot_DX)

    pos = SubRudder.Position
    rot = SubRudder.Rotation
    rot_DX = MatrixConvertToDX(rot)
    SubRudderMesh.SetPosition(pos.x, pos.y, pos.z)
    SubRudderMesh.SetRotationMatrix(rot_DX)

    pos = SubPropSpindle.Position
    rot = SubPropSpindle.Rotation
    rot_DX = MatrixConvertToDX(rot)
    SubPropSpindleMesh.SetPosition(pos.x, pos.y, pos.z)
    SubPropSpindleMesh.SetRotationMatrix(rot_DX)

    If HydrodynamicsOn Then
      'Now apply hydrodynamic forces to each of our geoms
      SubBodyGeom.ApplyHydrodynamicForces(LinearViscosity, AngularViscosity, 
Density, Flow)
      SubRightWingGeom.ApplyHydrodynamicForces(LinearViscosity, 
AngularViscosity, Density, Flow)
      SubLeftWingGeom.ApplyHydrodynamicForces(LinearViscosity, 
AngularViscosity, Density, Flow)
      SubRudderGeom.ApplyHydrodynamicForces(LinearViscosity, 
AngularViscosity, Density, Flow)

    End If

  End Sub

  'This Sub is called by ODE after you call Collide for the space
  Public Sub MyCallBack(ByVal o1 As ManagedODE.Geom, ByVal o2 As 
ManagedODE.Geom)

    If o1 Is Nothing Or o2 Is Nothing Then Exit Sub

    Dim I As Integer

    Dim cgeoms() As ManagedODE.ContactGeom = gCallCollide.Collide(o1, o2, 5)

    If (cgeoms.Length > 0) Then

      Dim contacts() As ManagedODE.Contact = 
gContact.ToContactsFromContactGeoms(cgeoms)

      For I = 0 To contacts.Length - 1

        contacts(I).Surface.mode = ManagedODE.SurfaceMode.Bounce
        contacts(I).Surface.mu = 60000.1 'World.Infinity;
        contacts(I).Surface.bounce = 0.31
        contacts(I).Surface.bounce_vel = 2
        Dim gContactJoint As New ManagedODE.JointContact(gWorld, 
gContactGroup, contacts(I))
        gContactJoint.Attach(contacts(I).Geom.Geom1.Body, 
contacts(I).Geom.Geom2.Body)

      Next

    End If

  End Sub

  'Gets user input
  Public Sub DoInput()

    Static ABeenPressed As Boolean
    Static DBeenPressed As Boolean
    Static RightBeenPressed As Boolean
    Static LeftBeenPressed As Boolean
    Static GBeenPressed As Boolean
    Static HBeenPressed As Boolean

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_A) Or 
Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_D) Then

      If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_A) Then

        If ABeenPressed = False Then

          SubLeftWingHinge.DesiredVelocity = 50
          SubLeftWingHinge.MaxForce = 500000

          SubRightWingHinge.DesiredVelocity = 50
          SubRightWingHinge.MaxForce = 500000

          ABeenPressed = True

        Else

          If SubRightWingHinge.Angle >= 0.3 Or SubLeftWingHinge.Angle >= 0.3 
Then

            SubLeftWingHinge.DesiredVelocity = 0
            SubLeftWingHinge.MaxForce = 5000000

            SubRightWingHinge.DesiredVelocity = 0
            SubRightWingHinge.MaxForce = 5000000

          End If

        End If

      End If

      If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_D) Then

        If DBeenPressed = False Then

          SubLeftWingHinge.DesiredVelocity = -50
          SubLeftWingHinge.MaxForce = 500000

          SubRightWingHinge.DesiredVelocity = -50
          SubRightWingHinge.MaxForce = 500000

          DBeenPressed = True

        Else

          If SubRightWingHinge.Angle <= -0.3 Or SubLeftWingHinge.Angle <= 
-0.3 Then

            SubLeftWingHinge.DesiredVelocity = 0
            SubLeftWingHinge.MaxForce = 5000000

            SubRightWingHinge.DesiredVelocity = 0
            SubRightWingHinge.MaxForce = 5000000

          End If

        End If

      End If

    Else

      SubLeftWingHinge.DesiredVelocity = 
-(System.Math.Abs(SubLeftWingHinge.Angle()) ^ 1.1) * 
System.Math.Sign(SubLeftWingHinge.Angle())
      SubLeftWingHinge.MaxForce = 9000000

      SubRightWingHinge.DesiredVelocity = 
-(System.Math.Abs(SubRightWingHinge.Angle()) ^ 1.1) * 
System.Math.Sign(SubRightWingHinge.Angle())
      SubRightWingHinge.MaxForce = 9000000

      ABeenPressed = False
      DBeenPressed = False

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_RIGHT) Or 
Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_LEFT) Then

      If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_RIGHT) Then

        If RightBeenPressed = False Then

          SubRudderHinge.DesiredVelocity = 50
          SubRudderHinge.MaxForce = 500000
          RightBeenPressed = True

        Else

          If SubRudderHinge.Angle >= 0.8 Then

            SubRudderHinge.DesiredVelocity = 0
            SubRudderHinge.MaxForce = 500000000

          End If

        End If

      End If

      If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_LEFT) Then

        If LeftBeenPressed = False Then

          SubRudderHinge.DesiredVelocity = -50
          SubRudderHinge.MaxForce = 500000
          LeftBeenPressed = True

        Else

          If SubRudderHinge.Angle <= -0.8 Then

            SubRudderHinge.DesiredVelocity = 0
            SubRudderHinge.MaxForce = 500000000

          End If

        End If

      End If

    Else

      SubRudderHinge.DesiredVelocity = 
-(System.Math.Abs(SubRudderHinge.Angle()) ^ 1.1) * 
System.Math.Sign(SubRudderHinge.Angle())
      SubRudderHinge.MaxForce = 9000000

      RightBeenPressed = False
      LeftBeenPressed = False

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_W) Then

      SubPropSpindle.AddRelForce(0, -100000, 0)

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_G) Then

      If Not GBeenPressed Then

        If GravityOn Then

          gWorld.SetGravity(0, 0, 0)
          GravityOn = False

        Else

          gWorld.SetGravity(0, Gravity, 0)
          GravityOn = True

        End If

        GBeenPressed = True

      End If

    Else

      GBeenPressed = False

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_H) Then

      If Not HBeenPressed Then

        If HydrodynamicsOn Then

          HydrodynamicsOn = False

        Else

          HydrodynamicsOn = True

        End If

        HBeenPressed = True

      End If

    Else

      HBeenPressed = False

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_U) Then

      LinearViscosity += 0.0001

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_J) Then

      LinearViscosity -= 0.0001

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_I) Then

      AngularViscosity += 0.1

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_K) Then

      AngularViscosity -= 0.1

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_O) Then

      Density += 0.00005

    End If

    If Input.IsKeyPressed(TrueVision3D.CONST_TV_KEY.TV_KEY_L) Then

      Density -= 0.00005

    End If

  End Sub

  'utility function to convert an ODEManaged.Matrix3 to a D3DMatrix
  Private Function MatrixConvertToDX(ByVal Matrix As ManagedODE.Matrix3) As 
DxVBLibA.D3DMATRIX

    Dim mat As DxVBLibA.D3DMATRIX

    mat.m11 = Matrix.m11
    mat.m12 = Matrix.m12
    mat.m13 = Matrix.m13
    mat.m21 = Matrix.m21
    mat.m22 = Matrix.m22
    mat.m23 = Matrix.m23
    mat.m31 = Matrix.m31
    mat.m32 = Matrix.m32
    mat.m33 = Matrix.m33
    mat.m14 = 0
    mat.m24 = 0
    mat.m34 = 0
    mat.m44 = 1
    MatrixConvertToDX = mat

  End Function

  Private Function DegToRad(ByVal degrees As Double) As Double

    DegToRad = degrees * 0.017453292519943295

  End Function

End Module


I hope this helps.

Cheers,

Ander

----Original Message Follows----
Hi Ander,

Sorry to bother you again with this, but I tried to use the procedures  that 
you posted, and my bodies just explode after some iterations. I tried
to tweak the gravity, step size, mass and viscosity parameters
with no avail. I also tried to switch from dWorldStepFast1 to
dWorldStep, and the results are the same. So, could you please answer me 
some more questions? Thanks in advance.

First, In your demo, which function (from the two that you posted) are you 
using? Are you using it after each time step?

Also, which values are you using for viscosity, gravity, step size and mass 
density? What size range are you using for the objects in the simulation? 
Are you using dWorldStepFast1 or dWorldStep?

Sorry to bother you again, and thanks in advance. Best regards,

Artur Matos.

_______________________________________________
ODE mailing list
ODE at q12.org
http://q12.org/mailman/listinfo/ode

_________________________________________________________________
Hot chart ringtones and polyphonics. Go to  
http://ninemsn.com.au/mobilemania/default.asp



More information about the ODE mailing list