[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