main.lua 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. -- "Second screen experience" demo
  2. -- Click grid on desktop screen to build a scene simultaneously visible in VR space
  3. --
  4. -- Sample contributed by andi mcc
  5. local shader = require 'shader'
  6. -- In order for lovr.mouse to work, and therefore for this example to work,
  7. -- we must be using LuaJIT and we must be using GLFW (ie: we can't be on Android)
  8. if type(jit) == 'table' and lovr.system.getOS() ~= "android" then
  9. lovr.mouse = require 'mouse'
  10. end
  11. local mirror = lovr.mirror -- Backup lovr.mirror before it is overwritten
  12. local font = lovr.graphics.newFont(36) -- Font appropriate for screen-space usage
  13. font:setFlipEnabled(true)
  14. font:setPixelDensity(1)
  15. -- Simple 2D triangle mesh
  16. local triangle = lovr.graphics.newMesh(
  17. {{0,-1,0, 0,0,1}, {0.75,1,0, 0,0,1}, {-0.75,1,0, 0,0,1}},
  18. 'triangles', 'static'
  19. )
  20. -- Constants
  21. local pixwidth = lovr.graphics.getWidth() -- Window pixel width and height
  22. local pixheight = lovr.graphics.getHeight()
  23. local aspect = pixwidth/pixheight -- Window aspect ratio
  24. local height = 2 -- Window width and height in screen coordinates
  25. local width = aspect*2 -- ( We will pick the coordinate system [[-1,1],[-aspect,aspect]] )
  26. local topmargin = 0.2 -- Space between top of screen and top of grid
  27. local cells = 7 -- Number of cells in grid (per side)
  28. local towerscalexz = 2 -- How wide is one block in 3D space?
  29. local towerscaley = 3 -- How tall (maximum) is one block in 3D space?
  30. -- Derived constants
  31. local gridheight = (height-topmargin*2) -- Height of grid
  32. local gridspan = gridheight/2 -- Half height of grid
  33. local cellheight = gridheight/cells -- Height of one grid cell
  34. local cellspan = cellheight/2 -- Half height of one grid cell
  35. local bannedcell = math.ceil(cells/2) -- Do not allow clicks at this x,y coordinate
  36. local fontscale = height/lovr.graphics.getHeight() -- Scale argument to screen-space print() functions
  37. -- Screen-space coordinate system
  38. local matrix = lovr.math.newMat4():orthographic(-aspect, aspect, -1, 1, -64, 64)
  39. -- State: We will store the blocks to draw as a 2D array of heights (nil for no block)
  40. local grid = {}
  41. for x=1,cells do grid[x] = {} end
  42. function lovr.load()
  43. lovr.handlers['mousepressed'] = function(x,y)
  44. local inx = x * width / pixwidth - width/2 -- Convert pixel x,y to our coordinate system
  45. local iny = y * height / pixheight - height/2
  46. local gridorigin = -gridspan - cellheight -- Upper left of grid ()
  47. local gx = (inx - gridorigin) / cellheight -- Convert coordinate system to grid cells
  48. local gy = (iny - gridorigin) / cellheight
  49. local fx = math.floor(gx)
  50. local fy = math.floor(gy)
  51. if fx >= 1 and fy >= 1 and fx <= cells and fy <= cells -- If the click was within the grid
  52. and not (fx == bannedcell and fy == bannedcell) then -- and was not the banned center cell
  53. if grid[fx][fy] then
  54. grid[fx][fy] = nil -- toggle off
  55. else
  56. grid[fx][fy] = lovr.math.random() -- toggle on (random height)
  57. end
  58. end
  59. end
  60. end
  61. function drawGrid()
  62. -- Draw cell backgrounds (where present)
  63. for _x=1,cells do for _y=1,cells do
  64. local gray = grid[_x][_y]
  65. if gray then
  66. local x = -gridspan + _x * cellheight - cellspan -- Center of cell
  67. local y = -gridspan + _y * cellheight - cellspan
  68. lovr.graphics.setColor(gray,gray,gray,1)
  69. lovr.graphics.plane('fill', x, y, 0, cellheight, cellheight)
  70. end
  71. end end
  72. -- Draw grid lines
  73. lovr.graphics.setColor(1,1,1,1)
  74. for c=0,cells do
  75. local x = -gridspan + c * cellheight
  76. local y = -gridspan + c * cellheight
  77. lovr.graphics.line(-gridspan, y, 0, gridspan, y, 0)
  78. lovr.graphics.line(x, -gridspan, 0, x, gridspan, 0)
  79. end
  80. -- Draw a red triangle indicating the position and orientation of the headset player
  81. lovr.graphics.push()
  82. local x, y, z, angle, ax, ay, az = lovr.headset.getPose()
  83. -- Flatten the 3-space current rotation of the headset into just its xz axis
  84. -- Equation from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToEuler/index.htm
  85. local s = math.sin(angle)
  86. local c = math.cos(angle)
  87. local t = 1-c;
  88. local xzangle = math.atan2(ay*s - ax*az*t , 1 - (ay*ay + az*az) * t);
  89. lovr.graphics.setColor(1,0,0,1)
  90. lovr.graphics.translate(x / towerscalexz, z / towerscalexz, 0)
  91. lovr.graphics.scale(cellheight*0.5*0.75)
  92. lovr.graphics.rotate(-xzangle, 0, 0, 1)
  93. triangle:draw()
  94. lovr.graphics.pop()
  95. end
  96. -- Draw HUD overlay
  97. function lovr.mirror()
  98. mirror()
  99. --lovr.graphics.clear() -- Uncomment to hide headset view in background of window
  100. lovr.graphics.setShader(nil)
  101. lovr.graphics.setDepthTest(nil)
  102. lovr.graphics.origin()
  103. lovr.graphics.setViewPose(1, mat4())
  104. lovr.graphics.setProjection(1, matrix) -- Switch to screen space coordinates
  105. drawGrid()
  106. -- Draw instructions
  107. lovr.graphics.setColor(1,1,1,1)
  108. lovr.graphics.setFont(font)
  109. lovr.graphics.print("Instructions: Click the grid to create or remove blocks.", 0, (gridheight+cellheight)/2, 0, fontscale)
  110. end
  111. -- Draw one block
  112. function floorbox(_x,_y,gray)
  113. local x = -gridspan + _x * cellheight - cellspan
  114. local z = -gridspan + _y * cellheight - cellspan
  115. local height = gray * towerscaley
  116. lovr.graphics.box('fill', x*towerscalexz, height/2, z*towerscalexz, cellheight*towerscalexz, height, cellheight*towerscalexz)
  117. end
  118. -- Draw 3D scene
  119. function lovr.draw()
  120. lovr.graphics.setDepthTest('lequal', true) -- mirror() will have disabled this
  121. lovr.graphics.setShader(shader)
  122. lovr.graphics.setColor(0,1,1)
  123. for x=1,cells do for y=1,cells do
  124. local gray = grid[x][y]
  125. if gray then floorbox(x,y,gray) end
  126. end end
  127. lovr.graphics.setShader()
  128. if not lovr.mouse then -- If you can't click, you can't create any blocks
  129. lovr.graphics.print('This example only works on a desktop computer.', 0, 1.7, -3, .2)
  130. end
  131. end