Here's a little thing I tacked onto the ragdoll demo as an experiment. The shadows don't look quite right somehow though, perhaps they should fade with distance or something.
' ###################################################################################################
' # JV-ODE - RagDoll Demo #
' # Code by Jim Williams (VIP3R) #
' ###################################################################################################
SuperStrict
Framework BRL.GLMax2D
Import BRL.Random
Import DevCode.JVODE
Import DevCode.JVODEOpenGL
AppTitle:String="JV-ODE - RagDoll Demo"
SetGraphicsDriver GLMax2DDriver()
Graphics 800,600,0,0
Global CamX:Float
Global CamZ:Float
Global numrags:Int = 10
Global RagDollMax:Int=numrags+1
Global ODEJointMax:Int=15
Global I:Int
Global WorldERP:Float=0.1
Global RDBody:Int[RagDollMax,ODEJointMax]
Global RDJoint:Int[RagDollMax,ODEJointMax]
Type ODEGeom
Field body:Int
Field geom:Int
Field mesh:Int
Field rgb:Int[]
Field scale:Float[]
End Type
Global ODEGeomList:TList=CreateList()
' ###################################################################################################
' ### Setup ODE
Global World:Int=dWorldCreate()
Global Space:Int=dHashSpaceCreate(0)
Global ContactGroup:Int=dJointGroupCreate(0)
dWorldSetAutoDisableFlag(World,1)
dWorldSetGravity(World,0,-2.8,0)
dWorldSetERP(World,WorldERP)
dContactSetMode(dContactSlip1+dContactBounce)
dContactSetBounce(0.75)
dContactSetMu(48)
' ### Setup Scene
InitOpenGL(GL_SMOOTH) ' ### GL_SMOOTH - GL_FLAT
InitLight(-40,80,100) ' ### xpos - ypos - zpos
' ### Create plane
dCreatePlane(Space,0,1,0,0)
' ###################################################################################################
' ### Create RagDolls
Local Count:Int
For Count=1 To numrags
CreateRagDoll(Count)
Next
' ###################################################################################################
Local PTime:Int
Local PhysicsTime:Float
While Not AppTerminate() And Not KeyDown(KEY_ESCAPE)
UpdateControls()
ClearScene()
UpdateCamera(-30+CamX,9,-25+CamZ,30,1,0,0) ' ### xpos - ypos - zpos - angle - rx - ry - rz
DrawPlanarShadow()'UpdateGeoms()
PTime=MilliSecs()
dSpaceCollide(Space,World,ContactGroup)
dWorldQuickStep(World,0.1)
dJointGroupEmpty(ContactGroup)
PhysicsTime=MilliSecs()-PTime
EnableGLText(255,255,255) ' ### red - green - blue
GLDrawText "JV-ODE Version "+FixFloat(dGetVersion()),0,0
GLDrawText "Physics Time:"+FixFloat(PhysicsTime),0,15
GLDrawText "F1 - Drop RagDolls",300,0
GLDrawText "Space - Throw RagDolls",300,15
GLDrawText "Arrow Keys - Move Camera",300,30
GLDrawText "F2 - Attach RagDolls",580,0
GLDrawText "L Mouse Button - Push Body",580,15
GLDrawText "R Mouse Button - Pull Body",580,30
Flip
Wend
dJointGroupDestroy(ContactGroup)
dSpaceDestroy(Space)
dWorldDestroy(World)
dCloseODE()
End
' ###################################################################################################
Function CreateRagDoll(rd:Int)
Local ode:ODEGeom
Local xp:Float=8+(rd*4)
Local yp:Float=6
Local zp:Float=4
' ### RagDoll Dimensions
Local HeadRad:Float=0.4
Local BodyUX:Float=1.0
Local BodyUY:Float=1.5
Local BodyUZ:Float=0.4
Local BodyLX:Float=1.4
Local BodyLY:Float=0.75
Local BodyLZ:Float=0.5
Local ArmURad:Float=0.08
Local ArmULen:Float=1.1
Local ArmLRad:Float=0.08
Local ArmLLen:Float=1.1
Local LegURad:Float=0.125
Local LegULen:Float=1.3
Local LegLRad:Float=0.125
Local LegLLen:Float=1.3
Local FeetX:Float=0.5
Local FeetY:Float=0.25
Local FeetZ:Float=1.0
Local HandX:Float=0.1
Local HandY:Float=0.4
Local HandZ:Float=0.28
' ### Create Head
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,0]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp,yp,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateSphere(Space,HeadRad)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dSphereClass
ode.rgb=[255,255,255]
ode.scale=[HeadRad]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Body (Upper)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,1]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp,yp-1.25,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,BodyUX,BodyUY,BodyUZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[0,200,200]
ode.scale=[BodyUX,BodyUY,BodyUZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Body (Lower)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,2]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp,yp-2.5,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,BodyLX,BodyLY,BodyLZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[0,100,100]
ode.scale=[BodyLX,BodyLY,BodyLZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Arm (Upper)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,3]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.9,yp-1.25,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,ArmURad,ArmULen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[255,0,0]
ode.scale=[ArmURad,ArmURad,ArmULen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Arm (Lower)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,4]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.9,yp-2.35,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,ArmLRad,ArmLLen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[125,0,0]
ode.scale=[ArmLRad,ArmLRad,ArmLLen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Hand
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,5]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.9,yp-3.05,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,HandX,HandY,HandZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[255,255,255]
ode.scale=[HandX,HandY,HandZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Arm (Upper)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,6]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.9,yp-1.25,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,ArmURad,ArmULen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[0,255,0]
ode.scale=[ArmURad,ArmURad,ArmULen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Arm (Lower)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,7]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.9,yp-2.35,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,ArmLRad,ArmLLen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[0,125,0]
ode.scale=[ArmLRad,ArmLRad,ArmLLen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Hand
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,8]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.9,yp-3.05,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,HandX,HandY,HandZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[255,255,255]
ode.scale=[HandX,HandY,HandZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Leg (Upper)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,9]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.5,yp-3.6,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,LegURad,LegULen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[255,0,0]
ode.scale=[LegURad,LegURad,LegULen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Leg (Lower)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,10]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.5,yp-4.9,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,LegLRad,LegLLen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[125,0,0]
ode.scale=[LegLRad,LegLRad,LegLLen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Left Foot
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,11]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp+0.5,yp-5.7,zp-0.25)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,FeetX,FeetY,FeetZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[255,255,255]
ode.scale=[FeetX,FeetY,FeetZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Leg (Upper)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,12]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.5,yp-3.6,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,LegURad,LegULen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[0,255,0]
ode.scale=[LegURad,LegURad,LegULen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Leg (Lower)
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,13]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.5,yp-4.9,zp)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateCylinder(Space,LegLRad,LegLLen)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dCylinderClass
ode.rgb=[0,125,0]
ode.scale=[LegLRad,LegLRad,LegLLen]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Create Right Foot
ode:ODEGeom=New ODEGeom
ode.body=dBodyCreate(World)
RDBody[rd,14]=ode.body
dBodySetAxisAngle(ode.body,0,0,0,0)
dBodySetPosition(ode.body,xp-0.5,yp-5.7,zp-0.25)
dBodySetAutoDisableFlag(ode.body,1)
ode.geom=dCreateBox(Space,FeetX,FeetY,FeetZ)
dGeomSetBody(ode.geom,ode.body)
ode.mesh=dBoxClass
ode.rgb=[255,255,255]
ode.scale=[FeetX,FeetY,FeetZ]
ListAddLast(ODEGeomList,ode:ODEGeom)
' ### Static Joint To Head
RDJoint[rd,0]=dJointCreateBall(World,0)
dJointAttach(RDJoint[rd,0],0,RDBody[rd,0])
dJointSetBallAnchor(RDJoint[rd,0],xp,yp,zp)
' ### Head To Body (Upper)
RDJoint[rd,1]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,1],RDBody[rd,0],RDBody[rd,1])
dJointSetHingeAxis(RDJoint[rd,1],1,0,1)
dJointSetHingeAnchor(RDJoint[rd,1],xp,yp-0.44,zp)
dJointSetHingeParam(RDJoint[rd,1],dParamLoStop,-0.7)
dJointSetHingeParam(RDJoint[rd,1],dParamHiStop,0.7)
' ### Body (Upper) To Body (Lower)
RDJoint[rd,2]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,2],RDBody[rd,1],RDBody[rd,2])
dJointSetHingeAxis(RDJoint[rd,2],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,2],xp,yp-2.05,zp)
dJointSetHingeParam(RDJoint[rd,2],dParamLoStop,-0.25)
dJointSetHingeParam(RDJoint[rd,2],dParamHiStop,0.25)
' ### Left Arm (Upper) To Body (Upper)
RDJoint[rd,3]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,3],RDBody[rd,3],RDBody[rd,1])
dJointSetHingeAxis(RDJoint[rd,3],1,-1,1)
dJointSetHingeAnchor(RDJoint[rd,3],xp+0.9,yp-0.7,zp)
dJointSetHingeParam(RDJoint[rd,3],dParamLoStop,-1.5)
dJointSetHingeParam(RDJoint[rd,3],dParamHiStop,1.5)
' ### Left Arm (Lower) To Left Arm (Upper)
RDJoint[rd,4]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,4],RDBody[rd,4],RDBody[rd,3])
dJointSetHingeAxis(RDJoint[rd,4],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,4],xp+0.9,yp-1.8,zp)
dJointSetHingeParam(RDJoint[rd,4],dParamLoStop,0.0)
dJointSetHingeParam(RDJoint[rd,4],dParamHiStop,2.0)
' ### Left Hand To Left Arm (Lower)
RDJoint[rd,5]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,5],RDBody[rd,5],RDBody[rd,4])
dJointSetHingeAxis(RDJoint[rd,5],0,0,1)
dJointSetHingeAnchor(RDJoint[rd,5],xp+0.9,yp-2.9,zp)
dJointSetHingeParam(RDJoint[rd,5],dParamLoStop,-0.3)
dJointSetHingeParam(RDJoint[rd,5],dParamHiStop,0.3)
' ### Right Arm (Upper) To Body (Upper)
RDJoint[rd,6]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,6],RDBody[rd,6],RDBody[rd,1])
dJointSetHingeAxis(RDJoint[rd,6],1,1,1)
dJointSetHingeAnchor(RDJoint[rd,6],xp-0.9,yp-0.7,zp)
dJointSetHingeParam(RDJoint[rd,6],dParamLoStop,-1.5)
dJointSetHingeParam(RDJoint[rd,6],dParamHiStop,1.5)
' ### Right Arm (Lower) To Right Arm (Upper)
RDJoint[rd,7]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,7],RDBody[rd,7],RDBody[rd,6])
dJointSetHingeAxis(RDJoint[rd,7],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,7],xp-0.9,yp-1.8,zp)
dJointSetHingeParam(RDJoint[rd,7],dParamLoStop,0.0)
dJointSetHingeParam(RDJoint[rd,7],dParamHiStop,2.0)
' ### Right Hand To Right Arm (Lower)
RDJoint[rd,8]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,8],RDBody[rd,8],RDBody[rd,7])
dJointSetHingeAxis(RDJoint[rd,8],0,0,1)
dJointSetHingeAnchor(RDJoint[rd,8],xp-0.9,yp-2.9,zp)
dJointSetHingeParam(RDJoint[rd,8],dParamLoStop,-0.3)
dJointSetHingeParam(RDJoint[rd,8],dParamHiStop,0.3)
' ### Left Leg (Upper) To Body (Lower)
RDJoint[rd,9]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,9],RDBody[rd,9],RDBody[rd,2])
dJointSetHingeAxis(RDJoint[rd,9],1,0,-1)
dJointSetHingeAnchor(RDJoint[rd,9],xp+0.5,yp-2.9,zp)
dJointSetHingeParam(RDJoint[rd,9],dParamLoStop,-1.0)
dJointSetHingeParam(RDJoint[rd,9],dParamHiStop,1.0)
' ### Left Leg (Lower) To Left Leg (Upper)
RDJoint[rd,10]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,10],RDBody[rd,10],RDBody[rd,9])
dJointSetHingeAxis(RDJoint[rd,10],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,10],xp+0.5,yp-4.25,zp)
dJointSetHingeParam(RDJoint[rd,10],dParamLoStop,-2.0)
dJointSetHingeParam(RDJoint[rd,10],dParamHiStop,0.0)
' ### Left Foot To Left Leg (Lower)
RDJoint[rd,11]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,11],RDBody[rd,11],RDBody[rd,10])
dJointSetHingeAxis(RDJoint[rd,11],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,11],xp+0.5,yp-5.5,zp)
dJointSetHingeParam(RDJoint[rd,11],dParamLoStop,-0.25)
dJointSetHingeParam(RDJoint[rd,11],dParamHiStop,0.25)
' ### Right Leg (Upper) To Body (Lower)
RDJoint[rd,12]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,12],RDBody[rd,12],RDBody[rd,2])
dJointSetHingeAxis(RDJoint[rd,12],1,0,1)
dJointSetHingeAnchor(RDJoint[rd,12],xp-0.5,yp-2.9,zp)
dJointSetHingeParam(RDJoint[rd,12],dParamLoStop,-1.0)
dJointSetHingeParam(RDJoint[rd,12],dParamHiStop,1.0)
' ### Right Leg (Lower) To Right Leg (Upper)
RDJoint[rd,13]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,13],RDBody[rd,13],RDBody[rd,12])
dJointSetHingeAxis(RDJoint[rd,13],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,13],xp-0.5,yp-4.25,zp)
dJointSetHingeParam(RDJoint[rd,13],dParamLoStop,-2.0)
dJointSetHingeParam(RDJoint[rd,13],dParamHiStop,0.0)
' ### Right Foot To Right Leg (Lower)
RDJoint[rd,14]=dJointCreateHinge(World,0)
dJointAttach(RDJoint[rd,14],RDBody[rd,14],RDBody[rd,13])
dJointSetHingeAxis(RDJoint[rd,14],1,0,0)
dJointSetHingeAnchor(RDJoint[rd,14],xp-0.5,yp-5.5,zp)
dJointSetHingeParam(RDJoint[rd,14],dParamLoStop,-0.25)
dJointSetHingeParam(RDJoint[rd,14],dParamHiStop,0.25)
End Function
' ###################################################################################################
Function UpdateControls()
If KeyDown(KEY_F1)=1 Then
For i = 1 To numrags
dJointAttach(RDJoint[i,0],0,0)
Next
EndIf
If KeyDown(KEY_F2)=1 Then
For i = 1 To numrags
dJointAttach(RDJoint[i,0],0,RDBody[i,0])
Next
EndIf
If KeyDown(KEY_SPACE)=1
For i = 1 To numrags
dBodyAddForce RDBody[i,0],0,150,0
Next
End If
If KeyDown(KEY_UP)=1 Then CamZ:+0.3
If KeyDown(KEY_DOWN)=1 Then CamZ:-0.3
If KeyDown(KEY_LEFT)=1 Then CamX:+0.3
If KeyDown(KEY_RIGHT)=1 Then CamX:-0.3
If MouseDown(MOUSE_LEFT)=1
For i = 1 To numrags
dBodyAddForce RDBody[i,1],0,0,10
Next
End If
If MouseDown(MOUSE_RIGHT)=1
For i = 1 To numrags
dBodyAddForce RDBody[i,1],0,0,-10
Next
End If
End Function
' ###################################################################################################
Function UpdateGeoms()
Local ode:ODEGeom
' ### Update Geoms
For ode:ODEGeom=EachIn ODEGeomList
glPushMatrix()
glTranslatef(dGeomGetPositionX(ode.geom),dGeomGetPositionY(ode.geom),dGeomGetPositionZ(ode.geom))
dGeomGetAxisAngle(ode.geom)
glRotatef(dVectorW(),dVectorX(),dVectorY(),dVectorZ())
SetDrawColour(ode.rgb[0],ode.rgb[1],ode.rgb[2])
' ### DrawSphere: radius - slices - stacks
' ### DrawCube: xscale - yscale - zscale
' ### DrawCylinder: radiusb - radiust - length - slices - loops
' ### DrawCCylinder: radiusb - radiust - length - slices - loops
If ode.mesh=dSphereClass Then DrawSphere(ode.scale[0],14,14)
If ode.mesh=dBoxClass Then DrawCube(ode.scale[0],ode.scale[1],ode.scale[2])
If ode.mesh=dCylinderClass Then DrawCylinder(ode.scale[0],ode.scale[1],ode.scale[2],8,8)
If ode.mesh=dCapsuleClass Then DrawCapsule(ode.scale[0],ode.scale[1],ode.scale[2],8,8)
glPopMatrix()
Next
End Function
' ###################################################################################################
Function DrawPlanarShadow()
' ### Update Plane
SetDrawColour(230,230,240) ' ### red - green - blue
DrawPlane(-(CamX-(CamX Mod -20)),0,-(CamZ-(CamZ Mod -20)))
Local plane:Float[]=[0.0,1.0,0.0,0.0]
Local shadowmatrix:Float[16]
Local dot:Float
Local lightpos:Float[]=[-40.0,180.0,-100.0,0.0]
'now set shadow matrix
dot = plane[0]*lightpos[0]+plane[1]*lightpos[1]+plane[2]*lightpos[2]+plane[3]*lightpos[3]
shadowmatrix[0] = dot - lightpos[0]*plane[0]
shadowmatrix[4] = 0.0 - lightpos[0]*plane[1]
shadowmatrix[8] = 0.0 - lightpos[0]*plane[2]
shadowmatrix[12] = 0.0 - lightpos[0]*plane[3]
shadowmatrix[1] = 0.0 - lightpos[1]*plane[0]
shadowmatrix[5] = dot - lightpos[1]*plane[1]
shadowmatrix[9] = 0.0 - lightpos[1]*plane[2]
shadowmatrix[13] = 0.0 - lightpos[1]*plane[3]
shadowmatrix[2] = 0.0 - lightpos[2]*plane[0]
shadowmatrix[6] = 0.0 - lightpos[2]*plane[1]
shadowmatrix[10] = dot - lightpos[2]*plane[2]
shadowmatrix[14] = 0.0 - lightpos[2]*plane[3]
shadowmatrix[3] = 0.0 - lightpos[3]*plane[0]
shadowmatrix[7] = 0.0 - lightpos[3]*plane[1]
shadowmatrix[11] = 0.0 - lightpos[3]*plane[2]
shadowmatrix[15] = dot - lightpos[3]*plane[3]
glPushMatrix()
glDisable(GL_TEXTURE_2D)
glDisable(GL_LIGHTING)
glDisable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glColor4f(0.0,0.0,0.0,0.5)
glMultMatrixf(shadowmatrix)
UpdateGeoms()'drawobject as shadow
glEnable(GL_DEPTH_TEST)
glDisable(GL_BLEND)
glEnable(GL_LIGHTING)
glPopMatrix()
UpdateGeoms()'drawobject as object
End Function