Randomize Timer

Const MAX_OBJECTS  = 7
Const MAX_MODELS   = 2
Const MAX_TEXTURES = 12
Const MAX_SOUNDS   = 10
Const MAX_POWER    = 25
Const GLFW_KEY_W = Asc("W")
Const GLFW_KEY_S = Asc("S")
Const GLFW_KEY_A = Asc("A")
Const GLFW_KEY_D = Asc("D")
Const GLFW_KEY_Y = Asc("Y")
Const GLFW_KEY_N = Asc("N")
Const Matrix_Copy_Size = 16 * Sizeof( Single )
Const ShadowMapSize = 2^11
Const Gravity     As Single  = 9.8
Const OBJECT_RIGID_BODY = 1
Const OBJECT_COLLISION_TREE = 2


'#include once "fbmld.bi"
'#include once "icon.rc" 
#include once "GL/gl.bi" 
#include once "GL/glu.bi"
#include once "GL/glfw.bi"
#include once "GL/glext.bi"
#include once "\al\al.bi"
#include once "\al\alut.bi"
#include once "Newton.bi"
#include once "global_structures.bi"
#include once "Display.bas"
#include once "3DMath.bi"
#include once "3DMath.bas"
#include once "Vector.bi"
#include once "Vector.bas"
#include once "Model_Module.bi"
#include once "Model_Module.bas"
#include once "IO.bas"

Declare Sub Force_Torque Cdecl( Byval RBody As NewtonBody Ptr )
Declare Sub Character_Controller Cdecl( Byval RBody As NewtonBody Ptr )
Declare Function Character_Raycast_World( Byval nWorld As NewtonWorld Ptr, Byref Cam As Character_Struct) As Ray_Struct
Declare Function Character_Ray_Filter Cdecl(Byval nBody As NewtonBody Ptr, Byval Normal As dFloat Ptr, Byval Collision_ID As Integer, Byval User_Data As Any Ptr, Byval Intersect_Param As dFloat) As dFloat
Declare Sub Physics_Transform Cdecl( Byval RBody As NewtonBody Ptr, Byval Matrix As dFloat Ptr )
Declare Sub Char_Physics_Transform Cdecl( Byval RBody As NewtonBody Ptr, Byval Matrix As dFloat Ptr )
Declare Function HingeCallback Cdecl(Byval Hinge As NewtonJoint Ptr, Byval desc As NewtonHingeSliderUpdateDesc Ptr) As Uinteger
Declare Sub LevelCollisionCallBack Cdecl( Byval rBody As NewtonBody Ptr, Byval RBody2 As NewtonBody Ptr, Byval Vert As dFloat Ptr, Byval Stride_In_Bytes As Integer, Byval Index_Count As Integer, Byval Index_Array As Integer Ptr)

Declare Sub Build_Collision_Tree( Byval nWorld As NewtonWorld Ptr, Byref Model As Model3D Ptr, Byref Object As Object_Struct )
Declare Sub Add_Cube_To_World( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byval Mass As dFLoat )
Declare Sub Add_Sphere_To_World( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byval Mass As dFLoat )
Declare Sub Rolling_Friction_Callback Cdecl(Byval rjoint As NewtonJoint Ptr)


Declare Function Ball_World_Contact_Begin Cdecl(Byval Material As NewtonMaterial Ptr, Byval rBody1 As NewtonBody Ptr, Byval rBody2 As NewtonBody Ptr) As Integer
Declare Function Ball_World_Contact_Process Cdecl(Byval Material As NewtonMaterial Ptr, Byval Contact As NewtonContact Ptr) As Integer
Declare Sub      Ball_World_Contact_End Cdecl(Byval Material As NewtonMaterial Ptr)

Declare Sub Add_Convex_Hull_To_World( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byref Model As Model3D Ptr, Byval Mass As dFLoat )
Declare Sub Add_Camera_To_World( Byval nWorld As NewtonWorld Ptr, Byref Cam As Character_Struct, Byval Mass As Single )
Declare Sub Add_Compound_To_World( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byref Model As Model3D Ptr Ptr, Byval Mass As dFLoat )

Declare Sub Load_Compound_From_File( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byref Model As Model3D Ptr Ptr, Byval Mass As dFLoat )

Declare Sub Destroy_Objects( Byref Object As Object_Struct Ptr )

Declare Sub Render_Objects( Byval Object As Object_Struct Ptr)
Declare Sub Render_Objects_Shadows( Byval Object As Object_Struct Ptr)
Declare Sub Create_Shadow_Buffer( Byref Texture As Gluint )
Declare Sub Initialize_Extensions()
Declare Sub Init_Light( Byref Light As Light_Struct )

Declare Sub Enable_Shadow_Projection(Byval Shadow_Map_Texture As Gluint, Byref Light_Projection_Matrix As Single Ptr, Byref Light_View_Matrix As Single Ptr)
Declare Sub Disable_Shadow_Projection()


Declare Sub Load_Sounds( Byref Wav_Bff As ALuint Ptr, Byref Wav_Src As ALuint Ptr )


Dim Shared glGenFramebuffersEXT            As PFNglGenFramebuffersEXTPROC
Dim Shared glDeleteFramebuffersEXT         As PFNglDeleteFramebuffersEXTPROC
Dim Shared glBindFramebufferEXT            As PFNglBindFramebufferEXTPROC
Dim Shared glFramebufferTexture2DEXT       As PFNglFramebufferTexture2DEXTPROC
Dim Shared glFramebufferRenderbufferEXT    As PFNglFramebufferRenderbufferEXTPROC
Dim Shared glGenRenderbuffersEXT           As PFNglGenRenderbuffersEXTPROC
Dim Shared glBindRenderbufferEXT           As PFNglBindRenderbufferEXTPROC
Dim Shared glRenderbufferStorageEXT        As PFNglRenderbufferStorageEXTPROC
Dim Shared glGenerateMipmapEXT             As PFNglGenerateMipmapEXTPROC
Dim Shared As Gluint Frame_Buffer, Depth_RB
Dim Shared As Integer Use_Shadows, End_Game

Dim Display As GlfwVidMode
Dim As Gluint Texture(1 To max_textures), Shadow_Map_Texture, Text_List
Dim As Integer i, i2
Init_Gl_Window Display
Initialize_Extensions()

Load_Textures( Texture() )
Text_List = GlGenLists(256)
Make_Font_DList( Text_List, Texture(1), 16, 16, 8 )
Create_Shadow_Buffer( Shadow_Map_Texture )


'Initialize Newton 
Dim nWorld As NewtonWorld Ptr = NewtonCreate( 0, 0 )
NewtonSetPlatformArchitecture (nWorld, 2) 'Doesn't seem to be a need for this...

Dim bModel As GLUquadricObj Ptr
bModel = gluNewQuadric
gluQuadricDrawStyle bModel, GLU_FILL
gluQuadricOrientation bModel, GLU_OUTSIDE
GluQuadricNormals bModel, GLU_SMOOTH
GluQuadricTexture bModel, Texture(1)

Dim As Model3D Ptr Ptr Models
Models = Callocate( Max_Models * Sizeof(Model3D) )

Dim As Object_Struct Ptr Object
Object = Callocate( Max_Objects * Sizeof(Object_Struct) )

Dim Cam As Character_Struct

LoadMesh( Models[0], "Models/Table_Small2.obj", 1, Texture() )
LoadMesh( Models[1], "Models/Ball_small.obj", 5, Texture() )



Dim As Gluint dList, Shadow_List
dList = GlGenLists(Max_Models)
For i = 0 To Max_Models - 1
    GlNewList dList+i, GL_COMPILE
    Render_Model( Models[i], Texture() )
    GlEndList
Next

Shadow_List = GlGenLists(Max_Models)
For i = 0 To Max_Models - 1
    GlNewList Shadow_List+i, GL_COMPILE
    Render_Model_Shadow( Models[i] )
    GlEndList
Next


Dim As AlUint Ptr Wav_Bff, Wav_Src
Load_sounds( Wav_Bff, Wav_Src )



'Set default material properties
'This must be done before setting the other material interactions,
'because subsequent interactions use the default as a reference.
Dim As Integer Default_Mat = NewtonMaterialGetDefaultGroupID (nWorld)
NewtonMaterialSetDefaultSoftness (nWorld, Default_Mat, Default_Mat, .75)
NewtonMaterialSetDefaultElasticity (nWorld, Default_Mat, Default_Mat, .25)
NewtonMaterialSetDefaultCollidable (nWorld, Default_Mat, Default_Mat, 1)
NewtonMaterialSetDefaultFriction (nWorld, Default_Mat, Default_Mat, 1, .9)

'This is the world material ID.
'Fine tuned material properties are set in the callbacks,
'because it gives finer control.
'For instance, you can add each polygon's texture ID as the user data,
'and then perform a different action, according to what ID...
'the ball is actually colliding with.
'That's how the scoring works, just look in the callbacks...
Dim As Integer World_Mat = NewtonMaterialCreateGroupID (nWorld)
NewtonMaterialSetDefaultSoftness (nWorld,   World_Mat, World_Mat, .75)
NewtonMaterialSetDefaultElasticity (nWorld, World_Mat, World_Mat, .25)
NewtonMaterialSetDefaultCollidable (nWorld, World_Mat, World_Mat, 1)
NewtonMaterialSetDefaultFriction (nWorld,   World_Mat, World_Mat, 1, .9)


'Material for the camera... same deal.
Dim As Integer Cam_Mat = NewtonMaterialCreateGroupID (nWorld)
NewtonMaterialSetDefaultSoftness (nWorld,   Cam_Mat, World_Mat, .75)
NewtonMaterialSetDefaultElasticity (nWorld, Cam_Mat, World_Mat, .25)
NewtonMaterialSetDefaultCollidable (nWorld, Cam_Mat, World_Mat, 1)
NewtonMaterialSetDefaultFriction (nWorld,   Cam_Mat, World_Mat, 1, .9)





'Add the balls to the world
Dim As Integer Sound_Num
For i = 1 To MAX_OBJECTS - 1
    
    Object[i].max_models = 1
    Object[i].Model_ID = Callocate( Object[i].max_models * Sizeof( Uinteger ) )
    Object[i].Model_ID[0] = 1
    Object[i].Designation = "Sphere - Object #" + Str$(i)
    Object[i].Index = i
    Object[i].Use_Gravity = True
    Add_Sphere_To_World( nWorld, Object[i], 5 )
    NewtonBodyCoriolisForcesMode (Object[i].Body, 1)
    Object[i].max_Sounds = 5
    Object[i].Sound = Callocate( Object[i].max_Sounds * Sizeof( Aluint ) )
    
    Sound_Num+=1
    Object[i].Sound[0] = Wav_Src[0]
    Object[i].Sound[1] = Wav_Src[Sound_Num]
    Object[i].Sound[2] = Wav_Src[7]
    Object[i].Sound[3] = Wav_Src[8]
    Object[i].Sound[4] = Wav_Src[9]
    
    Object[i].Material = NewtonMaterialCreateGroupID( nWorld )
    NewtonMaterialSetDefaultSoftness (nWorld, Object[i].Material, World_Mat, .75)
    NewtonMaterialSetDefaultElasticity (nWorld, Object[i].Material, World_Mat, .25)
    NewtonMaterialSetDefaultCollidable (nWorld, Object[i].Material, World_Mat, 1)
    NewtonMaterialSetDefaultFriction (nWorld, Object[i].Material, World_Mat, 1, .9)
    NewtonMaterialSetCollisionCallback (nWorld, Object[i].Material, World_Mat, @Object[i], @Ball_World_Contact_Begin, @Ball_World_Contact_Process, @Ball_World_Contact_End)
    
    NewtonBodySetMaterialGroupID( Object[i].Body, Object[i].Material )
    NewtonMaterialSetContinuousCollisionMode( nWorld, World_Mat, Object[i].Material, 1 )
    
    
    
    Object[i].dList = Callocate(Object[i].max_models*Sizeof(Gluint))
    For i2 = 0 To Object[i].max_models-1
        Object[i].dList[i2] = dList+Object[i].Model_ID[i2]
    Next
    
    Object[i].Shadow_dList = Callocate(Object[i].max_models*Sizeof(Gluint))
    For i2 = 0 To Object[i].max_models-1
        Object[i].Shadow_dList[i2] = Shadow_List+Object[i].Model_ID[i2]
    Next
    
    alSourcei(Object[i].Sound[1],   AL_LOOPING,    AL_True)
    alSourcePlay( Object[i].Sound[1] )
    alSourcePause ( Object[i].Sound[1] )
Next


For i = 1 To MAX_OBJECTS - 1
    For i2 = 1 To MAX_OBJECTS - 1
        NewtonMaterialSetDefaultSoftness   (nWorld, Object[i].Material, Object[i2].Material, 1  )
        NewtonMaterialSetDefaultElasticity (nWorld, Object[i].Material, Object[i2].Material, .5 )
        NewtonMaterialSetDefaultCollidable (nWorld, Object[i].Material, Object[i2].Material, 1  )
        NewtonMaterialSetDefaultFriction   (nWorld, Object[i].Material, Object[i2].Material, .5, .49)
    Next
Next

Object[0].max_models = 1
Object[0].Model_ID = Callocate( Object[0].max_models * Sizeof( Uinteger ) )
Object[0].dList = Callocate(Object[0].max_models*Sizeof(Gluint))
Object[0].Shadow_dList = Callocate(Object[0].max_models*Sizeof(Gluint))
Object[0].dList[0] = dList
Object[0].Shadow_dList[0] = Shadow_List
Object[0].Model_ID[0] = 0
Build_Collision_Tree( nWorld, Models[0], Object[0] )
NewtonBodySetMaterialGroupID( Object[0].Body, World_Mat )


Add_Camera_To_World( nWorld, Cam, 150 )
NewtonBodySetMaterialGroupID( Cam.Body, Cam_Mat )
NewtonMaterialSetContinuousCollisionMode( nWorld, World_Mat, cam_Mat, 1 )


Dim As Light_Struct Light
Init_Light Light

NewtonSetMinimumFrameRate( nWorld, 300 )
Dim As dFloat Newt_time
Dim As dFloat Frequency = 1/300
Dim As dFloat Accumulative_Step


Dim As dFloat Glfw_Timer, Game_Time
Dim As Integer MouseX, MouseY, moving
Dim As Integer Percentage
Dim As Single Power_Bar_Len
GlfwDisable( GLFW_MOUSE_CURSOR)



Dim As Single Ptr Camera_Projection_Matrix = Callocate( Matrix_Copy_Size )
Dim As Single Ptr Light_Projection_Matrix = Callocate( Matrix_Copy_Size )
Dim As Single Ptr Light_View_Matrix = Callocate( Matrix_Copy_Size )

Dim As dFloat FOVy = 45.0
Dim As dFloat Aspect = Display.Width / Display.Height
Dim As dFloat znear = .1
Dim As dFloat zfar = 250


Glmatrixmode GL_MODELVIEW
Glloadidentity()
gluPerspective FOVy, Aspect, zNear, zFar
glGetFloatv(GL_MODELVIEW_MATRIX, @Camera_Projection_Matrix[0])


Glloadidentity()
gluPerspective(100.0f, 1.0f, 3, 30)
glGetFloatv(GL_MODELVIEW_MATRIX, @Light_Projection_Matrix[0])


Restart_Game:
GlfwSetMousePos( 320, 240 )
Cam.Score = 0
Cam.Sel_Body = 0
Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0, 0, 2.1, 5, 1 }
NewtonBodySetMatrix( Cam.Body, @initMatrix(0) )
Cam.UVec.X = 0
Cam.UVec.Y = 1
Cam.UVec.Z = 0

Cam.RVec.X = 1 
Cam.RVec.Y = 0
Cam.RVec.Z = 0

Cam.DVec.X = 0
Cam.DVec.Y = 0
Cam.DVec.Z = -1
Dim As Single PosY
For i = 1 To MAX_OBJECTS - 1
    PosY+=.25
    alSourcePause ( Object[i].Sound[1] )
    Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0, 0, PosY+.5, 3.4, 1 }
    NewtonBodySetMatrix( Object[i].Body, @initMatrix(0) )
    Dim As Vector3D Omega
    NewtonBodySetOmega( Object[i].Body, @Omega.X )
    NewtonBodySetVelocity( Object[i].Body, @Omega.X )
Next

Newt_Time = GlfwGetTime
Game_Time = GlfwGetTime
Do
    Glfw_Timer = GlfwGetTime
    GlfwGetMousePos( @MouseX, @MouseY )
    Cam.Angle.X = ( 240 - MouseY )/1000
    Cam.Angle.Y = ( 320 - MouseX )/1000
    Cam.Angle.Z = -Cam.RVec.Y
    
    GlfwSetMousePos( 320, 240 )
    Dim As Vector3D Orientation(1)
    Orientation(0) = Cam.Vec.P*Cam.Vec.D
    Orientation(1) = Cam.Vec.U
    
    alListenerfv( AL_POSITION, @Cam.Vec.P.X )
    alListenerfv AL_ORIENTATION, @Orientation(0).X
    'No need to worry about doppler effects in this game. hehehe
    alListener3f AL_VELOCITY, 0,0,0
    
    
    Dim As Single Time_Step = GlfwGetTime - Newt_Time
    Accumulative_Step = Time_Step + Frequency
    While Accumulative_Step >= Frequency
        NewtonUpdate(nworld, Frequency)
        Accumulative_Step -= Frequency
        
        
        Moving = False
        If GlfwGetKey( GLFW_KEY_D ) Then
            Cam.Force.X += Cam.RVec.X * Cam.Mass
            Cam.Force.Z += Cam.RVec.Z * Cam.Mass
            Moving = True
        End If
        
        If GlfwGetKey( GLFW_KEY_A ) Then
            Cam.Force.X += -Cam.RVec.X * Cam.Mass
            Cam.Force.Z += -Cam.RVec.Z * Cam.Mass
            Moving = True
        End If
        
        If GlfwGetKey( GLFW_KEY_W ) Then
            Cam.Force.X += Cam.DVec.X * Cam.Mass
            Cam.Force.Z += Cam.DVec.Z * Cam.Mass
            Moving = True
        End If
        
        If GlfwGetKey( GLFW_KEY_S ) Then
            Cam.Force.X += -Cam.DVec.X * Cam.Mass
            Cam.Force.Z += -Cam.DVec.Z * Cam.Mass
            Moving = True
        End If
        
        Dim As Single Max_Force = Cam.Mass^2
        If Abs(Cam.Force.X) >=Max_Force Then
            Cam.Force.X = Sgn(Cam.Force.X)*Max_Force
        End If
        
        If Abs(Cam.Force.Z) >=Max_Force Then
            Cam.Force.Z = Sgn(Cam.Force.Z)*Max_Force
        End If
        
        If Not Moving Then
            Cam.Force.X = 0
            Cam.Force.Z = 0
            Dim Vel As Vector3D
            NewtonBodyGetVelocity( Cam.Body, @Vel.X )
            Vel.X *= .75
            Vel.Z *= .75
            NewtonBodySetVelocity( Cam.Body, @Vel.X )
        End If
    Wend
    Newt_Time = GlfwGetTime
    
    For i = 1 To MAX_OBJECTS - 1
        Cam.Score+=Object[i].Add_Score
        Object[i].Add_Score = 0
        If Object[i].Body = Cam.Sel_Body Then
            Object[i].Use_Gravity = False
        Else
            Object[i].Use_Gravity = True
        End If
        If Not Object[i].Ground_Flag Then
            alSourcePause ( Object[i].Sound[1] )
        End If
        Object[i].Ground_Flag = False
    Next
    
    Light.Position.X = 0'Cam.Vec.P.X
    Light.Position.Y = 7'Cam.Vec.P.Y+5
    Light.Position.Z = 6'Cam.Vec.P.Z
    
    Light.Direction.X =  0'Cam.Vec.D.X
    Light.Direction.Y =  -1
    Light.Direction.Z =  0'Cam.Vec.D.Z
    
    If Use_Shadows Then
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, Frame_Buffer)
        glViewport(0, 0, ShadowMapSize, ShadowMapSize)
        Glclear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
        Glmatrixmode GL_MODELVIEW
        Glloadidentity()
        Glpushmatrix
        
        Glulookat( Light.Position.X, Light.Position.Y, Light.Position.Z, _
        0, 0, 0, _
        0.0f, 1.0f, 0.0f)
        glGetFloatv(GL_MODELVIEW_MATRIX, @Light_View_Matrix[0])
        Glpopmatrix
        
        
        'First pass.... render depth values
        
        Glmatrixmode(GL_TEXTURE)
        Glloadidentity
        
        Glmatrixmode GL_PROJECTION
        glLoadMatrixf @Light_Projection_Matrix[0]
        
        Glmatrixmode GL_MODELVIEW
        glLoadMatrixf @Light_View_Matrix[0]
        
        glDisable(GL_LIGHTING)
        glDisable(GL_ALPHA_TEST)
        GlDisable GL_BLEND
        
        glCullFace(GL_FRONT)
        glShadeModel(GL_FLAT)
        glColorMask(0, 0, 0, 0)
        GlEnable GL_POLYGON_OFFSET_FILL
        GlPOLYGONOFFSET -1, 8
        Render_Objects_Shadows( Object )
        
        GlDisable GL_POLYGON_OFFSET_FILL
        
        glCullFace(GL_BACK)
        GlEnable GL_CULL_FACE
        glShadeModel(GL_SMOOTH)
        glColorMask(1, 1, 1, 1)
        'Second pass... render normally
        'We need to call this inside this If...Then block because
        'we don't want to bind the FBO, if FBO's aren't even supported!
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0 )
    End If
    
    
    Glclear GL_COLOR_BUFFER_BIT Or GL_DEPTH_BUFFER_BIT
    glViewport(0, 0, Display.Width, Display.Height)
    Glmatrixmode(GL_PROJECTION)
    glLoadMatrixf(@Camera_Projection_Matrix[0])
    Glmatrixmode GL_MODELVIEW
    Glloadidentity
    glEnable(GL_LIGHTING)    
    glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE )
    
    Rot_X Cam, Cam.Angle.X
    Rot_Y Cam, Cam.Angle.Y
    Rot_Z Cam, Cam.Angle.Z
    
    Glulookat Cam.Vec.P.X, Cam.Vec.P.Y, Cam.Vec.P.Z, _
    Cam.Vec.P.X+Cam.DVec.X, Cam.Vec.P.Y+Cam.DVec.Y, Cam.Vec.P.Z+Cam.DVec.Z, _
    Cam.UVec.X, Cam.UVec.Y, Cam.UVec.Z
    
    Dim As Ray_Struct Ray_Data
    Ray_Data = Character_Raycast_World( nWorld, Cam )
    glLightfv GL_LIGHT0, GL_AMBIENT, @light.ambient.R
    glLightfv GL_LIGHT0, GL_DIFFUSE, @light.diffuse.R
    glLightfv(GL_LIGHT0, GL_POSITION, @Light.Position.X )
    'glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, @Light.Direction.X )
    Render_Objects( Object )
    
    
    
    If Use_Shadows Then
        'Third pass... render shadows
        Dim As RGBAlpha Low_Ambient=>(.1,.1,.1, 1 )
        Dim As RGBAlpha Low_Diffuse=>(.2,.2,.2, 1 )
        glLightfv GL_LIGHT0, GL_AMBIENT, @Low_Ambient.R
        glLightfv GL_LIGHT0, GL_DIFFUSE, @Low_Diffuse.R
        Enable_Shadow_Projection( Shadow_Map_Texture, Light_Projection_Matrix, Light_View_Matrix )
        Render_Objects_Shadows( Object )
        Disable_Shadow_Projection()
    End If
    
    
    Glmatrixmode GL_Texture
    Glloadidentity
    Glmatrixmode GL_MODELVIEW   
    GlColor3F 1,1,1
    Glpushmatrix
    GlMultMatrixF( @Cam.bMatrix[0] )
    GlCallList dList+7
    Glpopmatrix
    
    '       Commented out the following code which shows the intersection point,
    '       with a vector aligned to the intersected poly's normal.
    '       Great for debugging!
    '        Glpushmatrix
    '        Glbegin GL_LINES
    '        GlVertex3F Ray_Data.Intersection_Point.X, Ray_Data.Intersection_Point.Y, Ray_Data.Intersection_Point.Z
    '        GlVertex3F Ray_Data.Intersection_Point.X + (Ray_Data.Normal.X*2), Ray_Data.Intersection_Point.Y  + (Ray_Data.Normal.Y*2), Ray_Data.Intersection_Point.Z  + (Ray_Data.Normal.Z*2)
    '        Glend
    '        Glpopmatrix
    
    
    'Not used in this demo...
    'If GlfwGetKey( Asc("P") ) Then
    '    Save_Object_Configuration( Object[2] )
    'End If
    
    
    Dim As Integer Time_Remaining = 300 - (GlfwGetTime-Game_Time)
    Dim As Integer Minutes = Int( Time_Remaining / 60 )
    Dim As Integer Seconds = Int( Time_Remaining - (Minutes * 60) )
    Dim As String Sec = Str$( Seconds )
    If Seconds <10 Or Seconds> 59 Then Sec = "0" & Seconds
    Dim As String Show_Time = Minutes & ":" & Sec
    
    GlPrint "YER SCORE!!! " + Str$(Cam.Score), Texture(1), Text_List, 0, Display.Height-8,1,1,0, Display
    GlPrint "Time remaining... " + Show_Time, Texture(1), Text_List, 0, Display.Height-16,1,1,0, Display
    
    Glmatrixmode Gl_Projection 
    Glpushmatrix 
    Glloadidentity 
    Glmatrixmode Gl_Modelview 
    Glpushmatrix 
    Glloadidentity
    GlDisable GL_LIGHTING
    GlColor3F 1,1,1
    GlOrtho 0,Display.Width, 0, Display.Height, -1, 1
    Glpushmatrix
    GlBlendFunc GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
    GlTranslateF Display.Width\2,Display.Height\2,0
    GlEnable GL_TEXTURE_2D
    GlBindTexture GL_TEXTURE_2D, Texture(9)
    Glbegin GL_QUADS
    GlTexcoord2D 0,1
    GlVertex3F -10,10, 0
    
    GlTexcoord2D 0,0
    GlVertex3F -10,-10, 0
    
    GlTexcoord2D 1,0
    GlVertex3F  10, -10, 0
    
    GlTexcoord2D 1,1
    GlVertex3F  10, 10, 0
    Glend
    Glpopmatrix
    
    Percentage = (Cam.Launch_Power / MAX_POWER) * 100
    Power_Bar_Len = ( Percentage * 244 ) / 100
    If Cam.Sel_Body Then
        GlColor4F 0,0,1,.75
        GlDisable GL_TEXTURE_2D
        Glbegin GL_QUADS
        GlVertex3F    1,   Power_Bar_Len, 0
        GlVertex3F    1,   0, 0
        GlVertex3F   63,   0, 0
        GlVertex3F   63,   Power_Bar_Len, 0
        Glend
    End If
    
    GlEnable GL_TEXTURE_2D
    GlColor3F 1,1,1
    Glpushmatrix
    GlBindTexture GL_TEXTURE_2D, Texture(10)
    Glbegin GL_QUADS
    GlTexcoord2D 0,1
    GlVertex3F 0,256, 0
    
    GlTexcoord2D 0,0
    GlVertex3F 0,0, 0
    
    GlTexcoord2D 1,0
    GlVertex3F  64, 0, 0
    
    GlTexcoord2D 1,1
    GlVertex3F  64, 256, 0
    Glend
    Glpopmatrix
    
    
    Glmatrixmode Gl_Projection 
    Glpopmatrix
    Glmatrixmode Gl_Modelview 
    Glpopmatrix
    
    '5 minute game...
    'Throw as many as you can within 5 minutes!
    If GlfwGetTime() - Game_Time>300 Then
        Sleep 1000
        Glclear GL_COLOR_BUFFER_BIT
        
        GlPrint "TIME'S UP!!!", Texture(1), Text_List, (Display.Width\2)- Len("TIME'S UP!!!")*4, (Display.Height\2)+16,1,1,0, Display
        GlPrint "Your final score was " + Str$(Cam.Score), Texture(1), Text_List, (Display.Width\2)- Len("Your final score was " + Str$(Cam.Score))*4, (Display.Height\2),1,1,0, Display
        GlPrint "Thanks for playing!", Texture(1), Text_List, (Display.Width\2)- Len("Thanks for playing!")*4, (Display.Height\2)-16,1,1,0, Display
        GlPrint "You wanna play again? Y/N", Texture(1), Text_List, (Display.Width\2)- Len("You wanna play again? Y/N")*4, (Display.Height\2)-32,1,1,0, Display
        GlfwSwapBuffers
        Dim As Integer Choice
        Do
            If GlfwGetKey(GLFW_KEY_Y) Then Choice = True
            If GlfwGetKey(GLFW_KEY_N) Then Choice = 1
            GlfwPollEvents
            Sleep 1
        Loop Until Choice
        If Choice = True Then
            Goto Restart_Game
        Else
            End_Game = True
        End If
    End If
    
    If GlfwGetKey(GLFW_KEY_ESC) Then End_Game = True
    
    
    GlfwSwapBuffers
Loop Until End_Game

'Temporary slop to clean up after myself...
NewtonDestroy(nWorld) 
GluDeleteQuadric bModel
For i = 0 To MAX_MODELS - 1
    UnloadMesh( Models[i] )
Next
Deallocate( Models )

Destroy_Objects( Object )
Deallocate(Cam.Matrix)
Deallocate(Cam.bMatrix)
Deallocate(Camera_Projection_Matrix)
Deallocate(Light_Projection_Matrix)
Deallocate(Light_View_Matrix)
GlfwTerminate

alDeleteSources( MAX_SOUNDS, Wav_Src )
alDeleteBuffers( MAX_SOUNDS, Wav_Bff)
alutExit
If Wav_Src Then Deallocate(Wav_Src)
If Wav_Bff Then Deallocate(Wav_Bff)




Function Ball_World_Contact_Begin Cdecl(Byval Material As NewtonMaterial Ptr, Byval rBody1 As NewtonBody Ptr, Byval rBody2 As NewtonBody Ptr) As Integer
    Return 1
End Function


Function Ball_World_Contact_Process Cdecl(Byval Material As NewtonMaterial Ptr, Byval Contact As NewtonContact Ptr) As Integer
    Dim Contact_Surface As Integer
    Dim As dFloat ConTang1, ConTang2, Mag, NormSpeed1, NormSpeed2
    
    Dim Object As Object_Struct Ptr
    
    Object = NewtonMaterialGetMaterialPairUserData( Material )
    
    Contact_Surface = NewtonMaterialGetContactFaceAttribute( Material )
    
    ConTang1  = NewtonMaterialGetContactTangentSpeed( Material, Contact, 0 )
    ConTang2  = NewtonMaterialGetContactTangentSpeed( Material, Contact, 1 )
    NormSpeed1 = NewtonMaterialGetContactNormalSpeed( Material, Contact )
    Mag = (NormSpeed1*NormSpeed1)
    
    If Mag>=1 Then
        If Object->Use_Gravity Then
            alSourcefv  ( Object->Sound[0], AL_POSITION, @Object->Matrix[12] )
            alSourcef   ( Object->Sound[0], AL_GAIN,     Mag/5               )
            alSourcePlay( Object->Sound[0] )
        End If
    End If
    
    Dim As Vector3D Velocity
    NewtonBodyGetVelocity( Object->Body, @Velocity.X )
    Dim As Single Vel_Mag = Magnitude( Velocity )
    
    If  Vel_Mag >= .25 Then
        Object->Ground_Flag = True
        Dim As AlInt State
        AlGetSourcei(Object->Sound[1],    AL_Source_State,  @State)
        alSourcef   (Object->Sound[1],    AL_PITCH,         Vel_Mag/Pi2 )
        If State = Al_Paused Then
            If Object->Use_Gravity Then
                alSourcefv( Object->Sound[1], AL_POSITION, @Object->Vec.P.X )
                alSourcePlay( Object->Sound[1] )
            End If
        End If         
    End If
    
    
    
    Select Case Contact_Surface
    Case 4
        NewtonMaterialSetContactFrictionState( Material, 1,0)
        NewtonMaterialSetContactFrictionState( Material, 1,1)
        NewtonMaterialSetContactStaticFrictionCoef( Material, 1.4,0)
        NewtonMaterialSetContactStaticFrictionCoef( Material, 1.4,1)
        NewtonMaterialSetContactKineticFrictionCoef( Material, 1.395, 0)
        NewtonMaterialSetContactKineticFrictionCoef( Material, 1.395, 1)
        NewtonMaterialSetContactElasticity( Material, .01 )
    Case 9
        If Object->Add_Score = 0 Then
            Dim As dfloat ModMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0,  0,2.332,-8.936, 1 }
            NewtonBodySetMatrix( Object->Body, @ModMatrix(0) )
            Object->Add_Score = 100
            alSourcefv Object->Sound[2], AL_POSITION, @Object->Vec.P.X
            alSourcePlay Object->Sound[2]
        End If
    Case 10
        If Object->Add_Score = 0 Then
            Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0,  0,2.332,-8.936, 1 }
            NewtonBodySetMatrix( Object->Body, @InitMatrix(0) )
            Object->Add_Score = 25
            alSourcefv Object->Sound[3], AL_POSITION, @Object->Vec.P.X
            alSourcePlay Object->Sound[3]
        End If
    Case 11
        If Object->Add_Score = 0 Then
            Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0,  0,2.332,-8.936, 1 }
            NewtonBodySetMatrix( Object->Body, @InitMatrix(0) )
            Object->Add_Score = 10
            alSourcefv Object->Sound[4], AL_POSITION, @Object->Vec.P.X
            alSourcePlay Object->Sound[4]
        End If
    End Select
    
    Return 1
End Function

Sub Ball_World_Contact_End Cdecl(Byval Material As NewtonMaterial Ptr)
    'Not used in this demo...
End Sub




Sub Add_Sphere_To_World( Byval nWorld As NewtonWorld Ptr, Byref Object As Object_Struct, Byval Mass As dFLoat )
    Dim As Integer i
    Static PosY As Single
    Posy+=.25
    
    Object.Matrix = Callocate( Matrix_Copy_Size )
    
    
    Object.Sub_Matrix = Callocate( Object.Max_Models * Matrix_Copy_Size )
    For i = 0 To Object.Max_models - 1
        Object.Sub_Matrix[i] = Callocate( Matrix_Copy_Size )
    Next
    
    Dim As dfloat ModMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0, 0, 0, 0, 1 }
    MemCpy( @Object.Sub_Matrix[0][0], @ModMatrix(0), Matrix_Copy_Size )
    
    Object.collision = NewtonCreateSphere(nWorld, .17, .17, .17, 0)
    Object.Body = NewtonCreateBody(nWorld, Object.collision)
    Object.ID = OBJECT_RIGID_BODY
    
    Dim As dFloat Radius = .17
    
    Dim As dFLoat Ixx = 0.4 * mass * ( radius * radius ) 
    Dim As dFLoat Iyy = 0.4 * mass * ( radius * radius ) 
    Dim As dFLoat Izz = 0.4 * mass * ( radius * radius ) 
    
    NewtonBodySetMassMatrix( Object.Body, Mass, Ixx, Iyy, Izz )
    
    Object.Mass = Mass
    Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0, 0, PosY+.5, 3.4, 1 }
    NewtonBodySetMatrix( Object.Body, @initMatrix(0) )
    
    Dim As Vector3D omega =>( 0, 0, 0 )    
    NewtonBodySetOmega( Object.Body, @omega.X )
    NewtonBodySetForceAndTorqueCallback( Object.Body, @Force_Torque )
    NewtonBodySetTransformCallback( Object.Body, @Physics_Transform )
    NewtonBodySetContinuousCollisionMode( Object.Body, 1 )
    
    Dim As Vector3D Ang_Damping =>(0,0,0)
    NewtonBodySetAngularDamping( Object.Body, @Ang_Damping.X )
    NewtonBodySetLinearDamping( Object.Body, 0 )
    
    Object.Max_Joints = 1
    Object.Joint = Callocate( Object.Max_Joints * Sizeof(Joint_Struct) )
    Object.Joint[0].nJoint = NewtonConstraintCreateUserJoint( nWorld, 1, @Rolling_Friction_Callback(), Object.Body, 0 )
    NewtonJointSetUserData(Object.Joint[0].nJoint, @Object )
    
    NewtonBodySetUserData( Object.Body, @Object.Body )
    NewtonReleaseCollision( nWorld, Object.collision )
End Sub



Sub Rolling_Friction_Callback Cdecl( Byval rjoint As NewtonJoint Ptr )
    
    
    Dim As Object_Struct Ptr Object = NewtonJointGetUserData( rJoint )
    
    Dim As Vector3D Omega, Pin
    Dim As dFloat OmegaMag, nTime, TorqueFriction, Mass, Ixx, Iyy, Izz
    
    Dim As dFloat frictionTorque, frictionCoef
    
    NewtonBodyGetOmega(Object->Body, @Omega.X )    
    OmegaMag = Sqr( Vector_Dot( Omega, Omega ) )
    
    If OmegaMag>0.1 Then
        Pin.X = Omega.X*(1/OmegaMag)
        Pin.Y = Omega.Y*(1/OmegaMag)
        Pin.Z = Omega.Z*(1/OmegaMag)
        
        NewtonUserJointAddAngularRow ( rjoint, 0.0f, @Pin.X )
        
        Dim As NewtonWorld Ptr nWorld = NewtonBodyGetWorld( Object->Body )
        nTime = NewtonGetTimeStep ( nworld )
        NewtonUserJointSetRowAcceleration ( rjoint, -omegaMag / nTime )
        
        NewtonBodyGetMassMatrix( Object->Body, @Mass, @Ixx, @Iyy, @Izz )
        frictionCoef = Mass^Pi
        frictionTorque = Ixx*Iyy*Izz*.75
        
        torqueFriction = frictionTorque * frictionCoef
        NewtonUserJointSetRowMinimumFriction (rjoint, -torqueFriction )
        NewtonUserJointSetRowMaximumFriction (rjoint,  torqueFriction )
    Else
        Omega.X *=.2
        Omega.Y *=.2
        Omega.Z *=.2
		NewtonBodySetOmega( Object->Body, @Omega.X )
    End If
    
    
End Sub





Sub Disable_Shadow_Projection()
    glDisable(GL_TEXTURE_GEN_S)
    glDisable(GL_TEXTURE_GEN_T)
    glDisable(GL_TEXTURE_GEN_R)
    glDisable(GL_TEXTURE_GEN_Q)
    glDisable(GL_ALPHA_TEST)
    GlDisable(GL_BLEND)
End Sub

Sub Enable_Shadow_Projection(Byval Shadow_Map_Texture As Gluint, Byref Light_Projection_Matrix As Single Ptr, Byref Light_View_Matrix As Single Ptr)    
    Dim As Single Texture_Matrix(15) =>{.5,0,0,0,0, .5,0,0,0,0, .5,0,.5,.5,.5, 1}
    
    Dim As Single Row1(3) = {1,0,0,0}
    Dim As Single Row2(3) = {0,1,0,0}
    Dim As Single Row3(3) = {0,0,1,0}
    Dim As Single Row4(3) = {0,0,0,1}
    
    glEnable(GL_TEXTURE_2D)
    glBindTexture(GL_TEXTURE_2D, Shadow_Map_Texture)
    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGenfv(GL_S, GL_EYE_PLANE, @Row1(0))
    glEnable(GL_TEXTURE_GEN_S)
    
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGenfv(GL_T, GL_EYE_PLANE, @Row2(0))
    glEnable(GL_TEXTURE_GEN_T)
    
    glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGenfv(GL_R, GL_EYE_PLANE, @Row3(0))
    glEnable(GL_TEXTURE_GEN_R)
    
    glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)
    glTexGenfv(GL_Q, GL_EYE_PLANE, @Row4(0))
    glEnable(GL_TEXTURE_GEN_Q)
    
    
    'Bind & enable shadow map texture
    
    GlEnable GL_BLEND
    GlBlendFunc Gl_Src_COLOR, Gl_DST_COLOR
    'GlColor4F( .5,.5,.5,.5 )
    
    'Set alpha test to discard false comparisons
    glAlphaFunc(GL_LEQUAL, .99)
    glEnable(GL_ALPHA_TEST)
    
    Glmatrixmode(GL_TEXTURE)
    Glloadidentity
    glLoadMatrixf(@Texture_Matrix(0))
    glMultMatrixf(@Light_Projection_Matrix[0])
    glMultMatrixf(@Light_View_Matrix[0])
	Glmatrixmode(GL_MODELVIEW)
End Sub






Sub Render_Objects( Byval Object As Object_Struct Ptr)
    Dim As Integer i,m
    
    For i = 1 To MAX_OBJECTS - 1
        Glpushmatrix
        glMultMatrixf( @Object[i].Matrix[0] )
        GlColor3F 1, 1, 1
        Dim As Integer m
        For m = 0 To Object[i].Max_Models - 1
            Glpushmatrix
            GlMultMatrixF ( @Object[i].Sub_Matrix[m][0] )
            GlCallList Object[i].dList[m]
            Glpopmatrix
        Next
        
        Glpopmatrix
    Next 
    
    'Render the world model
    GlColor3F 1, 1, 1
    GlCallList Object[0].dList[0]
End Sub


Sub Render_Objects_Shadows( Byval Object As Object_Struct Ptr)
    Dim As Integer i,m
    
    For i = 1 To MAX_OBJECTS - 1
        Glpushmatrix
        glMultMatrixf( @Object[i].Matrix[0] )
        GlColor3F 1, 1, 1
        Dim As Integer m
        For m = 0 To Object[i].Max_Models - 1
            Glpushmatrix
            GlMultMatrixF ( @Object[i].Sub_Matrix[m][0] )
            GlCallList Object[i].Shadow_dList[m]
            Glpopmatrix
        Next
        
        Glpopmatrix
    Next 
    
    GlCallList Object[0].Shadow_dList[0]
End Sub




Sub Create_Shadow_Buffer( Byref Texture As Gluint )
    If glfwExtensionSupported( "GL_ARB_depth_texture" ) = 0 Then 
        Print "Error: ARB depthtexture extension not supported!" 
        Print "Shadowing will not work." 
        Beep
        Sleep 2000
        Use_Shadows = False
        Exit Sub
    End If 
    
    If glfwExtensionSupported( "GL_ARB_shadow" ) = 0 Then 
        Print "Error: ARB Shadow extension not supported!" 
        Print "Shadowing will not work." 
        Beep
        Sleep 2000
        Use_Shadows = False
        Exit Sub
    End If
    
    Use_Shadows= True
    glGenTextures(1, @Texture )
    glBindTexture(GL_TEXTURE_2D, Texture )
    glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, ShadowMapSize, ShadowMapSize, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
    glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FAIL_VALUE_ARB, .5)
    
    'Can't do anything like this without a PCF shader,
    'which would limit the amount of people that can try it even more :(
    'glGenerateMipmapEXT( GL_TEXTURE_2D )
    '    
    '    If glfwExtensionSupported( ("GL_EXT_texture_filter_anisotropic")) Then
    '        Dim As GlFloat Largest_Texture_Filter
    '        glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, @Largest_Texture_Filter)
    '        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, Largest_Texture_Filter)
    '    End If
    
    
    
    
    
    
    glGenFramebuffersEXT (1, @Frame_Buffer)
    'glGenRenderbuffersEXT(1, @Depth_rb)
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, Frame_Buffer)
    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, Texture, 0)
    'glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, Texture, 0)
    'glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, Texture)
    glDrawBuffer(GL_NONE)
    glReadBuffer(GL_NONE)
    'glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, Depth_Rb)
    'glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, ShadowMapSize, ShadowMapSize)
    'glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, Depth_Rb)
    
    
    
    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0)
End Sub








Sub Destroy_Objects( Byref Object As Object_Struct Ptr)
    Dim As Integer i, i2
    
    For i = 0 To Max_Objects - 1
        If Object[i].Model_ID Then 
            Deallocate( Object[i].Model_ID )
            Object[i].Model_ID = 0
        End If
        
        If Object[i].Matrix Then 
            Deallocate( Object[i].Matrix )
            Object[i].Matrix = 0
        End If
        
        For i2 = 0 To Object[i].max_models - 1
            If Object[i].Sub_Matrix[i2] Then
                Deallocate( Object[i].Sub_Matrix[i2] )
                Object[i].Sub_Matrix[i2] = 0
            End If
        Next
        
        If Object[i].Sub_Matrix Then 
            Deallocate( Object[i].Sub_Matrix )
            Object[i].Sub_Matrix = 0
        End If
        
        If Object[i].Joint Then Deallocate(Object[i].Joint)
        If Object[i].dList Then Deallocate(Object[i].dList)
        If Object[i].Shadow_dList Then Deallocate(Object[i].Shadow_dList)
        If Object[i].Sound Then Deallocate( Object[i].Sound )
    Next
    
    If Object Then Deallocate( Object )
End Sub


Sub Character_Controller Cdecl( Byval RBody As NewtonBody Ptr )
    Dim As dFloat Mass, Ixx, Iyy, Izz
    NewtonBodyGetMassMatrix( RBody, @Mass, @Ixx, @Iyy, @Izz )
    
    Dim Char As Character_Struct Ptr
    Char = NewtonBodyGetUserData( RBody )
    
    
    Dim As Vector3D Gravity_Force
    Gravity_Force.X = 0
    Gravity_Force.Y = -Mass*Gravity
    Gravity_Force.Z = 0
    
    Dim As Vector3D Rot
    
    Rot.X = Char->DVec.X - Char->Vec.D.X
    Rot.Y = Char->DVec.Y - Char->Vec.D.Y
    Rot.Z = Char->DVec.Z - Char->Vec.D.Z
    Dim As Single Mag = Magnitude( Rot )
    Rot/=Mag
    
    
    'NewtonBodySetOmega(rBody, @Rot.X )
    
    Dim As Vector3D tVel
    NewtonBodyGetVelocity( RBody, @tVel.X )
    Mag = Magnitude( tVel )
    Vector_Normalize( tVel )
    Char->Force.X +=(Char->dVec.X - tVel.X) * Mag^2
    Char->Force.Z +=(Char->dVec.Z - tVel.Z) * Mag^2
    
    NewtonBodySetForce( RBody, @Char->Force.X )
    NewtonBodyAddForce( RBody, @Gravity_Force.X)
End Sub



Function Character_Raycast_World( Byval nWorld As NewtonWorld Ptr, Byref Cam As Character_Struct ) As Ray_Struct
    Dim As Vector3D Ray_Begin
    Ray_Begin.X = Cam.Vec.P.X
    Ray_Begin.Y = Cam.Vec.P.Y
    Ray_Begin.Z = Cam.Vec.P.Z
    
    Dim As Vector3D Ray_End
    Ray_End.X = Cam.Vec.P.X + (Cam.DVec.X * 20)
    Ray_End.Y = Cam.Vec.P.Y + (Cam.DVec.Y * 20)
    Ray_End.Z = Cam.Vec.P.Z + (Cam.DVec.Z * 20)
    Dim As dFloat Raycast
    
    
    Dim Ray_Data As Ray_Struct
    Ray_Data.Designation = "No objects in range."
    
    NewtonWorldRaycast( nWorld, @Ray_Begin.X, @Ray_End.X, @Character_Ray_Filter, @Ray_Data, 0 )
    Dim As Vector3D Intersect_Point
    Dim As Object_Struct Ptr Hit_Object
    
    If Raycast < 1.0 Then
        Intersect_Point.X = Ray_Begin.X + (Ray_Data.Param * (Ray_End.X - Ray_Begin.X ))
        Intersect_Point.Y = Ray_Begin.Y + (Ray_Data.Param * (Ray_End.Y - Ray_Begin.Y ))
        Intersect_Point.Z = Ray_Begin.Z + (Ray_Data.Param * (Ray_End.Z - Ray_Begin.Z ))
        Ray_Data.InterSection_Point = Intersect_Point
        
        If Ray_Data.Newton_ID Then
            
            Hit_Object = NewtonBodyGetUserData( Ray_Data.Newton_ID )
            Ray_Data.Designation = Hit_Object->Designation
            Dim As dFLoat Mass = Cam.Mass/Hit_Object->Mass
            
            Dim As Vector3D Mag_Vector
            Mag_Vector.X = Intersect_Point.X - Hit_Object->Matrix[12]
            Mag_Vector.Y = Intersect_Point.Y - Hit_Object->Matrix[13]
            Mag_Vector.Z = Intersect_Point.Z - Hit_Object->Matrix[14]
            Dim As Single Mag = Magnitude( Mag_Vector  )
            'Vector_Normalize( Mag_Vector )
            
            Dim As Vector3D Tan_Vector
            Tan_vector.X = Mag_Vector.X * Mag
            Tan_vector.Y = Mag_Vector.Y * Mag
            Tan_vector.Z = Mag_Vector.Z * Mag
            
            Dim As Vector3D Omega = Vector_Cross( Ray_Data.Normal, Tan_Vector )
            'Omega.X'/=Mass
            'Omega.Y'/=Mass
            'Omega.Z'/=Mass
            'Omega/=(Mass*10)
            
            Mass = Cam.Mass*(Cam.Mass/ Hit_Object->Mass)*Pi
            Dim As Vector3D Force_Vector
            Force_Vector.X = -Ray_Data.Normal.X*5
            Force_Vector.Y = -Ray_Data.Normal.Y*5
            Force_Vector.Z = -Ray_Data.Normal.Z*5
            
            Ray_Data.Vec.D = Ray_Data.Normal
            Ray_Data.Vec.U = Vector_Cross( Ray_Data.Normal, Mag_Vector )
            Vector_Normalize( Ray_Data.Vec.U )
            Ray_Data.Vec.R = Vector_Cross( Ray_Data.Vec.U, Ray_Data.Vec.D )
            
            Matrix_From_Vectors( @Cam.bMatrix[0], Ray_Data.Vec )
            
            Cam.bMatrix[12 ] = Intersect_Point.X + (Ray_Data.Vec.D.X * .3)
            Cam.bMatrix[13 ] = Intersect_Point.Y + (Ray_Data.Vec.D.Y * .3)
            Cam.bMatrix[14 ] = Intersect_Point.Z + (Ray_Data.Vec.D.Z * .3)
            
            If Hit_Object->ID = OBJECT_RIGID_BODY Then
                NewtonWorldUnfreezeBody( nWorld, Ray_Data.Newton_ID )
                
                If Cam.Sel_Body Then
                    If GlfwGetMouseButton( GLFW_MOUSE_BUTTON_LEFT ) Then
                        'If Cam.Sel_Body = Ray_Data.Newton_ID Then
                        Force_Vector = Cam.dVec*Cam.Launch_Power
                        Hit_Object->Use_Gravity = True
                        'NewtonBodySetOmega( Ray_Data.Newton_ID, @Omega.X )
                        NewtonAddBodyImpulse( Ray_Data.Newton_ID, @Force_Vector.X, @Intersect_Point.X )
                        'Hit_Object->External_Force = Force_Vector
                        'Hit_Object->External_Omega = Omega
                        Cam.Sel_Body = 0
                        'End If
                    End If
                End If
                
                If GlfwGetMouseButton( GLFW_MOUSE_BUTTON_RIGHT ) Then
                    Cam.Sel_Body    = Ray_Data.Newton_ID
                    Cam.Sel_Body_ID = Hit_Object->Index
                End If
                
                
                
                
            Elseif Hit_Object->ID = OBJECT_COLLISION_TREE Then
                Ray_Data.Designation + = " Face #" +Str$(Ray_Data.Collision_ID)
            End If
        End If
    End If
    
    
    If Cam.Sel_Body Then
        Dim As Vector3D New_Posit
        Dim As Integer Use_New_Position
        New_Posit.X = (Cam.Matrix[12]- Intersect_Point.X)
        New_Posit.Y = (Cam.Matrix[13]- Intersect_Point.Y)
        New_Posit.Z = (Cam.Matrix[14]- Intersect_Point.Z)
        Dim As Single Mag = Magnitude( New_Posit )
        If Hit_Object Then
            If Mag<3 And Hit_Object->ID = OBJECT_COLLISION_TREE Then Use_New_Position = True
        End If
        
        Dim As Object_Struct Ptr Hit_Object
        Hit_Object = NewtonBodyGetUserData( Cam.Sel_Body )
        Hit_Object->Use_Gravity = False
        Dim As Single Matrix(16)
        NewtonBodyGetMatrix(Cam.Sel_Body, @Matrix(0))
        Dim As Vector3D Velocity
        Velocity.X = (Cam.Matrix[12]+(Cam.dVec.X*3)) - Matrix(12)
        Velocity.Y = (Cam.Matrix[13]+(Cam.dVec.Y*3)) - Matrix(13)
        Velocity.Z = (Cam.Matrix[14]+(Cam.dVec.Z*3)) - Matrix(14)
        If Use_New_Position Then
            '            Velocity.X = (Intersect_Point.X+(Ray_Data.Normal.X*.17)) - Matrix(12)
            '            Velocity.Y = (Intersect_Point.Y+(Ray_Data.Normal.Y*.17)) - Matrix(13)
            '            Velocity.Z = (Intersect_Point.Z+(Ray_Data.Normal.Z*.17)) - Matrix(14)
            Velocity.X = (Cam.Matrix[12]+(Cam.dVec.X*Mag)) - Matrix(12)
            Velocity.Y = (Cam.Matrix[13]+(Cam.dVec.Y*Mag)) - Matrix(13)
            Velocity.Z = (Cam.Matrix[14]+(Cam.dVec.Z*Mag)) - Matrix(14)
        End If
        
        Velocity *=Pi2*2
        NewtonBodySetVelocity( Cam.Sel_Body, @Velocity.X )
        Dim As Vector3D Omega=>(0,0,0)
        NewtonBodySetOmega( Cam.Sel_Body, @Omega.X )
        Cam.Launch_Power+=.5
        If Cam.Launch_Power>MAX_POWER Then Cam.Launch_Power = 0
    End If
    
    
    Return Ray_Data
End Function


Function Character_Ray_Filter Cdecl(Byval nBody As NewtonBody Ptr, Byval Normal As dFloat Ptr, Byval Collision_ID As Integer, Byval User_Data As Any Ptr, Byval Intersect_Param As dFloat) As dFloat
    
    
    Dim As dFloat Mass, Mx, My, Mz
    Dim As Ray_Struct Ptr Ray
    Dim As Object_Struct Ptr Object
    
    NewtonBodyGetMassMatrix( nBody, @Mass, @Mx, @My, @Mz)
    'Collision trees are always processed with 0 mass.
    'If the object that this ray hits has mass, then we know it's a rigid body model, 
    'and not the terrain model.
    If Mass>0 Then
        Object = NewtonBodyGetUserData( nBody )
        Ray              = User_Data
		Ray->Param       = Intersect_Param
        Ray->Normal.X    = Normal[0]
        Ray->Normal.Y    = Normal[1]
        Ray->Normal.Z    = Normal[2]
		Ray->Newton_ID = nBody
        Return Ray->Param
    Elseif Mass = 0 Then 
        Object = NewtonBodyGetUserData( nBody )
        Ray              = User_Data
		Ray->Param       = Intersect_Param
        Ray->Normal.X    = Normal[0]
        Ray->Normal.Y    = Normal[1]
        Ray->Normal.Z    = Normal[2]
        Ray->Collision_ID = Collision_ID
		Ray->Newton_ID = nBody
        Return Ray->Param
    Else
        Return 1.0
    End If
    
End Function


Sub Force_Torque Cdecl( Byval RBody As NewtonBody Ptr )
    Dim As dFloat Mass, Ixx, Iyy, Izz
    NewtonBodyGetMassMatrix( RBody, @Mass, @Ixx, @Iyy, @Izz )
    
    
    
    Dim As Object_Struct Ptr Object
    Object = NewtonBodyGetUserData( RBody )
    Dim As Vector3D Omega
    NewtonBodyGetOmega(RBody, @Omega.X)
    Omega.X += Object->External_Omega.X
    Omega.Y += Object->External_Omega.Y
    Omega.Z += Object->External_Omega.Z
    
    NewtonBodySetOmega(RBody, @Omega.X) 
    'NewtonBodySetForce(RBody, @Object->External_Force.X) 
    
    Dim As Vector3D Force => (0, -Mass*Gravity, 0 )
    If Not Object->Use_Gravity Then Force.Y = 0
    'NewtonBodyGetForce(RBody, @Force.X)
    Force.X += Object->External_Force.X
    Force.Y += Object->External_Force.Y
    Force.Z += Object->External_Force.Z    
    
    NewtonBodySetForce(RBody, @Force.X) 
    
    'We need to zero out the external forcea here,
    'so it doesn't keep adding it on each update.
    Object->External_Force.X = 0
    Object->External_Force.Y = 0
    Object->External_Force.Z = 0
    Object->External_Omega.X = 0
    Object->External_Omega.Y = 0
    Object->External_Omega.Z = 0
End Sub


Sub Physics_Transform Cdecl( Byval RBody As NewtonBody Ptr, Byval Matrix As dFloat Ptr )
    Dim Object As Object_Struct Ptr
    Object = NewtonBodyGetUserData( RBody )
    Memcpy(@Object->Matrix[0], @Matrix[0], Matrix_Copy_Size )
    Vectors_From_Matrix( Object->Vec, @Matrix[0] )
End Sub


Sub Char_Physics_Transform Cdecl( Byval RBody As NewtonBody Ptr, Byval Matrix As dFloat Ptr )
    Dim Char As Character_Struct Ptr
    Char = NewtonBodyGetUserData( RBody )
    Memcpy(@Char->Matrix[0], @Matrix[0], Matrix_Copy_Size )
    Vectors_From_Matrix( Char->Vec, @Matrix[0] )
End Sub


Sub LevelCollisionCallBack Cdecl( Byval rBody As NewtonBody Ptr, Byval RBody2 As NewtonBody Ptr, Byval Vert As dFloat Ptr, Byval Stride_In_Bytes As Integer, Byval Index_Count As Integer, Byval Index_Array As Integer Ptr)
    'It Doesn't really seem like we need this since we're using materials
    'Dim As dFloat Matrix(15), Force(3)
    'Dim As EntityType ptr World
    
    'World = NewtonWorldGetuserData(rBody)
    'Col_Face_ID = NewtonTreeCollisionGetFaceAtribute (Tree_Collision, Index_Array)
    'NewtonTreeCollisionSetFaceAtribute (Tree_Collision, Index_Array, New_Id)
End Sub





Sub Build_Collision_Tree( Byval nWorld As NewtonWorld Ptr, Byref Model As Model3D Ptr, Byref Object As Object_Struct )
    Dim As Uinteger i, CurSurf, count = 3
    Dim As dFLoat Matrix(15)
    '// set the global position of the terrain
    Matrix(0 ) = 1.0
    Matrix(5 ) = 1.0
    Matrix(10) = 1.0
    Matrix(15) = 1.0
    Matrix(12) = 0
    Matrix(13) = 0
    Matrix(14) = 0
    
    
    Object.Matrix = Callocate( Matrix_Copy_Size )
    
    Object.Sub_Matrix = Callocate( Object.Max_Models * Matrix_Copy_Size )
    For i = 0 To Object.Max_models - 1
        Object.Sub_Matrix[i] = Callocate( Matrix_Copy_Size )
    Next
    
    Object.Collision = NewtonCreateTreeCollision(nWorld, @LevelCollisionCallback)
    NewtonTreeCollisionBeginBuild(Object.Collision)
    Object.Body = NewtonCreateBody(nWorld, Object.Collision)
    Object.ID = OBJECT_COLLISION_TREE
    Object.Designation = "Collision Tree"
    'NewtonBodySetMatrix ( Object.Body, @Matrix(0) )
    
    
    
    
    For CurSurf = 0 To Model->max_Surfaces - 1        
        For i = Model->Surfaces[CurSurf].Start_Id To Model->Surfaces[CurSurf].End_Id
            Dim As dFloat nPoint(8)
            
            nPoint(0) = Model->Vertices[Model->Triangles[i].Point_ID(1)].X
            nPoint(1) = Model->Vertices[Model->Triangles[i].Point_ID(1)].Y
            nPoint(2) = Model->Vertices[Model->Triangles[i].Point_ID(1)].Z
            
            nPoint(3) = Model->Vertices[Model->Triangles[i].Point_ID(2)].X
            nPoint(4) = Model->Vertices[Model->Triangles[i].Point_ID(2)].Y
            nPoint(5) = Model->Vertices[Model->Triangles[i].Point_ID(2)].Z
            
            nPoint(6) = Model->Vertices[Model->Triangles[i].Point_ID(3)].X
            nPoint(7) = Model->Vertices[Model->Triangles[i].Point_ID(3)].Y
            nPoint(8) = Model->Vertices[Model->Triangles[i].Point_ID(3)].Z
            
            NewtonTreeCollisionAddFace( Object.Collision, Count, @nPoint(0), Sizeof( Vector3D ), Model->Surfaces[CurSurf].Texture_Id)
            'NewtonTreeCollisionAddFace( Object.Collision, Count, @nPoint(0), Sizeof( Vector3D ), i )
        Next
    Next
    
    
    NewtonTreeCollisionEndBuild( Object.Collision, 0)
    
    Dim As dFloat boxp0(2), boxp1(2)
    NewtonCollisionCalculateAABB (Object.Collision, @Matrix(0), @boxP0(0), @boxP1(0))
    'Release the collision tree (release the app from book keeping Newton objects)
    
    
    'Add some extra padding to the world size
    boxP0(0) -= 100.0f
    boxP0(1) -= 100.0f
    boxP0(2) -= 100.0f
    boxP1(0) += 100.0f
    boxP1(1) += 100.0f
    boxP1(2) += 100.0f
    'set the world size
    NewtonSetWorldSize (nWorld, @boxP0(0), @boxP1(0))
    NewtonReleaseCollision (nWorld, Object.Collision)
    
    NewtonBodySetTransformCallback( Object.Body, @Physics_Transform )
    NewtonBodySetUserData( Object.Body, @Object.Body )
    'NewtonWorldSetUserData( nWorld, @Object.Body )
End Sub






Sub Add_Camera_To_World( Byval nWorld As NewtonWorld Ptr, Byref Char As Character_Struct, Byval Mass As Single )
    Dim As Integer i
    
    Char.Matrix = Callocate( Matrix_Copy_Size )
    Char.bMatrix = Callocate( Matrix_Copy_Size )
    
    Char.collision = NewtonCreateSphere(nWorld, 1.0, 2.0, 1.0, 0 )
    Char.Body = NewtonCreateBody(nWorld, Char.collision )
    NewtonBodySetMassMatrix(Char.Body, Mass, Mass, Mass, Mass)
    Char.Mass = Mass
    Dim As dfloat initMatrix(15) => {1,0,0,0, 0,1,0,0, 0,0,1,0, 0, 3, 5, 1 }
    NewtonBodySetMatrix( Char.Body, @initMatrix(0) )
    
    
    NewtonBodySetForceAndTorqueCallback( Char.Body, @Character_Controller )
    NewtonBodySetTransformCallback( Char.Body, @Char_Physics_Transform )
    NewtonBodySetUserData( Char.Body, @Char.Body )
    Dim As Vector3D PinDir =>( 0,1,0 )
    NewtonConstraintCreateUpVector( nWorld, @PinDir.X, Char.Body )
    NewtonBodySetAutoFreeze( Char.Body, 0 )
    NewtonWorldUnfreezeBody (nWorld, Char.Body)
    NewtonReleaseCollision( nWorld, Char.collision )
    
    NewtonBodySetContinuousCollisionMode( Char.Body, 1 )
    
    Glmatrixmode GL_MODELVIEW
    Glloadidentity
    glGetFloatv GL_MODELVIEW_MATRIX, @Char.bMatrix[0]
    
    Char.UVec.X = 0
    Char.UVec.Y = 1
    Char.UVec.Z = 0
    
    Char.RVec.X = 1 
    Char.RVec.Y = 0
    Char.RVec.Z = 0
    
    Char.DVec.X = 0
    Char.DVec.Y = 0
    Char.DVec.Z = -1
End Sub


Sub Init_Light( Byref Light As Light_Struct )
    Light.Ambient.R  = 0.45
    Light.Ambient.G  = 0.45
    Light.Ambient.B  = 0.45
    Light.Ambient.A  = 0.45
    
    Light.Diffuse.R  = 0.35
    Light.Diffuse.G  = 0.35
    Light.Diffuse.B  = 0.35
    Light.Diffuse.A  = 0.35
    
    Light.Specular.R = 0.75
    Light.Specular.G = 0.75
    Light.Specular.B = 0.75
    Light.Specular.A = 0.75
    
    Light.Position.X = 0
    Light.Position.Y = 0.0
    Light.Position.Z = 0.0
    Light.Position.W = 1.0
    
    Light.Direction.X = 0
    Light.Direction.Y = 0
    Light.Direction.Z = -1
    
    glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR)
    glLightfv GL_LIGHT0, GL_AMBIENT, @light.ambient.R
    glLightfv GL_LIGHT0, GL_DIFFUSE, @light.diffuse.R
    glLightfv GL_LIGHT0, GL_SPECULAR, @light.specular.R
    glLightfv GL_LIGHT0, GL_POSITION, @light.position.X
    'glLightfv GL_LIGHT0,GL_SPOT_DIRECTION, @Light.Direction.X
    'glLightf GL_LIGHT0,GL_SPOT_CUTOFF,90.0   
    
    glEnable GL_LIGHT0
    glEnable GL_LIGHTING
End Sub


Sub Initialize_Extensions()
    glGenFramebuffersEXT         = Cptr(PFNglGenFramebuffersEXTPROC, glfwGetProcAddress( "glGenFramebuffersEXT" ))
    glDeleteFramebuffersEXT      = Cptr(PFNglDeleteFramebuffersEXTPROC, glfwGetProcAddress( "glDeleteFramebuffersEXT" ))
    glBindFramebufferEXT         = Cptr(PFNglBindFramebufferEXTPROC, glfwGetProcAddress( "glBindFramebufferEXT" ))
    glFramebufferTexture2DEXT    = Cptr(PFNglFramebufferTexture2DEXTPROC, glfwGetProcAddress( "glFramebufferTexture2DEXT" ))
    glFramebufferRenderbufferEXT = Cptr(PFNglFramebufferRenderbufferEXTPROC, glfwGetProcAddress( "glFramebufferRenderbufferEXT" ))
    glGenRenderbuffersEXT        = Cptr(PFNglGenRenderbuffersEXTPROC, glfwGetProcAddress( "glGenRenderbuffersEXT" ))
    glBindRenderbufferEXT        = Cptr(PFNglBindRenderbufferEXTPROC, glfwGetProcAddress( "glBindRenderbufferEXT" ))
    glRenderbufferStorageEXT     = Cptr(PFNglRenderbufferStorageEXTPROC, glfwGetProcAddress( "glRenderbufferStorageEXT" ))
    glGenerateMipmapEXT          = Cptr(PFNglGenerateMipmapEXTPROC, glfwGetProcAddress( "glGenerateMipmapEXT" ))
End Sub


Sub Load_Sounds( Byref Wav_Bff As ALuint Ptr, Byref Wav_Src As ALuint Ptr )
    
    If Not Wav_Bff Then Wav_Bff = Callocate( MAX_SOUNDS * Sizeof( AlUint ) )
    If Not Wav_Src Then Wav_Src = Callocate( MAX_SOUNDS * Sizeof( AlUint ) )
    
    Dim i As Uinteger    
    Dim wavFormat As ALenum, _
    wavSize As ALsizei,_
    wavFreq As ALsizei, _
    wavData As Any Ptr, _
    wavLoop As ALboolean, _
    RollOff As Single
    
    
    alutInit(0, 0)
    alGenBuffers(Max_Sounds, @Wav_Bff[0])
    
    If alGetError <> AL_NO_ERROR Then
        alDeleteBuffers(MAX_SOUNDS, @Wav_Bff[0])
        Print "Failed to generate buffers!"
        alutExit
        End
    End If
    
    alGenSources(MAX_SOUNDS, @Wav_Src[0])
    
    If alGetError <> AL_NO_ERROR Then
        alDeleteBuffers(MAX_SOUNDS, @Wav_Bff[0])
        alDeleteBuffers(MAX_SOUNDS, @Wav_Src[0])
        Print "Failed to generate sources!"
        alutExit
        End
    End If
    
    For i = 0 To MAX_SOUNDS - 1
        
        If i = 0 Then alutLoadWAVFile("Sound/Ball2Ball1.wav", @wavFormat, @wavData, @wavSize, @wavFreq, @wavLoop)
        If i >= 1 And i<= 6 Then alutLoadWAVFile("Sound/Rolling.wav", @wavFormat, @wavData, @wavSize, @wavFreq, @wavLoop)
        If i = 7 Then alutLoadWAVFile("Sound/Win1.wav", @wavFormat, @wavData, @wavSize, @wavFreq, @wavLoop)
        If i = 8 Then alutLoadWAVFile("Sound/Win2.wav", @wavFormat, @wavData, @wavSize, @wavFreq, @wavLoop)
        If i = 9 Then alutLoadWAVFile("Sound/Win3.wav", @wavFormat, @wavData, @wavSize, @wavFreq, @wavLoop)
        
        If alGetError <> AL_NO_ERROR Then
            alDeleteBuffers(MAX_SOUNDS, @Wav_Bff[0])
            alDeleteBuffers(MAX_SOUNDS, @Wav_Src[0])
            Print "Error: Failed to load WAV data!"
            'OpenAL needs some serious work.
            'I think it will still run though, so I commented exiting.
            'alutExit
            'End
        End If
        
        alBufferData(Wav_Bff[i], wavFormat, wavData, wavSize, wavFreq)
        alutUnloadWAV(wavFormat, wavData, wavSize, wavFreq)
        
        If alGetError <> AL_NO_ERROR Then
            alDeleteBuffers(MAX_SOUNDS, @Wav_Bff[0])
            Print "Error: Failed to bind audio buffer to source!"
            'alutExit
            'End
        End If
        
        alSourcei(Wav_Src[i],   AL_BUFFER,     Wav_Bff[i])
        alSourcef(Wav_Src[i],   AL_PITCH,      1.0)
        alSourcef(Wav_Src[i],   AL_GAIN,       1.0)
        alSourcei(Wav_Src[i],   AL_LOOPING,    AL_False)
        alsourcef(Wav_Src[i],   Al_ROLLOFF_FACTOR, .5)
    Next
End Sub
