// Project: shadows
// Created: 2019-03-03 by Jan Bögemann

//~#include "math.agc"
#include "shadows.agc"

#renderer "Basic"

// show all errors
SetErrorMode(2)

// set window properties
SetWindowTitle( "3D Shadows" )
SetWindowSize(1920,1080,0)

// set display properties
SetVirtualResolution(1920,1080)
SetOrientationAllowed( 1, 1, 1, 1 )
SetScissor(0,0,0,0)
SetPrintColor(0,0,0)
SetPrintSize(12)
SetSyncRate(60,0)
SetAntialiasMode(1)
UseNewDefaultFonts(1)
SetClearColor(127,201,255)

Create3DPhysicsWorld()
Set3DPhysicsGravity(0,-1,0)

//~SetShadowMappingMode(1)
//~SetShadowSmoothing(1)
//~SetShadowMapSize(2048,2048)
//~SetShadowRange(500)
//~SetShadowBias(0.001)
//~SetShadowLightStepSize(1)
SetAmbientColor(60,60,60)

CreatePointLight(1,0,0,0,200,255,255,255)
SetPointLightMode(1,1)
Shadow_PointLight_Init(1,1000)

FloorImageID=LoadImage("Concrete.png")
SetImageWrapU(FloorImageID,1)
SetImageWrapV(FloorImageID,1)

FloorObjectID=CreateObjectBox(1000,1,1000)
SetObjectImage(FloorObjectID,FloorImageID,0)
SetObjectUVScale(FloorObjectID,0,8,8)
Create3DPhysicsStaticBody(FloorObjectID)
SetObjectShapeBox(FloorObjectID)
Shadow_AddObject(FloorObjectID,0)

BoxImageID=LoadImage("Crate_color.png")

for ObjectID=0 to 55
	BoxObjectID=CreateObjectBox(4.9,4.9,4.9)
	SetObjectImage(BoxObjectID,BoxImageID,0)
	SetObjectPosition(BoxObjectID,-(4*5)+mod(ObjectID,8)*5,1+(ObjectID/8)*5,0)
	Create3DPhysicsDynamicBody(BoxObjectID)
	SetObjectShapeBox(BoxObjectID)
	Shadow_AddObject(BoxObjectID,1)
//~	SetObjectCastShadow(BoxObjectID,1)
next ObjectID

global BallImageID
BallImageID=LoadImage("soccerball2.jpg")

SoldierImageID=LoadImage("Masked Soldier.png")
SetImageWrapU(SoldierImageID,1)
SetImageWrapV(SoldierImageID,1)

SoldierObjectID=LoadObjectWithChildren("Masked Soldier Frag.x")
SetObjectImage(SoldierObjectID,SoldierImageID,0)
SetObjectPosition(SoldierObjectID,50,0,0)
SetObjectScalePermanent(SoldierObjectID,0.5,0.5,0.5)
Shadow_AddObject(SoldierObjectID,1)
SetObjectAnimationSpeed(SoldierObjectID,15)
PlayObjectAnimation(SoldierObjectID,"Animation",3002,3547,1,0)

//~SetObjectCastShadow(SoldierObjectID,1)

LightObjectID=CreateObjectSphere(1,12,16)
SetObjectLightMode(LightObjectID,0)

SetCameraPosition(1,0,20,-40)
SetCameraLookAt(1,0,0,0,0)
currentX#=GetCameraAngleX(1)
currentY#=GetCameraAngleY(1)
newX#=currentX#
newY#=currentY#

CreatePointLight(2,5,5,5,50,255,255,255)
SetPointLightMode(2,1)

lightstate=1

do
	Print(ScreenFPS())

	currentPosX#=0
	currentPosY#=0
	currentPosZ#=0
	if (GetRawKeyState(87)) then currentPosZ#=0.8
	if (GetRawKeyState(83)) then currentPosZ#=-0.8

	if (GetRawKeyState(65)) then currentPosX#=-0.8
	if (GetRawKeyState(68)) then currentPosX#=0.8

	if (GetRawKeyState(81)) then currentPosY#=0.8
	if (GetRawKeyState(69)) then currentPosY#=-0.8

	newPosX#=CurveValue(currentPosX#,newPosX#,8)
	newPosY#=CurveValue(currentPosY#,newPosY#,8)
	newPosZ#=CurveValue(currentPosZ#,newPosZ#,8)
	MoveCameraLocalZ(1,newPosZ#)
	MoveCameraLocalX(1,newPosX#)
	MoveCameraLocalY(1,newPosY#)
	
	if GetRawMouseRightPressed()
		lightstate=1-lightstate
		if lightstate=0
			Shadow_LightPosX#=GetCameraX(1)
			Shadow_LightPosY#=GetCameraY(1)
			Shadow_LightPosZ#=GetCameraZ(1)
		endif
	endif
	if lightstate=1
		Angle#=Angle#+10*GetFrameTime()
		Shadow_LightPosX#=sin(Angle#)*50
		Shadow_LightPosY#=15+sin(180+Angle#*5)*10
		Shadow_LightPosZ#=cos(Angle#)*50
	endif

	SetObjectPosition(LightObjectID,Shadow_LightPosX#,Shadow_LightPosY#,Shadow_LightPosZ#)
	SetPointLightPosition(1,Shadow_LightPosX#,Shadow_LightPosY#,Shadow_LightPosZ#)

    if (GetPointerPressed()=1)
        startx#=GetPointerX()
        starty#=GetPointerY()
        angx#=GetCameraAngleX(1)
        angy#=GetCameraAngleY(1)
        pressed=1
    endif

    if (GetPointerState()=1)
        fDiffX#=(GetPointerX()-startx#)*0.15
        fDiffY#=(GetPointerY()-starty#)*0.15
        currentX#=angx#+fDiffY#
        if (tempnewX#>89) then tempnewX#=89
        if (tempnewX#<-89) then tempnewX#=-89
		currentY#=angy#+fDiffX#
    endif
	newX#=CurveValue(currentX#,newX#,4)
	newY#=CurveValue(currentY#,newY#,4)
	SetCameraRotation(1,newX#,newY#,0)

	if GetRawMouseRightPressed()=1 then ThrowBall(200,0.5)
	if GetRawKeyPressed(27)=1 then exit

	Step3DPhysicsWorld()
	Update(GetFrameTime())
	SetClearColor(255,255,255)
	Shadow_PointLight_Update(1,Shadow_LightPosX#,Shadow_LightPosY#,Shadow_LightPosZ#,200)
	SetClearColor(127,201,255)
	SetRenderToScreen()
	ClearScreen()
	Render()
	Swap()
loop

Shadow_RemoveAllObjects()
end


function ThrowBall( initialSpeed as float, mass as float )
    local directionX as float
    local directionY as float
    local directionZ as float
    directionX = Get3DVectorXFromScreen( GetPointerX(), GetPointerY() )
    directionY = Get3DVectorYFromScreen( GetPointerX(), GetPointerY() )
    directionZ = Get3DVectorZFromScreen( GetPointerX(), GetPointerY() )
    throwBall as integer
    throwBall = CreateObjectSphere( 2, 16, 32 )
    SetObjectImage( throwBall, BallImageID, 0 )
    SetObjectPosition( throwBall, GetCameraX( 1 ), GetCameraY( 1 ), GetCameraZ( 1 ) )
    //3D Physics code
    Create3DPhysicsDynamicBody( throwBall )
    SetObjectShapeSphere( throwBall )
    SetObject3DPhysicsMass( throwBall, mass )
    SetObject3DPhysicsLinearVelocity( throwBall, directionX, directionY, directionZ, initialSpeed )
    SetObject3DPhysicsFriction( throwBall, 0.8 )
    SetObject3DPhysicsRollingFriction( throwBall, 0.7 )
    Shadow_AddObject(throwBall,1)
endfunction

function CurveValue(Destination#,Current#,Smooth#)
	Current#=Current#+((Destination#-Current#)/Smooth#)
endfunction Current#

