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