

function random(a, b)
	if (a > b) then
		local c = b
		b = a
		a = c
	end
	local delta = b-a
	return (a + math.random()*delta)
end



local demo_dir = gh_utils.get_demo_dir()
    
local lib_dir = gh_utils.get_scripting_libs_dir() 		
dofile(lib_dir .. "lua/gx_cam_lib_v1.lua")
dofile(lib_dir .. "lua/libfont/libfont1.lua")   
dofile(lib_dir .. "lua/imgui.lua")    


winW, winH = gh_window.getsize(0)


is_windows = 0
is_linux = 0
is_rpi = 0

if (gh_utils.get_platform() == 1) then -- return 1 if Windows, 2 if osx, 3 if linux, 4 if rpi and 5 if tinker board
  is_windows = 1
end

if (gh_utils.get_platform() == 3) then -- return 1 if Windows, 2 if osx, 3 if linux, 4 if rpi and 5 if tinker board
  is_linux = 1
end

if (gh_utils.get_platform() == 4) then -- return 1 if Windows, 2 if osx, 3 if linux, 4 if rpi and 5 if tinker board
  is_rpi = 1
end

win_hovered = 0


--[[
local aspect = winW / winH
camera = gh_camera.create_persp(60, aspect, 0.1, 1000.0)
gh_camera.set_viewport(camera, 0, 0, winW, winH)
gh_camera.set_position(camera, 0, 0.2, 0.4)
gh_camera.set_lookat(camera, 0, 0, 0, 1)
gh_camera.setupvec(camera, 0, 1, 0, 0)
--]]





orbit_mode = 0
keyboard_speed = 10.0
camera_fov = 60.0
camera_lookat_x = 0
camera_lookat_y = 0
camera_lookat_z = 0

camera = gx_camera.create_perspective(60, 1, 0, 0, winW, winH, 0.1, 1000)
gh_camera.set_position(camera, 0, 2, 8)

if (orbit_mode == 1) then
  gx_camera.init_orientation(camera, 0, 0, 0, 30, 90)
  gx_camera.set_mode_orbit()
else
  gx_camera.set_mode_fly()
end

gx_camera.set_orbit_lookat(camera, camera_lookat_x, camera_lookat_y, camera_lookat_z)
gx_camera.set_keyboard_speed(keyboard_speed)
gh_camera.set_fov(camera, camera_fov)






camera_ortho = gh_camera.create_ortho(-winW/2, winW/2, -winH/2, winH/2, 1.0, 10.0)
gh_camera.set_viewport(camera_ortho, 0, 0, winW, winH)
gh_camera.set_position(camera_ortho, 0, 0, 4)





ground_color = {r=0.7, g=0.7, b=0.7, a=1.0}


texture_prog = gh_node.getid("texture_prog")
gh_gpu_program.uniform1i(texture_prog, "tex0", 0)


local PF_U8_RGB = 1
local PF_U8_RGBA = 3
local PF_F32_RGBA = 6
local pixel_format = PF_U8_RGBA
local gen_mipmaps = 1
local compressed_texture = 0

local filename = demo_dir .. "data/9452-diffuse.jpg"
box_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)

--filename = demo_dir .. "data/10912-diffuse.jpg"
--sphere_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)

filename = demo_dir .. "data/4791-diffuse.jpg"
ground_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)

filename = demo_dir .. "data/13643-diffuse.jpg"
column_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)


filename = demo_dir .. "data/2261-diffuse.jpg"
bullet_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)

filename = demo_dir .. "data/Bullet_Physics_Library_Logo.png"
bullet_physics_logo_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)

filename = demo_dir .. "data/crosshair01.jpg"
crosshair_tex = gh_texture.create_from_file_v6(filename, pixel_format, gen_mipmaps, compressed_texture)






local SAMPLER_FILTERING_NEAREST = 1
local SAMPLER_FILTERING_LINEAR = 2
local SAMPLER_FILTERING_TRILINEAR = 3
local SAMPLER_ADDRESSING_WRAP = 1
local SAMPLER_ADDRESSING_CLAMP_TO_EDGE = 2
local SAMPLER_ADDRESSING_MIRROR = 3
gh_texture.bind(box_tex, 0)
gh_texture.set_sampler_params(box_tex, SAMPLER_FILTERING_TRILINEAR, SAMPLER_ADDRESSING_WRAP, 16.0)
gh_texture.bind(ground_tex, 0)
gh_texture.set_sampler_params(ground_tex, SAMPLER_FILTERING_TRILINEAR, SAMPLER_ADDRESSING_WRAP, 16.0)
gh_texture.bind(0, 0)






--quad = gh_mesh.create_quad(350, 150)
logo_quad = gh_mesh.create_quad(180, 80)

crosshair_quad = gh_mesh.create_quad(128, 128)



block_size = 2.0 -- 2-meter blocks!


sphere_radius = 0.5
sphere = gh_mesh.create_sphere(sphere_radius, 20, 20)
gh_object.set_position(sphere, -1, 3, 0)
gh_object.set_euler_angles(sphere, 0, 0, 0)


ground = gh_mesh.create_plane(20, 20, 2, 2)
gh_object.set_position(ground, 0, 0, 0)




--http://soundbible.com/2068-Woosh.html
--https://www.freesoundeffects.com/free-sounds/war-and-battle-sound-effects-10042/


sound_enabled = 0
sound_fmod = 0
sound_ffmpeg = 0

if ((is_windows == 1) or (is_linux == 1)) then
  sound_enabled = 1
  sound_fmod = 1
end

if (is_rpi == 1) then
  sound_enabled = 1
  sound_ffmpeg = 1
end

impact_sound = 0
gun_sound = 0
av0 = 0
av1 = 0
  
if (sound_enabled == 1) then

  if (sound_fmod == 1) then
    local absolute_path = 0
    local stream = 0
    -- sound = gh_audio.sound_create("data/Gun+Shot2.mp3", absolute_path, stream)
    impact_sound = gh_audio.sound_create("data/Explosion+1.mp3", absolute_path, stream)
    gh_audio.sound_set_loop_state(impact_sound, 0)

    gun_sound = gh_audio.sound_create("data/Gun+Silencer.mp3", absolute_path, stream)
    gh_audio.sound_set_loop_state(gun_sound, 0)
  end 
  
  if (sound_ffmpeg == 1) then
    local volume = 0.7
    local av_media_filename = "data/Gun+Silencer.mp3"
    local loop_mode = 0
    local audio_filename = demo_dir .. av_media_filename
    av0 = gh_av.decoder_open(audio_filename, loop_mode)
    if (av0 > 0) then
      gh_av.set_volume(av0, volume)
      gh_av.pause(av0, 1)
      gh_av.start_audio_video_processing(av0, 0, 1)
    else
      print("Unable to load the audio file " .. audio_filename)
    end
    
    av_media_filename = "data/Explosion+1.mp3"
    audio_filename = demo_dir .. av_media_filename
    av1 = gh_av.decoder_open(audio_filename, loop_mode)
    if (av1 > 0) then
      gh_av.set_volume(av1, volume)
      gh_av.pause(av1, 1)
      gh_av.start_audio_video_processing(av1, 0, 1)
    else
      print("Unable to load the audio file " .. audio_filename)
    end
    
  end
end














play_impact_sound = 0
play_gun_sound = 0



gh_renderer.set_vsync(0)

last_time = gh_utils.get_elapsed_time()


gl_renderer = gh_renderer.get_renderer_model()
gl_version = gh_renderer.get_api_version()


fps_time = 0
fps = 0
frames = 0








wall = {
  num_blocks = 0,
  block_size = 0,
  num_blocks_x = 0,
  num_blocks_y = 0,
  blocks = {}
}


function create_blocks(scene, wall_mat, num_blocks_x, num_blocks_y, block_size)
  local mass = 10.0
  local y_start = block_size / 2.0
  local num_blocks = num_blocks_x * num_blocks_y
  wall.num_blocks = num_blocks
  wall.block_size = block_size
  wall.num_blocks_x = num_blocks_x
  wall.num_blocks_y = num_blocks_y
  
  for i=1, num_blocks do
    local block = { meshid=0, aid=0 }
    block.meshid = gh_mesh.create_box(block_size, block_size, block_size, 1, 1, 1)
    block.aid = gh_bullet3.actor_create_box(block_size, block_size, block_size,   0, 0, 0,   mass,  wall_mat)
    wall.blocks[i] = block
    
    gh_bullet3.scene_add_actor(scene, block.aid)
    
    local instance_index = -1 -- no instancing
    gh_bullet3.actor_set_3d_object(block.aid, block.meshid, instance_index)
  end
end

function reset_blocks_position()
  
  local y_start = wall.block_size / 2.0
  local num_blocks = 0
  local block_counter = 1
  
  for y=0, wall.num_blocks_y-1 do
  
    local x_start = -wall.num_blocks_x/2*wall.block_size + wall.block_size/4
    for x=0, wall.num_blocks_x-1 do

      local block = wall.blocks[block_counter]
      block_counter = block_counter+1
      
      local aid = block.aid
    
      gh_bullet3.actor_clear_forces(aid)
      --local rz = random(-0.10, 0.10)
      local rz = 0
      gh_bullet3.actor_set_position(aid,  x_start, y_start, rz)
      gh_bullet3.actor_set_orientation(aid,  0.0, 0.0, 0.0, 1.0)
      gh_bullet3.actor_set_damping(aid, 0.5, 0.5)
      gh_bullet3.actor_set_linear_velocity(aid, 0, 0, 0)
      gh_bullet3.actor_set_angular_velocity(aid, 0, 0, 0)
      gh_bullet3.actor_set_sleeping_thresholds(aid, 1.0, 1.0)
      gh_bullet3.actor_set_collision_margin(aid, 0.01)
      --gh_bullet3.actor_set_ccd_params(aid, wall.block_size/2.0, wall.block_size/4.0)
      
      local ACTIVE_TAG = 1
      local ISLAND_SLEEPING = 2
      local WANTS_DEACTIVATION = 3
      local DISABLE_DEACTIVATION = 4
      local DISABLE_SIMULATION = 5
      gh_bullet3.actor_set_activation_state(aid, WANTS_DEACTIVATION)
      --gh_bullet3.actor_set_active_state(aid, 0)
      
      
      local rx = random(-0.05, 0.05)
      --local rx = 0.01
      --x_start = x_start + block_size + 0.01 + rx
      x_start = x_start + block_size + 0.2
    end
    --local ry = random(0.0, 0.2)
    local ry = 0.0
    y_start = y_start + block_size + ry
  end
end



function create_wall(scene, wall_mat, num_blocks_x, num_blocks_y, block_size)
  create_blocks(scene, wall_mat, num_blocks_x, num_blocks_y, block_size)
  reset_blocks_position()
end


function reset_columns()
  gh_bullet3.actor_clear_forces(b3_cyl1)
  gh_bullet3.actor_set_linear_velocity(b3_cyl1, 0.0, 0.0, 0.0)
  gh_bullet3.actor_set_angular_velocity(b3_cyl1, 0.0, 0.0, 0.0)
  gh_bullet3.actor_set_position(b3_cyl1, -8.0, cyl_height/2, 0)

  gh_bullet3.actor_clear_forces(b3_cyl2)
  gh_bullet3.actor_set_linear_velocity(b3_cyl2, 0.0, 0.0, 0.0)
  gh_bullet3.actor_set_angular_velocity(b3_cyl2, 0.0, 0.0, 0.0)
  gh_bullet3.actor_set_position(b3_cyl2, 8.0, cyl_height/2, 0)
end  







bullets = {}
num_bullets = 10
bullet_counter = 0
fire_bullet = 0
throw_bullet_last_time = 0
bullet_speed = 40


function bullets_create(scene, bullet_mat, radius)
  local mass = 10.0
  for i=1, num_bullets do
    local bullet = { sceneid=0, aid=0, contact=0, can_play_impact_sound=0, is_sleeping=1 }
    bullet.aid = gh_bullet3.actor_create_sphere(radius,  0, radius+0.5, 0,   mass,  bullet_mat)
    gh_bullet3.actor_clear_forces(bullet.aid)
    gh_bullet3.actor_set_linear_velocity(bullet.aid, 0, 0, 0)
    gh_bullet3.actor_set_angular_velocity(bullet.aid, 0, 0, 0)
    gh_bullet3.actor_set_sleeping_thresholds(bullet.aid, 1.0, 1.0)
    local WANTS_DEACTIVATION = 3
    local ISLAND_SLEEPING = 2
    gh_bullet3.actor_set_activation_state(bullet.aid, WANTS_DEACTIVATION)
    bullets[i] = bullet
    
    --gh_bullet3.scene_add_actor(scene, bullet.aid)

  end
end
 
function bullets_reset(scene)
  bullet_counter = 0
  for i=1, num_bullets do
    local bullet = bullets[i]
    gh_bullet3.scene_remove_actor(scene, bullet.aid)
    bullet.sceneid = 0
    
    --gh_bullet3.actor_set_position(bullet.aid, 0, 1000 + num_bullets*10, 0)
    --gh_bullet3.actor_clear_forces(bullet.aid)
    --gh_bullet3.actor_set_linear_velocity(bullet.aid, 0, 0, 0)
    --gh_bullet3.actor_set_angular_velocity(bullet.aid, 0, 0, 0)
    --local WANTS_DEACTIVATION = 3
    --gh_bullet3.actor_set_activation_state(bullet.aid, WANTS_DEACTIVATION)
  end
end



function bullet_throw(scene, camera, bullet_speed)
  local dir_x, dir_y, dir_z = gh_camera.get_view_vector(camera)
  local vel_x = dir_x * bullet_speed
  local vel_y = dir_y * bullet_speed
  local vel_z = dir_z * bullet_speed
  
  local pos_x, pos_y, pos_z = gh_camera.get_position(camera)

  pos_x = pos_x + dir_x * 2.0
  pos_y = pos_y + dir_y * 2.0
  pos_z = pos_z + dir_z * 2.0

  if (bullet_counter >= num_bullets) then
    bullet_counter = 1
   end
  
  bullet_counter = bullet_counter + 1
  local bullet = bullets[bullet_counter]
  
  bullet.can_play_impact_sound = 1
  bullet.contact = 0
  bullet.is_sleeping = 0
  
  gh_bullet3.actor_set_position(bullet.aid, pos_x, pos_y, pos_z)
  gh_bullet3.actor_set_linear_velocity(bullet.aid, vel_x, vel_y, vel_z)
  local linear_damping = 0.5
  local angular_damping = 0.8
  gh_bullet3.actor_set_damping(bullet.aid, linear_damping, angular_damping)
  local ACTIVE_TAG = 1
  gh_bullet3.actor_set_activation_state(bullet.aid, ACTIVE_TAG)
  
  if (bullet.sceneid == 0) then
    gh_bullet3.scene_add_actor(scene, bullet.aid)
    bullet.sceneid = scene
  end
  
end
    





local cyl_central_axis = 1 -- X=0, Y=1, Z=2    
local cyl_radius = 1.0
cyl_height = 10.0
cylinder = gh_mesh.create_cylinder_xyz(cyl_central_axis, cyl_radius, cyl_height, 10, 10)
--gh_object.set_euler_angles(cylinder, 90, 0, 0)






num_collision_objects = 0

reset_simulation = 1
run_simulation = 1
scene_gravity = {x=0, y=-10, z=0}

max_contacts = 0
box_contact_info = {n=0, x=0, y=0, z=0}
sphere_contact_info = {n=0, x=0, y=0, z=0}



---[[


bullet3_ver = gh_bullet3.get_version()


gh_bullet3.init()

--b3_scene = gh_bullet3.scene_create()
b3_scene = gh_bullet3.scene_create_sap(-100, 0.0, -100,   100, 100.0, 100)

b3_solver_num_iterations = 10
gh_bullet3.scene_set_solver_num_iterations(b3_scene, b3_solver_num_iterations)

gh_bullet3.scene_set_gravity(b3_scene, scene_gravity.x, scene_gravity.y, scene_gravity.z)

local restitution = 0.0
local friction = 0.8
b3_wall_mat = gh_bullet3.material_create(restitution, friction)


local restitution = 0.01
local friction = 1.9
b3_mat = gh_bullet3.material_create(restitution, friction)
--b3_mat = 0

local mass = 0.0 -- mass = 0 --> kinematic
local ground_height = 2.0
--b3_ground = gh_bullet3.actor_create_box(b3_scene, 20, ground_height, 20,   0, -ground_height/2.0, 0,   mass,  b3_mat)
b3_ground = gh_bullet3.actor_create_static_plane(0, 1, 0,   0,  b3_mat)
gh_bullet3.scene_add_actor(b3_scene, b3_ground)




mass = 500.0 -- mass > 0 --> dynamic

b3_cyl1 = gh_bullet3.actor_create_cylinder(cyl_central_axis, cyl_height, cyl_radius,    7.0, cyl_height/2, 0,   mass,  b3_mat)
gh_bullet3.scene_add_actor(b3_scene, b3_cyl1)
gh_bullet3.actor_set_damping(b3_cyl1, 0.25, 0.25)

b3_cyl2 = gh_bullet3.actor_create_cylinder(cyl_central_axis, cyl_height, cyl_radius,    -7.0, cyl_height/2, 0,   mass,  b3_mat)
gh_bullet3.scene_add_actor(b3_scene, b3_cyl2)
gh_bullet3.actor_set_damping(b3_cyl2, 0.25, 0.25)

reset_columns()



--gh_bullet3.actor_set_damping(b3_box, 0.2, 0.2)


--b3_box = gh_bullet3.actor_create_box(b3_scene, block_size, block_size, block_size,   1, 3, 0,   mass,  b3_mat)
--gh_bullet3.actor_set_damping(b3_box, 0.2, 0.2)

num_blocks_x = 6
num_blocks_y = 6
create_wall(b3_scene, b3_wall_mat, num_blocks_x, num_blocks_y, block_size)



local restitution = 0.01
local friction = 0.5
bullet_mat = gh_bullet3.material_create(restitution, friction)


bullets_create(b3_scene, bullet_mat, sphere_radius)
bullets_reset()

gh_bullet3.scene_step_simulation(b3_scene, 0.016, 2, 1.0/60.0)






--local vx = random(-0.1, 0.1)
--local vy = random(-0.2, 0.2)
--local vz = random(-0.2, 0.2)
--gh_bullet3.actor_set_angular_velocity(b3_box, vx, vy, vz)

--b3_sphere = gh_bullet3.actor_create_sphere(b3_scene, sphere_radius,  -1, 3, 3,   mass,  b3_mat)
--gh_bullet3.actor_set_damping(b3_sphere, 0.25, 0.5)

--local vx = random(-0.1, 0.1)
--local vy = random(-0.2, 0.2)
--local vz = random(-0.2, 0.2)
--gh_bullet3.actor_set_angular_velocity(b3_sphere, vx, vy, vz)

--]]











