return {
  callbacks = {
    {
      name = "conf",
      tag = "callbacks",
      summary = "Called to read configuration settings at startup.",
      description = "The `lovr.conf` callback lets you configure default settings for LÖVR.  It is called once right before the game starts.\n\n:::note\nMake sure you put `lovr.conf` in a file called `conf.lua`, a special file that's loaded before the rest of the framework initializes.\n:::",
      key = "lovr.conf",
      module = "lovr",
      examples = {
        {
          description = "A noop conf.lua that sets all configuration settings to their defaults:",
          code = "function lovr.conf(t)\n\n  -- Set the project version and identity\n  t.version = '0.18.0'\n  t.identity = 'default'\n\n  -- Set save directory precedence\n  t.saveprecedence = true\n\n  -- Enable or disable different modules\n  t.modules.audio = true\n  t.modules.data = true\n  t.modules.event = true\n  t.modules.graphics = true\n  t.modules.headset = true\n  t.modules.math = true\n  t.modules.physics = true\n  t.modules.system = true\n  t.modules.thread = true\n  t.modules.timer = true\n\n  -- Audio\n  t.audio.spatializer = nil\n  t.audio.samplerate = 48000\n  t.audio.start = true\n\n  -- Graphics\n  t.graphics.debug = false\n  t.graphics.vsync = true\n  t.graphics.stencil = false\n  t.graphics.antialias = true\n  t.graphics.shadercache = true\n\n  -- Headset settings\n  t.headset.drivers = { 'openxr', 'simulator' }\n  t.headset.start = true\n  t.headset.supersample = false\n  t.headset.seated = false\n  t.headset.antialias = true\n  t.headset.stencil = false\n  t.headset.submitdepth = true\n  t.headset.overlay = false\n\n  -- Math settings\n  t.math.globals = true\n\n  -- Thread settings\n  t.thread.workers = -1\n\n  -- Configure the desktop window\n  t.window.width = 1080\n  t.window.height = 600\n  t.window.fullscreen = false\n  t.window.resizable = false\n  t.window.title = 'LÖVR'\n  t.window.icon = nil\nend"
        }
      },
      notes = "Disabling unused modules can improve startup time.\n\n`t.window` can be set to nil to avoid creating the window.  The window can later be opened manually using `lovr.system.openWindow`.\n\nEnabling the `t.graphics.debug` flag will add additional error checks and will send messages from the GPU driver to the `lovr.log` callback.  This will decrease performance but can help provide information on performance problems or other bugs.  It will also cause `lovr.graphics.newShader` to embed debugging information in shaders which allows inspecting variables and stepping through shaders line-by-line in tools like RenderDoc.\n\n`t.graphics.debug` can also be enabled using the `--graphics-debug` command line option.",
      related = {
        "lovr.load"
      },
      variants = {
        {
          arguments = {
            {
              name = "t",
              type = "table",
              description = "The table to edit the configuration settings on.",
              table = {
                {
                  name = "version",
                  type = "string",
                  description = "The version of LÖVR this project targets (not used yet)."
                },
                {
                  name = "identity",
                  type = "string",
                  description = "A unique label for this project."
                },
                {
                  name = "saveprecedence",
                  type = "boolean",
                  description = "Whether the files in the save directory should have precedence over files in the source archive."
                },
                {
                  name = "modules",
                  type = "table",
                  description = "The set of enabled modules to use.",
                  table = {
                    {
                      name = "audio",
                      type = "boolean",
                      description = "Whether the audio module should be enabled."
                    },
                    {
                      name = "data",
                      type = "boolean",
                      description = "Whether the data module should be enabled."
                    },
                    {
                      name = "event",
                      type = "boolean",
                      description = "Whether the event module should be enabled."
                    },
                    {
                      name = "graphics",
                      type = "boolean",
                      description = "Whether the graphics module should be enabled."
                    },
                    {
                      name = "headset",
                      type = "boolean",
                      description = "Whether the headset module should be enabled."
                    },
                    {
                      name = "math",
                      type = "boolean",
                      description = "Whether the math module should be enabled."
                    },
                    {
                      name = "physics",
                      type = "boolean",
                      description = "Whether the physics module should be enabled."
                    },
                    {
                      name = "system",
                      type = "boolean",
                      description = "Whether the system module should be enabled."
                    },
                    {
                      name = "thread",
                      type = "boolean",
                      description = "Whether the thread module should be enabled."
                    },
                    {
                      name = "timer",
                      type = "boolean",
                      description = "Whether the timer module should be enabled."
                    }
                  }
                },
                {
                  name = "audio",
                  type = "table",
                  description = "Configuration for the audio module.",
                  table = {
                    {
                      name = "spatializer",
                      type = "string",
                      description = "An audio spatializer to use (`simple`, `oculus`, or `phonon`).  If `nil`, all of them are attempted."
                    },
                    {
                      name = "samplerate",
                      type = "number",
                      description = "The sample rate to use for audio playback."
                    },
                    {
                      name = "start",
                      type = "boolean",
                      description = "Whether the playback device should be automatically started."
                    }
                  }
                },
                {
                  name = "graphics",
                  type = "table",
                  description = "Configuration for the graphics module.",
                  table = {
                    {
                      name = "debug",
                      type = "boolean",
                      description = "Whether debug messages from the GPU should get sent to lovr.log."
                    },
                    {
                      name = "vsync",
                      type = "boolean",
                      description = "Whether vsync is enabled (forced off when VR is active)."
                    },
                    {
                      name = "stencil",
                      type = "boolean",
                      description = "Whether the desktop window should have a stencil buffer."
                    },
                    {
                      name = "antialias",
                      type = "boolean",
                      description = "Whether the desktop window rendering should be antialiased."
                    },
                    {
                      name = "hdr",
                      type = "boolean",
                      description = "Whether the (**super experimental**) HDR mode should be enabled.  See `lovr.graphics.isHDR`."
                    },
                    {
                      name = "shadercache",
                      type = "boolean",
                      description = "Whether the shader cache should be loaded and saved to disk."
                    }
                  }
                },
                {
                  name = "headset",
                  type = "table",
                  description = "Configuration for the headset.",
                  table = {
                    {
                      name = "drivers",
                      type = "table",
                      description = "An ordered list of preferred headset drivers."
                    },
                    {
                      name = "start",
                      type = "boolean",
                      description = "Whether a VR session should begin at startup."
                    },
                    {
                      name = "supersample",
                      type = "number",
                      description = "A scaling factor to apply to the headset texture.  Can be any positive floating point number, which gets multiplied by the default texture resolution.  A value greater than 1 improves visual quality but reduces performance.  Can also be a boolean, where \"true\" means \"2.0\"."
                    },
                    {
                      name = "seated",
                      type = "boolean",
                      description = "Whether <a data-key=\"lovr.headset.isSeated\">seated mode</a> should be used instead of standing, changing the headset coordinate space to place y=0 at eye level."
                    },
                    {
                      name = "antialias",
                      type = "boolean",
                      description = "Whether headset rendering should be antialiased."
                    },
                    {
                      name = "stencil",
                      type = "boolean",
                      description = "Whether headset rendering should have a stencil buffer."
                    },
                    {
                      name = "submitdepth",
                      type = "boolean",
                      description = "Whether the depth buffer should be sent to the VR runtime (improves reprojection)."
                    },
                    {
                      name = "overlay",
                      type = "boolean",
                      description = "Whether the project should run as an overlay.  Can also be a number to control sort order against other overlays (default is zero, higher numbers go on top).  Requires the `overlay` headset feature to be supported, see `lovr.headset.getFeatures`."
                    }
                  }
                },
                {
                  name = "math",
                  type = "table",
                  description = "Configuration for the math module.",
                  table = {
                    {
                      name = "globals",
                      type = "boolean",
                      description = "Whether vector object functions should be added to the global scope."
                    }
                  }
                },
                {
                  name = "thread",
                  type = "table",
                  description = "Configuration for the thread module.",
                  table = {
                    {
                      name = "workers",
                      type = "number",
                      description = "The number of worker threads to spawn.  Can be negative, which will be added to the number of cores in the system."
                    }
                  }
                },
                {
                  name = "window",
                  type = "table",
                  description = "Configuration for the window.",
                  table = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the window (or 0 to use the monitor width)."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the window (or 0 to use the monitor height) ."
                    },
                    {
                      name = "fullscreen",
                      type = "boolean",
                      description = "Whether the window is fullscreen."
                    },
                    {
                      name = "resizable",
                      type = "boolean",
                      description = "Whether the window is resizable."
                    },
                    {
                      name = "title",
                      type = "string",
                      description = "The window title."
                    },
                    {
                      name = "icon",
                      type = "string",
                      description = "The path to the window icon file."
                    }
                  }
                }
              }
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "draw",
      tag = "callbacks",
      summary = "Called continuously to render frames to the display.",
      description = "This callback is called every frame, and receives a `Pass` object as an argument which can be used to render graphics to the display.  If a VR headset is connected, this function renders to the headset display, otherwise it will render to the desktop window.",
      key = "lovr.draw",
      module = "lovr",
      notes = "To render to the desktop window when a VR headset is connected, use the `lovr.mirror` callback.\n\nThe display is cleared to the global background color before this callback is called, which can be changed using `lovr.graphics.setBackgroundColor`.\n\nSince the `lovr.graphics.submit` function always returns true, the following idiom can be used to submit graphics work manually and override the default submission:\n\n    function lovr.draw(pass)\n      local passes = {}\n\n      -- ... record multiple passes and add to passes table\n\n      return lovr.graphics.submit(passes)\n    end",
      related = {
        "lovr.mirror",
        "lovr.headset.getPass",
        "lovr.graphics.getWindowPass",
        "lovr.graphics.setBackgroundColor"
      },
      variants = {
        {
          arguments = {
            {
              name = "pass",
              type = "Pass",
              description = "A render pass targeting the main display (headset or window)."
            }
          },
          returns = {
            {
              name = "skip",
              type = "boolean",
              description = "If truthy, the input Pass will not be submitted to the GPU."
            }
          }
        }
      }
    },
    {
      name = "errhand",
      tag = "callbacks",
      summary = "Called when an error occurs.",
      description = "The `lovr.errhand` callback is run whenever an error occurs.  It receives a parameter containing the error message.  It should return a handler function that will run in a loop to render the error screen.\n\nThis handler function is of the same type as the one returned by `lovr.run` and has the same requirements (such as pumping events).  If an error occurs while this handler is running, the program will terminate immediately -- `lovr.errhand` will not be given a second chance.  Errors which occur in the error handler or in the handler it returns may not be cleanly reported, so be careful.\n\nA default error handler is supplied that renders the error message as text to the headset and to the window.",
      key = "lovr.errhand",
      module = "lovr",
      examples = {
        {
          description = "The default error handler.",
          code = "function lovr.errhand(message)\n  local function formatTraceback(s)\n    return s:gsub('\\n[^\\n]+$', ''):gsub('\\t', ''):gsub('stack traceback:', '\\nStack:\\n')\n  end\n\n  message = 'Error:\\n\\n' .. tostring(message) .. formatTraceback(debug.traceback('', 4))\n\n  print(message)\n\n  if not lovr.graphics or not lovr.graphics.isInitialized() then\n    return function() return 1 end\n  end\n\n  if lovr.audio then lovr.audio.stop() end\n\n  if not lovr.headset or lovr.headset.getPassthrough() == 'opaque' then\n    lovr.graphics.setBackgroundColor(.11, .10, .14)\n  else\n    lovr.graphics.setBackgroundColor(0, 0, 0, 0)\n  end\n\n  local font = lovr.graphics.getDefaultFont()\n\n  return function()\n    lovr.system.pollEvents()\n\n    for name, a in lovr.event.poll() do\n      if name == 'quit' then return a or 1\n      elseif name == 'restart' then return 'restart', lovr.restart and lovr.restart()\n      elseif name == 'keypressed' and a == 'f5' then lovr.event.restart()\n      elseif name == 'keypressed' and a == 'escape' then lovr.event.quit() end\n    end\n\n    if lovr.headset and lovr.headset.getDriver() ~= 'simulator' then\n      lovr.headset.update()\n      local pass = lovr.headset.getPass()\n      if pass then\n        font:setPixelDensity()\n\n        local scale = .35\n        local font = lovr.graphics.getDefaultFont()\n        local wrap = .7 * font:getPixelDensity()\n        local lines = font:getLines(message, wrap)\n        local width = math.min(font:getWidth(message), wrap) * scale\n        local height = .8 + #lines * font:getHeight() * scale\n        local x = -width / 2\n        local y = math.min(height / 2, 10)\n        local z = -10\n\n        pass:setColor(.95, .95, .95)\n        pass:text(message, x, y, z, scale, 0, 0, 0, 0, wrap, 'left', 'top')\n\n        lovr.graphics.submit(pass)\n        lovr.headset.submit()\n      end\n    end\n\n    if lovr.system.isWindowOpen() then\n      local pass = lovr.graphics.getWindowPass()\n      if pass then\n        local w, h = lovr.system.getWindowDimensions()\n        pass:setProjection(1, lovr.math.mat4():orthographic(0, w, 0, h, -1, 1))\n        font:setPixelDensity(1)\n\n        local scale = .6\n        local wrap = w * .8 / scale\n        local width = math.min(font:getWidth(message), wrap) * scale\n        local x = w / 2 - width / 2\n\n        pass:setColor(.95, .95, .95)\n        pass:text(message, x, h / 2, 0, scale, 0, 0, 0, 0, wrap, 'left', 'middle')\n\n        lovr.graphics.submit(pass)\n        lovr.graphics.present()\n      end\n    end\n\n    lovr.math.drain()\n  end\nend"
        }
      },
      related = {
        "lovr.quit"
      },
      variants = {
        {
          arguments = {
            {
              name = "message",
              type = "string",
              description = "The error message."
            }
          },
          returns = {
            {
              name = "handler",
              type = "function",
              description = "The error handler function.  It should return nil to continue running, \"restart\" to restart the app, or a number representing an exit status.",
              arguments = {},
              returns = {
                {
                  name = "result",
                  type = "*"
                }
              }
            }
          }
        }
      }
    },
    {
      name = "filechanged",
      tag = "callbacks",
      summary = "Called when a file is changed.",
      description = "The `lovr.filechanged` callback is called when a file is changed.  File watching must be enabled, either by passing `--watch` when starting LÖVR or by calling `lovr.filesystem.watch`.\n\nCurrently, only files in the source directory are watched.  On Android, files in the sdcard directory are watched.",
      key = "lovr.filechanged",
      module = "lovr",
      notes = "LÖVR provides a default implementation for `lovr.filechanged` that restarts the project if a non-hidden file was changed:\n\n    function lovr.filechanged(path)\n      if not path:match('^%.') then\n        lovr.event.restart()\n      end\n    end",
      related = {
        "lovr.filesystem.watch",
        "lovr.filesystem.unwatch"
      },
      variants = {
        {
          arguments = {
            {
              name = "path",
              type = "string",
              description = "The path to the file that changed."
            },
            {
              name = "action",
              type = "FileAction",
              description = "What happened to the file."
            },
            {
              name = "oldpath",
              type = "string",
              description = "The old path, for `rename` actions."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "focus",
      tag = "callbacks",
      summary = "Called when the application gains or loses input focus.",
      description = "The `lovr.focus` callback is called whenever the application acquires or loses focus (for example, when opening or closing the system VR menu).  The callback receives a `focused` argument, indicating whether or not the application is now focused.  Additionally, both the headset and desktop window have separate focus states, so a `display` argument indicates which display gained or lost input focus.  It may make sense to pause the game, reduce visual fidelity, or mute audio when the application loses focus.",
      key = "lovr.focus",
      module = "lovr",
      related = {
        "lovr.headset.isFocused",
        "lovr.visible"
      },
      variants = {
        {
          arguments = {
            {
              name = "focused",
              type = "boolean",
              description = "Whether the program is now focused."
            },
            {
              name = "display",
              type = "DisplayType",
              description = "Whether the headset or desktop window changed input focus."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "keypressed",
      tag = "callbacks",
      summary = "Called when a key is pressed.",
      description = "This callback is called when a key is pressed.",
      key = "lovr.keypressed",
      module = "lovr",
      related = {
        "lovr.system.wasKeyPressed",
        "lovr.keyreleased",
        "lovr.textinput",
        "lovr.system.isKeyDown"
      },
      variants = {
        {
          arguments = {
            {
              name = "key",
              type = "KeyCode",
              description = "The key that was pressed."
            },
            {
              name = "scancode",
              type = "number",
              description = "The id of the key (ignores keyboard layout, may vary between keyboards)."
            },
            {
              name = "isrepeat",
              type = "boolean",
              description = "Whether the event is the result of a key repeat instead of an actual press."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "keyreleased",
      tag = "callbacks",
      summary = "Called when a key is released.",
      description = "This callback is called when a key is released.",
      key = "lovr.keyreleased",
      module = "lovr",
      related = {
        "lovr.system.wasKeyReleased",
        "lovr.keypressed",
        "lovr.textinput",
        "lovr.system.isKeyDown"
      },
      variants = {
        {
          arguments = {
            {
              name = "key",
              type = "KeyCode",
              description = "The key that was released."
            },
            {
              name = "scancode",
              type = "number",
              description = "The id of the key (ignores keyboard layout, may vary between keyboards)."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "load",
      tag = "callbacks",
      summary = "Called once at startup.",
      description = "This callback is called once when the app starts.  It should be used to perform initial setup work, like loading resources and initializing classes and variables.",
      key = "lovr.load",
      module = "lovr",
      examples = {
        {
          code = "function lovr.load(arg)\n  model = lovr.graphics.newModel('sponza.gltf')\n  texture = lovr.graphics.newTexture('cena.png')\n  effects = lovr.graphics.newShader('vert.glsl', 'frag.glsl')\n  loadLevel(1)\nend"
        }
      },
      notes = "If the project was loaded from a restart using `lovr.event.restart`, the return value from the previously-run `lovr.restart` callback will be made available to this callback as the `restart` key in the `arg` table.\n\nThe `arg` table follows the [Lua standard](https://en.wikibooks.org/wiki/Lua_Programming/command_line_parameter).  The arguments passed in from the shell are put into a global table named `arg` and passed to `lovr.load`, but with indices offset such that the \"script\" (the project path) is at index 0.  So all arguments (if any) intended for the project are at successive indices starting with 1, and the executable and its \"internal\" arguments are in normal order but stored in negative indices.",
      related = {
        "lovr.quit"
      },
      variants = {
        {
          arguments = {
            {
              name = "arg",
              type = "table",
              description = "The command line arguments provided to the program."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "log",
      tag = "callbacks",
      summary = "Called when a message is logged.",
      description = "This callback is called when a message is logged.  The default implementation of this callback prints the message to the console using `print`, but it's possible to override this callback to render messages in VR, write them to a file, filter messages, and more.\n\nThe message can have a \"tag\" that is a short string representing the sender, and a \"level\" indicating how severe the message is.\n\nThe `t.graphics.debug` flag in `lovr.conf` can be used to get log messages from the GPU driver, tagged as `GPU`.  The `t.headset.debug` will enable OpenXR messages from the VR runtime, tagged as `XR`.\n\nIt is also possible to emit custom log messages using `lovr.event.push`, or by calling the callback.",
      key = "lovr.log",
      module = "lovr",
      related = {
        "Pass:text"
      },
      variants = {
        {
          arguments = {
            {
              name = "message",
              type = "string",
              description = "The log message.  It may end in a newline."
            },
            {
              name = "level",
              type = "string",
              description = "The log level (`debug`, `info`, `warn`, or `error`)."
            },
            {
              name = "tag",
              type = "string",
              description = "The log tag."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "mirror",
      tag = "callbacks",
      summary = "Called to render content to the desktop window.",
      description = "This callback is called every frame after rendering to the headset and is usually used to render a mirror of the headset display onto the desktop window.  It can be overridden for custom mirroring behavior.  For example, a stereo view could be drawn instead of a single eye or a 2D HUD could be rendered.",
      key = "lovr.mirror",
      module = "lovr",
      examples = {
        {
          description = "The default `lovr.mirror` implementation draws the headset mirror texture to the window if the headset is active, or just calls `lovr.draw` if there isn't a headset.",
          code = "function lovr.mirror(pass)\n  if lovr.headset then\n    local texture = lovr.headset.getTexture()\n    if texture then\n      pass:fill(texture)\n    else\n      return true\n    end\n  else\n    return lovr.draw and lovr.draw(pass)\n  end\nend"
        }
      },
      related = {
        "lovr.system.openWindow",
        "lovr.draw"
      },
      variants = {
        {
          arguments = {
            {
              name = "pass",
              type = "Pass",
              description = "A render pass targeting the window."
            }
          },
          returns = {
            {
              name = "skip",
              type = "boolean",
              description = "If truthy, the input Pass will not be submitted to the GPU."
            }
          }
        }
      }
    },
    {
      name = "mount",
      tag = "callbacks",
      summary = "Called when the headset is put on or taken off.",
      description = "The `lovr.mount` callback is called when the headset is put on or taken off.",
      key = "lovr.mount",
      module = "lovr",
      related = {
        "lovr.headset.isMounted"
      },
      variants = {
        {
          arguments = {
            {
              name = "mounted",
              type = "boolean",
              description = "Whether the headset is mounted."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "mousemoved",
      tag = "callbacks",
      summary = "Called when the mouse is moved.",
      description = "This callback is called when the mouse is moved.",
      key = "lovr.mousemoved",
      module = "lovr",
      related = {
        "lovr.mousepressed",
        "lovr.mousereleased",
        "lovr.wheelmoved",
        "lovr.system.getMouseX",
        "lovr.system.getMouseY",
        "lovr.system.getMousePosition"
      },
      variants = {
        {
          arguments = {
            {
              name = "x",
              type = "number",
              description = "The new x position of the mouse."
            },
            {
              name = "y",
              type = "number",
              description = "The new y position of the mouse."
            },
            {
              name = "dx",
              type = "number",
              description = "The movement on the x axis since the last mousemove event."
            },
            {
              name = "dy",
              type = "number",
              description = "The movement on the y axis since the last mousemove event."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "mousepressed",
      tag = "callbacks",
      summary = "Called when a mouse button is pressed.",
      description = "This callback is called when a mouse button is pressed.",
      key = "lovr.mousepressed",
      module = "lovr",
      related = {
        "lovr.mousereleased",
        "lovr.mousemoved",
        "lovr.wheelmoved",
        "lovr.system.isMouseDown"
      },
      variants = {
        {
          arguments = {
            {
              name = "x",
              type = "number",
              description = "The x position of the mouse when the button was pressed."
            },
            {
              name = "y",
              type = "number",
              description = "The y position of the mouse when the button was pressed."
            },
            {
              name = "button",
              type = "number",
              description = "The button that was pressed.  Will be 1 for the primary button, 2 for the secondary button, or 3 for the middle mouse button."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "mousereleased",
      tag = "callbacks",
      summary = "Called when a mouse button is released.",
      description = "This callback is called when a mouse button is released.",
      key = "lovr.mousereleased",
      module = "lovr",
      related = {
        "lovr.mousepressed",
        "lovr.mousemoved",
        "lovr.wheelmoved",
        "lovr.system.isMouseDown"
      },
      variants = {
        {
          arguments = {
            {
              name = "x",
              type = "number",
              description = "The x position of the mouse when the button was released."
            },
            {
              name = "y",
              type = "number",
              description = "The y position of the mouse when the button was released."
            },
            {
              name = "button",
              type = "number",
              description = "The button that was released.  Will be 1 for the primary button, 2 for the secondary button, or 3 for the middle mouse button."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "permission",
      tag = "callbacks",
      summary = "Called when a permission request is answered.",
      description = "This callback contains a permission response previously requested with `lovr.system.requestPermission`.  The callback contains information on whether permission was granted or denied.",
      key = "lovr.permission",
      module = "lovr",
      related = {
        "lovr.system.requestPermission"
      },
      variants = {
        {
          arguments = {
            {
              name = "permission",
              type = "Permission",
              description = "The type of permission."
            },
            {
              name = "granted",
              type = "boolean",
              description = "Whether permission was granted or denied."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "quit",
      tag = "callbacks",
      summary = "Called before quitting.",
      description = "This callback is called right before the application is about to quit.  Use it to perform any necessary cleanup work.  A truthy value can be returned from this callback to abort quitting.",
      key = "lovr.quit",
      module = "lovr",
      examples = {
        {
          code = "function lovr.quit()\n  if shouldQuit() then\n    return false\n  else\n    return true\n  end\nend"
        }
      },
      related = {
        "lovr.event.quit",
        "lovr.load"
      },
      variants = {
        {
          arguments = {},
          returns = {
            {
              name = "abort",
              type = "boolean",
              description = "Whether quitting should be aborted."
            }
          }
        }
      }
    },
    {
      name = "recenter",
      tag = "callbacks",
      summary = "Called when the user recenters the coordinate space.",
      description = "The `lovr.recenter` callback is called whenever the user performs a \"recenter\" gesture to realign the virtual coordinate space.  On most VR systems this will move the origin to the user's current position and rotate its yaw to match the view direction.  The y=0 position will always be on the floor or at eye level, depending on whether `t.headset.seated` was set in `lovr.conf`.",
      key = "lovr.recenter",
      module = "lovr",
      notes = "Note that the pose of the `floor` device will not always be at the origin of the coordinate space.  It uses a fixed position on the floor in the real world, usually the center of the configured play area.  This allows virtual objects to be positioned in a room without having them jump around after a recenter.",
      related = {
        "lovr.headset.getBoundsWidth",
        "lovr.headset.getBoundsDepth",
        "lovr.headset.getBoundsDimensions",
        "lovr.headset.getBoundsGeometry",
        "lovr.headset.isSeated"
      },
      variants = {
        {
          arguments = {},
          returns = {}
        }
      }
    },
    {
      name = "resize",
      tag = "callbacks",
      summary = "Called when the window is resized.",
      description = "This callback is called when the desktop window is resized.",
      key = "lovr.resize",
      module = "lovr",
      related = {
        "Pass:getDimensions",
        "Pass:getWidth",
        "Pass:getHeight",
        "lovr.headset.getDisplayDimensions",
        "lovr.conf"
      },
      variants = {
        {
          arguments = {
            {
              name = "width",
              type = "number",
              description = "The new width of the window."
            },
            {
              name = "height",
              type = "number",
              description = "The new height of the window."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "restart",
      tag = "callbacks",
      summary = "Called when restarting.",
      description = "This callback is called when a restart from `lovr.event.restart` is happening.  A value can be returned to send it to the next LÖVR instance, available as the `restart` key in the argument table passed to `lovr.load`.  Object instances can not be used as the restart value, since they are destroyed as part of the cleanup process.",
      key = "lovr.restart",
      module = "lovr",
      examples = {
        {
          code = "function lovr.restart()\n  return currentLevel:getName()\nend"
        }
      },
      notes = "Only nil, booleans, numbers, and strings are supported types for the return value.",
      related = {
        "lovr.event.restart",
        "lovr.load",
        "lovr.quit"
      },
      variants = {
        {
          arguments = {},
          returns = {
            {
              name = "cookie",
              type = "*",
              description = "The value to send to the next `lovr.load`."
            }
          }
        }
      }
    },
    {
      name = "run",
      tag = "callbacks",
      summary = "The main entry point.",
      description = "This callback is the main entry point for a LÖVR program.  It calls `lovr.load` and returns a function that will be called every frame.",
      key = "lovr.run",
      module = "lovr",
      examples = {
        {
          description = "The default `lovr.run`:",
          code = "function lovr.run()\n  if lovr.timer then lovr.timer.step() end\n  if lovr.load then lovr.load(arg) end\n  return function()\n    if lovr.system then lovr.system.pollEvents() end\n    if lovr.event then\n      for name, a, b, c, d in lovr.event.poll() do\n        if name == 'restart' then return 'restart', lovr.restart and lovr.restart()\n        elseif name == 'quit' and (not lovr.quit or not lovr.quit(a)) then return a or 0\n        elseif name ~= 'quit' and lovr.handlers[name] then lovr.handlers[name](a, b, c, d) end\n      end\n    end\n    local dt = 0\n    if lovr.timer then dt = lovr.timer.step() end\n    if lovr.headset and lovr.headset.isActive() then dt = lovr.headset.update() end\n    if lovr.update then lovr.update(dt) end\n    if lovr.graphics then\n      local headset = lovr.headset and lovr.headset.getPass()\n      if headset and (not lovr.draw or lovr.draw(headset)) then headset = nil end\n      local window = lovr.graphics.getWindowPass()\n      if window and (not lovr.mirror or lovr.mirror(window)) then window = nil end\n      lovr.graphics.submit(headset, window)\n      lovr.graphics.present()\n    end\n    if lovr.headset then lovr.headset.submit() end\n    if lovr.math then lovr.math.drain() end\n  end\nend"
        }
      },
      notes = "The main loop function can return one of the following values:\n\n- Returning `nil` will keep the main loop running.\n- Returning the string 'restart' plus an optional value will restart LÖVR.  The value can be\n  accessed in the `restart` key of the `arg` global.\n- Returning a number will exit LÖVR using the number as the exit code (0 means success).\n\nCare should be taken when overriding this callback.  For example, if the main loop does not call `lovr.system.pollEvents` then the OS will think LÖVR is unresponsive, or if the quit event is not handled then closing the window won't work.",
      related = {
        "lovr.load",
        "lovr.quit"
      },
      variants = {
        {
          arguments = {},
          returns = {
            {
              name = "loop",
              type = "function",
              description = "The main loop function.",
              arguments = {},
              returns = {
                {
                  name = "result",
                  type = "*"
                }
              }
            }
          }
        }
      }
    },
    {
      name = "textinput",
      tag = "callbacks",
      summary = "Called when text has been entered.",
      description = "This callback is called when text has been entered.\n\nFor example, when `shift + 1` is pressed on an American keyboard, `lovr.textinput` will be called with `!`.",
      key = "lovr.textinput",
      module = "lovr",
      notes = "Some characters in UTF-8 unicode take multiple bytes to encode.  Due to the way Lua works, the length of these strings will be bigger than 1 even though they are just a single character.  The `utf8` library included with LÖVR can be used to manipulate UTF-8 strings.  `Pass:text` will also correctly handle UTF-8.",
      related = {
        "lovr.keypressed",
        "lovr.keyreleased"
      },
      variants = {
        {
          arguments = {
            {
              name = "text",
              type = "string",
              description = "The UTF-8 encoded character."
            },
            {
              name = "code",
              type = "number",
              description = "The integer codepoint of the character."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "threaderror",
      tag = "callbacks",
      summary = "Called when an error occurs in a thread.",
      description = "The `lovr.threaderror` callback is called whenever an error occurs in a Thread.  It receives the Thread object where the error occurred and an error message.\n\nThe default implementation of this callback will call `lovr.errhand` with the error.",
      key = "lovr.threaderror",
      module = "lovr",
      related = {
        "Thread",
        "Thread:getError",
        "lovr.errhand"
      },
      variants = {
        {
          arguments = {
            {
              name = "thread",
              type = "Thread",
              description = "The Thread that errored."
            },
            {
              name = "message",
              type = "string",
              description = "The error message."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "update",
      tag = "callbacks",
      summary = "Called every frame to update the application logic.",
      description = "The `lovr.update` callback should be used to update your game's logic.  It receives a single parameter, `dt`, which represents the amount of elapsed time between frames.  You can use this value to scale timers, physics, and animations in your game so they play at a smooth, consistent speed.",
      key = "lovr.update",
      module = "lovr",
      examples = {
        {
          code = "function lovr.update(dt)\n  ball.vy = ball.vy + ball.gravity * dt\n  ball.y = ball.y + ball.vy * dt\nend"
        }
      },
      related = {
        "lovr.timer.getDelta"
      },
      variants = {
        {
          arguments = {
            {
              name = "dt",
              type = "number",
              description = "The number of seconds elapsed since the last update."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "visible",
      tag = "callbacks",
      summary = "Called when the application gains or loses visibility.",
      description = "The `lovr.visible` callback is called whenever the application becomes visible or invisible. `lovr.draw` may still be called even while invisible to give the VR runtime timing info.  If the VR runtime decides the application doesn't need to render anymore, LÖVR will detect this and stop calling `lovr.draw`.\n\nThis event is also fired when the desktop window is minimized or restored.  It's possible to distinguish between the headset and window using the `display` parameter.",
      key = "lovr.visible",
      module = "lovr",
      related = {
        "lovr.headset.isVisible",
        "lovr.focus"
      },
      variants = {
        {
          arguments = {
            {
              name = "visible",
              type = "boolean",
              description = "Whether the application is visible."
            },
            {
              name = "display",
              type = "DisplayType",
              description = "Whether the headset or desktop window changed visibility."
            }
          },
          returns = {}
        }
      }
    },
    {
      name = "wheelmoved",
      tag = "callbacks",
      summary = "Called when a mouse wheel is moved.",
      description = "This callback is called on scroll action, from a mouse wheel or a touchpad",
      key = "lovr.wheelmoved",
      module = "lovr",
      related = {
        "lovr.mousepressed",
        "lovr.mousereleased",
        "lovr.mousemoved",
        "lovr.system.isMouseDown"
      },
      variants = {
        {
          arguments = {
            {
              name = "dx",
              type = "number",
              description = "The relative horizontal motion; rightward movement resuts in positive values."
            },
            {
              name = "dy",
              type = "number",
              description = "The relative vertical motion; upward movement results in positive values."
            }
          },
          returns = {}
        }
      }
    }
  },
  modules = {
    {
      name = "enet",
      tag = "libraries",
      summary = "UDP networking library.",
      description = "ENet is a UDP networking plugin bundled with LÖVR that can be used for networking and multiplayer experiences.  ENet allows messages to be marked for reliable and in-order delivery, allowing the speed of UDP to be used without sacrificing reliability.\n\nThe full documentation and examples can be found on the [lua-enet](http://leafo.net/lua-enet/) page.  LÖVE also has lua-enet documentation [here](https://love2d.org/wiki/lua-enet).",
      key = "enet",
      enums = {},
      examples = {
        {
          description = "Here's a simple echo server example. The client sends a message to the server and waits for a response. The server waits for a message and sends it back to the client.",
          code = "-- client/main.lua\nlocal enet = require 'enet'\n\nfunction lovr.load()\n  local host = enet.host_create()\n  local server = host:connect('localhost:6789')\n\n  local done = false\n  while not done do\n    local event = host:service(100)\n    if event then\n      if event.type == 'connect' then\n        print('Connected to', event.peer)\n        event.peer:send('hello world')\n      elseif event.type == 'receive' then\n        print('Got message: ', event.data, event.peer)\n        done = true\n      end\n    end\n  end\n\n  server:disconnect()\n  host:flush()\nend\n\n-- server/main.lua\nlocal enet = require 'enet'\n\nfunction lovr.load()\n  local host = enet.host_create('localhost:6789')\n  while true do\n    local event = host:service(100)\n    if event and event.type == 'receive' then\n      print('Got message: ', event.data, event.peer)\n      event.peer:send(event.data)\n    end\n  end\nend"
        }
      },
      external = true,
      functions = {},
      objects = {}
    },
    {
      name = "http",
      tag = "libraries",
      summary = "HTTP(S) requests.",
      description = "The [lovr-http](https://github.com/bjornbytes/lovr-http) plugin performs HTTP requests.\n\nFirst, `require` the plugin and save it into a variable: `local http = require 'http'`.\n\nThe module has one function:\n\n    status, data, headers = http.request(url, [options])\n\nThis will perform an HTTP request and block until the request is complete.\n\n### Arguments\n\n`url` is the URL to request.  If it doesn't have a protocol, then `http://` will be added.\n\n`options` is optional, and is used for advanced request settings.\n\n`options.method` is the HTTP method to use, also called the verb.  `GET` is used by default if there's no data in the request, otherwise it defauls to `POST`.  It will be converted to all-caps.\n\n`options.data` is the data to send to the server, also called the body.  It can be a few different types:\n\n- When `data` is nil, no request body will be sent (and `method` will default to `GET`).\n- When `data` is a string, the string will be used directly as the request body.\n- When `data` is a table, then pairs in the table will be URL encoded and concatenated together\n  to form an `application/x-www-form-urlencoded` body.  For example, if data is\n  `{ n = 10, k = 'v!' }`, then the request body will be something like `k=v%21&n=10`. Table\n  pairs will only be used if the key is a string and the value is a string or number.\n- When `data` is a lightuserdata, the data pointed to by the lightuserdata will be used as the\n  request body. Additionally, the `datasize` option should be an integer indicating how big the\n  request body is, in bytes.\n\nWhen `options.data` is set, the `Content-Type` request header will default to `application/x-www-urlencoded` unless it's set to something else.\n\n`options.headers` is a table of request headers to send to the server.  Pairs in the table will only be used if the key is a string and the value is a string or number.\n\n### Returns\n\nIf an error occurs, the function returns `nil, errormessage`.\n\nOtherwise, 3 values are returned:\n\n- `status` is an integer with the HTTP status code (200 is OK, 404 is Not Found, etc.).\n- `data` is a string with the data sent by the server (HTML, JSON, binary, etc.).\n- `headers` is a table of response headers.",
      key = "http",
      enums = {},
      examples = {
        {
          code = "local http = require 'http'\n\nlocal status, data, headers = http.request('https://zombo.com')\n\nprint('welcome')\nprint(status)\nprint(data)\nprint('headers:')\nfor k, v in pairs(headers) do\n  print('\\t' .. k, v)\nend"
        }
      },
      external = true,
      functions = {},
      notes = "On Linux, this module requires the `curl` library to be installed.  Example on Debian-based distributions:\n\n    sudo apt install libcurl4",
      objects = {}
    },
    {
      name = "lovr",
      summary = "In the beginning, there was nothing.",
      description = "`lovr` is the single global table that is exposed to every LÖVR app. It contains a set of **modules** and a set of **callbacks**.",
      key = "lovr",
      enums = {},
      functions = {
        {
          name = "getVersion",
          tag = "version",
          summary = "Get the current version.",
          description = "Get the current major, minor, and patch version of LÖVR.",
          key = "lovr.getVersion",
          module = "lovr",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "major",
                  type = "number",
                  description = "The major version."
                },
                {
                  name = "minor",
                  type = "number",
                  description = "The minor version."
                },
                {
                  name = "patch",
                  type = "number",
                  description = "The patch number."
                },
                {
                  name = "codename",
                  type = "string",
                  description = "The version codename."
                },
                {
                  name = "commit",
                  type = "string",
                  description = "The commit hash (not available in all builds)."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Object",
          summary = "The base object.",
          description = "The superclass of all LÖVR objects.  All objects have these methods.",
          key = "Object",
          module = "lovr",
          methods = {
            {
              name = "release",
              summary = "Immediately release the Lua reference to an object.",
              description = "Immediately destroys Lua's reference to the object it's called on.  After calling this function on an object, it is an error to do anything with the object from Lua (call methods on it, pass it to other functions, etc.).  If nothing else is using the object, it will be destroyed immediately, which can be used to destroy something earlier than it would normally be garbage collected in order to reduce memory.",
              key = "Object:release",
              module = "lovr",
              notes = "The object may not be destroyed immediately if something else is referring to it (e.g. it is pushed to a Channel or exists in the payload of a pending event).",
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "type",
              summary = "Get the type name of the object.",
              description = "Returns the name of the object's type as a string.",
              key = "Object:type",
              module = "lovr",
              examples = {
                {
                  code = "function isTexture(obj)\n  return type(obj) == 'userdata' and obj:type() == 'Texture'\nend"
                }
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "type",
                      type = "string",
                      description = "The type of the object."
                    }
                  }
                }
              }
            }
          },
          notes = "Note that the functions here don't apply to any vector objects, see `Vectors`."
        }
      },
      sections = {
        {
          name = "Modules",
          tag = "modules",
          description = "Modules are the **what** of your app; you can use the functions in modules to tell LÖVR to do things. For example, you can draw things on the screen, figure out what buttons on a controller are pressed, or load a 3D model from a file.  Each module does what it says on the tin, so the `lovr.graphics` module deals with rendering graphics and `lovr.headset` allows you to interact with VR hardware."
        },
        {
          name = "Callbacks",
          tag = "callbacks",
          description = "Callbacks are the **when** of the application; you write code inside callbacks which LÖVR then calls at certain points in time.  For example, the `lovr.load` callback is called once at startup, and `lovr.focus` is called when the VR application gains or loses input focus."
        },
        {
          name = "Version",
          tag = "version",
          description = "This function returns the current version of LÖVR."
        },
        {
          name = "Libraries",
          tag = "libraries",
          description = "LÖVR bundles a few third-party modules by default."
        }
      }
    },
    {
      name = "audio",
      tag = "modules",
      summary = "Plays sound.",
      description = "The `lovr.audio` module is responsible for playing sound effects and music.  To play a sound, create a `Source` object and call `Source:play` on it.  Currently ogg, wav, and mp3 audio formats are supported.",
      key = "lovr.audio",
      enums = {
        {
          name = "AudioMaterial",
          summary = "Different types of audio materials.",
          description = "Different types of audio material presets, for use with `lovr.audio.setGeometry`.",
          key = "AudioMaterial",
          module = "lovr.audio",
          values = {
            {
              name = "generic",
              description = "Generic default audio material."
            },
            {
              name = "brick",
              description = "Brick."
            },
            {
              name = "carpet",
              description = "Carpet."
            },
            {
              name = "ceramic",
              description = "Ceramic."
            },
            {
              name = "concrete",
              description = "Concrete."
            },
            {
              name = "glass",
              description = "Glass."
            },
            {
              name = "gravel",
              description = "Gravel."
            },
            {
              name = "metal",
              description = "Metal."
            },
            {
              name = "plaster",
              description = "Plaster."
            },
            {
              name = "rock",
              description = "Rock."
            },
            {
              name = "wood",
              description = "Wood."
            }
          }
        },
        {
          name = "AudioShareMode",
          summary = "How audio devices are shared on the system.",
          description = "Audio devices can be created in shared mode or exclusive mode.  In exclusive mode, the audio device is the only one active on the system, which gives better performance and lower latency. However, exclusive devices aren't always supported and might not be allowed, so there is a higher chance that creating one will fail.",
          key = "AudioShareMode",
          module = "lovr.audio",
          related = {
            "lovr.audio.setDevice"
          },
          values = {
            {
              name = "shared",
              description = "Shared mode."
            },
            {
              name = "exclusive",
              description = "Exclusive mode."
            }
          }
        },
        {
          name = "AudioType",
          summary = "Different types of audio devices",
          description = "When referencing audio devices, this indicates whether it's the playback or capture device.",
          key = "AudioType",
          module = "lovr.audio",
          related = {
            "lovr.audio.getDevices",
            "lovr.audio.setDevice",
            "lovr.audio.start",
            "lovr.audio.stop",
            "lovr.audio.isStarted"
          },
          values = {
            {
              name = "playback",
              description = "The playback device (speakers, headphones)."
            },
            {
              name = "capture",
              description = "The capture device (microphone)."
            }
          }
        },
        {
          name = "Effect",
          summary = "Different types of Source effects.",
          description = "Different types of effects that can be applied with `Source:setEffectEnabled`.",
          key = "Effect",
          module = "lovr.audio",
          notes = "The active spatializer will determine which effects are supported.  If an unsupported effect is enabled on a Source, no error will be reported.  Instead, it will be silently ignored.\n\nSee `lovr.audio.getSpatializer` for a table of the supported effects for each spatializer.",
          values = {
            {
              name = "absorption",
              description = "Models absorption as sound travels through the air, water, etc."
            },
            {
              name = "attenuation",
              description = "Decreases audio volume with distance (1 / max(distance, 1))."
            },
            {
              name = "occlusion",
              description = "Causes audio to drop off when the Source is occluded by geometry."
            },
            {
              name = "reverb",
              description = "Models reverb caused by audio bouncing off of geometry."
            },
            {
              name = "spatialization",
              description = "Spatializes the Source using either simple panning or an HRTF."
            },
            {
              name = "transmission",
              description = "Causes audio to be heard through walls when occluded, based on audio materials."
            }
          }
        },
        {
          name = "TimeUnit",
          summary = "Time units for sound samples.",
          description = "When figuring out how long a Source is or seeking to a specific position in the sound file, units can be expressed in terms of seconds or in terms of frames.  A frame is one set of samples for each channel (one sample for mono, two samples for stereo).",
          key = "TimeUnit",
          module = "lovr.audio",
          values = {
            {
              name = "seconds",
              description = "Seconds."
            },
            {
              name = "frames",
              description = "Frames."
            }
          }
        },
        {
          name = "VolumeUnit",
          summary = "Different units of volume.",
          description = "When accessing the volume of Sources or the audio listener, this can be done in linear units with a 0 to 1 range, or in decibels with a range of -∞ to 0.",
          key = "VolumeUnit",
          module = "lovr.audio",
          values = {
            {
              name = "linear",
              description = "Linear volume range."
            },
            {
              name = "db",
              description = "Decibels."
            }
          }
        }
      },
      functions = {
        {
          name = "getAbsorption",
          tag = "listener",
          summary = "Get the absorption coefficients.",
          description = "Returns the global air absorption coefficients for the medium.  This affects Sources that have the `absorption` effect enabled, causing audio volume to drop off with distance as it is absorbed by the medium it's traveling through (air, water, etc.).  The difference between absorption and the attenuation effect is that absorption is more subtle and is frequency-dependent, so higher-frequency bands can get absorbed more quickly than lower ones. This can be used to apply \"underwater\" effects and stuff.",
          key = "lovr.audio.getAbsorption",
          module = "lovr.audio",
          notes = "Absorption is currently only supported by the phonon spatializer.\n\nThe frequency bands correspond to `400Hz`, `2.5KHz`, and `15KHz`.\n\nThe default coefficients are `.0002`, `.0017`, and `.0182` for low, mid, and high.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "low",
                  type = "number",
                  description = "The absorption coefficient for the low frequency band."
                },
                {
                  name = "mid",
                  type = "number",
                  description = "The absorption coefficient for the mid frequency band."
                },
                {
                  name = "high",
                  type = "number",
                  description = "The absorption coefficient for the high frequency band."
                }
              }
            }
          }
        },
        {
          name = "getDevice",
          tag = "devices",
          summary = "Get the current audio device.",
          description = "Returns information about the active playback or capture device.",
          key = "lovr.audio.getDevice",
          module = "lovr.audio",
          notes = "If no device has been set yet, this function returns `nil`.\n\nThe device doesn't need to be started.",
          related = {
            "lovr.audio.getDevices",
            "lovr.audio.setDevice"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The type of device to query.",
                  default = "'playback'"
                }
              },
              returns = {
                {
                  name = "name",
                  type = "string | nil",
                  description = "The name of the device, or `nil` if no device is set."
                },
                {
                  name = "id",
                  type = "userdata | nil",
                  description = "The opaque id of the device, or `nil` if no device is set."
                }
              }
            }
          }
        },
        {
          name = "getDevices",
          tag = "devices",
          summary = "Get a list of audio devices.",
          description = "Returns a list of playback or capture devices.  Each device has an `id`, `name`, and a `default` flag indicating whether it's the default device.\n\nTo use a specific device id for playback or capture, pass it to `lovr.audio.setDevice`.",
          key = "lovr.audio.getDevices",
          module = "lovr.audio",
          related = {
            "lovr.audio.setDevice",
            "lovr.audio.getDevice",
            "lovr.audio.start",
            "lovr.audio.stop"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The type of devices to query (playback or capture).",
                  default = "'playback'"
                }
              },
              returns = {
                {
                  name = "devices",
                  type = "table",
                  description = "The list of devices.",
                  table = {
                    {
                      name = "[].id",
                      type = "userdata",
                      description = "A unique, opaque id for the device."
                    },
                    {
                      name = "[].name",
                      type = "string",
                      description = "A human readable name for the device."
                    },
                    {
                      name = "[].default",
                      type = "boolean",
                      description = "Whether the device is the default audio device."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "getOrientation",
          tag = "listener",
          summary = "Get the orientation of the listener.",
          description = "Returns the orientation of the virtual audio listener in angle/axis representation.",
          key = "lovr.audio.getOrientation",
          module = "lovr.audio",
          related = {
            "lovr.audio.getPosition",
            "lovr.audio.getPose",
            "Source:getOrientation"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "angle",
                  type = "number",
                  description = "The number of radians the listener is rotated around its axis of rotation."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              }
            }
          }
        },
        {
          name = "getPose",
          tag = "listener",
          summary = "Get the pose of the listener.",
          description = "Returns the position and orientation of the virtual audio listener.",
          key = "lovr.audio.getPose",
          module = "lovr.audio",
          related = {
            "lovr.audio.getPosition",
            "lovr.audio.getOrientation",
            "Source:getPose"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the listener, in meters."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the listener, in meters."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the listener, in meters."
                },
                {
                  name = "angle",
                  type = "number",
                  description = "The number of radians the listener is rotated around its axis of rotation."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              }
            }
          }
        },
        {
          name = "getPosition",
          tag = "listener",
          summary = "Get the position of the listener.",
          description = "Returns the position of the virtual audio listener, in meters.",
          key = "lovr.audio.getPosition",
          module = "lovr.audio",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the listener."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the listener."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the listener."
                }
              }
            }
          }
        },
        {
          name = "getSampleRate",
          tag = "devices",
          summary = "Get the playback device sample rate.",
          description = "Returns the sample rate used by the playback device.  This can be changed using `lovr.conf`.",
          key = "lovr.audio.getSampleRate",
          module = "lovr.audio",
          related = {
            "lovr.conf"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "rate",
                  type = "number",
                  description = "The sample rate of the playback device, in Hz."
                }
              }
            }
          }
        },
        {
          name = "getSpatializer",
          tag = "listener",
          summary = "Get the name of the active spatializer",
          description = "Returns the name of the active spatializer (`simple`, `oculus`, or `phonon`).\n\nThe `t.audio.spatializer` setting in `lovr.conf` can be used to express a preference for a particular spatializer.  If it's `nil`, all spatializers will be tried in the following order: `phonon`, `oculus`, `simple`.",
          key = "lovr.audio.getSpatializer",
          module = "lovr.audio",
          notes = "Using a feature or effect that is not supported by the current spatializer will not error, it just won't do anything.\n\n<table>\n  <thead>\n    <tr>\n      <td>Feature</td>\n      <td>simple</td>\n      <td>phonon</td>\n      <td>oculus</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td>Effect: Spatialization</td>\n      <td>x</td>\n      <td>x</td>\n      <td>x</td>\n    </tr>\n    <tr>\n      <td>Effect: Attenuation</td>\n      <td>x</td>\n      <td>x</td>\n      <td>x</td>\n    </tr>\n    <tr>\n      <td>Effect: Absorption</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>Effect: Occlusion</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>Effect: Transmission</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>Effect: Reverb</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>lovr.audio.setGeometry</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>Source:setDirectivity</td>\n      <td>x</td>\n      <td>x</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td>Source:setRadius</td>\n      <td></td>\n      <td>x</td>\n      <td></td>\n    </tr>\n  </tbody> </table>",
          related = {
            "lovr.conf"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "spatializer",
                  type = "string",
                  description = "The name of the active spatializer."
                }
              }
            }
          }
        },
        {
          name = "getVolume",
          tag = "listener",
          summary = "Get the master volume.",
          description = "Returns the master volume.  All audio sent to the playback device has its volume multiplied by this factor.",
          key = "lovr.audio.getVolume",
          module = "lovr.audio",
          notes = "The default volume is 1.0 (0 dB).",
          variants = {
            {
              arguments = {
                {
                  name = "units",
                  type = "VolumeUnit",
                  description = "The units to return (linear or db).",
                  default = "'linear'"
                }
              },
              returns = {
                {
                  name = "volume",
                  type = "number",
                  description = "The master volume."
                }
              }
            }
          }
        },
        {
          name = "isStarted",
          tag = "devices",
          summary = "Check if an audio device is started.",
          description = "Returns whether an audio device is started.",
          key = "lovr.audio.isStarted",
          module = "lovr.audio",
          related = {
            "lovr.audio.start",
            "lovr.audio.stop"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The type of device to check.",
                  default = "'playback'"
                }
              },
              returns = {
                {
                  name = "started",
                  type = "boolean",
                  description = "Whether the device is active."
                }
              }
            }
          }
        },
        {
          name = "newSource",
          tag = "sources",
          summary = "Create a new Source.",
          description = "Creates a new Source from an ogg, wav, or mp3 file.",
          key = "lovr.audio.newSource",
          module = "lovr.audio",
          examples = {
            {
              code = "function lovr.load()\n  sandstorm = lovr.audio.newSource('darude.ogg', {\n    decode = false,\n    effects = { 'spatialization', attenuation = false, reverb = true }\n  })\n\n  sandstorm:play()\nend"
            }
          },
          related = {
            "Source:clone"
          },
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing audio data to load."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Optional options.",
                  default = "nil",
                  table = {
                    {
                      name = "decode",
                      type = "boolean",
                      description = "Whether to immediately decode compressed sounds, instead of progressively decoding as the Source plays.  Enabling this will use more memory but reduce CPU overhead during playback.  Recommended for short sound effects.",
                      default = "false"
                    },
                    {
                      name = "pitchable",
                      type = "boolean",
                      description = "Whether the pitch of the Source can be changed with `Source:setPitch`.  Setting this to false will improve performance slightly.",
                      default = "true"
                    },
                    {
                      name = "spatial",
                      type = "boolean",
                      description = "Whether the Source should use spatial effects.  Non-spatial sources will get routed directly to the speakers without further processing.  Enabling an effect on a non-spatial source will raise an error.",
                      default = "true"
                    },
                    {
                      name = "effects",
                      type = "table",
                      description = "A table of `Effect`s to enable on the Source.  This can be a list (numeric keys, effect name values) or a map (effect name keys, boolean values) or a mix of the two.  Effects can also be enabled later using `Source:setEffectEnabled`.  If nil, all effects will be enabled.  Ignored if the `spatial` flag is false.",
                      default = "nil"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "source",
                  type = "Source",
                  description = "The new Source."
                }
              }
            },
            {
              arguments = {
                {
                  name = "sound",
                  type = "Sound",
                  description = "The Sound containing raw audio samples to play."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Optional options.",
                  default = "nil",
                  table = {
                    {
                      name = "decode",
                      type = "boolean",
                      description = "Whether to immediately decode compressed sounds, instead of progressively decoding as the Source plays.  Enabling this will use more memory but reduce CPU overhead during playback.  Recommended for short sound effects.",
                      default = "false"
                    },
                    {
                      name = "pitchable",
                      type = "boolean",
                      description = "Whether the pitch of the Source can be changed with `Source:setPitch`.  Setting this to false will improve performance slightly.",
                      default = "true"
                    },
                    {
                      name = "spatial",
                      type = "boolean",
                      description = "Whether the Source should use spatial effects.  Non-spatial sources will get routed directly to the speakers without further processing.  Enabling an effect on a non-spatial source will raise an error.",
                      default = "true"
                    },
                    {
                      name = "effects",
                      type = "table",
                      description = "A table of `Effect`s to enable on the Source.  This can be a list (numeric keys, effect name values) or a map (effect name keys, boolean values) or a mix of the two.  Effects can also be enabled later using `Source:setEffectEnabled`.  If nil, all effects will be enabled.  Ignored if the `spatial` flag is false.",
                      default = "nil"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "source",
                  type = "Source",
                  description = "The new Source."
                }
              }
            }
          }
        },
        {
          name = "setAbsorption",
          tag = "listener",
          summary = "Set the absorption coefficients.",
          description = "Sets the global air absorption coefficients for the medium.  This affects Sources that have the `absorption` effect enabled, causing audio volume to drop off with distance as it is absorbed by the medium it's traveling through (air, water, etc.).  The difference between absorption and the attenuation effect is that absorption is more subtle and is frequency-dependent, so higher-frequency bands can get absorbed more quickly than lower ones.  This can be used to apply \"underwater\" effects and stuff.",
          key = "lovr.audio.setAbsorption",
          module = "lovr.audio",
          notes = "Absorption is currently only supported by the phonon spatializer.\n\nThe frequency bands correspond to `400Hz`, `2.5KHz`, and `15KHz`.\n\nThe default coefficients are `.0002`, `.0017`, and `.0182` for low, mid, and high.",
          variants = {
            {
              arguments = {
                {
                  name = "low",
                  type = "number",
                  description = "The absorption coefficient for the low frequency band."
                },
                {
                  name = "mid",
                  type = "number",
                  description = "The absorption coefficient for the mid frequency band."
                },
                {
                  name = "high",
                  type = "number",
                  description = "The absorption coefficient for the high frequency band."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setDevice",
          tag = "devices",
          summary = "Switch audio devices.",
          description = "Switches either the playback or capture device to a new one.\n\nIf a device for the given type is already active, it will be stopped and destroyed.  The new device will not be started automatically, use `lovr.audio.start` to start it.\n\nA device id (previously retrieved using `lovr.audio.getDevices`) can be given to use a specific audio device, or `nil` can be used for the id to use the default audio device.\n\nA sink can be also be provided when changing the device.  A sink is an audio stream (`Sound` object with a `stream` type) that will receive all audio samples played (for playback) or all audio samples captured (for capture).  When an audio device with a sink is started, be sure to periodically call `Sound:read` on the sink to read audio samples from it, otherwise it will overflow and discard old data.  The sink can have any format, data will be converted as needed. Using a sink for the playback device will reduce performance, but this isn't the case for capture devices.\n\nAudio devices can be started in `shared` or `exclusive` mode.  Exclusive devices may have lower latency than shared devices, but there's a higher chance that requesting exclusive access to an audio device will fail (either because it isn't supported or allowed).  One strategy is to first try the device in exclusive mode, switching to shared if it doesn't work.",
          key = "lovr.audio.setDevice",
          module = "lovr.audio",
          related = {
            "lovr.audio.getDevice",
            "lovr.audio.getDevices",
            "lovr.audio.start",
            "lovr.audio.stop"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The device to switch.",
                  default = "'playback'"
                },
                {
                  name = "id",
                  type = "userdata",
                  description = "The id of the device to use, or `nil` to use the default device.",
                  default = "nil"
                },
                {
                  name = "sink",
                  type = "Sound",
                  description = "An optional audio stream to use as a sink for the device.",
                  default = "nil"
                },
                {
                  name = "mode",
                  type = "AudioShareMode",
                  description = "The sharing mode for the device.",
                  default = "shared"
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether creating the audio device succeeded."
                }
              }
            }
          }
        },
        {
          name = "setGeometry",
          tag = "listener",
          summary = "Set the geometry for audio effects.",
          description = "Sets a mesh of triangles to use for modeling audio effects, using a table of vertices or a Model.  When the appropriate effects are enabled, audio from `Source` objects will correctly be occluded by walls and bounce around to create realistic reverb.\n\nAn optional `AudioMaterial` may be provided to specify the acoustic properties of the geometry.",
          key = "lovr.audio.setGeometry",
          module = "lovr.audio",
          notes = "This is currently only supported/used by the `phonon` spatializer.\n\nThe `Effect`s that use geometry are:\n\n- `occlusion`\n- `reverb`\n- `transmission`\n\nIf an existing geometry has been set, this function will replace it.\n\nThe triangles must use counterclockwise winding.",
          related = {
            "lovr.audio.getSpatializer",
            "Source:setEffectEnabled"
          },
          variants = {
            {
              arguments = {
                {
                  name = "vertices",
                  type = "table",
                  description = "A flat table of vertices.  Each vertex is 3 numbers representing its x, y, and z position. The units used for audio coordinates are up to you, but meters are recommended."
                },
                {
                  name = "indices",
                  type = "table",
                  description = "A list of indices, indicating how the vertices are connected into triangles.  Indices are 1-indexed and are 32 bits (they can be bigger than 65535)."
                },
                {
                  name = "material",
                  type = "AudioMaterial",
                  description = "The acoustic material to use.",
                  default = "'generic'"
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether audio geometry is supported by the current spatializer and the geometry was loaded successfully."
                }
              }
            },
            {
              arguments = {
                {
                  name = "model",
                  type = "Model",
                  description = "A model to use for the audio geometry."
                },
                {
                  name = "material",
                  type = "AudioMaterial",
                  description = "The acoustic material to use.",
                  default = "'generic'"
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether audio geometry is supported by the current spatializer and the geometry was loaded successfully."
                }
              }
            }
          }
        },
        {
          name = "setOrientation",
          tag = "listener",
          summary = "Set the orientation of the listener.",
          description = "Sets the orientation of the virtual audio listener in angle/axis representation.",
          key = "lovr.audio.setOrientation",
          module = "lovr.audio",
          related = {
            "lovr.audio.setPosition",
            "lovr.audio.setPose",
            "Source:setOrientation"
          },
          variants = {
            {
              description = "Set the listener orientation using numbers.",
              arguments = {
                {
                  name = "angle",
                  type = "number",
                  description = "The number of radians the listener should be rotated around its rotation axis."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              },
              returns = {}
            },
            {
              description = "Set the listener orientation using a vector.",
              arguments = {
                {
                  name = "orientation",
                  type = "Quat",
                  description = "The orientation of the listener."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setPose",
          tag = "listener",
          summary = "Set the pose of the listener.",
          description = "Sets the position and orientation of the virtual audio listener.",
          key = "lovr.audio.setPose",
          module = "lovr.audio",
          notes = "The position of the listener doesn't use any specific units, but usually they can be thought of as meters to match the headset module.",
          related = {
            "lovr.audio.setPosition",
            "lovr.audio.setOrientation",
            "Source:setPose"
          },
          variants = {
            {
              description = "Set the pose of the listener using numbers.",
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the listener."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the listener."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the listener."
                },
                {
                  name = "angle",
                  type = "number",
                  description = "The number of radians the listener is rotated around its axis of rotation."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              },
              returns = {}
            },
            {
              description = "Set the pose of the listener using vector types.",
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The position of the listener."
                },
                {
                  name = "orientation",
                  type = "Quat",
                  description = "The orientation of the listener."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setPosition",
          tag = "listener",
          summary = "Set the position of the listener.",
          description = "Sets the position of the virtual audio listener.  The position doesn't have any specific units, but usually they can be thought of as meters, to match the headset module.",
          key = "lovr.audio.setPosition",
          module = "lovr.audio",
          related = {
            "lovr.audio.setOrientation",
            "lovr.audio.setPose",
            "Source:setPosition"
          },
          variants = {
            {
              description = "Set the listener position using numbers.",
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the listener."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the listener."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the listener."
                }
              },
              returns = {}
            },
            {
              description = "Set the listener position using a vector.",
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The listener position."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setVolume",
          tag = "listener",
          summary = "Set the master volume.",
          description = "Sets the master volume.  All audio sent to the playback device has its volume multiplied by this factor.",
          key = "lovr.audio.setVolume",
          module = "lovr.audio",
          notes = "The volume will be clamped to a 0-1 range (0 dB).",
          variants = {
            {
              arguments = {
                {
                  name = "volume",
                  type = "number",
                  description = "The master volume."
                },
                {
                  name = "units",
                  type = "VolumeUnit",
                  description = "The units of the value.",
                  default = "'linear'"
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "start",
          tag = "devices",
          summary = "Start an audio device.",
          description = "Starts the active playback or capture device.  By default the playback device is initialized and started, but this can be controlled using the `t.audio.start` flag in `lovr.conf`.",
          key = "lovr.audio.start",
          module = "lovr.audio",
          notes = "Starting an audio device may fail if:\n\n- The device is already started\n- No device was initialized with `lovr.audio.setDevice`\n- Lack of `audiocapture` permission on Android (see `lovr.system.requestPermission`)\n- Some other problem accessing the audio device",
          related = {
            "lovr.audio.getDevices",
            "lovr.audio.setDevice",
            "lovr.audio.stop",
            "lovr.audio.isStarted",
            "lovr.system.requestPermission",
            "lovr.permission"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The type of device to start.",
                  default = "'playback'"
                }
              },
              returns = {
                {
                  name = "started",
                  type = "boolean",
                  description = "Whether the device was successfully started."
                }
              }
            }
          }
        },
        {
          name = "stop",
          tag = "devices",
          summary = "Stop an audio device.",
          description = "Stops the active playback or capture device.  This may fail if:\n\n- The device is not started\n- No device was initialized with `lovr.audio.setDevice`",
          key = "lovr.audio.stop",
          module = "lovr.audio",
          notes = "Switching devices with `lovr.audio.setDevice` will stop the existing one.",
          related = {
            "lovr.audio.getDevices",
            "lovr.audio.setDevice",
            "lovr.audio.start",
            "lovr.audio.isStarted"
          },
          variants = {
            {
              arguments = {
                {
                  name = "type",
                  type = "AudioType",
                  description = "The type of device to stop.",
                  default = "'playback'"
                }
              },
              returns = {
                {
                  name = "stopped",
                  type = "boolean",
                  description = "Whether the device was successfully stopped."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Source",
          summary = "A playable sound object.",
          description = "A Source is an object representing a single sound.  Currently ogg, wav, and mp3 formats are supported.\n\nWhen a Source is playing, it will send audio to the speakers.  Sources do not play automatically when they are created.  Instead, the `play`, `pause`, and `stop` functions can be used to control when they should play.\n\n`Source:seek` and `Source:tell` can be used to control the playback position of the Source.  A Source can be set to loop when it reaches the end using `Source:setLooping`.",
          key = "Source",
          module = "lovr.audio",
          constructors = {
            "lovr.audio.newSource",
            "Source:clone"
          },
          extends = "Object",
          methods = {
            {
              name = "clone",
              tag = "sourceUtility",
              summary = "Create an identical copy of the Source.",
              description = "Creates a copy of the Source, referencing the same `Sound` object and inheriting all of the settings of this Source.  However, it will be created in the stopped state and will be rewound to the beginning.",
              key = "Source:clone",
              module = "lovr.audio",
              notes = "This is a good way to create multiple Sources that play the same sound, since the audio data won't be loaded multiple times and can just be reused.  You can also create multiple `Source` objects and pass in the same `Sound` object for each one, which will have the same effect.",
              related = {
                "lovr.audio.newSource"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "source",
                      type = "Source",
                      description = "A genetically identical copy of the Source."
                    }
                  }
                }
              }
            },
            {
              name = "getDirectivity",
              tag = "sourceEffects",
              summary = "Get the directivity of the Source.",
              description = "Returns the directivity settings for the Source.\n\nThe directivity is controlled by two parameters: the weight and the power.\n\nThe weight is a number between 0 and 1 controlling the general \"shape\" of the sound emitted. 0.0 results in a completely omnidirectional sound that can be heard from all directions.  1.0 results in a full dipole shape that can be heard only from the front and back.  0.5 results in a cardioid shape that can only be heard from one direction.  Numbers in between will smoothly transition between these.\n\nThe power is a number that controls how \"focused\" or sharp the shape is.  Lower power values can be heard from a wider set of angles.  It is an exponent, so it can get arbitrarily large.  Note that a power of zero will still result in an omnidirectional source, regardless of the weight.",
              key = "Source:getDirectivity",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "weight",
                      type = "number",
                      description = "The dipole weight.  0.0 is omnidirectional, 1.0 is a dipole, 0.5 is cardioid."
                    },
                    {
                      name = "power",
                      type = "number",
                      description = "The dipole power, controlling how focused the directivity shape is."
                    }
                  }
                }
              }
            },
            {
              name = "getDuration",
              tag = "sourcePlayback",
              summary = "Get the duration of the Source.",
              description = "Returns the duration of the Source.",
              key = "Source:getDuration",
              module = "lovr.audio",
              related = {
                "Sound:getDuration"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "unit",
                      type = "TimeUnit",
                      description = "The unit to return.",
                      default = "'seconds'"
                    }
                  },
                  returns = {
                    {
                      name = "duration",
                      type = "number",
                      description = "The duration of the Source."
                    }
                  }
                }
              }
            },
            {
              name = "getOrientation",
              tag = "sourceEffects",
              summary = "Get the orientation of the Source.",
              description = "Returns the orientation of the Source, in angle/axis representation.",
              key = "Source:getOrientation",
              module = "lovr.audio",
              related = {
                "Source:getPosition",
                "Source:getPose",
                "lovr.audio.getOrientation"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Source is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPitch",
              tag = "sourcePlayback",
              summary = "Get the pitch of the Source.",
              description = "Returns the pitch of the Source.",
              key = "Source:getPitch",
              module = "lovr.audio",
              notes = "The default pitch is 1.  Every doubling/halving of the pitch will raise/lower the pitch by one octave.  Changing the pitch also changes the playback speed.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "pitch",
                      type = "number",
                      description = "The pitch."
                    }
                  }
                }
              }
            },
            {
              name = "getPose",
              tag = "sourceEffects",
              summary = "Get the pose of the Source.",
              description = "Returns the position and orientation of the Source.",
              key = "Source:getPose",
              module = "lovr.audio",
              related = {
                "Source:getPosition",
                "Source:getOrientation",
                "lovr.audio.getPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Source, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Source, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Source, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Source is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              tag = "sourceEffects",
              summary = "Get the position of the Source.",
              description = "Returns the position of the Source, in meters.  Setting the position will cause the Source to be distorted and attenuated based on its position relative to the listener.",
              key = "Source:getPosition",
              module = "lovr.audio",
              related = {
                "Source:getOrientation",
                "Source:getPose",
                "lovr.audio.getPosition"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    }
                  }
                }
              }
            },
            {
              name = "getRadius",
              tag = "sourceEffects",
              summary = "Get the radius of the Source.",
              description = "Returns the radius of the Source, in meters.\n\nThis does not control falloff or attenuation.  It is only used for smoothing out occlusion.  If a Source doesn't have a radius, then when it becomes occluded by a wall its volume will instantly drop.  Giving the Source a radius that approximates its emitter's size will result in a smooth transition between audible and occluded, improving realism.",
              key = "Source:getRadius",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the Source, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getSound",
              tag = "sourceUtility",
              summary = "Get the Sound object backing the Source.",
              description = "Returns the `Sound` object backing the Source.  Multiple Sources can share one Sound, allowing its data to only be loaded once.  An easy way to do this sharing is by using `Source:clone`.",
              key = "Source:getSound",
              module = "lovr.audio",
              related = {
                "Source:clone",
                "lovr.audio.newSource"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "sound",
                      type = "Sound",
                      description = "The Sound object."
                    }
                  }
                }
              }
            },
            {
              name = "getVolume",
              tag = "sourcePlayback",
              summary = "Get the volume of the Source.",
              description = "Returns the current volume factor for the Source.",
              key = "Source:getVolume",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {
                    {
                      name = "units",
                      type = "VolumeUnit",
                      description = "The units to return (linear or db).",
                      default = "'linear'"
                    }
                  },
                  returns = {
                    {
                      name = "volume",
                      type = "number",
                      description = "The volume of the Source."
                    }
                  }
                }
              }
            },
            {
              name = "isEffectEnabled",
              tag = "sourceEffects",
              summary = "Check if an effect is enabled.",
              description = "Returns whether a given `Effect` is enabled for the Source.",
              key = "Source:isEffectEnabled",
              module = "lovr.audio",
              notes = "The active spatializer will determine which effects are supported.  If an unsupported effect is enabled on a Source, no error will be reported.  Instead, it will be silently ignored.  See `lovr.audio.getSpatializer` for a table showing the effects supported by each spatializer.\n\nCalling this function on a non-spatial Source will always return false.",
              related = {
                "Source:isSpatial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "effect",
                      type = "Effect",
                      description = "The effect."
                    }
                  },
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether the effect is enabled."
                    }
                  }
                }
              }
            },
            {
              name = "isLooping",
              tag = "sourcePlayback",
              summary = "Check if the Source is looping.",
              description = "Returns whether or not the Source will loop when it finishes.",
              key = "Source:isLooping",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "looping",
                      type = "boolean",
                      description = "Whether or not the Source is looping."
                    }
                  }
                }
              }
            },
            {
              name = "isPlaying",
              tag = "sourcePlayback",
              summary = "Check if the Source is playing.",
              description = "Returns whether or not the Source is playing.",
              key = "Source:isPlaying",
              module = "lovr.audio",
              related = {
                "Source:play",
                "Source:pause",
                "Source:stop"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "playing",
                      type = "boolean",
                      description = "Whether the Source is playing."
                    }
                  }
                }
              }
            },
            {
              name = "isSpatial",
              tag = "sourceEffects",
              summary = "Check if the Source is spatial.",
              description = "Returns whether the Source was created with the `spatial` flag.  Non-spatial sources are routed directly to the speakers and can not use effects.",
              key = "Source:isSpatial",
              module = "lovr.audio",
              related = {
                "Source:isEffectEnabled",
                "Source:setEffectEnabled"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "spatial",
                      type = "boolean",
                      description = "Whether the source is spatial."
                    }
                  }
                }
              }
            },
            {
              name = "pause",
              tag = "sourcePlayback",
              summary = "Pause the Source.",
              description = "Pauses the source.  It can be resumed with `Source:resume` or `Source:play`. If a paused source is rewound, it will remain paused.",
              key = "Source:pause",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "play",
              tag = "sourcePlayback",
              summary = "Play the Source.",
              description = "Plays the Source.  This doesn't do anything if the Source is already playing.",
              key = "Source:play",
              module = "lovr.audio",
              notes = "There is a maximum of 64 Sources that can be playing at once.  If 64 Sources are already playing, this function will return `false`.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "success",
                      type = "boolean",
                      description = "Whether the Source successfully started playing."
                    }
                  }
                }
              }
            },
            {
              name = "seek",
              tag = "sourcePlayback",
              summary = "Set the playback position of the Source.",
              description = "Seeks the Source to the specified position.",
              key = "Source:seek",
              module = "lovr.audio",
              notes = "Seeking a Source backed by a stream `Sound` has no meaningful effect.",
              variants = {
                {
                  arguments = {
                    {
                      name = "position",
                      type = "number",
                      description = "The position to seek to."
                    },
                    {
                      name = "unit",
                      type = "TimeUnit",
                      description = "The units for the seek position.",
                      default = "'seconds'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDirectivity",
              tag = "sourceEffects",
              summary = "Set the directivity of the Source.",
              description = "Sets the directivity settings for the Source.\n\nThe directivity is controlled by two parameters: the weight and the power.\n\nThe weight is a number between 0 and 1 controlling the general \"shape\" of the sound emitted. 0.0 results in a completely omnidirectional sound that can be heard from all directions.  1.0 results in a full dipole shape that can be heard only from the front and back.  0.5 results in a cardioid shape that can only be heard from one direction.  Numbers in between will smoothly transition between these.\n\nThe power is a number that controls how \"focused\" or sharp the shape is.  Lower power values can be heard from a wider set of angles.  It is an exponent, so it can get arbitrarily large.  Note that a power of zero will still result in an omnidirectional source, regardless of the weight.",
              key = "Source:setDirectivity",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {
                    {
                      name = "weight",
                      type = "number",
                      description = "The dipole weight.  0.0 is omnidirectional, 1.0 is a dipole, 0.5 is cardioid."
                    },
                    {
                      name = "power",
                      type = "number",
                      description = "The dipole power, controlling how focused the directivity shape is."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setEffectEnabled",
              tag = "sourceEffects",
              summary = "Enable or disable an effect.",
              description = "Enables or disables an effect on the Source.",
              key = "Source:setEffectEnabled",
              module = "lovr.audio",
              notes = "The active spatializer will determine which effects are supported.  If an unsupported effect is enabled on a Source, no error will be reported.  Instead, it will be silently ignored.  See `lovr.audio.getSpatializer` for a table showing the effects supported by each spatializer.\n\nCalling this function on a non-spatial Source will throw an error.",
              related = {
                "Source:isSpatial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "effect",
                      type = "Effect",
                      description = "The effect."
                    },
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether the effect should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLooping",
              tag = "sourcePlayback",
              summary = "Set whether or not the Source loops.",
              description = "Sets whether or not the Source loops.",
              key = "Source:setLooping",
              module = "lovr.audio",
              notes = "Attempting to loop a Source backed by a stream `Sound` will cause an error.",
              variants = {
                {
                  arguments = {
                    {
                      name = "loop",
                      type = "boolean",
                      description = "Whether or not the Source will loop."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setOrientation",
              tag = "sourceEffects",
              summary = "Set the orientation of the Source.",
              description = "Sets the orientation of the Source in angle/axis representation.",
              key = "Source:setOrientation",
              module = "lovr.audio",
              related = {
                "Source:setPosition",
                "Source:setPose",
                "lovr.audio.setOrientation"
              },
              variants = {
                {
                  description = "Set the orientation using angle/axis numbers.",
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Source should be rotated around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the orientation using a quaternion.",
                  arguments = {
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPitch",
              tag = "sourcePlayback",
              summary = "Set the pitch of the Source.",
              description = "Sets the pitch of the Source.",
              key = "Source:setPitch",
              module = "lovr.audio",
              notes = "The default pitch is 1.  Every doubling/halving of the pitch will raise/lower the pitch by one octave.  Changing the pitch also changes the playback speed.",
              variants = {
                {
                  arguments = {
                    {
                      name = "pitch",
                      type = "number",
                      description = "The new pitch."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPose",
              tag = "sourceEffects",
              summary = "Set the pose of the Source.",
              description = "Sets the position and orientation of the Source.",
              key = "Source:setPose",
              module = "lovr.audio",
              notes = "The position doesn't have any defined units, but meters are used by convention.",
              related = {
                "Source:setPosition",
                "Source:setOrientation",
                "lovr.audio.setPose"
              },
              variants = {
                {
                  description = "Set the pose using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Source."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Source."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Source."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Source is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the pose using vector types.",
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPosition",
              tag = "sourceEffects",
              summary = "Set the position of the Source.",
              description = "Sets the position of the Source.  Setting the position will cause the Source to be distorted and attenuated based on its position relative to the listener.\n\nOnly mono sources can be positioned.  Setting the position of a stereo Source will cause an error.",
              key = "Source:setPosition",
              module = "lovr.audio",
              notes = "The position doesn't have any defined units, but meters are used by convention.",
              related = {
                "Source:setOrientation",
                "Source:setPose"
              },
              variants = {
                {
                  description = "Set the position using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the position."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the position using a vector.",
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setRadius",
              tag = "sourceEffects",
              summary = "Set the radius of the Source.",
              description = "Sets the radius of the Source, in meters.\n\nThis does not control falloff or attenuation.  It is only used for smoothing out occlusion.  If a Source doesn't have a radius, then when it becomes occluded by a wall its volume will instantly drop.  Giving the Source a radius that approximates its emitter's size will result in a smooth transition between audible and occluded, improving realism.",
              key = "Source:setRadius",
              module = "lovr.audio",
              variants = {
                {
                  arguments = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The new radius of the Source, in meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setVolume",
              tag = "sourcePlayback",
              summary = "Set the volume of the Source.",
              description = "Sets the current volume factor for the Source.",
              key = "Source:setVolume",
              module = "lovr.audio",
              notes = "The volume will be clamped to a 0-1 range (0 dB).",
              variants = {
                {
                  arguments = {
                    {
                      name = "volume",
                      type = "number",
                      description = "The new volume."
                    },
                    {
                      name = "units",
                      type = "VolumeUnit",
                      description = "The units of the value.",
                      default = "'linear'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "stop",
              tag = "sourcePlayback",
              summary = "Stop the Source.",
              description = "Stops the source, also rewinding it to the beginning.",
              key = "Source:stop",
              module = "lovr.audio",
              related = {
                "Source:play",
                "Source:pause",
                "Source:isPlaying"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "tell",
              tag = "sourcePlayback",
              summary = "Get the playback position of the Source.",
              description = "Returns the current playback position of the Source.",
              key = "Source:tell",
              module = "lovr.audio",
              notes = "The return value for Sources backed by a stream `Sound` has no meaning.",
              variants = {
                {
                  arguments = {
                    {
                      name = "unit",
                      type = "TimeUnit",
                      description = "The unit to return.",
                      default = "'seconds'"
                    }
                  },
                  returns = {
                    {
                      name = "position",
                      type = "number",
                      description = "The current playback position."
                    }
                  }
                }
              }
            }
          },
          sections = {
            {
              name = "Playback",
              tag = "sourcePlayback"
            },
            {
              name = "Effects",
              tag = "sourceEffects"
            },
            {
              name = "Utility",
              tag = "sourceUtility"
            }
          }
        }
      },
      sections = {
        {
          name = "Sources",
          tag = "sources",
          description = "Sources are objects that represent a single sound instance."
        },
        {
          name = "Listener",
          tag = "listener",
          description = "The listener is a virtual object in 3D space that \"hears\" all the sounds that are playing. It can be positioned and oriented in 3D space, which controls how Sources in the world are heard.  Usually this would be locked to the headset pose."
        },
        {
          name = "Devices",
          tag = "devices",
          description = "It's possible to list the available audio devices on the system, and pick a specific device to use for either playback or capture.  Devices can also be manually started and stopped. Other useful features of `lovr.audio.setDevice` include the ability to stream all audio data to a custom sink and the option to create a device in exclusive mode for higher performance. By default, the default playback device is automatically initialized and started, but this can be configured using `lovr.conf`."
        }
      }
    },
    {
      name = "data",
      tag = "modules",
      summary = "Exposes low level functions for working with data.",
      description = "The `lovr.data` module provides functions for accessing underlying data representations for several LÖVR objects.",
      key = "lovr.data",
      enums = {
        {
          name = "AnimationProperty",
          summary = "Different animated properties.",
          description = "This indicates the different node properties that can be animated.",
          key = "AnimationProperty",
          module = "lovr.data",
          values = {
            {
              name = "translation",
              description = "Node translation."
            },
            {
              name = "rotation",
              description = "Node rotation."
            },
            {
              name = "scale",
              description = "Node scale."
            },
            {
              name = "weights",
              description = "Node blend shape weights."
            }
          }
        },
        {
          name = "AttributeType",
          summary = "Data types for vertex attributes in meshes.",
          description = "These are the data types that can be used by vertex data in meshes.",
          key = "AttributeType",
          module = "lovr.data",
          values = {
            {
              name = "i8",
              description = "Signed 8 bit integers (-128 to 127)."
            },
            {
              name = "u8",
              description = "Unsigned 8 bit integers (0 to 255)."
            },
            {
              name = "i16",
              description = "Signed 16 bit integers (-32768 to 32767)."
            },
            {
              name = "u16",
              description = "Unsigned 16 bit integers (0 to 65535)."
            },
            {
              name = "i32",
              description = "Signed 32 bit integers (-2147483648 to 2147483647)."
            },
            {
              name = "u32",
              description = "Unsigned 32 bit integers (0 to 429467295)."
            },
            {
              name = "f32",
              description = "Floating point numbers."
            }
          }
        },
        {
          name = "ChannelLayout",
          summary = "Different channel layouts for Sounds.",
          description = "Sounds can have different numbers of channels, and those channels can map to various speaker layouts.",
          key = "ChannelLayout",
          module = "lovr.data",
          related = {
            "lovr.data.newSound",
            "Sound:getFormat"
          },
          values = {
            {
              name = "mono",
              description = "1 channel."
            },
            {
              name = "stereo",
              description = "2 channels.  The first channel is for the left speaker and the second is for the right."
            },
            {
              name = "ambisonic",
              description = "4 channels.  Ambisonic channels don't map directly to speakers but instead represent directions in 3D space, sort of like the images of a skybox.  Currently, ambisonic sounds can only be loaded, not played."
            }
          }
        },
        {
          name = "DefaultAttribute",
          summary = "Attributes that can be loaded from a model.",
          description = "These are the different types of attributes that may be present in meshes loaded from models.",
          key = "DefaultAttribute",
          module = "lovr.data",
          values = {
            {
              name = "position",
              description = "Vertex positions."
            },
            {
              name = "normal",
              description = "Vertex normal vectors."
            },
            {
              name = "uv",
              description = "Vertex texture coordinates."
            },
            {
              name = "color",
              description = "Vertex colors."
            },
            {
              name = "tangent",
              description = "Vertex tangent vectors."
            },
            {
              name = "joints",
              description = "Vertex joint indices."
            },
            {
              name = "weights",
              description = "Vertex joint weights."
            }
          }
        },
        {
          name = "ModelDrawMode",
          summary = "Different draw modes for meshes in ModelDatas.",
          description = "The DrawMode of a mesh determines how its vertices are connected together.",
          key = "ModelDrawMode",
          module = "lovr.data",
          related = {
            "ModelData:getMeshDrawMode"
          },
          values = {
            {
              name = "points",
              description = "Each vertex is draw as a single point."
            },
            {
              name = "lines",
              description = "Every pair of vertices is drawn as a line."
            },
            {
              name = "linestrip",
              description = "Draws a single line through all of the vertices."
            },
            {
              name = "lineloop",
              description = "Draws a single line through all of the vertices, then connects back to the first vertex."
            },
            {
              name = "strip",
              description = "Vertices are rendered as triangles.  After the first 3 vertices, each subsequent vertex connects to the previous two."
            },
            {
              name = "triangles",
              description = "Every 3 vertices forms a triangle."
            },
            {
              name = "fan",
              description = "Vertices are rendered as triangles.  After the first 3 vertices, each subsequent vertex is connected to the previous vertex and the first vertex."
            }
          }
        },
        {
          name = "SampleFormat",
          summary = "Different data types for samples in a Sound.",
          description = "Sounds can store audio samples as 16 bit integers or 32 bit floats.",
          key = "SampleFormat",
          module = "lovr.data",
          related = {
            "lovr.data.newSound",
            "Sound:getFormat"
          },
          values = {
            {
              name = "f32",
              description = "32 bit floating point samples (between -1.0 and 1.0)."
            },
            {
              name = "i16",
              description = "16 bit integer samples (between -32768 and 32767)."
            }
          }
        },
        {
          name = "SmoothMode",
          summary = "Different ways to interpolate between animation keyframes.",
          description = "Different ways to interpolate between animation keyframes.",
          key = "SmoothMode",
          module = "lovr.data",
          values = {
            {
              name = "step",
              description = "The animated property will snap to the nearest keyframe."
            },
            {
              name = "linear",
              description = "The animated property will linearly interpolate between keyframes."
            },
            {
              name = "cubic",
              description = "The animated property will follow a smooth curve between nearby keyframes."
            }
          }
        },
        {
          name = "TextureFormat",
          summary = "Different pixel formats in `Image` and `Texture` objects.",
          description = "Different data layouts for pixels in `Image` and `Texture` objects.\n\nFormats starting with `d` are depth formats, used for depth/stencil render targets.\n\nFormats starting with `bc` and `astc` are compressed formats.  Compressed formats have better performance since they stay compressed on the CPU and GPU, reducing the amount of memory bandwidth required to look up all the pixels needed for shading.\n\nFormats without the `f` suffix are unsigned normalized formats, which store values in the range `[0,1]`.  The `f` suffix indicates a floating point format which can store values outside this range, and is used for HDR rendering or storing data in a texture.",
          key = "TextureFormat",
          module = "lovr.data",
          values = {
            {
              name = "r8",
              description = "One 8-bit channel.  1 byte per pixel."
            },
            {
              name = "rg8",
              description = "Two 8-bit channels.  2 bytes per pixel."
            },
            {
              name = "rgba8",
              description = "Four 8-bit channels.  4 bytes per pixel."
            },
            {
              name = "bgra8",
              description = "Four 8-bit channels.  4 bytes per pixel."
            },
            {
              name = "r16",
              description = "One 16-bit channel.  2 bytes per pixel."
            },
            {
              name = "rg16",
              description = "Two 16-bit channels.  4 bytes per pixel."
            },
            {
              name = "rgba16",
              description = "Four 16-bit channels.  8 bytes per pixel."
            },
            {
              name = "r16f",
              description = "One 16-bit floating point channel.  2 bytes per pixel."
            },
            {
              name = "rg16f",
              description = "Two 16-bit floating point channels.  4 bytes per pixel."
            },
            {
              name = "rgba16f",
              description = "Four 16-bit floating point channels.  8 bytes per pixel."
            },
            {
              name = "r32f",
              description = "One 32-bit floating point channel.  4 bytes per pixel."
            },
            {
              name = "rg32f",
              description = "Two 32-bit floating point channels.  8 bytes per pixel."
            },
            {
              name = "rgba32f",
              description = "Four 32-bit floating point channels.  16 bytes per pixel."
            },
            {
              name = "rgb565",
              description = "Packs three channels into 16 bits.  2 bytes per pixel."
            },
            {
              name = "rgb5a1",
              description = "Packs four channels into 16 bits, with \"cutout\" alpha.  2 bytes per pixel."
            },
            {
              name = "rgb10a2",
              description = "Packs four channels into 32 bits.  4 bytes per pixel."
            },
            {
              name = "rg11b10f",
              description = "Packs three unsigned floating point channels into 32 bits.  4 bytes per pixel."
            },
            {
              name = "d16",
              description = "One 16-bit depth channel.  2 bytes per pixel."
            },
            {
              name = "d24",
              description = "One 24-bit depth channel.  4 bytes per pixel."
            },
            {
              name = "d24s8",
              description = "One 24-bit depth channel and one 8-bit stencil channel.  4 bytes per pixel."
            },
            {
              name = "d32f",
              description = "One 32-bit floating point depth channel.  4 bytes per pixel."
            },
            {
              name = "d32fs8",
              description = "One 32-bit floating point depth channel and one 8-bit stencil channel.  5 bytes per pixel."
            },
            {
              name = "bc1",
              description = "3 channels.  8 bytes per 4x4 block, or 0.5 bytes per pixel.  Good for opaque images."
            },
            {
              name = "bc2",
              description = "Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  Not good for anything, because it only has 16 distinct levels of alpha."
            },
            {
              name = "bc3",
              description = "Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for color images with transparency."
            },
            {
              name = "bc4u",
              description = "One unsigned normalized channel.  8 bytes per 4x4 block or 0.5 bytes per pixel.  Good for grayscale images, like heightmaps."
            },
            {
              name = "bc4s",
              description = "One signed normalized channel.  8 bytes per 4x4 block or 0.5 bytes per pixel.  Similar to bc4u but has a range of -1 to 1."
            },
            {
              name = "bc5u",
              description = "Two unsigned normalized channels.  16 bytes per 4x4 block, or 1 byte per pixel.  Good for normal maps."
            },
            {
              name = "bc5s",
              description = "Two signed normalized channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for normal maps."
            },
            {
              name = "bc6uf",
              description = "Three unsigned floating point channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for HDR images."
            },
            {
              name = "bc6sf",
              description = "Three floating point channels.  16 bytes per 4x4 block or 1 byte per pixel.  Good for HDR images."
            },
            {
              name = "bc7",
              description = "Four channels.  16 bytes per 4x4 block or 1 byte per pixel.  High quality.  Good for most color images, including transparency."
            },
            {
              name = "astc4x4",
              description = "Four channels, 16 bytes per 4x4 block or 1 byte per pixel."
            },
            {
              name = "astc5x4",
              description = "Four channels, 16 bytes per 5x4 block or 0.80 bytes per pixel."
            },
            {
              name = "astc5x5",
              description = "Four channels, 16 bytes per 5x5 block or 0.64 bytes per pixel."
            },
            {
              name = "astc6x5",
              description = "Four channels, 16 bytes per 6x5 block or 0.53 bytes per pixel."
            },
            {
              name = "astc6x6",
              description = "Four channels, 16 bytes per 6x6 block or 0.44 bytes per pixel."
            },
            {
              name = "astc8x5",
              description = "Four channels, 16 bytes per 8x5 block or 0.40 bytes per pixel."
            },
            {
              name = "astc8x6",
              description = "Four channels, 16 bytes per 8x6 block or 0.33 bytes per pixel."
            },
            {
              name = "astc8x8",
              description = "Four channels, 16 bytes per 8x8 block or 0.25 bytes per pixel."
            },
            {
              name = "astc10x5",
              description = "Four channels, 16 bytes per 10x5 block or 0.32 bytes per pixel."
            },
            {
              name = "astc10x6",
              description = "Four channels, 16 bytes per 10x6 block or 0.27 bytes per pixel."
            },
            {
              name = "astc10x8",
              description = "Four channels, 16 bytes per 10x8 block or 0.20 bytes per pixel."
            },
            {
              name = "astc10x10",
              description = "Four channels, 16 bytes per 10x10 block or 0.16 bytes per pixel."
            },
            {
              name = "astc12x10",
              description = "Four channels, 16 bytes per 12x10 block or 0.13 bytes per pixel."
            },
            {
              name = "astc12x12",
              description = "Four channels, 16 bytes per 12x12 block or 0.11 bytes per pixel."
            }
          }
        }
      },
      functions = {
        {
          name = "newBlob",
          summary = "Create a new Blob.",
          description = "Creates a new Blob.",
          key = "lovr.data.newBlob",
          module = "lovr.data",
          related = {
            "lovr.filesystem.newBlob"
          },
          variants = {
            {
              arguments = {
                {
                  name = "size",
                  type = "number",
                  description = "The amount of data to allocate for the Blob, in bytes.  All of the bytes will be filled with zeroes."
                },
                {
                  name = "name",
                  type = "string",
                  description = "A name for the Blob (used in error messages)",
                  default = "''"
                }
              },
              returns = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "The new Blob."
                }
              }
            },
            {
              arguments = {
                {
                  name = "contents",
                  type = "string",
                  description = "A string to use for the Blob's contents."
                },
                {
                  name = "name",
                  type = "string",
                  description = "A name for the Blob (used in error messages)",
                  default = "''"
                }
              },
              returns = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "The new Blob."
                }
              }
            },
            {
              arguments = {
                {
                  name = "source",
                  type = "Blob",
                  description = "A Blob to copy the contents from."
                },
                {
                  name = "name",
                  type = "string",
                  description = "A name for the Blob (used in error messages)",
                  default = "''"
                }
              },
              returns = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "The new Blob."
                }
              }
            }
          }
        },
        {
          name = "newImage",
          summary = "Create a new Image.",
          description = "Creates a new Image.  Image data can be loaded and decoded from an image file.  Alternatively, a blank image can be created with a given width, height, and format.",
          key = "lovr.data.newImage",
          module = "lovr.data",
          notes = "The supported image file formats are png, jpg, hdr, dds, ktx1, ktx2, and astc.\n\nDDS and KTX files can contain cubemaps and array textures, in any of the texture formats LÖVR supports.",
          variants = {
            {
              description = "Load image data from a file.",
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing an image file to load."
                }
              },
              returns = {
                {
                  name = "image",
                  type = "Image",
                  description = "The new Image."
                }
              }
            },
            {
              description = "Create an Image with a given size and pixel format.",
              arguments = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the texture."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the texture."
                },
                {
                  name = "format",
                  type = "TextureFormat",
                  description = "The format of the texture's pixels.",
                  default = "rgba8"
                },
                {
                  name = "data",
                  type = "Blob",
                  description = "Raw pixel values to use as the contents.  If `nil`, the data will all be zero.",
                  default = "nil"
                }
              },
              returns = {
                {
                  name = "image",
                  type = "Image",
                  description = "The new Image."
                }
              }
            },
            {
              description = "Clone an existing Image.",
              arguments = {
                {
                  name = "source",
                  type = "Image",
                  description = "The Image to clone."
                }
              },
              returns = {
                {
                  name = "image",
                  type = "Image",
                  description = "The new Image."
                }
              }
            }
          }
        },
        {
          name = "newModelData",
          summary = "Create a new ModelData.",
          description = "Loads a 3D model from a file.  The supported 3D file formats are OBJ and glTF.",
          key = "lovr.data.newModelData",
          module = "lovr.data",
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing the model data to import."
                }
              },
              returns = {
                {
                  name = "modelData",
                  type = "ModelData",
                  description = "The new ModelData."
                }
              }
            }
          }
        },
        {
          name = "newRasterizer",
          summary = "Create a new Rasterizer.",
          description = "Creates a new Rasterizer from a TTF or BMFont file.",
          key = "lovr.data.newRasterizer",
          module = "lovr.data",
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing the font file to load."
                },
                {
                  name = "size",
                  type = "number",
                  description = "The resolution to render the font at, in pixels (TTF only).  Higher resolutions use more memory and processing power but may provide better quality results for some fonts/situations.",
                  default = "32"
                }
              },
              returns = {
                {
                  name = "rasterizer",
                  type = "Rasterizer",
                  description = "The new Rasterizer."
                }
              }
            },
            {
              description = "Create a Rasterizer for the default font included with LÖVR (Varela Round).",
              arguments = {
                {
                  name = "size",
                  type = "number",
                  description = "The resolution to render the font at, in pixels (TTF only).  Higher resolutions use more memory and processing power but may provide better quality results for some fonts/situations.",
                  default = "32"
                }
              },
              returns = {
                {
                  name = "rasterizer",
                  type = "Rasterizer",
                  description = "The new Rasterizer."
                }
              }
            }
          }
        },
        {
          name = "newSound",
          summary = "Create a new Sound.",
          description = "Creates a new Sound.  A sound can be loaded from an audio file, or it can be created empty with capacity for a certain number of audio frames.\n\nWhen loading audio from a file, use the `decode` option to control whether compressed audio should remain compressed or immediately get decoded to raw samples.\n\nWhen creating an empty sound, the `contents` parameter can be set to `'stream'` to create an audio stream.  On streams, `Sound:setFrames` will always write to the end of the stream, and `Sound:getFrames` will always read the oldest samples from the beginning.  The number of frames in the sound is the total capacity of the stream's buffer.",
          key = "lovr.data.newSound",
          module = "lovr.data",
          notes = "It is highly recommended to use an audio format that matches the format of the audio module: `f32` sample formats at a sample rate of 48000, with 1 channel for spatialized sources or 2 channels for unspatialized sources.  This will avoid the need to convert audio during playback, which boosts performance of the audio thread.\n\nThe WAV importer supports 16, 24, and 32 bit integer data and 32 bit floating point data.  The data must be mono, stereo, or 4-channel full-sphere ambisonic.  The `WAVE_FORMAT_EXTENSIBLE` extension is supported.\n\nAmbisonic channel layouts are supported for import (but not yet for playback).  Ambisonic data can be loaded from WAV files.  It must be first-order full-sphere ambisonic data with 4 channels.  If the WAV has a `WAVE_FORMAT_EXTENSIBLE` chunk with an `AMBISONIC_B_FORMAT` format GUID, then the data is understood as using the AMB format with Furse-Malham channel ordering and normalization.  *All other* 4-channel files are assumed to be using the AmbiX format with ACN channel ordering and SN3D normalization.  AMB files will get automatically converted to AmbiX on import, so ambisonic Sounds will always be in a consistent format.\n\nOGG and MP3 files will always have the `f32` format when loaded.",
          variants = {
            {
              description = "Create a raw or stream Sound from a frame count and format info:",
              arguments = {
                {
                  name = "frames",
                  type = "number",
                  description = "The number of frames the Sound can hold."
                },
                {
                  name = "format",
                  type = "SampleFormat",
                  description = "The sample data type.",
                  default = "'f32'"
                },
                {
                  name = "channels",
                  type = "ChannelLayout",
                  description = "The channel layout.",
                  default = "'stereo'"
                },
                {
                  name = "sampleRate",
                  type = "number",
                  description = "The sample rate, in Hz.",
                  default = "48000"
                },
                {
                  name = "contents",
                  type = "Blob | string | nil",
                  description = "A Blob containing raw audio samples to use as the initial contents, 'stream' to create an audio stream, or `nil` to leave the data initialized to zero.",
                  default = "nil"
                }
              },
              returns = {
                {
                  name = "sound",
                  type = "Sound",
                  description = "Sounds good."
                }
              }
            },
            {
              description = "Load a sound from a filename or Blob containing the data of an audio file.  Compressed audio formats (OGG, MP3) can optionally be decoded into raw sounds.\n\nIf you want to load a Blob containing raw audio samples, use the first variant of this function and pass the Blob as the `contents`.",
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing a sound file to load."
                },
                {
                  name = "decode",
                  type = "boolean",
                  description = "Whether compressed audio files should be immediately decoded.",
                  default = "false"
                }
              },
              returns = {
                {
                  name = "sound",
                  type = "Sound",
                  description = "Sounds good."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Blob",
          summary = "A chunk of binary data.",
          description = "A Blob is an object that holds binary data.  It can be passed to most functions that take filename arguments, like `lovr.graphics.newModel` or `lovr.audio.newSource`.  Blobs aren't usually necessary for simple projects, but they can be really helpful if:\n\n- You need to work with low level binary data, potentially using the LuaJIT FFI for increased\n  performance.\n- You are working with data that isn't stored as a file, such as programmatically generated data\n  or a string from a network request.\n- You want to load data from a file once and then use it to create many different objects.\n\nA Blob's size cannot be changed once it is created.",
          key = "Blob",
          module = "lovr.data",
          constructors = {
            "lovr.data.newBlob",
            "lovr.filesystem.newBlob"
          },
          extends = "Object",
          methods = {
            {
              name = "getSize",
              summary = "Get the size of the Blob, in bytes.",
              description = "Returns the size of the Blob's contents, in bytes.",
              key = "Blob:getSize",
              module = "lovr.data",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "bytes",
                      type = "number",
                      description = "The size of the Blob, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "getName",
              summary = "Get the label of the Blob.",
              description = "Returns the filename the Blob was loaded from, or the custom name given to it when it was created.  This label is also used in error messages.",
              key = "Blob:getName",
              module = "lovr.data",
              notes = "If a Blob was created without a name, its name will default to the empty string.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the Blob."
                    }
                  }
                }
              }
            },
            {
              name = "getPointer",
              summary = "Get a raw pointer to the Blob's data.",
              description = "Returns a raw pointer to the Blob's data.  This can be used to interface with other C libraries using the LuaJIT FFI.  Use this only if you know what you're doing!",
              key = "Blob:getPointer",
              module = "lovr.data",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "pointer",
                      type = "userdata",
                      description = "A pointer to the data."
                    }
                  }
                }
              }
            },
            {
              name = "getString",
              summary = "Get the Blob's contents as a string.",
              description = "Returns a binary string containing the Blob's data.",
              key = "Blob:getString",
              module = "lovr.data",
              examples = {
                {
                  description = "Print each byte of the main.lua file:",
                  code = "blob = lovr.filesystem.newBlob('main.lua')\nstr = blob:getString()\n\nfor i = 1, #str do\n  print(string.byte(str, i))\nend"
                }
              },
              notes = "This effectively allocates a new copy of the Blob as a Lua string, so this should be avoided for really big Blobs!",
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset into the Blob where the string will start.",
                      default = "0"
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes the string will contain.  If nil, the rest of the data in the Blob will be used, based on the `offset` parameter.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "data",
                      type = "string",
                      description = "The Blob's data."
                    }
                  }
                }
              }
            },
            {
              name = "getI8",
              summary = "Unpack signed 8-bit integers from the Blob.",
              description = "Returns signed 8-bit integers from the data in the Blob.",
              key = "Blob:getI8",
              module = "lovr.data",
              related = {
                "Blob:setI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` signed 8-bit integers, from -128 to 127."
                    }
                  }
                }
              }
            },
            {
              name = "getU8",
              summary = "Unpack unsigned 8-bit integers from the Blob.",
              description = "Returns unsigned 8-bit integers from the data in the Blob.",
              key = "Blob:getU8",
              module = "lovr.data",
              related = {
                "Blob:setU8",
                "Blob:getI8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` unsigned 8-bit integers, from 0 to 255."
                    }
                  }
                }
              }
            },
            {
              name = "getI16",
              summary = "Unpack signed 16-bit integers from the Blob.",
              description = "Returns signed 16-bit integers from the data in the Blob.",
              key = "Blob:getI16",
              module = "lovr.data",
              related = {
                "Blob:setI16",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` signed 16-bit integers, from -32768 to 32767."
                    }
                  }
                }
              }
            },
            {
              name = "getU16",
              summary = "Unpack unsigned 16-bit integers from the Blob.",
              description = "Returns unsigned 16-bit integers from the data in the Blob.",
              key = "Blob:getU16",
              module = "lovr.data",
              related = {
                "Blob:setU16",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` unsigned 16-bit integers, from 0 to 65535."
                    }
                  }
                }
              }
            },
            {
              name = "getI32",
              summary = "Unpack signed 32-bit integers from the Blob.",
              description = "Returns signed 32-bit integers from the data in the Blob.",
              key = "Blob:getI32",
              module = "lovr.data",
              related = {
                "Blob:setI32",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getU32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` signed 32-bit integers, from -2147483648 to 2147483647."
                    }
                  }
                }
              }
            },
            {
              name = "getU32",
              summary = "Unpack unsigned 32-bit integers from the Blob.",
              description = "Returns unsigned 32-bit integers from the data in the Blob.",
              key = "Blob:getU32",
              module = "lovr.data",
              related = {
                "Blob:setU32",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getF32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of integers to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` unsigned 32-bit integers, from 0 to 4294967296."
                    }
                  }
                }
              }
            },
            {
              name = "getF32",
              summary = "Unpack 32-bit floating point numbers from the Blob.",
              description = "Returns 32-bit floating point numbers from the data in the Blob.",
              key = "Blob:getF32",
              module = "lovr.data",
              related = {
                "Blob:setF32",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of floats to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` 32-bit floats."
                    }
                  }
                }
              }
            },
            {
              name = "getF64",
              summary = "Unpack 64-bit floating point numbers from the Blob.",
              description = "Returns 64-bit floating point numbers from the data in the Blob.",
              key = "Blob:getF64",
              module = "lovr.data",
              related = {
                "Blob:setF64",
                "Blob:getI8",
                "Blob:getU8",
                "Blob:getI16",
                "Blob:getU16",
                "Blob:getI32",
                "Blob:getU32",
                "Blob:getF32"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of doubles to read.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "`count` 64-bit doubles."
                    }
                  }
                }
              }
            },
            {
              name = "setI8",
              summary = "Write 8-bit signed integers to the Blob.",
              description = "Writes 8-bit signed integers to the Blob.",
              key = "Blob:setI8",
              module = "lovr.data",
              related = {
                "Blob:getI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 8-bit signed integers (each taking up 1 byte, ranging from\n-127 to 128)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 8-bit signed integers (each taking up 1 byte, ranging from -127 to 128)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setU8",
              summary = "Write 8-bit unsigned integers to the Blob.",
              description = "Writes 8-bit unsigned integers to the Blob.",
              key = "Blob:setU8",
              module = "lovr.data",
              related = {
                "Blob:getU8",
                "Blob:setI8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 8-bit unsigned integers (each taking up 1 byte, ranging from 0 to 255)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 8-bit unsigned integers (each taking up 1 byte, ranging from 0 to 255)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setI16",
              summary = "Write 16-bit signed integers to the Blob.",
              description = "Writes 16-bit signed integers to the Blob.",
              key = "Blob:setI16",
              module = "lovr.data",
              related = {
                "Blob:getI16",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 16-bit signed integers (each taking up 2 bytes, ranging from\n-32768 to 32767)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 16-bit signed integers (each taking up 2 bytes, ranging from -32768 to 32767)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setU16",
              summary = "Write 16-bit unsigned integers to the Blob.",
              description = "Writes 16-bit unsigned integers to the Blob.",
              key = "Blob:setU16",
              module = "lovr.data",
              related = {
                "Blob:getU16",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 16-bit unsigned integers (each taking up 2 bytes, ranging from 0 to 65535)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 16-bit unsigned integers (each taking up 2 bytes, ranging from 0 to 65535)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setI32",
              summary = "Write 32-bit signed integers to the Blob.",
              description = "Writes 32-bit signed integers to the Blob.",
              key = "Blob:setI32",
              module = "lovr.data",
              related = {
                "Blob:getI32",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setU32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 32-bit signed integers (each taking up 4 bytes, ranging from\n-2147483648 to 2147483647)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 32-bit signed integers (each taking up 4 bytes, ranging from -2147483648 to 2147483647)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setU32",
              summary = "Write 32-bit unsigned integers to the Blob.",
              description = "Writes 32-bit unsigned integers to the Blob.",
              key = "Blob:setU32",
              module = "lovr.data",
              related = {
                "Blob:getU32",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setF32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 32-bit unsigned integers (each taking up 4 bytes, ranging from 0 to 4294967296)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 32-bit unsigned integers (each taking up 4 bytes, ranging from 0 to 4294967296)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setF32",
              summary = "Write 32-bit floating point numbers to the Blob.",
              description = "Writes 32-bit floating point numbers to the Blob.",
              key = "Blob:setF32",
              module = "lovr.data",
              related = {
                "Blob:getF32",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF64"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 32-bit floats (each taking up 4 bytes)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 32-bit floats (each taking up 4 bytes)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setF64",
              summary = "Write 64-bit floating point numbers to the Blob.",
              description = "Writes 64-bit floating point numbers to the Blob.",
              key = "Blob:setF64",
              module = "lovr.data",
              related = {
                "Blob:getF64",
                "Blob:setI8",
                "Blob:setU8",
                "Blob:setI16",
                "Blob:setU16",
                "Blob:setI32",
                "Blob:setU32",
                "Blob:setF32"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "Numbers to write to the blob as 64-bit floating point numbers (each taking up 8 bytes)."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A non-negative byte offset to start writing at."
                    },
                    {
                      name = "table",
                      type = "{number}",
                      description = "A table of numbers to write to the blob as 64-bit floating point numbers (each taking up 8 bytes)."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Image",
          summary = "An object that stores pixel data for Textures.",
          description = "An Image stores raw 2D pixel info for `Texture`s.  It has a width, height, and format.  The Image can be initialized with the contents of an image file or it can be created with uninitialized contents.  The supported image formats are `png`, `jpg`, `hdr`, `dds`, `ktx`, and `astc`.\n\nUsually you can just use Textures, but Image can be useful if you want to manipulate individual pixels, load Textures in a background thread, or use the FFI to efficiently access the raw image data.",
          key = "Image",
          module = "lovr.data",
          constructors = {
            "lovr.data.newImage"
          },
          extends = "Object",
          methods = {
            {
              name = "encode",
              summary = "Encode the Image as png.",
              description = "Encodes the Image to an **uncompressed** png.  This intended mainly for debugging.",
              key = "Image:encode",
              module = "lovr.data",
              related = {
                "lovr.filesystem.write"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "A new Blob containing the PNG image data."
                    }
                  }
                }
              }
            },
            {
              name = "getBlob",
              summary = "Get the bytes backing this Image as a `Blob`.",
              description = "Returns a Blob containing the raw bytes of the Image.",
              key = "Image:getBlob",
              module = "lovr.data",
              related = {
                "Blob:getPointer",
                "Sound:getBlob"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob instance containing the bytes for the `Image`."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              summary = "Get the dimensions of the Image.",
              description = "Returns the dimensions of the Image, in pixels.",
              key = "Image:getDimensions",
              module = "lovr.data",
              related = {
                "Image:getWidth",
                "Image:getHeight",
                "Texture:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Image, in pixels."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Image, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getFormat",
              summary = "Get the pixel format of the Image.",
              description = "Returns the format of the Image.",
              key = "Image:getFormat",
              module = "lovr.data",
              related = {
                "TextureFormat",
                "Texture:getFormat"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the pixels in the Image."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              summary = "Get the height of the Image.",
              description = "Returns the height of the Image, in pixels.",
              key = "Image:getHeight",
              module = "lovr.data",
              related = {
                "Image:getWidth",
                "Image:getDimensions",
                "Texture:getHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Image, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getPixel",
              summary = "Get the value of a pixel of the Image.",
              description = "Returns the value of a pixel of the Image.",
              key = "Image:getPixel",
              module = "lovr.data",
              notes = "The following texture formats are supported: `r8`, `rg8`, `rgba8`, `r16`, `rg16`, `rgba16`, `r32f`, `rg32f`, `rgba32f`.",
              related = {
                "Image:setPixel",
                "Image:mapPixel",
                "TextureFormat",
                "Texture:getPixels",
                "Texture:setPixels",
                "Texture:newReadback"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the pixel to get (0-indexed)."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the pixel to get (0-indexed)."
                    }
                  },
                  returns = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the pixel, from 0.0 to 1.0."
                    }
                  }
                }
              }
            },
            {
              name = "getPointer",
              summary = "Get a raw pointer to the Image pixel data.",
              description = "Returns a raw pointer to the Image's pixel data.  This can be used to interface with other C libraries or the LuaJIT FFI.",
              key = "Image:getPointer",
              module = "lovr.data",
              examples = {
                {
                  description = "Simple example of writing to Image pixels with LuaJIT's FFI module.",
                  code = "local ffi = require 'ffi'\n\nfunction lovr.load()\n  image = lovr.data.newImage(2, 2)\n\n  ffi.cdef [[\n    typedef struct { uint8_t r, g, b, a; } Pixel;\n  ]]\n\n  pointer = image:getPointer()\n  pixels = ffi.cast('Pixel*', pointer)\n  pixels[0] = { 255, 0, 0, 255 }\n  pixels[1] = { 0, 255, 0, 255 }\n  pixels[2] = { 0, 0, 255, 255 }\n  pixels[3] = { 255, 255, 255, 255 }\n\n  texture = lovr.graphics.newTexture(image)\nend\n\nfunction lovr.draw(pass)\n  pass:setSampler('nearest')\n  pass:fill(texture)\nend"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "level",
                      type = "number",
                      description = "The mipmap level to get the pointer of (for DDS and KTX images).",
                      default = "1"
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The array layer to get the pointer of (for DDS and KTX images).",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "pointer",
                      type = "userdata",
                      description = "A pointer to the raw pixel data."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              summary = "Get the width of the Image.",
              description = "Returns the width of the Image, in pixels.",
              key = "Image:getWidth",
              module = "lovr.data",
              related = {
                "Image:getHeight",
                "Image:getDimensions",
                "Texture:getWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Image, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "mapPixel",
              summary = "Transform an Image by applying a function to every pixel.",
              description = "Transforms pixels in the Image using a function.\n\nThe callback function passed to this function will be called once for each pixel.  For each pixel, the function will be called with its x and y coordinate and the red, green, blue, and alpha components of its color.  Whatever the function returns will be used as the new color for the pixel.\n\nThe callback function will potentially be called thousands of times, so it's best to keep the amount of code in there small and fast.",
              key = "Image:mapPixel",
              module = "lovr.data",
              examples = {
                {
                  description = "Convert an Image to grayscale.",
                  code = "image:mapPixel(function(x, y, r, g, b, a)\n  local brightness = .21 * r + .72 * g + .07 * b\n  return brightness, brightness, brightness, a\nend)"
                },
                {
                  description = "Efficient Image updates using FFI.  Due to the low-level nature, this will be a lot faster, but it's specialized to the `rgba8` image format and risks crashing if used improperly.",
                  code = "local ffi = require 'ffi'\n\nfunction lovr.load()\n  local w, h = 256, 256\n\n  image = lovr.data.newImage(w, h)\n\n  local pointer = ffi.cast('uint8_t*', image:getPointer())\n\n  for y = 0, h - 1 do\n    for x = 0, w - 1 do\n      pointer[(y * w + x) * 4 + 0] = (x / w) * 255\n      pointer[(y * w + x) * 4 + 1] = (y / h) * 255\n      pointer[(y * w + x) * 4 + 2] = 255\n      pointer[(y * w + x) * 4 + 3] = 255\n    end\n  end\n\n  texture = lovr.graphics.newTexture(image)\nend\n\nfunction lovr.draw(pass)\n  pass:fill(texture)\nend"
                }
              },
              notes = "The following texture formats are supported: `r8`, `rg8`, `rgba8`, `r16`, `rg16`, `rgba16`, `r32f`, `rg32f`, `rgba32f`.",
              related = {
                "Image:setPixel",
                "Image:getPixel",
                "TextureFormat",
                "Texture:setPixels"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "callback",
                      type = "function",
                      description = "The function that will be called for each pixel."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the upper-left corner of the area of the Image to affect.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the upper-left corner of the area of the Image to affect.",
                      default = "0"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The width of the area to affect.",
                      default = "image:getWidth()"
                    },
                    {
                      name = "h",
                      type = "number",
                      description = "The height of the area to affect.",
                      default = "image:getHeight()"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "paste",
              summary = "Copy pixels from another Image to this one.",
              description = "Copies a rectangle of pixels from one Image to this one.",
              key = "Image:paste",
              module = "lovr.data",
              notes = "The two Images must have the same pixel format.\n\nCompressed images cannot be copied.\n\nThe rectangle cannot go outside the dimensions of the source or destination textures.",
              related = {
                "Image:getPixel",
                "Image:setPixel",
                "Texture:setPixels"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "source",
                      type = "Image",
                      description = "The Image to copy pixels from."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate to paste to (0-indexed).",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate to paste to (0-indexed).",
                      default = "0"
                    },
                    {
                      name = "fromX",
                      type = "number",
                      description = "The x coordinate in the source to paste from (0-indexed).",
                      default = "0"
                    },
                    {
                      name = "fromY",
                      type = "number",
                      description = "The y coordinate in the source to paste from (0-indexed).",
                      default = "0"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the region to copy.",
                      default = "source:getWidth()"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the region to copy.",
                      default = "source:getHeight()"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPixel",
              summary = "Set the value of a pixel of the Image.",
              description = "Sets the value of a single pixel of the Image.\n\nIf you need to change a bunch of pixels, consider using `Image:mapPixel`.",
              key = "Image:setPixel",
              module = "lovr.data",
              notes = "The following texture formats are supported: `r8`, `rg8`, `rgba8`, `r16`, `rg16`, `rgba16`, `r32f`, `rg32f`, `rgba32f`.",
              related = {
                "Image:mapPixel",
                "Image:getPixel",
                "TextureFormat",
                "Texture:setPixels"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the pixel to set (0-indexed)."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the pixel to set (0-indexed)."
                    },
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the pixel, from 0.0 to 1.0."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the pixel, from 0.0 to 1.0.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "ModelData",
          summary = "An object that loads and stores data for 3D models.",
          description = "A ModelData is a container object that loads and holds data contained in 3D model files.  This can include a variety of things like the node structure of the asset, the vertex data it contains, contains, the `Image` and `Material` properties, and any included animations.\n\nThe current supported formats are OBJ, glTF, and STL.\n\nUsually you can just load a `Model` directly, but using a `ModelData` can be helpful if you want to load models in a thread or access more low-level information about the Model.",
          key = "ModelData",
          module = "lovr.data",
          constructors = {
            "lovr.data.newModelData"
          },
          extends = "Object",
          methods = {
            {
              name = "getAnimationChannelCount",
              summary = "Get the number of channels in an animation.",
              description = "Returns the number of channels in an animation.\n\nA channel is a set of keyframes targeting a single property of a node.",
              key = "ModelData:getAnimationChannelCount",
              module = "lovr.data",
              related = {
                "ModelData:getAnimationNode",
                "ModelData:getAnimationProperty"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "number | string",
                      description = "The name or index of an animation."
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of channels in the animation."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationCount",
              summary = "Get the number of animations in the model.",
              description = "Returns the number of animations in the model.",
              key = "ModelData:getAnimationCount",
              module = "lovr.data",
              related = {
                "Model:getAnimationCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of animations in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationDuration",
              summary = "Get the duration of an animation.",
              description = "Returns the duration of an animation.",
              key = "ModelData:getAnimationDuration",
              module = "lovr.data",
              notes = "The duration of the animation is calculated as the latest timestamp of all of its channels.",
              related = {
                "Model:getAnimationDuration"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string | number",
                      description = "The name or index of an animation."
                    }
                  },
                  returns = {
                    {
                      name = "duration",
                      type = "number",
                      description = "The duration of the animation, in seconds."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationKeyframe",
              summary = "Get a keyframe in a channel of an animation.",
              description = "Returns a single keyframe in a channel of an animation.",
              key = "ModelData:getAnimationKeyframe",
              module = "lovr.data",
              notes = "The number of values returned after `time` depends on the `AnimationProperty` targeted by the channel:\n\n- `translation`: 3 numbers\n- `rotation`: 4 numbers (returned as raw quaternion components)\n- `scale`: 3 numbers\n- `weights`: variable, contains 1 number for each blend shape in the node",
              related = {
                "ModelData:getAnimationSmoothMode",
                "ModelData:getAnimationKeyframeCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "number",
                      description = "The name or index of an animation."
                    },
                    {
                      name = "channel",
                      type = "number",
                      description = "The index of a channel in the animation."
                    },
                    {
                      name = "keyframe",
                      type = "number",
                      description = "The index of a keyframe in the channel."
                    }
                  },
                  returns = {
                    {
                      name = "time",
                      type = "number",
                      description = "The timestamp of the keyframe."
                    },
                    {
                      name = "...",
                      type = "number",
                      description = "The data for the keyframe (3 or more numbers, depending on the property)."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationKeyframeCount",
              summary = "Get the number of keyframes in a channel of an animation.",
              description = "Returns the number of keyframes in a channel of an animation.",
              key = "ModelData:getAnimationKeyframeCount",
              module = "lovr.data",
              related = {
                "ModelData:getAnimationSmoothMode",
                "ModelData:getAnimationKeyframe"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string | number",
                      description = "The name or index of an animation."
                    },
                    {
                      name = "channel",
                      type = "number",
                      description = "The index of a channel in the animation."
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of keyframes in the channel."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationName",
              summary = "Get the name of an animation.",
              description = "Returns the name of an animation.",
              key = "ModelData:getAnimationName",
              module = "lovr.data",
              related = {
                "Model:getAnimationName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of an animation."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string | nil",
                      description = "The name of the animation, or `nil` if the animation doesn't have a name."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationNode",
              summary = "Get the node targeted by the channel of an animation.",
              description = "Returns the index of the node targeted by an animation's channel.",
              key = "ModelData:getAnimationNode",
              module = "lovr.data",
              related = {
                "ModelData:getAnimationProperty",
                "ModelData:getAnimationSmoothMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "number",
                      description = "The index or name of an animation."
                    },
                    {
                      name = "channel",
                      type = "number",
                      description = "The index of a channel in the animation."
                    }
                  },
                  returns = {
                    {
                      name = "node",
                      type = "number",
                      description = "The index of the node targeted by the channel."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationProperty",
              summary = "Get the property targeted by a channel of an animation.",
              description = "Returns the property targeted by an animation's channel.",
              key = "ModelData:getAnimationProperty",
              module = "lovr.data",
              related = {
                "ModelData:getAnimationNode",
                "ModelData:getAnimationSmoothMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string | number",
                      description = "The name or index of an animation."
                    },
                    {
                      name = "channel",
                      type = "number",
                      description = "The index of a channel in the animation."
                    }
                  },
                  returns = {
                    {
                      name = "property",
                      type = "AnimationProperty",
                      description = "The property (translation, rotation, scale, or weights) affected by the keyframes."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationSmoothMode",
              summary = "Get the smooth mode of a channel in an animation.",
              description = "Returns the smooth mode of a channel in an animation.",
              key = "ModelData:getAnimationSmoothMode",
              module = "lovr.data",
              related = {
                "ModelData:getAnimationNode",
                "ModelData:getAnimationProperty"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string | number",
                      description = "The name or index of an animation."
                    },
                    {
                      name = "channel",
                      type = "number",
                      description = "The index of a channel in the animation."
                    }
                  },
                  returns = {
                    {
                      name = "smooth",
                      type = "SmoothMode",
                      description = "The smooth mode of the keyframes."
                    }
                  }
                }
              }
            },
            {
              name = "getBlendShapeCount",
              summary = "Get the number of blend shapes in the model.",
              description = "Returns the number of blend shapes in the model.",
              key = "ModelData:getBlendShapeCount",
              module = "lovr.data",
              related = {
                "ModelData:getBlendShapeName",
                "Model:getBlendShapeCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of blend shapes in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getBlendShapeName",
              summary = "Get the name of a blend shape in the model.",
              description = "Returns the name of a blend shape in the model.",
              key = "ModelData:getBlendShapeName",
              module = "lovr.data",
              notes = "This function will throw an error if the blend shape index is invalid.",
              related = {
                "ModelData:getBlendShapeCount",
                "Model:getBlendShapeName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of a blend shape."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the blend shape."
                    }
                  }
                }
              }
            },
            {
              name = "getBlob",
              summary = "Get a Blob in the model.",
              description = "Returns one of the Blobs in the model, by index.",
              key = "ModelData:getBlob",
              module = "lovr.data",
              related = {
                "ModelData:getBlobCount",
                "ModelData:getImage"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the Blob to get."
                    }
                  },
                  returns = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob object."
                    }
                  }
                }
              }
            },
            {
              name = "getBlobCount",
              summary = "Get the number of Blobs stored in the model.",
              description = "Returns the number of Blobs in the model.",
              key = "ModelData:getBlobCount",
              module = "lovr.data",
              related = {
                "ModelData:getBlob",
                "ModelData:getImageCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of Blobs in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingBox",
              summary = "Get the bounding box of the model.",
              description = "Returns the 6 values of the model's axis-aligned bounding box.",
              key = "ModelData:getBoundingBox",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getHeight",
                "ModelData:getDepth",
                "ModelData:getDimensions",
                "ModelData:getCenter",
                "ModelData:getBoundingSphere",
                "Model:getBoundingBox"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the vertices in the model."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the vertices in the model."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the vertices in the model."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the vertices in the model."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the vertices in the model."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the vertices in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingSphere",
              summary = "Get the bounding sphere of the model.",
              description = "Returns a sphere approximately enclosing the vertices in the model.",
              key = "ModelData:getBoundingSphere",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getHeight",
                "ModelData:getDepth",
                "ModelData:getDimensions",
                "ModelData:getCenter",
                "ModelData:getBoundingBox",
                "Model:getBoundingSphere"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the position of the sphere."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the position of the sphere."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the position of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the bounding sphere."
                    }
                  }
                }
              }
            },
            {
              name = "getCenter",
              summary = "Get the center of the model's bounding box.",
              description = "Returns the center of the model's axis-aligned bounding box, relative to the model's origin.",
              key = "ModelData:getCenter",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getHeight",
                "ModelData:getDepth",
                "ModelData:getDimensions",
                "ModelData:getBoundingBox",
                "Model:getCenter"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x offset of the center of the bounding box."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y offset of the center of the bounding box."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z offset of the center of the bounding box."
                    }
                  }
                }
              }
            },
            {
              name = "getDepth",
              summary = "Get the depth of the model.",
              description = "Returns the depth of the model, computed from its axis-aligned bounding box.",
              key = "ModelData:getDepth",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getHeight",
                "ModelData:getDimensions",
                "ModelData:getCenter",
                "ModelData:getBoundingBox",
                "Model:getDepth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the model."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              summary = "Get the dimensions of the model.",
              description = "Returns the width, height, and depth of the model, computed from its axis-aligned bounding box.",
              key = "ModelData:getDimensions",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getHeight",
                "ModelData:getDepth",
                "ModelData:getCenter",
                "ModelData:getBoundingBox",
                "Model:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the model."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the model."
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the model."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              summary = "Get the height of the model.",
              description = "Returns the height of the model, computed from its axis-aligned bounding box.",
              key = "ModelData:getHeight",
              module = "lovr.data",
              related = {
                "ModelData:getWidth",
                "ModelData:getDepth",
                "ModelData:getDimensions",
                "ModelData:getCenter",
                "ModelData:getBoundingBox",
                "Model:getHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the model."
                    }
                  }
                }
              }
            },
            {
              name = "getImage",
              summary = "Get an Image in the model.",
              description = "Returns one of the Images in the model, by index.",
              key = "ModelData:getImage",
              module = "lovr.data",
              related = {
                "ModelData:getImageCount",
                "ModelData:getBlob"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the Image to get."
                    }
                  },
                  returns = {
                    {
                      name = "image",
                      type = "Image",
                      description = "The Image object."
                    }
                  }
                }
              }
            },
            {
              name = "getImageCount",
              summary = "Get the number of Images stored in the model.",
              description = "Returns the number of Images in the model.",
              key = "ModelData:getImageCount",
              module = "lovr.data",
              related = {
                "ModelData:getImage",
                "ModelData:getBlobCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of Images in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterial",
              summary = "Get the material properties for a material in the model.",
              description = "Returns a table with all of the properties of a material.",
              key = "ModelData:getMaterial",
              module = "lovr.data",
              related = {
                "ModelData:getMaterialCount",
                "ModelData:getMeshMaterial",
                "lovr.graphics.newMaterial",
                "Model:getMaterial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "material",
                      type = "number",
                      description = "The name or index of a material."
                    }
                  },
                  returns = {
                    {
                      name = "properties",
                      type = "table",
                      description = "The material properties.",
                      table = {
                        {
                          name = "color",
                          type = "{number}",
                          description = "The color of the material.  The table contains the `r`, `g`, `b`, and `a` components of the color, from 0 to 1."
                        },
                        {
                          name = "glow",
                          type = "{number}",
                          description = "The glow color of the material (sometimes called emissive).  The table contains the `r`, `g`, and `b` components of the color from 0 to 1, and a fourth number indicating the strength of the glow."
                        },
                        {
                          name = "uvShift",
                          type = "{number}",
                          description = "A table with 2 numbers indicating an offset to apply to UVs."
                        },
                        {
                          name = "uvScale",
                          type = "{number}",
                          description = "A table with 2 numbers indicating a scale to apply to UVs.  By default, shaders apply the UV scale before the UV offset."
                        },
                        {
                          name = "metalness",
                          type = "number",
                          description = "The metalness parameter of the material.  This is typically 0 or 1.  By default, shaders multiply this property with the value from the metalness texture (when present) to get the final metalness used for shading."
                        },
                        {
                          name = "roughness",
                          type = "number",
                          description = "The roughness parameter of the material.  By default, shaders multiply this property with the value from the roughness texture (when present) to get the final roughness used for shading."
                        },
                        {
                          name = "clearcoat",
                          type = "number",
                          description = "The clearcoat parameter of the material."
                        },
                        {
                          name = "clearcoatRoughness",
                          type = "number",
                          description = "The roughness of the clearcoat layer."
                        },
                        {
                          name = "occlusionStrength",
                          type = "number",
                          description = "A number multiplied by the value from the ambient occlusion texture to control how strong the occlusion effect is."
                        },
                        {
                          name = "normalScale",
                          type = "number",
                          description = "A number multiplied by the value from the normal texture to control how strong the normal mapping effect is."
                        },
                        {
                          name = "alphaCutoff",
                          type = "number",
                          description = "If a pixel has an alpha value less than the alpha cutoff, it will be discarded, which prevents it from occluding things behind it.  This is sometimes called \"holepunch\" or \"cutout\" alpha.  It's useful for textures with transparency."
                        },
                        {
                          name = "texture",
                          type = "number | nil",
                          description = "The index of the Image used for the color texture."
                        },
                        {
                          name = "glowTexture",
                          type = "number | nil",
                          description = "The index of the Image used for the glow texture."
                        },
                        {
                          name = "occlusionTexture",
                          type = "number | nil",
                          description = "The index of the Image used for the ambient occlusion texture.  The red channel of the texture is used for ambient occlusion, allowing multiple parameters to use the same texture."
                        },
                        {
                          name = "metalnessTexture",
                          type = "number | nil",
                          description = "The index of the Image used for the metalness texture.  The blue channel of the texture is used for metalness, allowing multiple parameters to use the same texture."
                        },
                        {
                          name = "roughnessTexture",
                          type = "number | nil",
                          description = "The index of the Image to use for the roughness texture.  The green channel of the texture is used for roughness, allowing multiple parameters to use the same texture."
                        },
                        {
                          name = "clearcoatTexture",
                          type = "number | nil",
                          description = "The index of the Image to use for the clearcoat texture.  The red channel of the texture is used for the clearcoat parameter, allowing multiple parameters to use the same texture."
                        },
                        {
                          name = "normalTexture",
                          type = "number | nil",
                          description = "The index of the Image to use for the normal map."
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              name = "getMaterialCount",
              summary = "Get the number of materials in the model.",
              description = "Returns the number of materials in the model.",
              key = "ModelData:getMaterialCount",
              module = "lovr.data",
              related = {
                "ModelData:getMaterialName",
                "ModelData:getMeshMaterial",
                "ModelData:getMaterial",
                "Model:getMaterialCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of materials in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterialName",
              summary = "Get the name of a material in the model.",
              description = "Returns the name of a material in the model.",
              key = "ModelData:getMaterialName",
              module = "lovr.data",
              related = {
                "ModelData:getMaterialCount",
                "ModelData:getMeshMaterial",
                "ModelData:getMaterial",
                "Model:getMaterialName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of a material."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the material, or nil if the material does not have a name."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshCount",
              summary = "Get the number of meshes in the model.",
              description = "Returns the number of meshes in the model.",
              key = "ModelData:getMeshCount",
              module = "lovr.data",
              related = {
                "ModelData:getNodeMeshes"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of meshes in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshDrawMode",
              summary = "Get the draw mode of a mesh.",
              description = "Returns the draw mode of a mesh.  This controls how its vertices are connected together (points, lines, or triangles).",
              key = "ModelData:getMeshDrawMode",
              module = "lovr.data",
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "mode",
                      type = "ModelDrawMode",
                      description = "The draw mode of the mesh."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshIndex",
              summary = "Get one of the vertex indices in a mesh.",
              description = "Returns one of the vertex indices in a mesh.  If a mesh has vertex indices, they define the order and connectivity of the vertices in the mesh, allowing a vertex to be reused multiple times without duplicating its data.",
              key = "ModelData:getMeshIndex",
              module = "lovr.data",
              related = {
                "ModelData:getMeshIndexFormat",
                "ModelData:getMeshIndexCount",
                "ModelData:getMeshVertex",
                "ModelData:getTriangles"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh to get the vertex from."
                    },
                    {
                      name = "index",
                      type = "number",
                      description = "The index of a vertex index in the mesh to retrieve."
                    }
                  },
                  returns = {
                    {
                      name = "vertexindex",
                      type = "number",
                      description = "The vertex index.  Like all indices in Lua, this is 1-indexed."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshIndexCount",
              summary = "Get the number of vertex indices in a mesh.",
              description = "Returns the number of vertex indices in a mesh.  Vertex indices allow for vertices to be reused when defining triangles.",
              key = "ModelData:getMeshIndexCount",
              module = "lovr.data",
              notes = "This may return zero if the mesh does not use indices.",
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertex indices in the mesh."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshIndexFormat",
              summary = "Get the data format of vertex indices in a mesh.",
              description = "Returns the data format of vertex indices in a mesh.  If a mesh doesn't use vertex indices, this function returns nil.",
              key = "ModelData:getMeshIndexFormat",
              module = "lovr.data",
              related = {
                "ModelData:getMeshVertexFormat"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "type",
                      type = "AttributeType",
                      description = "The data type of each vertex index (always u16 or u32)."
                    },
                    {
                      name = "blob",
                      type = "number",
                      description = "The index of a Blob in the mesh where the binary data is stored."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset into the Blob's data where the index data starts."
                    },
                    {
                      name = "stride",
                      type = "number",
                      description = "The number of bytes between subsequent vertex indices.  Indices are always tightly packed, so this will always be 2 or 4 depending on the data type."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshMaterial",
              summary = "Get the index of the material applied to a mesh.",
              description = "Returns the index of the material applied to a mesh.",
              key = "ModelData:getMeshMaterial",
              module = "lovr.data",
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "material",
                      type = "number",
                      description = "The index of the material applied to the mesh, or nil if the mesh does not have a material."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshVertex",
              summary = "Get the data for a single vertex in a mesh.",
              description = "Returns the data for a single vertex in a mesh.  The data returned depends on the vertex format of a mesh, which is given by `ModelData:getMeshVertexFormat`.",
              key = "ModelData:getMeshVertex",
              module = "lovr.data",
              related = {
                "ModelData:getMeshVertexFormat",
                "ModelData:getMeshVertexCount",
                "ModelData:getMeshIndex",
                "ModelData:getTriangles"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh to get the vertex from."
                    },
                    {
                      name = "vertex",
                      type = "number",
                      description = "The index of a vertex in the mesh to retrieve."
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "The data for all of the attributes of the vertex."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshVertexCount",
              summary = "Get the number of vertices in a mesh.",
              description = "Returns the number of vertices in a mesh.",
              key = "ModelData:getMeshVertexCount",
              module = "lovr.data",
              related = {
                "ModelData:getMeshIndexCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices in the mesh."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshVertexFormat",
              summary = "Get the vertex format of a mesh.",
              description = "Returns the vertex format of a mesh.  The vertex format defines the properties associated with each vertex (position, color, etc.), including their types and binary data layout.",
              key = "ModelData:getMeshVertexFormat",
              module = "lovr.data",
              notes = "The format is given as a table of vertex attributes.  Each attribute is a table containing the following:\n\n    { name, type, components, blob, offset, stride }\n\n- The `name` will be a `DefaultAttribute`.\n- The `type` will be an `AttributeType`.\n- The `component` count will be 1-4.\n- The `blob` is an index of one of the Blobs in the model (see `ModelData:getBlob`).\n- The `offset` is a byte offset from the start of the Blob where the attribute's data starts.\n- The `stride` is the number of bytes between consecutive values.",
              related = {
                "ModelData:getMeshIndexFormat"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "number",
                      description = "The index of a mesh."
                    }
                  },
                  returns = {
                    {
                      name = "format",
                      type = "table",
                      description = "The vertex format of the mesh."
                    }
                  }
                }
              }
            },
            {
              name = "getMetadata",
              summary = "Get extra information from the model file.",
              description = "Returns extra information stored in the model file.  Currently this is only implemented for glTF models and returns the JSON string from the glTF or glb file.  The metadata can be used to get application-specific data or add support for glTF extensions not supported by LÖVR.",
              key = "ModelData:getMetadata",
              module = "lovr.data",
              related = {
                "Model:getMetadata"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "metadata",
                      type = "string",
                      description = "The metadata from the model file."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeChildren",
              summary = "Get the children of a node.",
              description = "Given a parent node, this function returns a table with the indices of its children.",
              key = "ModelData:getNodeChildren",
              module = "lovr.data",
              related = {
                "ModelData:getNodeParent",
                "ModelData:getRootNode",
                "Model:getNodeChildren"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of the parent node."
                    }
                  },
                  returns = {
                    {
                      name = "children",
                      type = "{number}",
                      description = "A table containing the node index of each child of the parent node."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeCount",
              summary = "Get the number of nodes in the model.",
              description = "Returns the number of nodes in the model.",
              key = "ModelData:getNodeCount",
              module = "lovr.data",
              related = {
                "Model:getNodeCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of nodes in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeMeshes",
              summary = "Get the indices of meshes attached to a node.",
              description = "Returns a table of mesh indices attached to a node.  Meshes define the geometry and materials of a model, as opposed to the nodes which define the transforms and hierarchy.  A node can have multiple meshes, and meshes can be reused in multiple nodes.",
              key = "ModelData:getNodeMeshes",
              module = "lovr.data",
              related = {
                "ModelData:getMeshCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "meshes",
                      type = "table",
                      description = "A table with the node's mesh indices."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeName",
              summary = "Get the name of a node.",
              description = "Returns the name of a node.",
              key = "ModelData:getNodeName",
              module = "lovr.data",
              notes = "If the node does not have a name, this function returns `nil`.",
              related = {
                "Model:getNodeName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the node."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the node."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeOrientation",
              summary = "Get the local orientation of a node.",
              description = "Returns local orientation of a node, relative to its parent.",
              key = "ModelData:getNodeOrientation",
              module = "lovr.data",
              related = {
                "ModelData:getNodePosition",
                "ModelData:getNodeScale",
                "ModelData:getNodePose",
                "ModelData:getNodeTransform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeParent",
              summary = "Get the parent of a node.",
              description = "Given a child node, this function returns the index of its parent.",
              key = "ModelData:getNodeParent",
              module = "lovr.data",
              related = {
                "ModelData:getNodeChildren",
                "ModelData:getRootNode",
                "Model:getNodeParent"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of the child node."
                    }
                  },
                  returns = {
                    {
                      name = "parent",
                      type = "number",
                      description = "The index of the parent node."
                    }
                  }
                }
              }
            },
            {
              name = "getNodePose",
              summary = "Get the local pose of a node.",
              description = "Returns local pose (position and orientation) of a node, relative to its parent.",
              key = "ModelData:getNodePose",
              module = "lovr.data",
              related = {
                "ModelData:getNodePosition",
                "ModelData:getNodeOrientation",
                "ModelData:getNodeScale",
                "ModelData:getNodeTransform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getNodePosition",
              summary = "Get the local position of a node.",
              description = "Returns local position of a node, relative to its parent.",
              key = "ModelData:getNodePosition",
              module = "lovr.data",
              related = {
                "ModelData:getNodeOrientation",
                "ModelData:getNodeScale",
                "ModelData:getNodePose",
                "ModelData:getNodeTransform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeScale",
              summary = "Get the local scale of a node.",
              description = "Returns local scale of a node, relative to its parent.",
              key = "ModelData:getNodeScale",
              module = "lovr.data",
              related = {
                "ModelData:getNodePosition",
                "ModelData:getNodeOrientation",
                "ModelData:getNodePose",
                "ModelData:getNodeTransform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "sx",
                      type = "number",
                      description = "The x scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z scale."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeSkin",
              summary = "Get the index of the skin used by a node.",
              description = "Returns the index of the skin used by a node.  Skins are collections of joints used for skeletal animation.  A model can have multiple skins, and each node can use at most one skin to drive the animation of its meshes.",
              key = "ModelData:getNodeSkin",
              module = "lovr.data",
              related = {
                "ModelData:getSkinCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "skin",
                      type = "number",
                      description = "The index of the node's skin, or nil if the node isn't skeletally animated."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeTransform",
              summary = "Get the local transform of a node.",
              description = "Returns local transform (position, orientation, and scale) of a node, relative to its parent.",
              key = "ModelData:getNodeTransform",
              module = "lovr.data",
              notes = "For best results when animating, it's recommended to keep the 3 components of the scale the same.",
              related = {
                "ModelData:getNodePosition",
                "ModelData:getNodeOrientation",
                "ModelData:getNodeScale",
                "ModelData:getNodePose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z scale."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getRootNode",
              summary = "Get the index of the root node.",
              description = "Returns the index of the model's root node.",
              key = "ModelData:getRootNode",
              module = "lovr.data",
              related = {
                "ModelData:getNodeCount",
                "ModelData:getNodeParent",
                "Model:getRootNode"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "root",
                      type = "number",
                      description = "The index of the root node."
                    }
                  }
                }
              }
            },
            {
              name = "getSkinCount",
              summary = "Get the number of skins in the model.",
              description = "Returns the number of skins in the model.  A skin is a collection of joints targeted by an animation.",
              key = "ModelData:getSkinCount",
              module = "lovr.data",
              related = {
                "Model:hasJoints"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of skins in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getSkinInverseBindMatrix",
              summary = "Get the inverse bind matrix for a joint in the skin.",
              description = "Returns the inverse bind matrix for a joint in the skin.",
              key = "ModelData:getSkinInverseBindMatrix",
              module = "lovr.data",
              variants = {
                {
                  arguments = {
                    {
                      name = "skin",
                      type = "number",
                      description = "The index of a skin."
                    },
                    {
                      name = "joint",
                      type = "number",
                      description = "The index of a joint in the skin."
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "The 16 components of the 4x4 inverse bind matrix, in column-major order."
                    }
                  }
                }
              }
            },
            {
              name = "getSkinJoints",
              summary = "Get the joints in a skin.",
              description = "Returns a table with the node indices of the joints in a skin.",
              key = "ModelData:getSkinJoints",
              module = "lovr.data",
              notes = "There is currently a maximum of 256 joints per skin.",
              variants = {
                {
                  arguments = {
                    {
                      name = "skin",
                      type = "number",
                      description = "The index of a skin."
                    }
                  },
                  returns = {
                    {
                      name = "joints",
                      type = "table",
                      description = "The joints in the skin."
                    }
                  }
                }
              }
            },
            {
              name = "getTriangleCount",
              summary = "Get the total number of triangles in the model.",
              description = "Returns the total number of triangles in the model.  This count includes meshes that are attached to multiple nodes, and the count corresponds to the triangles returned by `ModelData:getTriangles`.",
              key = "ModelData:getTriangleCount",
              module = "lovr.data",
              related = {
                "ModelData:getTriangles",
                "ModelData:getVertexCount",
                "Model:getTriangleCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The total number of triangles in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getTriangles",
              summary = "Get all the triangles in the model.",
              description = "Returns the data for all triangles in the model.  There are a few differences between this and the mesh-specific functions like `ModelData:getMeshVertex` and `ModelData:getMeshIndex`:\n\n- Only vertex positions are returned, not other vertex attributes.\n- Positions are relative to the origin of the whole model, instead of local to a node.\n- If a mesh is attached to more than one node, its vertices will be in the table multiple times.\n- Vertex indices will be relative to the whole triangle list instead of a mesh.",
              key = "ModelData:getTriangles",
              module = "lovr.data",
              notes = "After this function is called on a ModelData once, the result is cached.",
              related = {
                "ModelData:getTriangleCount",
                "ModelData:getVertexCount",
                "Model:getTriangles"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "vertices",
                      type = "table",
                      description = "The triangle vertex positions, returned as a flat (non-nested) table of numbers.  The position of each vertex is given as an x, y, and z coordinate."
                    },
                    {
                      name = "indices",
                      type = "table",
                      description = "A list of numbers representing how to connect the vertices into triangles.  Each number is a 1-based index into the `vertices` table, and every 3 indices form a triangle."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexCount",
              summary = "Get the total vertex count of the model.",
              description = "Returns the total vertex count of a model.  This count includes meshes that are attached to multiple nodes, and the count corresponds to the vertices returned by `ModelData:getTriangles`.",
              key = "ModelData:getVertexCount",
              module = "lovr.data",
              related = {
                "ModelData:getTriangles",
                "ModelData:getTriangleCount",
                "Model:getVertexCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The total number of vertices in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              summary = "Get the width of the model.",
              description = "Returns the width of the model, computed from its axis-aligned bounding box.",
              key = "ModelData:getWidth",
              module = "lovr.data",
              related = {
                "ModelData:getHeight",
                "ModelData:getDepth",
                "ModelData:getDimensions",
                "ModelData:getCenter",
                "ModelData:getBoundingBox",
                "Model:getWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the model."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Rasterizer",
          summary = "An object that rasterizes glyphs from font files.",
          description = "A Rasterizer is an object that parses a TTF file, decoding and rendering glyphs from it.\n\nUsually you can just use `Font` objects.",
          key = "Rasterizer",
          module = "lovr.data",
          constructors = {
            "lovr.data.newRasterizer"
          },
          extends = "Object",
          methods = {
            {
              name = "getAdvance",
              summary = "Get the advance of a glyph.",
              description = "Returns the advance metric for a glyph, in pixels.  The advance is the horizontal distance to advance the cursor after rendering the glyph.",
              key = "Rasterizer:getAdvance",
              module = "lovr.data",
              examples = {
                {
                  code = "local rasterizer = lovr.data.newRasterizer()\nlocal advance1 = rasterizer:getAdvance('H') + rasterizer:getAdvance('i')\nlocal advance2 = rasterizer:getAdvance(72) + rasterizer:getAdvance(105)\nassert(advance1 == advance2)"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "advance",
                      type = "number",
                      description = "The advance of the glyph, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getAscent",
              summary = "Get the ascent of the font.",
              description = "Returns the ascent metric of the font, in pixels.  The ascent represents how far any glyph of the font ascends above the baseline.",
              key = "Rasterizer:getAscent",
              module = "lovr.data",
              related = {
                "Rasterizer:getDescent",
                "Font:getAscent"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "ascent",
                      type = "number",
                      description = "The ascent of the font, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getBearing",
              summary = "Get the bearing of a glyph.",
              description = "Returns the bearing metric for a glyph, in pixels.  The bearing is the horizontal distance from the cursor to the edge of the glyph.",
              key = "Rasterizer:getBearing",
              module = "lovr.data",
              examples = {
                {
                  code = "local rasterizer = lovr.data.newRasterizer()\n\n-- In the default font, H is wider than i\nassert(rasterizer:getBearing('H') > rasterizer:getBearing('i'))"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "bearing",
                      type = "number",
                      description = "The bearing of the glyph, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingBox",
              summary = "Get the bounding box of a glyph, or the font.",
              description = "Returns the bounding box of a glyph, or the bounding box surrounding all glyphs.  Note that font coordinates use a cartesian \"y up\" coordinate system.",
              key = "Rasterizer:getBoundingBox",
              module = "lovr.data",
              related = {
                "Rasterizer:getWidth",
                "Rasterizer:getHeight",
                "Rasterizer:getDimensions"
              },
              variants = {
                {
                  description = "Get the bounding box of a single glyph.",
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The left edge of the bounding box, in pixels."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The bottom edge of the bounding box, in pixels."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The right edge of the bounding box, in pixels."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The top edge of the bounding box, in pixels."
                    }
                  }
                },
                {
                  description = "Get the bounding box around all glyphs in the font.",
                  arguments = {},
                  returns = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The left edge of the bounding box, in pixels."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The bottom edge of the bounding box, in pixels."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The right edge of the bounding box, in pixels."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The top edge of the bounding box, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getCurves",
              summary = "Get the bezier curves defining a glyph.",
              description = "Returns the bezier curve control points defining the shape of a glyph.",
              key = "Rasterizer:getCurves",
              module = "lovr.data",
              related = {
                "Curve",
                "Rasterizer:newImage"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    },
                    {
                      name = "three",
                      type = "boolean",
                      description = "Whether the control points should be 3D or 2D."
                    }
                  },
                  returns = {
                    {
                      name = "curves",
                      type = "table",
                      description = "A table of curves.  Each curve is a table of numbers representing the control points (2 for a line, 3 for a quadratic curve, etc.)."
                    }
                  }
                }
              }
            },
            {
              name = "getDescent",
              summary = "Get the descent of the font.",
              description = "Returns the descent metric of the font, in pixels.  The descent represents how far any glyph of the font descends below the baseline.",
              key = "Rasterizer:getDescent",
              module = "lovr.data",
              related = {
                "Rasterizer:getAscent",
                "Font:getDescent"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "descent",
                      type = "number",
                      description = "The descent of the font, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              summary = "Get the dimensions of a glyph, or the font.",
              description = "Returns the dimensions of a glyph, or the largest dimensions of any glyph in the font.",
              key = "Rasterizer:getDimensions",
              module = "lovr.data",
              related = {
                "Rasterizer:getWidth",
                "Rasterizer:getHeight",
                "Rasterizer:getBoundingBox"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width, in pixels."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height, in pixels."
                    }
                  }
                },
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width, in pixels."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getFontSize",
              summary = "Get the size of the font.",
              description = "Returns the size of the font, in pixels.  This is the size the rasterizer was created with, and determines the size of images it rasterizes.",
              key = "Rasterizer:getFontSize",
              module = "lovr.data",
              related = {
                "Rasterizer:getHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "size",
                      type = "number",
                      description = "The font size, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getGlyphCount",
              summary = "Get the number of glyphs stored in the font file.",
              description = "Returns the number of glyphs stored in the font file.",
              key = "Rasterizer:getGlyphCount",
              module = "lovr.data",
              related = {
                "Rasterizer:hasGlyphs"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of glyphs stored in the font file."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              summary = "Get the height of a glyph, or the font.",
              description = "Returns the height of a glyph, or the maximum height of any glyph in the font.",
              key = "Rasterizer:getHeight",
              module = "lovr.data",
              related = {
                "Rasterizer:getWidth",
                "Rasterizer:getDimensions",
                "Rasterizer:getBoundingBox"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height, in pixels."
                    }
                  }
                },
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getKerning",
              summary = "Get the kerning between two glyphs.",
              description = "Returns the kerning between 2 glyphs, in pixels.  Kerning is a slight horizontal adjustment between 2 glyphs to improve the visual appearance.  It will often be negative.",
              key = "Rasterizer:getKerning",
              module = "lovr.data",
              related = {
                "Font:getKerning"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "first",
                      type = "string | number",
                      description = "The character or codepoint representing the first glyph."
                    },
                    {
                      name = "second",
                      type = "string | number",
                      description = "The character or codepoint representing the second glyph."
                    }
                  },
                  returns = {
                    {
                      name = "keming",
                      type = "number",
                      description = "The kerning between the two glyphs."
                    }
                  }
                }
              }
            },
            {
              name = "getLeading",
              summary = "Get the leading of the font.",
              description = "Returns the leading metric of the font, in pixels.  This is the full amount of space between lines.",
              key = "Rasterizer:getLeading",
              module = "lovr.data",
              related = {
                "Rasterizer:getAscent",
                "Rasterizer:getDescent"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "leading",
                      type = "number",
                      description = "The font leading, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              summary = "Get the width of a glyph, or the font.",
              description = "Returns the width of a glyph, or the maximum width of any glyph in the font.",
              key = "Rasterizer:getWidth",
              module = "lovr.data",
              related = {
                "Rasterizer:getHeight",
                "Rasterizer:getDimensions",
                "Rasterizer:getBoundingBox"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width, in pixels."
                    }
                  }
                },
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "hasGlyphs",
              summary = "Get whether the Rasterizer can rasterize a set of glyphs.",
              description = "Returns whether the Rasterizer can rasterize a set of glyphs.",
              key = "Rasterizer:hasGlyphs",
              module = "lovr.data",
              examples = {
                {
                  code = "rasterizer = lovr.data.newRasterizer()\n\nfunction lovr.draw(pass)\n  if rasterizer:hasGlyphs('Ö') then\n    pass:text('LÖVR!!!', 0, 2, -3)\n  else\n    pass:text('>:(', 0, 2, -3)\n  end\nend"
                }
              },
              related = {
                "Rasterizer:getGlyphCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "...",
                      type = "string | number",
                      description = "Strings (characters) or numbers (codepoints) to check for."
                    }
                  },
                  returns = {
                    {
                      name = "hasGlyphs",
                      type = "boolean",
                      description = "true if the Rasterizer can rasterize all of the supplied characters, false otherwise."
                    }
                  }
                }
              }
            },
            {
              name = "newImage",
              summary = "Get an Image of a rasterized glyph.",
              description = "Returns an `Image` containing a rasterized glyph.",
              key = "Rasterizer:newImage",
              module = "lovr.data",
              related = {
                "Rasterizer:getCurves"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "glyph",
                      type = "string | number",
                      description = "A character or codepoint to rasterize."
                    },
                    {
                      name = "spread",
                      type = "number",
                      description = "The width of the distance field, for signed distance field rasterization.",
                      default = "4.0"
                    },
                    {
                      name = "padding",
                      type = "number",
                      description = "The number of pixels of padding to add at the edges of the image.",
                      default = "spread / 2"
                    }
                  },
                  returns = {
                    {
                      name = "image",
                      type = "Image",
                      description = "The glyph image.  It will be in the `rgba32f` format."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Sound",
          summary = "An object that holds raw audio samples.",
          description = "A Sound stores the data for a sound.  The supported sound formats are OGG, WAV, and MP3.  Sounds cannot be played directly.  Instead, there are `Source` objects in `lovr.audio` that are used for audio playback.  All Source objects are backed by one of these Sounds, and multiple Sources can share a single Sound to reduce memory usage.\n\nMetadata\n---\n\nSounds hold a fixed number of frames.  Each frame contains one audio sample for each channel. The `SampleFormat` of the Sound is the data type used for each sample (floating point, integer, etc.).  The Sound has a `ChannelLayout`, representing the number of audio channels and how they map to speakers (mono, stereo, etc.).  The sample rate of the Sound indicates how many frames should be played per second.  The duration of the sound (in seconds) is the number of frames divided by the sample rate.\n\nCompression\n---\n\nSounds can be compressed.  Compressed sounds are stored compressed in memory and are decoded as they are played.  This uses a lot less memory but increases CPU usage during playback.  OGG and MP3 are compressed audio formats.  When creating a sound from a compressed format, there is an option to immediately decode it, storing it uncompressed in memory.  It can be a good idea to decode short sound effects, since they won't use very much memory even when uncompressed and it will improve CPU usage.  Compressed sounds can not be written to using `Sound:setFrames`.\n\nStreams\n---\n\nSounds can be created as a stream by passing `'stream'` as their contents when creating them. Audio frames can be written to the end of the stream, and read from the beginning.  This works well for situations where data is being generated in real time or streamed in from some other data source.\n\nSources can be backed by a stream and they'll just play whatever audio is pushed to the stream. The audio module also lets you use a stream as a \"sink\" for an audio device.  For playback devices, this works like loopback, so the mixed audio from all playing Sources will get written to the stream.  For capture devices, all the microphone input will get written to the stream. Conversion between sample formats, channel layouts, and sample rates will happen automatically.\n\nKeep in mind that streams can still only hold a fixed number of frames.  If too much data is written before it is read, older frames will start to get overwritten.  Similary, it's possible to read too much data without writing fast enough.\n\nAmbisonics\n---\n\nAmbisonic sounds can be imported from WAVs, but can not yet be played.  Sounds with a `ChannelLayout` of `ambisonic` are stored as first-order full-sphere ambisonics using the AmbiX format (ACN channel ordering and SN3D channel normalization).  The AMB format is supported for import and will automatically get converted to AmbiX.  See `lovr.data.newSound` for more info.",
          key = "Sound",
          module = "lovr.data",
          constructors = {
            "lovr.data.newSound"
          },
          extends = "Object",
          methods = {
            {
              name = "getBlob",
              summary = "Get the bytes backing this Sound as a Blob.",
              description = "Returns a Blob containing the raw bytes of the Sound.",
              key = "Sound:getBlob",
              module = "lovr.data",
              notes = "Samples for each channel are stored interleaved.  The data type of each sample is given by `Sound:getFormat`.",
              related = {
                "Blob:getPointer",
                "Image:getBlob"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob instance containing the bytes for the `Sound`."
                    }
                  }
                }
              }
            },
            {
              name = "getByteStride",
              summary = "Get the byte stride of the Sound.",
              description = "Returns the byte stride of the Sound.  This is the size of each frame, in bytes.  For example, a stereo sound with a 32-bit floating point format would have a stride of 8 (4 bytes per sample, and 2 samples per frame).",
              key = "Sound:getByteStride",
              module = "lovr.data",
              related = {
                "Sound:getChannelCount",
                "Sound:getFormat"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "stride",
                      type = "number",
                      description = "The size of a frame, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "getCapacity",
              summary = "Get the number of frames that can be written to the Sound.",
              description = "Returns the number of frames that can be written to the Sound.  For stream sounds, this is the number of frames that can currently be written without overwriting existing data.  For normal sounds, this returns the same value as `Sound:getFrameCount`.",
              key = "Sound:getCapacity",
              module = "lovr.data",
              related = {
                "Sound:getFrameCount",
                "Sound:getSampleCount",
                "Source:getDuration"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "capacity",
                      type = "number",
                      description = "The number of frames that can be written to the Sound."
                    }
                  }
                }
              }
            },
            {
              name = "getChannelCount",
              summary = "Get the number of channels in the Sound.",
              description = "Returns the number of channels in the Sound.  Mono sounds have 1 channel, stereo sounds have 2 channels, and ambisonic sounds have 4 channels.",
              key = "Sound:getChannelCount",
              module = "lovr.data",
              related = {
                "Sound:getChannelLayout",
                "Sound:getByteStride"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "channels",
                      type = "number",
                      description = "The number of channels in the sound."
                    }
                  }
                }
              }
            },
            {
              name = "getChannelLayout",
              summary = "Get the channel layout of the Sound.",
              description = "Returns the channel layout of the Sound.",
              key = "Sound:getChannelLayout",
              module = "lovr.data",
              related = {
                "Sound:getChannelCount",
                "Sound:getByteStride"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "channels",
                      type = "ChannelLayout",
                      description = "The channel layout."
                    }
                  }
                }
              }
            },
            {
              name = "getDuration",
              summary = "Get the duration of the Sound.",
              description = "Returns the duration of the Sound, in seconds.",
              key = "Sound:getDuration",
              module = "lovr.data",
              notes = "This can be computed as `(frameCount / sampleRate)`.",
              related = {
                "Sound:getFrameCount",
                "Sound:getSampleCount",
                "Sound:getSampleRate",
                "Source:getDuration"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "duration",
                      type = "number",
                      description = "The duration of the Sound, in seconds."
                    }
                  }
                }
              }
            },
            {
              name = "getFormat",
              summary = "Get the sample format of the Sound.",
              description = "Returns the sample format of the Sound.",
              key = "Sound:getFormat",
              module = "lovr.data",
              related = {
                "Sound:getChannelLayout",
                "Sound:getByteStride",
                "Sound:getSampleRate"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "format",
                      type = "SampleFormat",
                      description = "The data type of each sample."
                    }
                  }
                }
              }
            },
            {
              name = "getFrameCount",
              summary = "Get the number of frames in the Sound.",
              description = "Returns the number of frames in the Sound.  A frame stores one sample for each channel.",
              key = "Sound:getFrameCount",
              module = "lovr.data",
              notes = "For streams, this returns the number of frames in the stream's buffer.",
              related = {
                "Sound:getDuration",
                "Sound:getSampleCount",
                "Sound:getChannelCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frames",
                      type = "number",
                      description = "The number of frames in the Sound."
                    }
                  }
                }
              }
            },
            {
              name = "getFrames",
              summary = "Read frames from the Sound.",
              description = "Reads frames from the Sound into a table, Blob, or another Sound.",
              key = "Sound:getFrames",
              module = "lovr.data",
              variants = {
                {
                  arguments = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames to read.  If nil, reads as many frames as possible.\n\nCompressed sounds will automatically be decoded.\n\nReading from a stream will ignore the source offset and read the oldest frames.",
                      default = "nil"
                    },
                    {
                      name = "srcOffset",
                      type = "number",
                      description = "A frame offset to apply to the sound when reading frames.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table containing audio frames."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames read."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "table",
                      description = "An existing table to read frames into."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames to read.  If nil, reads as many frames as possible.\n\nCompressed sounds will automatically be decoded.\n\nReading from a stream will ignore the source offset and read the oldest frames.",
                      default = "nil"
                    },
                    {
                      name = "srcOffset",
                      type = "number",
                      description = "A frame offset to apply to the sound when reading frames.",
                      default = "0"
                    },
                    {
                      name = "dstOffset",
                      type = "number",
                      description = "An offset to apply to the destination when writing frames (indices for tables, bytes for Blobs, frames for Sounds).",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table containing audio frames."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames read."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "A Blob to read frames into."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames to read.  If nil, reads as many frames as possible.\n\nCompressed sounds will automatically be decoded.\n\nReading from a stream will ignore the source offset and read the oldest frames.",
                      default = "nil"
                    },
                    {
                      name = "srcOffset",
                      type = "number",
                      description = "A frame offset to apply to the sound when reading frames.",
                      default = "0"
                    },
                    {
                      name = "dstOffset",
                      type = "number",
                      description = "An offset to apply to the destination when writing frames (indices for tables, bytes for Blobs, frames for Sounds).",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames read."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "sound",
                      type = "Sound",
                      description = "Another Sound to copy frames into."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames to read.  If nil, reads as many frames as possible.\n\nCompressed sounds will automatically be decoded.\n\nReading from a stream will ignore the source offset and read the oldest frames.",
                      default = "nil"
                    },
                    {
                      name = "srcOffset",
                      type = "number",
                      description = "A frame offset to apply to the sound when reading frames.",
                      default = "0"
                    },
                    {
                      name = "dstOffset",
                      type = "number",
                      description = "An offset to apply to the destination when writing frames (indices for tables, bytes for Blobs, frames for Sounds).",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames read."
                    }
                  }
                }
              }
            },
            {
              name = "getSampleCount",
              summary = "Get the number of samples in the Sound.",
              description = "Returns the total number of samples in the Sound.",
              key = "Sound:getSampleCount",
              module = "lovr.data",
              notes = "For streams, this returns the number of samples in the stream's buffer.",
              related = {
                "Sound:getDuration",
                "Sound:getFrameCount",
                "Sound:getChannelCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "samples",
                      type = "number",
                      description = "The total number of samples in the Sound."
                    }
                  }
                }
              }
            },
            {
              name = "getSampleRate",
              summary = "Get the sample rate of the Sound.",
              description = "Returns the sample rate of the Sound, in Hz.  This is the number of frames that are played every second.  It's usually a high number like 48000.",
              key = "Sound:getSampleRate",
              module = "lovr.data",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The number of frames per second in the Sound."
                    }
                  }
                }
              }
            },
            {
              name = "isCompressed",
              summary = "Check if the Sound is compressed.",
              description = "Returns whether the Sound is compressed.  Compressed sounds are loaded from compressed audio formats like MP3 and OGG.  They use a lot less memory but require some extra CPU work during playback.  Compressed sounds can not be modified using `Sound:setFrames`.",
              key = "Sound:isCompressed",
              module = "lovr.data",
              related = {
                "Sound:isStream",
                "lovr.data.newSound"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "compressed",
                      type = "boolean",
                      description = "Whether the Sound is compressed."
                    }
                  }
                }
              }
            },
            {
              name = "isStream",
              summary = "Check if the Sound is a stream.",
              description = "Returns whether the Sound is a stream.",
              key = "Sound:isStream",
              module = "lovr.data",
              related = {
                "Sound:isCompressed",
                "lovr.data.newSound"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "stream",
                      type = "boolean",
                      description = "Whether the Sound is a stream."
                    }
                  }
                }
              }
            },
            {
              name = "setFrames",
              summary = "Write frames to the Sound.",
              description = "Writes frames to the Sound.",
              key = "Sound:setFrames",
              module = "lovr.data",
              examples = {
                {
                  description = "Generate a sine wave.",
                  code = "function lovr.load()\n  local length = 1\n  local rate = 48000\n  local frames = length * rate\n  local frequency = 440\n  local volume = 1.0\n\n  sound = lovr.data.newSound(frames, 'f32', 'stereo', rate)\n\n  local data = {}\n  for i = 1, frames do\n    local amplitude = math.sin((i - 1) * frequency / rate * (2 * math.pi)) * volume\n    data[2 * i - 1] = amplitude\n    data[2 * i - 0] = amplitude\n  end\n\n  sound:setFrames(data)\n\n  source = lovr.audio.newSource(sound)\n  source:setLooping(true)\n  source:play()\nend"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "source",
                      type = "table | Blob | Sound",
                      description = "A table, Blob, or Sound containing audio frames to write."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "How many frames to write.  If nil, writes as many as possible.",
                      default = "nil"
                    },
                    {
                      name = "dstOffset",
                      type = "number",
                      description = "A frame offset to apply when writing the frames.",
                      default = "0"
                    },
                    {
                      name = "srcOffset",
                      type = "number",
                      description = "A frame, byte, or index offset to apply when reading frames from the source.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of frames written."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    {
      name = "event",
      tag = "modules",
      summary = "Handles events from the operating system.",
      description = "The `lovr.event` module handles events from the operating system.\n\nDue to its low-level nature, it's rare to use `lovr.event` in simple projects.",
      key = "lovr.event",
      enums = {
        {
          name = "DisplayType",
          summary = "Distinguishes between the headset and window displays.",
          description = "This enum is used to distinguish whether a display is the headset display or the desktop window.",
          key = "DisplayType",
          module = "lovr.event",
          related = {
            "lovr.focus",
            "lovr.visible"
          },
          values = {
            {
              name = "headset",
              description = "The headset."
            },
            {
              name = "window",
              description = "The desktop window."
            }
          }
        },
        {
          name = "KeyCode",
          summary = "Keys that can be pressed.",
          description = "Keys that can be pressed on a keyboard.  Notably, numpad keys are missing right now.",
          key = "KeyCode",
          module = "lovr.event",
          related = {
            "lovr.keypressed",
            "lovr.keyreleased"
          },
          values = {
            {
              name = "a",
              description = "The A key."
            },
            {
              name = "b",
              description = "The B key."
            },
            {
              name = "c",
              description = "The C key."
            },
            {
              name = "d",
              description = "The D key."
            },
            {
              name = "e",
              description = "The E key."
            },
            {
              name = "f",
              description = "The F key."
            },
            {
              name = "g",
              description = "The G key."
            },
            {
              name = "h",
              description = "The H key."
            },
            {
              name = "i",
              description = "The I key."
            },
            {
              name = "j",
              description = "The J key."
            },
            {
              name = "k",
              description = "The K key."
            },
            {
              name = "l",
              description = "The L key."
            },
            {
              name = "m",
              description = "The M key."
            },
            {
              name = "n",
              description = "The N key."
            },
            {
              name = "o",
              description = "The O key."
            },
            {
              name = "p",
              description = "The P key."
            },
            {
              name = "q",
              description = "The Q key."
            },
            {
              name = "r",
              description = "The R key."
            },
            {
              name = "s",
              description = "The S key."
            },
            {
              name = "t",
              description = "The T key."
            },
            {
              name = "u",
              description = "The U key."
            },
            {
              name = "v",
              description = "The V key."
            },
            {
              name = "w",
              description = "The W key."
            },
            {
              name = "x",
              description = "The X key."
            },
            {
              name = "y",
              description = "The Y key."
            },
            {
              name = "z",
              description = "The Z key."
            },
            {
              name = "0",
              description = "The 0 key."
            },
            {
              name = "1",
              description = "The 1 key."
            },
            {
              name = "2",
              description = "The 2 key."
            },
            {
              name = "3",
              description = "The 3 key."
            },
            {
              name = "4",
              description = "The 4 key."
            },
            {
              name = "5",
              description = "The 5 key."
            },
            {
              name = "6",
              description = "The 6 key."
            },
            {
              name = "7",
              description = "The 7 key."
            },
            {
              name = "8",
              description = "The 8 key."
            },
            {
              name = "9",
              description = "The 9 key."
            },
            {
              name = "space",
              description = "The space bar."
            },
            {
              name = "return",
              description = "The enter key."
            },
            {
              name = "tab",
              description = "The tab key."
            },
            {
              name = "escape",
              description = "The escape key."
            },
            {
              name = "backspace",
              description = "The backspace key."
            },
            {
              name = "up",
              description = "The up arrow key."
            },
            {
              name = "down",
              description = "The down arrow key."
            },
            {
              name = "left",
              description = "The left arrow key."
            },
            {
              name = "right",
              description = "The right arrow key."
            },
            {
              name = "home",
              description = "The home key."
            },
            {
              name = "end",
              description = "The end key."
            },
            {
              name = "pageup",
              description = "The page up key."
            },
            {
              name = "pagedown",
              description = "The page down key."
            },
            {
              name = "insert",
              description = "The insert key."
            },
            {
              name = "delete",
              description = "The delete key."
            },
            {
              name = "f1",
              description = "The F1 key."
            },
            {
              name = "f2",
              description = "The F2 key."
            },
            {
              name = "f3",
              description = "The F3 key."
            },
            {
              name = "f4",
              description = "The F4 key."
            },
            {
              name = "f5",
              description = "The F5 key."
            },
            {
              name = "f6",
              description = "The F6 key."
            },
            {
              name = "f7",
              description = "The F7 key."
            },
            {
              name = "f8",
              description = "The F8 key."
            },
            {
              name = "f9",
              description = "The F9 key."
            },
            {
              name = "f10",
              description = "The F10 key."
            },
            {
              name = "f11",
              description = "The F11 key."
            },
            {
              name = "f12",
              description = "The F12 key."
            },
            {
              name = "`",
              description = "The backtick/backquote/grave accent key."
            },
            {
              name = "-",
              description = "The dash/hyphen/minus key."
            },
            {
              name = "=",
              description = "The equal sign key."
            },
            {
              name = "[",
              description = "The left bracket key."
            },
            {
              name = "]",
              description = "The right bracket key."
            },
            {
              name = "\\",
              description = "The backslash key."
            },
            {
              name = ";",
              description = "The semicolon key."
            },
            {
              name = "'",
              description = "The single quote key."
            },
            {
              name = ",",
              description = "The comma key."
            },
            {
              name = ".",
              description = "The period key."
            },
            {
              name = "/",
              description = "The slash key."
            },
            {
              name = "kp0",
              description = "The 0 numpad key."
            },
            {
              name = "kp1",
              description = "The 1 numpad key."
            },
            {
              name = "kp2",
              description = "The 2 numpad key."
            },
            {
              name = "kp3",
              description = "The 3 numpad key."
            },
            {
              name = "kp4",
              description = "The 4 numpad key."
            },
            {
              name = "kp5",
              description = "The 5 numpad key."
            },
            {
              name = "kp6",
              description = "The 6 numpad key."
            },
            {
              name = "kp7",
              description = "The 7 numpad key."
            },
            {
              name = "kp8",
              description = "The 8 numpad key."
            },
            {
              name = "kp9",
              description = "The 9 numpad key."
            },
            {
              name = "kp.",
              description = "The . numpad key."
            },
            {
              name = "kp/",
              description = "The / numpad key."
            },
            {
              name = "kp*",
              description = "The * numpad key."
            },
            {
              name = "kp-",
              description = "The - numpad key."
            },
            {
              name = "kp+",
              description = "The + numpad key."
            },
            {
              name = "kpenter",
              description = "The enter numpad key."
            },
            {
              name = "kp=",
              description = "The equals numpad key."
            },
            {
              name = "lctrl",
              description = "The left control key."
            },
            {
              name = "lshift",
              description = "The left shift key."
            },
            {
              name = "lalt",
              description = "The left alt key."
            },
            {
              name = "lgui",
              description = "The left OS key (windows, command, super)."
            },
            {
              name = "rctrl",
              description = "The right control key."
            },
            {
              name = "rshift",
              description = "The right shift key."
            },
            {
              name = "ralt",
              description = "The right alt key."
            },
            {
              name = "rgui",
              description = "The right OS key (windows, command, super)."
            },
            {
              name = "capslock",
              description = "The caps lock key."
            },
            {
              name = "scrolllock",
              description = "The scroll lock key."
            },
            {
              name = "numlock",
              description = "The numlock key."
            }
          }
        }
      },
      examples = {
        {
          description = "Adding a custom event.",
          code = "function lovr.load()\n  lovr.handlers['customevent'] = function(a, b, c)\n    print('custom event handled with args:', a, b, c)\n  end\n\n  lovr.event.push('customevent', 1, 2, 3)\nend"
        }
      },
      functions = {
        {
          name = "clear",
          summary = "Clear the event queue.",
          description = "Clears the event queue, removing any unprocessed events.",
          key = "lovr.event.clear",
          module = "lovr.event",
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "poll",
          summary = "Iterate over unprocessed events in the queue.",
          description = "This function returns a Lua iterator for all of the unprocessed items in the event queue.  Each event consists of a name as a string, followed by event-specific arguments.  This function is called in the default implementation of `lovr.run`, so it is normally not necessary to poll for events yourself.",
          key = "lovr.event.poll",
          module = "lovr.event",
          examples = {
            {
              code = "for name, arg1, arg2, arg3 in lovr.event.poll() do\n  print(name, arg1, arg2, arg3)\nend"
            }
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "iterator",
                  type = "function",
                  description = "The iterator function, usable in a for loop.",
                  arguments = {},
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "push",
          summary = "Manually push an event onto the queue.",
          description = "Pushes an event onto the event queue.  It will be processed the next time `lovr.event.poll` is called.  For an event to be processed properly, there needs to be a function in the `lovr.handlers` table with a key that's the same as the event name.",
          key = "lovr.event.push",
          module = "lovr.event",
          notes = "Arguments can be nil, booleans, numbers, strings, lightuserdata, vectors, tables, and LÖVR objects.",
          related = {
            "lovr.event.poll",
            "lovr.event.quit"
          },
          variants = {
            {
              arguments = {
                {
                  name = "name",
                  type = "string",
                  description = "The name of the event."
                },
                {
                  name = "...",
                  type = "*",
                  description = "The arguments for the event.  Currently, up to 4 are supported."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "quit",
          summary = "Quit the application.",
          description = "Pushes an event to quit.  An optional number can be passed to set the exit code for the application.  An exit code of zero indicates normal termination, whereas a nonzero exit code indicates that an error occurred.",
          key = "lovr.event.quit",
          module = "lovr.event",
          notes = "This function is equivalent to calling `lovr.event.push('quit', code)`.\n\nThe event won't be processed until the next time `lovr.event.poll` is called.\n\nThe `lovr.quit` callback will be called when the event is processed, which can be used to do any cleanup work.  The callback can also return `false` to abort the quitting process.",
          related = {
            "lovr.quit",
            "lovr.event.poll",
            "lovr.event.restart"
          },
          variants = {
            {
              arguments = {
                {
                  name = "code",
                  type = "number",
                  description = "The exit code of the program.",
                  default = "0"
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "restart",
          summary = "Restart the application.",
          description = "Pushes an event to restart the framework.",
          key = "lovr.event.restart",
          module = "lovr.event",
          notes = "The event won't be processed until the next time `lovr.event.poll` is called.\n\nThe `lovr.restart` callback can be used to persist a value between restarts.",
          related = {
            "lovr.restart",
            "lovr.event.poll",
            "lovr.event.quit"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        }
      },
      notes = "You can define your own custom events by adding a function to the `lovr.handlers` table with a key of the name of the event you want to add.  Then, push the event using `lovr.event.push`.",
      objects = {}
    },
    {
      name = "filesystem",
      tag = "modules",
      summary = "Provides access to the filesystem.",
      description = "The `lovr.filesystem` module provides access to the filesystem.\n\nAll files written will go in a special folder called the \"save directory\".  The location of the save directory is platform-specific:\n\n<table>\n  <tr>\n    <td>Windows</td>\n    <td><code>C:\\Users\\&lt;user&gt;\\AppData\\Roaming\\LOVR\\&lt;identity&gt;</code></td>\n  </tr>\n  <tr>\n    <td>macOS</td>\n    <td><code>/Users/&lt;user&gt;/Library/Application Support/LOVR/&lt;identity&gt;</code></td>\n  </tr>\n  <tr>\n    <td>Linux</td>\n    <td><code>/home/&lt;user&gt;/.local/share/LOVR/&lt;identity&gt;</code></td>\n  </tr>\n  <tr>\n    <td>Android</td>\n    <td><code>/sdcard/Android/data/&lt;identity&gt;/files</code></td>\n  </tr> </table>\n\n`<identity>` is a unique identifier for the project, and can be set in `lovr.conf`.  On Android, the identity can not be changed and will always be the package id (e.g. `org.lovr.app`).\n\nWhen files are read, they will be searched for in multiple places.  By default, the save directory is checked first, then the project source (folder or zip).  That way, when data is written to a file, any future reads will see the new data.  The `t.saveprecedence` conf setting can be used to change this precedence.\n\nConceptually, `lovr.filesystem` uses a \"virtual filesystem\", which is an ordered list of folders and zip files that are merged into a single filesystem hierarchy.  Folders and archives in the list can be added and removed with `lovr.filesystem.mount` and `lovr.filesystem.unmount`.\n\nLÖVR extends Lua's `require` function to look for modules in the virtual filesystem.  The search patterns can be changed with `lovr.filesystem.setRequirePath`, similar to `package.path`.",
      key = "lovr.filesystem",
      enums = {
        {
          name = "FileAction",
          summary = "Different actions that can be taken on files.",
          description = "The different actions that can be taken on files, reported by `lovr.filechanged` when filesystem watching is active.",
          key = "FileAction",
          module = "lovr.filesystem",
          values = {
            {
              name = "create",
              description = "The file was created."
            },
            {
              name = "delete",
              description = "The file was deleted."
            },
            {
              name = "modify",
              description = "The file's contents were modified."
            },
            {
              name = "rename",
              description = "The file was renamed."
            }
          }
        },
        {
          name = "OpenMode",
          summary = "Different ways to open a file.",
          description = "Different ways to open a `File` with `lovr.filesystem.newFile`.",
          key = "OpenMode",
          module = "lovr.filesystem",
          values = {
            {
              name = "r",
              description = "Open the file for reading."
            },
            {
              name = "w",
              description = "Open the file for writing (overwrites existing data)."
            },
            {
              name = "a",
              description = "Open the file for appending."
            }
          }
        }
      },
      functions = {
        {
          name = "append",
          tag = "filesystem-files",
          summary = "Append content to the end of a file.",
          description = "Appends content to the end of a file.",
          key = "lovr.filesystem.append",
          module = "lovr.filesystem",
          notes = "If the file does not exist, it is created.",
          variants = {
            {
              arguments = {
                {
                  name = "filename",
                  type = "string",
                  description = "The file to append to."
                },
                {
                  name = "content",
                  type = "string | Blob",
                  description = "A string or Blob to append to the file."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the operation was successful."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, or `nil` if there was no error."
                }
              }
            }
          }
        },
        {
          name = "createDirectory",
          tag = "filesystem-files",
          summary = "Create a directory.",
          description = "Creates a directory in the save directory.  Also creates any intermediate directories that don't exist.",
          key = "lovr.filesystem.createDirectory",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The directory to create, recursively."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the directory was created."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message."
                }
              }
            }
          }
        },
        {
          name = "getAppdataDirectory",
          tag = "filesystem-paths",
          summary = "Get the application data directory.",
          description = "Returns the application data directory.  This will be something like:\n\n- `C:\\Users\\user\\AppData\\Roaming` on Windows.\n- `/home/user/.config` on Linux.\n- `/Users/user/Library/Application Support` on macOS.",
          key = "lovr.filesystem.getAppdataDirectory",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string | nil",
                  description = "The absolute path to the appdata directory."
                }
              }
            }
          }
        },
        {
          name = "getDirectoryItems",
          tag = "filesystem-files",
          summary = "Get a list of files in a directory.",
          description = "Returns a sorted table containing all files and folders in a single directory.",
          key = "lovr.filesystem.getDirectoryItems",
          module = "lovr.filesystem",
          notes = "This function calls `table.sort` to sort the results, so if `table.sort` is not available in the global scope the results are not guaranteed to be sorted.",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The directory."
                }
              },
              returns = {
                {
                  name = "items",
                  type = "{string}",
                  description = "A table with a string for each file and subfolder in the directory."
                }
              }
            }
          }
        },
        {
          name = "getExecutablePath",
          tag = "filesystem-paths",
          summary = "Get the path of the LÖVR executable.",
          description = "Returns the absolute path of the LÖVR executable.",
          key = "lovr.filesystem.getExecutablePath",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string | nil",
                  description = "The absolute path of the LÖVR executable, or `nil` if it is unknown."
                }
              }
            }
          }
        },
        {
          name = "getIdentity",
          tag = "filesystem-virtual",
          summary = "Get the name of the save directory.",
          description = "Returns the identity of the game, which is used as the name of the save directory.  The default is `default`.  It can be changed using `t.identity` in `lovr.conf`.",
          key = "lovr.filesystem.getIdentity",
          module = "lovr.filesystem",
          notes = "On Android, this is always the package id (like `org.lovr.app`).",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "identity",
                  type = "string | nil",
                  description = "The name of the save directory, or `nil` if it isn't set."
                }
              }
            }
          }
        },
        {
          name = "getLastModified",
          tag = "filesystem-files",
          summary = "Get the modification time of a file.",
          description = "Returns when a file was last modified, since some arbitrary time in the past.",
          key = "lovr.filesystem.getLastModified",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The file to check."
                }
              },
              returns = {
                {
                  name = "time",
                  type = "number | nil",
                  description = "The modification time of the file, in seconds, or `nil` if there was an error."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, if there was an error."
                }
              }
            }
          }
        },
        {
          name = "getRealDirectory",
          tag = "filesystem-virtual",
          summary = "Get the absolute path to a file.",
          description = "Get the absolute path of the mounted archive containing a path in the virtual filesystem.  This can be used to determine if a file is in the game's source directory or the save directory.",
          key = "lovr.filesystem.getRealDirectory",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path to check."
                }
              },
              returns = {
                {
                  name = "realpath",
                  type = "string | nil",
                  description = "The absolute path of the mounted archive containing `path`, or `nil` if the file is not in the virtual filesystem."
                }
              }
            }
          }
        },
        {
          name = "getRequirePath",
          tag = "filesystem-lua",
          summary = "Get the require path.",
          description = "Returns the require path.  The require path is a semicolon-separated list of patterns that LÖVR will use to search for files when they are `require`d.  Any question marks in the pattern will be replaced with the module that is being required.  It is similar to Lua\\'s `package.path` variable, but the main difference is that the patterns are relative to the virtual filesystem.",
          key = "lovr.filesystem.getRequirePath",
          module = "lovr.filesystem",
          notes = "The default reqiure path is '?.lua;?/init.lua'.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string",
                  description = "The semicolon separated list of search patterns."
                }
              }
            }
          }
        },
        {
          name = "getSaveDirectory",
          tag = "filesystem-paths",
          summary = "Get the location of the save directory.",
          description = "Returns the absolute path to the save directory.",
          key = "lovr.filesystem.getSaveDirectory",
          module = "lovr.filesystem",
          notes = "The save directory takes the following form:\n\n    <appdata>/LOVR/<identity>\n\nWhere `<appdata>` is `lovr.filesystem.getAppdataDirectory` and `<identity>` is `lovr.filesystem.getIdentity` and can be customized using `lovr.conf`.",
          related = {
            "lovr.filesystem.getIdentity",
            "lovr.filesystem.getAppdataDirectory"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string",
                  description = "The absolute path to the save directory."
                }
              }
            }
          }
        },
        {
          name = "getSize",
          tag = "filesystem-files",
          summary = "Get the size of a file.",
          description = "Returns the size of a file, in bytes.",
          key = "lovr.filesystem.getSize",
          module = "lovr.filesystem",
          notes = "If the file does not exist, an error is thrown.",
          related = {
            "File:getSize"
          },
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string",
                  description = "The file."
                }
              },
              returns = {
                {
                  name = "size",
                  type = "number | nil",
                  description = "The size of the file, in bytes, or `nil` if there was an error."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, if the operation was not successful."
                }
              }
            }
          }
        },
        {
          name = "getSource",
          tag = "filesystem-paths",
          summary = "Get the location of the project source.",
          description = "Get the absolute path of the project's source directory or archive.",
          key = "lovr.filesystem.getSource",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string | nil",
                  description = "The absolute path of the project's source, or `nil` if it's unknown."
                }
              }
            }
          }
        },
        {
          name = "getUserDirectory",
          tag = "filesystem-paths",
          summary = "Get the location of the user's home directory.",
          description = "Returns the absolute path of the user's home directory.",
          key = "lovr.filesystem.getUserDirectory",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string | nil",
                  description = "The absolute path of the user's home directory."
                }
              }
            }
          }
        },
        {
          name = "getWorkingDirectory",
          tag = "filesystem-paths",
          summary = "Get the current working directory.",
          description = "Returns the absolute path of the working directory.  Usually this is where the executable was started from.",
          key = "lovr.filesystem.getWorkingDirectory",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "path",
                  type = "string | nil",
                  description = "The current working directory, or `nil` if it's unknown."
                }
              }
            }
          }
        },
        {
          name = "isDirectory",
          tag = "filesystem-files",
          summary = "Check whether a path is a directory.",
          description = "Check if a path exists and is a directory.",
          key = "lovr.filesystem.isDirectory",
          module = "lovr.filesystem",
          related = {
            "lovr.filesystem.isFile"
          },
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path to check."
                }
              },
              returns = {
                {
                  name = "isDirectory",
                  type = "boolean",
                  description = "Whether or not the path is a directory."
                }
              }
            }
          }
        },
        {
          name = "isFile",
          tag = "filesystem-files",
          summary = "Check whether a path is a file.",
          description = "Check if a path exists and is a file.",
          key = "lovr.filesystem.isFile",
          module = "lovr.filesystem",
          related = {
            "lovr.filesystem.isDirectory"
          },
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path to check."
                }
              },
              returns = {
                {
                  name = "isFile",
                  type = "boolean",
                  description = "Whether or not the path is a file."
                }
              }
            }
          }
        },
        {
          name = "isFused",
          tag = "filesystem-virtual",
          summary = "Check if the project is fused.",
          description = "Returns whether the current project source is fused to the executable.",
          key = "lovr.filesystem.isFused",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "fused",
                  type = "boolean",
                  description = "Whether or not the project is fused."
                }
              }
            }
          }
        },
        {
          name = "load",
          tag = "filesystem-lua",
          summary = "Load a file as Lua code.",
          description = "Load a file containing Lua code, returning a Lua chunk that can be run.",
          key = "lovr.filesystem.load",
          module = "lovr.filesystem",
          examples = {
            {
              description = "Safely loading code:",
              code = "local success, chunk = pcall(lovr.filesystem.load, filename)\nif not success then\n  print('Oh no! There was an error: ' .. tostring(chunk))\nelse\n  local success, result = pcall(chunk)\n  print(success, result)\nend"
            }
          },
          notes = "An error is thrown if the file contains syntax errors.",
          variants = {
            {
              arguments = {
                {
                  name = "filename",
                  type = "string",
                  description = "The file to load."
                },
                {
                  name = "mode",
                  type = "string",
                  description = "The type of code that can be loaded.  `t` allows text, `b` allows binary, and `bt` allows both.",
                  default = "'bt'"
                }
              },
              returns = {
                {
                  name = "chunk",
                  type = "function",
                  description = "The runnable chunk."
                }
              }
            }
          }
        },
        {
          name = "mount",
          tag = "filesystem-virtual",
          summary = "Mount a directory or archive.",
          description = "Mounts a directory or `.zip` archive, adding it to the virtual filesystem.  This allows you to read files from it.",
          key = "lovr.filesystem.mount",
          module = "lovr.filesystem",
          examples = {
            {
              description = "Mount `data.zip` with a file `images/background.png`:",
              code = "lovr.filesystem.mount('data.zip', 'assets')\nprint(lovr.filesystem.isFile('assets/images/background.png')) -- true"
            }
          },
          notes = "The `append` option lets you control the priority of the archive's files in the event of naming collisions.\n\nThis function is not thread safe.  Mounting or unmounting an archive while other threads call lovr.filesystem functions is not supported.",
          related = {
            "lovr.filesystem.unmount"
          },
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path to mount."
                },
                {
                  name = "mountpoint",
                  type = "string",
                  description = "The path in the virtual filesystem to mount to.",
                  default = "'/'"
                },
                {
                  name = "append",
                  type = "boolean",
                  description = "Whether the archive will be added to the end or the beginning of the search path.",
                  default = "false"
                },
                {
                  name = "root",
                  type = "string",
                  description = "A subdirectory inside the archive to use as the root.  If `nil`, the actual root of the archive is used.",
                  default = "nil"
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the archive was successfully mounted."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, if the archive failed to mount."
                }
              }
            }
          }
        },
        {
          name = "newBlob",
          tag = "filesystem-files",
          summary = "Create a new Blob from a file.",
          description = "Creates a new Blob that contains the contents of a file.",
          key = "lovr.filesystem.newBlob",
          module = "lovr.filesystem",
          related = {
            "lovr.data.newBlob",
            "Blob"
          },
          variants = {
            {
              arguments = {
                {
                  name = "filename",
                  type = "string",
                  description = "The file to load."
                }
              },
              returns = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "The new Blob."
                }
              }
            }
          }
        },
        {
          name = "newFile",
          tag = "filesystem-files",
          summary = "Open a file, returning a `File` object.",
          description = "Opens a file, returning a `File` object that can be used to read/write the file contents.\n\nNormally you can just use `lovr.filesystem.read`, `lovr.filesystem.write`, etc.  However, those methods open and close the file each time they are called.  So, when performing multiple operations on a file, creating a File object and keeping it open will have less overhead.",
          key = "lovr.filesystem.newFile",
          module = "lovr.filesystem",
          examples = {
            {
              code = "function lovr.load()\n  local file = lovr.filesystem.newFile('asdf.txt', 'w')\n  file:write('asdf')\n  file:release()\nend"
            }
          },
          related = {
            "lovr.filesystem.read",
            "lovr.filesystem.write",
            "lovr.filesystem.append"
          },
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path of the file to open."
                },
                {
                  name = "mode",
                  type = "OpenMode",
                  description = "The mode to open the file in (`r`, `w`, or `a`)."
                }
              },
              returns = {
                {
                  name = "file",
                  type = "File",
                  description = "A new file object, or nil if an error occurred."
                },
                {
                  name = "error",
                  type = "string",
                  description = "The error message, if an error occurred."
                }
              }
            }
          }
        },
        {
          name = "read",
          tag = "filesystem-files",
          summary = "Read a file.",
          description = "Read the contents of a file.",
          key = "lovr.filesystem.read",
          module = "lovr.filesystem",
          variants = {
            {
              arguments = {
                {
                  name = "filename",
                  type = "string",
                  description = "The name of the file to read."
                }
              },
              returns = {
                {
                  name = "contents",
                  type = "string | nil",
                  description = "The contents of the file, or nil if the file could not be read."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, if any."
                }
              }
            }
          }
        },
        {
          name = "remove",
          tag = "filesystem-files",
          summary = "Remove a file or directory.",
          description = "Remove a file or directory in the save directory.",
          key = "lovr.filesystem.remove",
          module = "lovr.filesystem",
          notes = "A directory can only be removed if it is empty.\n\nTo recursively remove a folder, use this function with `lovr.filesystem.getDirectoryItems`.",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The file or directory to remove."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the path was removed."
                },
                {
                  name = "error",
                  type = "string | nil",
                  description = "The error message, if any."
                }
              }
            }
          }
        },
        {
          name = "setIdentity",
          tag = "filesystem-virtual",
          summary = "Set the name of the save directory.",
          description = "Set the name of the save directory.  This function can only be called once and is called automatically at startup, so this function normally isn't called manually.  However, the identity can be changed by setting the `t.identity` option in `lovr.conf`.",
          key = "lovr.filesystem.setIdentity",
          module = "lovr.filesystem",
          related = {
            "lovr.conf",
            "lovr.filesystem.getSaveDirectory"
          },
          variants = {
            {
              arguments = {
                {
                  name = "identity",
                  type = "string",
                  description = "The name of the save directory."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setRequirePath",
          tag = "filesystem-lua",
          summary = "Set the require path.",
          description = "Sets the require path.  The require path is a semicolon-separated list of patterns that LÖVR will use to search for files when they are `require`d.  Any question marks in the pattern will be replaced with the module that is being required.  It is similar to Lua\\'s `package.path` variable, except the patterns will be checked using `lovr.filesystem` APIs. This allows `require` to work even when the project is packaged into a zip archive, or when the project is launched from a different directory.",
          key = "lovr.filesystem.setRequirePath",
          module = "lovr.filesystem",
          notes = "The default reqiure path is '?.lua;?/init.lua'.",
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "An optional semicolon separated list of search patterns.",
                  default = "nil"
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "unmount",
          tag = "filesystem-virtual",
          summary = "Unmount a mounted archive.",
          description = "Unmounts a directory or archive previously mounted with `lovr.filesystem.mount`.",
          key = "lovr.filesystem.unmount",
          module = "lovr.filesystem",
          notes = "This function is not thread safe.  Mounting or unmounting an archive while other threads call lovr.filesystem functions is not supported.",
          related = {
            "lovr.filesystem.mount"
          },
          variants = {
            {
              arguments = {
                {
                  name = "path",
                  type = "string",
                  description = "The path to unmount."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the archive was unmounted."
                }
              }
            }
          }
        },
        {
          name = "unwatch",
          tag = "filesystem-files",
          summary = "Stop watching files.",
          description = "Stops watching files.",
          key = "lovr.filesystem.unwatch",
          module = "lovr.filesystem",
          related = {
            "lovr.filesystem.watch",
            "lovr.filechanged"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "watch",
          tag = "filesystem-files",
          summary = "Start watching the filesystem for changes.",
          description = "Starts watching the filesystem for changes.  File events will be reported by the `lovr.filechanged` callback.\n\nCurrently, on PC, only files in the source directory will be watched.  On Android, files in the save directory will be watched instead, so that pushing new files with `adb` can be detected.",
          key = "lovr.filesystem.watch",
          module = "lovr.filesystem",
          related = {
            "lovr.filesystem.unwatch",
            "lovr.filechanged"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "write",
          tag = "filesystem-files",
          summary = "Write to a file.",
          description = "Write to a file in the save directory.",
          key = "lovr.filesystem.write",
          module = "lovr.filesystem",
          notes = "If the file does not exist, it is created.\n\nIf the file already has data in it, it will be replaced with the new content.\n\nIf the path contains subdirectories, all of the parent directories need to exist first or the write will fail.  Use `lovr.filesystem.createDirectory` to make sure they're created first.",
          related = {
            "lovr.filesystem.append",
            "lovr.filesystem.getSaveDirectory",
            "lovr.filesystem.read"
          },
          variants = {
            {
              arguments = {
                {
                  name = "filename",
                  type = "string",
                  description = "The file to write to."
                },
                {
                  name = "content",
                  type = "string | Blob",
                  description = "A string or Blob to write to the file."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the write was successful."
                },
                {
                  name = "error",
                  type = "string",
                  description = "The error message, if there was an error."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "File",
          summary = "Represents an open file handle.",
          description = "A File is an object that provides read or write access to a file on the filesystem.",
          key = "File",
          module = "lovr.filesystem",
          constructors = {
            "lovr.filesystem.newFile"
          },
          extends = "Object",
          methods = {
            {
              name = "getMode",
              summary = "Get the mode the file was opened in.",
              description = "Returns the mode the file was opened in.",
              key = "File:getMode",
              module = "lovr.filesystem",
              related = {
                "File:getPath"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mode",
                      type = "OpenMode",
                      description = "The mode the file was opened in (`r`, `w`, or `a`)."
                    }
                  }
                }
              }
            },
            {
              name = "getPath",
              summary = "Get the file's path.",
              description = "Returns the file's path.",
              key = "File:getPath",
              module = "lovr.filesystem",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "path",
                      type = "string",
                      description = "The file path."
                    }
                  }
                }
              }
            },
            {
              name = "getSize",
              summary = "Get the size of the File.",
              description = "Returns the size of the file, in bytes.",
              key = "File:getSize",
              module = "lovr.filesystem",
              related = {
                "lovr.filesystem.getSize"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "size",
                      type = "number",
                      description = "The size of the file, in bytes, or nil if an error occurred."
                    },
                    {
                      name = "error",
                      type = "string",
                      description = "The error message, if an error occurred."
                    }
                  }
                }
              }
            },
            {
              name = "isEOF",
              summary = "Check if the end of the file has been reached.",
              description = "Returns whether the end of file has been reached.  When true, `File:read` will no longer return data.",
              key = "File:isEOF",
              module = "lovr.filesystem",
              related = {
                "File:seek",
                "File:tell",
                "File:getSize"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "eof",
                      type = "boolean",
                      description = "Whether the end of the file has been reached."
                    }
                  }
                }
              }
            },
            {
              name = "read",
              summary = "Read data from the file.",
              description = "Reads data from the file.",
              key = "File:read",
              module = "lovr.filesystem",
              notes = "The file must have been opened for reading.\n\nThe maximum number of bytes that can be read at a time is 2^53 - 1.",
              related = {
                "File:write",
                "lovr.filesystem.read",
                "lovr.filesystem.newBlob"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "bytes",
                      type = "number",
                      description = "The number of bytes to read from the file, or `nil` to read the rest of the file."
                    }
                  },
                  returns = {
                    {
                      name = "data",
                      type = "string",
                      description = "The data that was read, or nil if an error occurred."
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes that were read, or the error message if an error occurred."
                    }
                  }
                }
              }
            },
            {
              name = "seek",
              summary = "Seek to a position in the file.",
              description = "Seeks to a new position in the file.  `File:read` and `File:write` will read/write relative to this position.",
              key = "File:seek",
              module = "lovr.filesystem",
              related = {
                "File:tell",
                "File:getSize"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "The new file offset, in bytes."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "tell",
              summary = "Get the seek position of the file.",
              description = "Returns the seek position of the file, which is where `File:read` and `File:write will read/write from.",
              key = "File:tell",
              module = "lovr.filesystem",
              related = {
                "File:seek"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "offset",
                      type = "number",
                      description = "The file offset, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "write",
              summary = "Write data to the file.",
              description = "Writes data to the file.",
              key = "File:write",
              module = "lovr.filesystem",
              notes = "The maximum number of bytes that can be written at a time is 2^53 - 1.\n\nUse `File:seek` to control where the data is written.",
              related = {
                "File:read",
                "lovr.filesystem.write",
                "lovr.filesystem.append"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "string",
                      type = "string",
                      description = "A string to write to the file."
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes to write, or nil to write all of the data from the string/Blob.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "success",
                      type = "boolean",
                      description = "Whether the data was successfully written."
                    },
                    {
                      name = "message",
                      type = "string",
                      description = "The error message."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob containing data to write to the file."
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes to write, or nil to write all of the data from the string/Blob.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "success",
                      type = "boolean",
                      description = "Whether the data was successfully written."
                    },
                    {
                      name = "message",
                      type = "string",
                      description = "The error message."
                    }
                  }
                }
              }
            }
          }
        }
      },
      sections = {
        {
          name = "Files",
          tag = "filesystem-files",
          description = "Operations for reading/writing files and querying their metadata."
        },
        {
          name = "Virtual Filesystem",
          tag = "filesystem-virtual"
        },
        {
          name = "Paths",
          tag = "filesystem-paths",
          description = "Useful system paths."
        },
        {
          name = "Lua",
          tag = "filesystem-lua"
        }
      }
    },
    {
      name = "graphics",
      tag = "modules",
      summary = "Renders graphics using the GPU.",
      description = "The graphics module renders graphics and performs computation using the GPU.\n\nMost of the graphics functions are on the `Pass` object.",
      key = "lovr.graphics",
      enums = {
        {
          name = "BlendAlphaMode",
          summary = "Whether premultiplied alpha is enabled.",
          description = "Controls whether premultiplied alpha is enabled.",
          key = "BlendAlphaMode",
          module = "lovr.graphics",
          notes = "The premultiplied mode should be used if pixels being drawn have already been blended, or \"pre-multiplied\", by the alpha channel.  This happens when rendering to a texture that contains pixels with transparent alpha values, since the stored color values have already been faded by alpha and don't need to be faded a second time with the alphamultiply blend mode.",
          related = {
            "BlendMode",
            "Pass:setBlendMode"
          },
          values = {
            {
              name = "alphamultiply",
              description = "Color channel values are multiplied by the alpha channel during blending."
            },
            {
              name = "premultiplied",
              description = "Color channel values are not multiplied by the alpha.  Instead, it's assumed that the colors have already been multiplied by the alpha.  This should be used if the pixels being drawn have already been blended, or \"pre-multiplied\"."
            }
          }
        },
        {
          name = "BlendMode",
          summary = "Blend modes.",
          description = "Different ways pixels can blend with the pixels behind them.",
          key = "BlendMode",
          module = "lovr.graphics",
          related = {
            "BlendAlphaMode",
            "Pass:setBlendMode"
          },
          values = {
            {
              name = "alpha",
              description = "Colors will be mixed based on alpha."
            },
            {
              name = "add",
              description = "Colors will be added to the existing color, alpha will not be changed."
            },
            {
              name = "subtract",
              description = "Colors will be subtracted from the existing color, alpha will not be changed."
            },
            {
              name = "multiply",
              description = "All color channels will be multiplied together, producing a darkening effect."
            },
            {
              name = "lighten",
              description = "The maximum value of each color channel will be used."
            },
            {
              name = "darken",
              description = "The minimum value of each color channel will be used."
            },
            {
              name = "screen",
              description = "The opposite of multiply: the pixel colors are inverted, multiplied, and inverted again, producing a lightening effect."
            },
            {
              name = "none",
              description = "The incoming colors will replace the existing colors.  This is the same as using a blend mode of `nil`."
            }
          }
        },
        {
          name = "CompareMode",
          summary = "Different ways of performing comparisons.",
          description = "The method used to compare depth and stencil values when performing the depth and stencil tests. Also used for compare modes in `Sampler`s.",
          key = "CompareMode",
          module = "lovr.graphics",
          notes = "This type can also be specified using mathematical notation, e.g. `=`, `>`, `<=`, etc. `notequal` can be provided as `~=` or `!=`.",
          related = {
            "Pass:setDepthTest",
            "Pass:setStencilTest",
            "Pass:setDepthWrite",
            "Pass:setStencilWrite"
          },
          values = {
            {
              name = "none",
              description = "The test does not take place, and acts as though it always passes."
            },
            {
              name = "equal",
              description = "The test passes if the values are equal."
            },
            {
              name = "notequal",
              description = "The test passes if the values are not equal."
            },
            {
              name = "less",
              description = "The test passes if the value is less than the existing one."
            },
            {
              name = "lequal",
              description = "The test passes if the value is less than or equal to the existing one."
            },
            {
              name = "greater",
              description = "The test passes if the value is greater than the existing one."
            },
            {
              name = "gequal",
              description = "The test passes if the value is greater than or equal to the existing one."
            }
          }
        },
        {
          name = "CullMode",
          summary = "Different ways of doing face culling.",
          description = "The different ways of doing triangle backface culling.",
          key = "CullMode",
          module = "lovr.graphics",
          related = {
            "Winding",
            "Pass:setCullMode",
            "Pass:setWinding"
          },
          values = {
            {
              name = "none",
              description = "Both sides of triangles will be drawn."
            },
            {
              name = "back",
              description = "Skips rendering the back side of triangles."
            },
            {
              name = "front",
              description = "Skips rendering the front side of triangles."
            }
          }
        },
        {
          name = "DataLayout",
          summary = "Different ways of padding GPU buffer data.",
          description = "The different ways to pack Buffer fields into memory.\n\nThe default is `packed`, which is suitable for vertex buffers and index buffers.  It doesn't add any padding between elements, and so it doesn't waste any space.  However, this layout won't necessarily work for uniform buffers and storage buffers.\n\nThe `std140` layout corresponds to the std140 layout used for uniform buffers in GLSL.  It adds the most padding between fields, and requires the stride to be a multiple of 16.  Example:\n\n    layout(std140) uniform ObjectScales { float scales[64]; };\n\nThe `std430` layout corresponds to the std430 layout used for storage buffers in GLSL.  It adds some padding between certain types, and may round up the stride.  Example:\n\n    layout(std430) buffer TileSizes { vec2 sizes[]; }",
          key = "DataLayout",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.newBuffer",
            "Buffer:getFormat",
            "Buffer:getStride",
            "DataType"
          },
          values = {
            {
              name = "packed",
              description = "The packed layout, without any padding."
            },
            {
              name = "std140",
              description = "The std140 layout."
            },
            {
              name = "std430",
              description = "The std430 layout."
            }
          }
        },
        {
          name = "DataType",
          summary = "Different types for `Buffer` fields.",
          description = "Different types for `Buffer` fields.  These are scalar, vector, or matrix types, usually packed into small amounts of space to reduce the amount of memory they occupy.\n\nThe names are encoded as follows:\n\n- The data type:\n  - `i` for signed integer\n  - `u` for unsigned integer\n  - `sn` for signed normalized (-1 to 1)\n  - `un` for unsigned normalized (0 to 1)\n  - `f` for floating point\n- The bit depth of each component\n- The letter `x` followed by the component count (for vectors)",
          key = "DataType",
          module = "lovr.graphics",
          notes = "In addition to these values, the following aliases can be used:\n\n<table>\n  <thead>\n    <tr>\n      <td>Alias</td>\n      <td>Maps to</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><code>vec2</code></td>\n      <td><code>f32x2</code></td>\n    </tr>\n    <tr>\n      <td><code>vec3</code></td>\n      <td><code>f32x3</code></td>\n    </tr>\n    <tr>\n      <td><code>vec4</code></td>\n      <td><code>f32x4</code></td>\n    </tr>\n    <tr>\n      <td><code>int</code></td>\n      <td><code>i32</code></td>\n    </tr>\n    <tr>\n      <td><code>uint</code></td>\n      <td><code>u32</code></td>\n    </tr>\n    <tr>\n      <td><code>float</code></td>\n      <td><code>f32</code></td>\n    </tr>\n    <tr>\n      <td><code>color</code></td>\n      <td><code>un8x4</code></td>\n    </tr>\n  </tbody> </table>\n\nAdditionally, the following convenience rules apply:\n\n- Field types can end in an `s`, which will be stripped off.\n- Field types can end in `x1`, which will be stripped off.\n\nSo you can write, e.g. `lovr.graphics.newBuffer(4, 'floats')`, which is cute!",
          related = {
            "lovr.graphics.newBuffer",
            "Buffer:getFormat"
          },
          values = {
            {
              name = "i8x4",
              description = "Four 8-bit signed integers."
            },
            {
              name = "u8x4",
              description = "Four 8-bit unsigned integers."
            },
            {
              name = "sn8x4",
              description = "Four 8-bit signed normalized values."
            },
            {
              name = "un8x4",
              description = "Four 8-bit unsigned normalized values (aka `color`)."
            },
            {
              name = "sn10x3",
              description = "Three 10-bit signed normalized values, and 2 padding bits."
            },
            {
              name = "un10x3",
              description = "Three 10-bit unsigned normalized values, and 2 padding bits."
            },
            {
              name = "i16",
              description = "One 16-bit signed integer."
            },
            {
              name = "i16x2",
              description = "Two 16-bit signed integers."
            },
            {
              name = "i16x4",
              description = "Four 16-bit signed integers."
            },
            {
              name = "u16",
              description = "One 16-bit unsigned integer."
            },
            {
              name = "u16x2",
              description = "Two 16-bit unsigned integers."
            },
            {
              name = "u16x4",
              description = "Four 16-bit unsigned integers."
            },
            {
              name = "sn16x2",
              description = "Two 16-bit signed normalized values."
            },
            {
              name = "sn16x4",
              description = "Four 16-bit signed normalized values."
            },
            {
              name = "un16x2",
              description = "Two 16-bit unsigned normalized values."
            },
            {
              name = "un16x4",
              description = "Four 16-bit unsigned normalized values."
            },
            {
              name = "i32",
              description = "One 32-bit signed integer (aka `int`)."
            },
            {
              name = "i32x2",
              description = "Two 32-bit signed integers."
            },
            {
              name = "i32x3",
              description = "Three 32-bit signed integers."
            },
            {
              name = "i32x4",
              description = "Four 32-bit signed integers."
            },
            {
              name = "u32",
              description = "One 32-bit unsigned integer (aka `uint`)."
            },
            {
              name = "u32x2",
              description = "Two 32-bit unsigned integers."
            },
            {
              name = "u32x3",
              description = "Three 32-bit unsigned integers."
            },
            {
              name = "u32x4",
              description = "Four 32-bit unsigned integers."
            },
            {
              name = "f16x2",
              description = "Two 16-bit floating point numbers."
            },
            {
              name = "f16x4",
              description = "Four 16-bit floating point numbers."
            },
            {
              name = "f32",
              description = "One 32-bit floating point number (aka `float`)."
            },
            {
              name = "f32x2",
              description = "Two 32-bit floating point numbers (aka `vec2`)."
            },
            {
              name = "f32x3",
              description = "Three 32-bit floating point numbers (aka `vec3`)."
            },
            {
              name = "f32x4",
              description = "Four 32-bit floating point numbers (aka `vec4`)."
            },
            {
              name = "mat2",
              description = "A 2x2 matrix containing four 32-bit floats."
            },
            {
              name = "mat3",
              description = "A 3x3 matrix containing nine 32-bit floats."
            },
            {
              name = "mat4",
              description = "A 4x4 matrix containing sixteen 32-bit floats."
            },
            {
              name = "index16",
              description = "Like u16, but 1-indexed."
            },
            {
              name = "index32",
              description = "Like u32, but 1-indexed."
            }
          }
        },
        {
          name = "DefaultShader",
          summary = "Built-in shaders.",
          description = "The set of shaders built in to LÖVR.  These can be passed to `Pass:setShader` or `lovr.graphics.newShader` instead of writing GLSL code.  The shaders can be further customized by using the `flags` option to change their behavior.  If the active shader is set to `nil`, LÖVR picks one of these shaders to use.",
          key = "DefaultShader",
          module = "lovr.graphics",
          values = {
            {
              name = "unlit",
              description = "Basic shader without lighting that uses colors and a texture."
            },
            {
              name = "normal",
              description = "Shades triangles based on their normal, resulting in a cool rainbow effect."
            },
            {
              name = "font",
              description = "Renders font glyphs."
            },
            {
              name = "cubemap",
              description = "Renders cubemaps."
            },
            {
              name = "equirect",
              description = "Renders spherical textures."
            },
            {
              name = "fill",
              description = "Renders a fullscreen triangle."
            }
          }
        },
        {
          name = "DrawMode",
          summary = "Different ways to draw mesh vertices.",
          description = "Different ways vertices in a mesh can be connected together and filled in with pixels.",
          key = "DrawMode",
          module = "lovr.graphics",
          values = {
            {
              name = "points",
              description = "Each vertex is rendered as a single point.  The size of the point can be controlled using the `pointSize` shader flag, or by writing to the `PointSize` variable in shaders.  The maximum point size is given by the `pointSize` limit from `lovr.graphics.getLimits`."
            },
            {
              name = "lines",
              description = "Pairs of vertices are connected with line segments.  To draw a single line through all of the vertices, an index buffer can be used to repeat vertices.  It is not currently possible to change the width of the lines, although cylinders or capsules can be used as an alternative."
            },
            {
              name = "triangles",
              description = "Every 3 vertices form a triangle, which is filled in with pixels (unless `Pass:setWireframe` is used).  This mode is the most commonly used."
            }
          }
        },
        {
          name = "DrawStyle",
          summary = "Different styles to draw shapes.",
          description = "Whether a shape should be drawn filled or outlined.",
          key = "DrawStyle",
          module = "lovr.graphics",
          related = {
            "Pass:plane",
            "Pass:cube",
            "Pass:box",
            "Pass:circle"
          },
          values = {
            {
              name = "fill",
              description = "The shape will be filled in (the default)."
            },
            {
              name = "line",
              description = "The shape will be outlined."
            }
          }
        },
        {
          name = "FilterMode",
          summary = "Different ways to smooth textures.",
          description = "Controls how `Sampler` objects smooth pixels in textures.",
          key = "FilterMode",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.newSampler",
            "Sampler:getFilter",
            "Texture:setPixels"
          },
          values = {
            {
              name = "nearest",
              description = "A pixelated appearance where the \"nearest neighbor\" pixel is used."
            },
            {
              name = "linear",
              description = "A smooth appearance where neighboring pixels are averaged."
            },
            {
              name = "cubic",
              description = "An even smoother appearance, but slower and typically only available on mobile GPUs. Use `lovr.graphics.isFormatSupported('format', 'cubic')` to check for support for a specific format, or `lovr.graphics.getFeatures().cubic` to see if cubic filtering is supported at all.\n\nNote that this can only be used for `min` and `mag` options in sampler.  Trying to use this for the `mip` filter mode will silently fall back to `linear`."
            }
          }
        },
        {
          name = "HorizontalAlign",
          summary = "Different ways to horizontally align text.",
          description = "Different ways to horizontally align text with `Pass:text`.",
          key = "HorizontalAlign",
          module = "lovr.graphics",
          related = {
            "VerticalAlign",
            "Pass:text",
            "Font:getVertices"
          },
          values = {
            {
              name = "left",
              description = "Left-aligned text."
            },
            {
              name = "center",
              description = "Centered text."
            },
            {
              name = "right",
              description = "Right-aligned text."
            }
          }
        },
        {
          name = "MeshStorage",
          summary = "Whether a Mesh stores its data on the CPU or GPU.",
          description = "Whether a Mesh stores its data on the CPU or GPU.",
          key = "MeshStorage",
          module = "lovr.graphics",
          notes = "There are some significant differences and tradeoffs between the two modes:\n\n- CPU meshes store a second copy of the vertices in RAM, which can be expensive for large\n  meshes.\n- When vertices are modified, CPU meshes will update the CPU copy, and only upload to the GPU\n  the next time the Mesh is drawn.  GPU meshes, on the other hand, will immediately upload\n  modified vertices to the GPU.  This means that calling `Mesh:setVertices` multiple times per\n  frame will be faster with a CPU mesh.\n- CPU meshes have an internal vertex buffer that can't be accessed from Lua.\n- CPU meshes can compute their bounding box using `Mesh:computeBoundingBox`.  GPU meshes can't.",
          related = {
            "lovr.graphics.newMesh"
          },
          values = {
            {
              name = "cpu",
              description = "The Mesh will store a copy of the vertices on the CPU."
            },
            {
              name = "gpu",
              description = "The Mesh will not keep a CPU copy, only storing vertices on the GPU."
            }
          }
        },
        {
          name = "OriginType",
          summary = "Different coordinate spaces for nodes in a Model.",
          description = "Different coordinate spaces for nodes in a `Model`.",
          key = "OriginType",
          module = "lovr.graphics",
          related = {
            "Model:getNodePosition",
            "Model:getNodeOrientation",
            "Model:getNodeScale",
            "Model:getNodePose",
            "Model:getNodeTransform",
            "Model:getRootNode",
            "Model:getNodeParent"
          },
          values = {
            {
              name = "root",
              description = "Transforms are relative to the origin (root) of the Model."
            },
            {
              name = "parent",
              description = "Transforms are relative to the parent of the node."
            }
          }
        },
        {
          name = "ShaderStage",
          summary = "Different shader stages.",
          description = "Different shader stages.  Graphics shaders have a `vertex` and `fragment` stage, and compute shaders have a single `compute` stage.",
          key = "ShaderStage",
          module = "lovr.graphics",
          values = {
            {
              name = "vertex",
              description = "The vertex stage, which computes transformed vertex positions."
            },
            {
              name = "fragment",
              description = "The fragment stage, which computes pixel colors."
            },
            {
              name = "compute",
              description = "The compute stage, which performs arbitrary computation."
            }
          }
        },
        {
          name = "ShaderType",
          summary = "Different types of Shaders.",
          description = "The two types of shaders that can be created.",
          key = "ShaderType",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.newShader",
            "Shader:getType",
            "ShaderStage"
          },
          values = {
            {
              name = "graphics",
              description = "A graphics shader with a vertex and pixel stage."
            },
            {
              name = "compute",
              description = "A compute shader with a single compute stage."
            }
          }
        },
        {
          name = "StackType",
          summary = "Types of stacks that can be pushed and popped.",
          description = "Different types of stacks that can be pushed and popped with `Pass:push` and `Pass:pop`.",
          key = "StackType",
          module = "lovr.graphics",
          values = {
            {
              name = "transform",
              description = "The transform stack (`Pass:transform`, `Pass:translate`, etc.)."
            },
            {
              name = "state",
              description = "Graphics state, like `Pass:setColor`, `Pass:setFont`, etc.  Notably this does not include camera poses/projections or shader variables changed with `Pass:send`."
            }
          }
        },
        {
          name = "StencilAction",
          summary = "Different ways of updating the stencil buffer.",
          description = "Different ways of updating the stencil buffer with `Pass:setStencilWrite`.",
          key = "StencilAction",
          module = "lovr.graphics",
          related = {
            "Pass:setStencilWrite",
            "Pass:setStencilTest",
            "Pass:setColorWrite"
          },
          values = {
            {
              name = "keep",
              description = "Stencil buffer pixels will not be changed by draws."
            },
            {
              name = "zero",
              description = "Stencil buffer pixels will be set to zero."
            },
            {
              name = "replace",
              description = "Stencil buffer pixels will be replaced with a custom value."
            },
            {
              name = "increment",
              description = "Stencil buffer pixels will be incremented each time they're rendered to."
            },
            {
              name = "decrement",
              description = "Stencil buffer pixels will be decremented each time they're rendered to."
            },
            {
              name = "incrementwrap",
              description = "Similar to increment, but will wrap around to 0 when it exceeds 255."
            },
            {
              name = "decrementwrap",
              description = "Similar to decrement, but will wrap around to 255 when it goes below 0."
            },
            {
              name = "invert",
              description = "The bits in the stencil buffer pixels will be inverted."
            }
          }
        },
        {
          name = "TextureFeature",
          summary = "Different ways Textures can be used.",
          description = "These are the different ways `Texture` objects can be used.  These are passed in to `lovr.graphics.isFormatSupported` to see which texture operations are supported by the GPU for a given format.",
          key = "TextureFeature",
          module = "lovr.graphics",
          values = {
            {
              name = "sample",
              description = "The Texture can be sampled (e.g. used in a `Material` or sent to a `texture2D` variable in shaders)."
            },
            {
              name = "render",
              description = "The Texture can used as a canvas in a `Pass`."
            },
            {
              name = "storage",
              description = "The Texture can be sent to a storage image variable in shaders (e.g. `image2D`)."
            },
            {
              name = "blit",
              description = "The Texture can be used with `Pass:blit` and `Pass:generateMipmaps`."
            },
            {
              name = "cubic",
              description = "The Texture can be used with a sampler that uses a `cubic` filter mode.  See `FilterMode`."
            }
          }
        },
        {
          name = "TextureType",
          summary = "The different types of textures.",
          description = "Different types of textures.  Textures are multidimensional blocks of GPU memory, and the texture's type determines how many dimensions there are, and adds some semantics about what the 3rd dimension means.",
          key = "TextureType",
          module = "lovr.graphics",
          values = {
            {
              name = "2d",
              description = "A single 2D image, the most common type."
            },
            {
              name = "3d",
              description = "A 3D image, where a sequence of 2D images defines a 3D volume.  Each mipmap level of a 3D texture gets smaller in the x, y, and z axes, unlike cubemap and array textures."
            },
            {
              name = "cube",
              description = "Six square 2D images with the same dimensions that define the faces of a cubemap, used for skyboxes or other \"directional\" images.  Can also have higher multiples of 6 images, which will be interpreted as a cubemap array image."
            },
            {
              name = "array",
              description = "Array textures are sequences of distinct 2D images that all have the same dimensions."
            }
          }
        },
        {
          name = "TextureUsage",
          summary = "Different operations `Texture` can be used for.",
          description = "These are the different things `Texture`s can be used for.  When creating a Texture, a set of these flags can be provided, restricting what operations are allowed on the texture.  Using a smaller set of flags may improve performance.  If none are provided, the only usage flag applied is `sample`.",
          key = "TextureUsage",
          module = "lovr.graphics",
          values = {
            {
              name = "sample",
              description = "Whether the texture can be sampled from in Shaders (i.e. used in a material, or bound to a variable with a `texture` type, like `texture2D`)."
            },
            {
              name = "render",
              description = "Whether the texture can be rendered to (i.e. by using it as a render target in `lovr.graphics.pass`)."
            },
            {
              name = "storage",
              description = "Whether the texture can be used as a storage texture for compute operations (i.e. bound to a variable with an `image` type, like `image2D`)."
            },
            {
              name = "transfer",
              description = "Whether the texture can be used for transfer operations like `Texture:setPixels`, `Texture:blit`, etc."
            }
          }
        },
        {
          name = "VerticalAlign",
          summary = "Different ways to vertically align text.",
          description = "Different ways to vertically align text with `Pass:text`.",
          key = "VerticalAlign",
          module = "lovr.graphics",
          related = {
            "HorizontalAlign",
            "Pass:text",
            "Font:getVertices"
          },
          values = {
            {
              name = "top",
              description = "Top-aligned text."
            },
            {
              name = "middle",
              description = "Centered text."
            },
            {
              name = "bottom",
              description = "Bottom-aligned text."
            }
          }
        },
        {
          name = "Winding",
          summary = "Different triangle windings.",
          description = "Indicates whether the front face of a triangle uses the clockwise or counterclockwise vertex order.",
          key = "Winding",
          module = "lovr.graphics",
          related = {
            "Pass:setWinding",
            "Pass:setCullMode"
          },
          values = {
            {
              name = "clockwise",
              description = "Clockwise winding."
            },
            {
              name = "counterclockwise",
              description = "Counterclockwise winding."
            }
          }
        },
        {
          name = "WrapMode",
          summary = "Different ways to wrap textures.",
          description = "Controls how `Sampler` objects wrap textures.",
          key = "WrapMode",
          module = "lovr.graphics",
          values = {
            {
              name = "clamp",
              description = "Pixels will be clamped to the edge, with pixels outside the 0-1 uv range using colors from the nearest edge."
            },
            {
              name = "repeat",
              description = "Tiles the texture."
            },
            {
              name = "mirror",
              description = "Similar to `repeat`, but flips the texture each time it repeats."
            },
            {
              name = "border",
              description = "Similar to `clamp`, but everything outside the 0-1 uv range will be filled with transparent black, i.e. `(0, 0, 0, 0)`."
            }
          }
        }
      },
      functions = {
        {
          name = "compileShader",
          tag = "graphics-objects",
          summary = "Compile shader code to bytecode.",
          description = "Compiles shader code to SPIR-V bytecode.  The bytecode can be passed to `lovr.graphics.newShader` to create shaders, which will be faster than creating it from GLSL. The bytecode is portable, so bytecode compiled on one platform will work on other platforms. This allows shaders to be precompiled in a build step.",
          key = "lovr.graphics.compileShader",
          module = "lovr.graphics",
          notes = "The input can be GLSL or SPIR-V.  If it's SPIR-V, it will be returned unchanged as a Blob.\n\nIf the shader fails to compile, an error will be thrown with the error message.",
          related = {
            "lovr.graphics.newShader",
            "Shader"
          },
          variants = {
            {
              arguments = {
                {
                  name = "stage",
                  type = "ShaderStage",
                  description = "The type of shader to compile."
                },
                {
                  name = "source",
                  type = "string | Blob",
                  description = "A string, filename, or Blob with shader code."
                }
              },
              returns = {
                {
                  name = "bytecode",
                  type = "Blob",
                  description = "A Blob containing compiled SPIR-V code."
                }
              }
            }
          }
        },
        {
          name = "getBackgroundColor",
          tag = "graphics-global",
          summary = "Get the background color.",
          description = "Returns the global background color.  The textures in a render pass will be cleared to this color at the beginning of the pass if no other clear option is specified.  Additionally, the headset and window will be cleared to this color before rendering.",
          key = "lovr.graphics.getBackgroundColor",
          module = "lovr.graphics",
          notes = "Setting the background color in `lovr.draw` will apply on the following frame, since the default pass is cleared before `lovr.draw` is called.\n\nInternally, this color is applied to the default pass objects when retrieving one of them using `lovr.headset.getPass` or `lovr.graphics.getWindowPass`.  Both are called automatically by the default `lovr.run` implementation.\n\nUsing the background color to clear the display is expected to be more efficient than manually clearing after a render pass begins, especially on mobile GPUs.",
          related = {
            "lovr.graphics.newPass",
            "Pass:setClear",
            "Texture:clear",
            "Pass:fill"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "r",
                  type = "number",
                  description = "The red component of the background color."
                },
                {
                  name = "g",
                  type = "number",
                  description = "The green component of the background color."
                },
                {
                  name = "b",
                  type = "number",
                  description = "The blue component of the background color."
                },
                {
                  name = "a",
                  type = "number",
                  description = "The alpha component of the background color."
                }
              }
            }
          }
        },
        {
          name = "getDefaultFont",
          tag = "graphics-objects",
          summary = "Get the default Font.",
          description = "Returns the default Font.  The default font is Varela Round, created at 32px with a spread value of `4.0`.  It's used by `Pass:text` if no Font is provided.",
          key = "lovr.graphics.getDefaultFont",
          module = "lovr.graphics",
          related = {
            "Pass:text",
            "lovr.graphics.newFont"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "font",
                  type = "Font",
                  description = "The default Font object."
                }
              }
            }
          }
        },
        {
          name = "getDevice",
          tag = "graphics-misc",
          summary = "Get information about the graphics device and driver.",
          description = "Returns information about the graphics device and driver.",
          key = "lovr.graphics.getDevice",
          module = "lovr.graphics",
          notes = "The device and vendor ID numbers will usually be PCI IDs, which are standardized numbers consisting of 4 hex digits.  Various online databases and system utilities can be used to look up these numbers.  Here are some example vendor IDs for a few popular GPU manufacturers:\n\n<table>\n  <thead>\n    <tr>\n      <td>ID</td>\n      <td>Vendor</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><code>0x1002</code></td>\n      <td>Advanced Micro Devices, Inc.</td>\n    </tr>\n    <tr>\n      <td><code>0x8086</code></td>\n      <td>Intel Corporation</td>\n    </tr>\n    <tr>\n      <td><code>0x10de</code></td>\n      <td>NVIDIA Corporation</td>\n    </tr>\n  </tbody> </table>\n\nIt is not currently possible to get the version of the driver, although this could be added.\n\nRegarding multiple GPUs: If OpenXR is enabled, the OpenXR runtime has control over which GPU is used, which ensures best compatibility with the VR headset.  Otherwise, the \"first\" GPU returned by the renderer will be used.  There is currently no other way to pick a GPU to use.",
          related = {
            "lovr.graphics.getFeatures",
            "lovr.graphics.getLimits"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "device",
                  type = "table",
                  table = {
                    {
                      name = "id",
                      type = "number",
                      description = "The vendor-unique number for this GPU."
                    },
                    {
                      name = "vendor",
                      type = "number",
                      description = "The identifier of the GPU vendor."
                    },
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the GPU."
                    },
                    {
                      name = "renderer",
                      type = "string",
                      description = "The renderer in use, currently either \"Vulkan\" or \"WebGPU\"."
                    },
                    {
                      name = "subgroupSize",
                      type = "number",
                      description = "The number of threads that run in a single GPU compute unit.  This is usually 32 or 64, and is sometimes called the \"wave\" or \"warp\" size.  This can be used to optimize compute shaders for the current hardware."
                    },
                    {
                      name = "discrete",
                      type = "boolean",
                      description = "Whether the GPU is a discrete graphics card."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "getFeatures",
          tag = "graphics-misc",
          summary = "Get the supported GPU features.",
          description = "Returns a table indicating which features are supported by the GPU.",
          key = "lovr.graphics.getFeatures",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.isFormatSupported",
            "lovr.graphics.getDevice",
            "lovr.graphics.getLimits"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "features",
                  type = "table",
                  description = "",
                  table = {
                    {
                      name = "textureBC",
                      type = "boolean",
                      description = "Whether `TextureFormat`s starting with `bc` are supported. This will almost always be `true` on desktop GPUs and will almost always be `false` on mobile GPUs."
                    },
                    {
                      name = "textureASTC",
                      type = "boolean",
                      description = "Whether `TextureFormat`s beginning with `astc` are supported.  This will almost always be `true` on mobile GPUs and will almost always be `false` on desktop GPUs."
                    },
                    {
                      name = "wireframe",
                      type = "boolean",
                      description = "When supported, `Pass:setWireframe` will work, otherwise it will do nothing. This will always be `true` when using Vulkan, and will always be `false` when using WebGPU."
                    },
                    {
                      name = "depthClamp",
                      type = "boolean",
                      description = "When supported, `Pass:setDepthClamp` will work, otherwise it will do nothing."
                    },
                    {
                      name = "depthResolve",
                      type = "boolean",
                      description = "When supported, multisampled render passes can use a non-multisampled depth texture. Otherwise, the depth texture sample count needs to match the render pass sample count."
                    },
                    {
                      name = "indirectDrawFirstInstance",
                      type = "boolean",
                      description = "Whether indirect draws can set the firstInstance property of buffer memory to something other than zero."
                    },
                    {
                      name = "float64",
                      type = "boolean",
                      description = "Whether shader code can use doubles."
                    },
                    {
                      name = "int64",
                      type = "boolean",
                      description = "Whether shader code can use signed and unsigned 64-bit integers."
                    },
                    {
                      name = "int16",
                      type = "boolean",
                      description = "Whether shader code can use signed and unsigned 16-bit integers."
                    },
                    {
                      name = "cubic",
                      type = "boolean",
                      description = "Whether the GPU supports cubic texture filtering.  To check for specific format support, use `lovr.graphics.isFormatSupported` with the `cubic` `TextureFeature`."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "getLimits",
          tag = "graphics-misc",
          summary = "Get the limits of the current GPU.",
          description = "Returns limits of the current GPU.",
          key = "lovr.graphics.getLimits",
          module = "lovr.graphics",
          notes = "The limit ranges are as follows:\n\n<table>\n  <thead>\n    <tr>\n      <td>Limit</td>\n      <td>Minimum</td>\n      <td>Maximum</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><code>textureSize2D</code></td>\n      <td>4096</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>textureSize3D</code></td>\n      <td>256</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>textureSizeCube</code></td>\n      <td>4096</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>textureLayers</code></td>\n      <td>256</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>renderSize</code></td>\n      <td>{ 4096, 4096, 6 }</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>uniformBuffersPerStage</code></td>\n      <td>9</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>storageBuffersPerStage</code></td>\n      <td>4</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>sampledTexturesPerStage</code></td>\n      <td>32</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>storageTexturesPerStage</code></td>\n      <td>4</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>samplersPerStage</code></td>\n      <td>15</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>resourcesPerShader</code></td>\n      <td>32</td>\n      <td>32*</td>\n    </tr>\n    <tr>\n      <td><code>uniformBufferRange</code></td>\n      <td>65536</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>storageBufferRange</code></td>\n      <td>134217728 (128MB)</td>\n      <td>1073741824 (1GB)*</td>\n    </tr>\n    <tr>\n      <td><code>uniformBufferAlign</code></td>\n      <td></td>\n      <td>256</td>\n    </tr>\n    <tr>\n      <td><code>storageBufferAlign</code></td>\n      <td></td>\n      <td>64</td>\n    </tr>\n    <tr>\n      <td><code>vertexAttributes</code></td>\n      <td>16</td>\n      <td>16*</td>\n    </tr>\n    <tr>\n      <td><code>vertexBufferStride</code></td>\n      <td>2048</td>\n      <td>65535*</td>\n    </tr>\n    <tr>\n      <td><code>vertexShaderOutputs</code></td>\n      <td>64</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>clipDistances</code></td>\n      <td>0</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>cullDistances</code></td>\n      <td>0</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>clipAndCullDistances</code></td>\n      <td>0</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>computeDispatchCount</code></td>\n      <td>{ 65536, 65536, 65536 }</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>computeWorkgroupSize</code></td>\n      <td>{ 128, 128, 64 }</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>computeWorkgroupVolume</code></td>\n      <td>128</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>computeSharedMemory</code></td>\n      <td>16384 (16KB)</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>pushConstantSize</code></td>\n      <td>128</td>\n      <td>256*</td>\n    </tr>\n    <tr>\n      <td><code>indirectDrawCount</code></td>\n      <td>1</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>instances</code></td>\n      <td>134217727</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>anisotropy</code></td>\n      <td>0.0</td>\n      <td></td>\n    </tr>\n    <tr>\n      <td><code>pointSize</code></td>\n      <td>1.0</td>\n      <td></td>\n    </tr>\n  </tbody> </table>\n\nNote: in the table above, `*` means that LÖVR itself is imposing a cap on the limit, instead of the GPU.",
          related = {
            "lovr.graphics.isFormatSupported",
            "lovr.graphics.getDevice",
            "lovr.graphics.getFeatures"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "limits",
                  type = "table",
                  description = "",
                  table = {
                    {
                      name = "textureSize2D",
                      type = "number",
                      description = "The maximum width/height of `2d` and `array` textures."
                    },
                    {
                      name = "textureSize3D",
                      type = "number",
                      description = "The maximum width/height/depth of `3d` textures."
                    },
                    {
                      name = "textureSizeCube",
                      type = "number",
                      description = "The maximum width/height of `cube` textures."
                    },
                    {
                      name = "textureLayers",
                      type = "number",
                      description = "The maximum depth of `array` textures."
                    },
                    {
                      name = "renderSize",
                      type = "table",
                      description = "The maximum width, height, and layer count of a texture (or texture view) used as a render target."
                    },
                    {
                      name = "uniformBuffersPerStage",
                      type = "number",
                      description = "The maximum number of uniform buffers in a shader stage."
                    },
                    {
                      name = "storageBuffersPerStage",
                      type = "number",
                      description = "The maximum number of storage buffers in a shader stage."
                    },
                    {
                      name = "sampledTexturesPerStage",
                      type = "number",
                      description = "The maximum number of sampled textures in a shader stage."
                    },
                    {
                      name = "storageTexturesPerStage",
                      type = "number",
                      description = "The maximum number of storage textures in a shader stage."
                    },
                    {
                      name = "samplersPerStage",
                      type = "number",
                      description = "The maximum number of samplers in a shader stage."
                    },
                    {
                      name = "resourcesPerShader",
                      type = "number",
                      description = "The maximum combined number of buffers, textures, and sampler variables in a Shader."
                    },
                    {
                      name = "uniformBufferRange",
                      type = "number",
                      description = "The maximum range of bytes that can be bound to a uniform buffer in a shader."
                    },
                    {
                      name = "storageBufferRange",
                      type = "number",
                      description = "The maximum range of bytes that can be bound to a storage buffer in a shader."
                    },
                    {
                      name = "uniformBufferAlign",
                      type = "number",
                      description = "When binding a range of bytes to a uniform buffer binding in a shader, the byte offset of the range must be a multiple of this limit's value."
                    },
                    {
                      name = "storageBufferAlign",
                      type = "number",
                      description = "When binding a range of bytes to a storage buffer binding in a shader, the byte offset of the range must be a multiple of this limit's value."
                    },
                    {
                      name = "vertexAttributes",
                      type = "number",
                      description = "The maximum number of input attributes in a vertex shader."
                    },
                    {
                      name = "vertexBufferStride",
                      type = "number",
                      description = "The maximum stride of a buffer used as a vertex buffer, in bytes."
                    },
                    {
                      name = "vertexShaderOutputs",
                      type = "number",
                      description = "The maximum number of components output from a vertex shader."
                    },
                    {
                      name = "clipDistances",
                      type = "number",
                      description = "The maximum number of clipping planes declared by a shader."
                    },
                    {
                      name = "cullDistances",
                      type = "number",
                      description = "The maximum number of cull distances declared by a shader."
                    },
                    {
                      name = "clipAndCullDistances",
                      type = "number",
                      description = "The maximum number of clipping planes and cull distances declared by a shader."
                    },
                    {
                      name = "workgroupCount",
                      type = "table",
                      description = "The maximum values of `x`, `y`, and `z` in `Pass:compute`."
                    },
                    {
                      name = "workgroupSize",
                      type = "table",
                      description = "The maximum values of `local_size_x`, `local_size_y`, and `local_size_z` declared in a compute shader."
                    },
                    {
                      name = "totalWorkgroupSize",
                      type = "number",
                      description = "The maximum product of `local_size_x`, `local_size_y`, and `local_size_z` in a compute shader."
                    },
                    {
                      name = "computeSharedMemory",
                      type = "number",
                      description = "The maximum number of bytes used by `shared` variables in compute shaders."
                    },
                    {
                      name = "indirectDrawCount",
                      type = "number",
                      description = "The maximum number of draws that can be issued by an indirect draw call."
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The maximum number of instances that can be rendered in a draw call."
                    },
                    {
                      name = "anisotropy",
                      type = "number",
                      description = "The maximum value of the `anisotropy` parameter in `lovr.graphics.newSampler`."
                    },
                    {
                      name = "pointSize",
                      type = "number",
                      description = "The maximum point size."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "getWindowPass",
          tag = "graphics-objects",
          summary = "Get the window pass.",
          description = "Returns the window pass.  This is a builtin render `Pass` object that renders to the desktop window texture.  If the desktop window was not open when the graphics module was initialized, this function will return `nil`.",
          key = "lovr.graphics.getWindowPass",
          module = "lovr.graphics",
          notes = "`lovr.conf` may be used to change the settings for the pass:  `t.graphics.antialias` enables antialiasing, and `t.graphics.stencil` enables the stencil buffer.\n\nThis pass clears the window texture to the background color, which can be changed using `lovr.graphics.setBackgroundColor`.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "pass",
                  type = "Pass | nil",
                  description = "The window pass, or `nil` if there is no window."
                }
              }
            }
          }
        },
        {
          name = "isFormatSupported",
          tag = "graphics-misc",
          summary = "Check if a Texture format is supported.",
          description = "Returns the type of operations the GPU supports for a texture format, if any.",
          key = "lovr.graphics.isFormatSupported",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.getDevice",
            "lovr.graphics.getFeatures",
            "lovr.graphics.getLimits"
          },
          variants = {
            {
              arguments = {
                {
                  name = "format",
                  type = "TextureFormat",
                  description = "The texture format to query."
                },
                {
                  name = "...features",
                  type = "TextureFeature",
                  description = "Zero or more features to check.  If no features are given, this function will return whether the GPU supports *any* feature for this format.  Otherwise, this function will only return true if *all* of the input features are supported."
                }
              },
              returns = {
                {
                  name = "linear",
                  type = "boolean",
                  description = "Whether the GPU supports these operations for textures with this format, when created with the `linear` flag set to `true`."
                },
                {
                  name = "srgb",
                  type = "boolean",
                  description = "Whether the GPU supports these operations for textures with this format, when created with the `linear` flag set to `false`."
                }
              }
            }
          }
        },
        {
          name = "isHDR",
          tag = "graphics-global",
          summary = "Check if the **super experimental** HDR mode is active.",
          description = "Returns whether the **super experimental** HDR mode is active.\n\nTo enable HDR, add `t.graphics.hdr` to `lovr.conf`.  When enabled, LÖVR will try to create an HDR10 window.  If the GPU supports it, then this function will return true and the window texture will be HDR:\n\n- Its format will be `rgb10a2` instead of `rgba8`.\n- The display will assume its colors are in the Rec.2020 color space, instead of sRGB.\n- The display will assume its colors are encoded with the PQ transfer function, instead of sRGB.\n\nFor now, it's up to you to write PQ-encoded Rec.2020 color data from your shader when rendering to the window.",
          key = "lovr.graphics.isHDR",
          module = "lovr.graphics",
          notes = "The following shader helper functions make it easier to convert between sRGB colors and HDR10:\n\n    vec3 pqToLinear(vec3 color);\n    vec3 linearToPQ(vec3 color);\n    vec3 sRGBToRec2020(vec3 color);\n    vec3 rec2020ToSRGB(vec3 color);",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "hdr",
                  type = "boolean",
                  description = "Whether HDR is enabled."
                }
              }
            }
          }
        },
        {
          name = "isTimingEnabled",
          tag = "graphics-global",
          summary = "Check if timing stats are enabled.",
          description = "Returns whether timing stats are enabled.  When enabled, `Pass:getStats` will return `submitTime` and `gpuTime` durations.  Timing is enabled by default when `t.graphics.debug` is set in `lovr.conf`.  Timing has a small amount of overhead, so it should only be enabled when needed.",
          key = "lovr.graphics.isTimingEnabled",
          module = "lovr.graphics",
          related = {
            "Pass:getStats"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "enabled",
                  type = "boolean",
                  description = "Whether timing is enabled."
                }
              }
            }
          }
        },
        {
          name = "newBuffer",
          tag = "graphics-objects",
          summary = "Create a new Buffer.",
          description = "Creates a Buffer.",
          key = "lovr.graphics.newBuffer",
          module = "lovr.graphics",
          examples = {
            {
              description = "Examples of different buffer formats.",
              code = "-- 2 matrices\nlovr.graphics.newBuffer('mat4', 2)\n\n-- 3 integers, with initial data\nlovr.graphics.newBuffer('int', { 1, 2, 3 })\n\n-- a simple mesh:\nlovr.graphics.newBuffer({\n  { name = 'VertexPosition', type = 'vec3' },\n  { name = 'VertexColor', type = 'color' }\n}, 4)\n\n-- a uniform buffer with vec3's, using the std140 packing\nlovr.graphics.newBuffer({ 'vec3', layout = 'std140' }, data)\n\n-- a uniform buffer with key-value fields\nlovr.graphics.newBuffer({\n  { 'AmbientColor', 'vec3' },\n  { 'LightPosition', 'vec3' },\n  { 'LightType', 'u32' },\n  { 'LightColor', 'vec4' },\n  layout = 'std140'\n})\n\n-- a buffer with nested structure and array types\nlovr.graphics.newBuffer({\n  { 'globals', {\n    { 'ObjectCount', 'int' },\n    { 'WorldSize', 'vec2' },\n    { 'Scale', 'float' }\n  }},\n  { 'materials', {\n    { 'Color', 'vec4' },\n    { 'Glow', 'vec3' },\n    { 'Roughness', 'float' }\n  }, length = 32 },\n  layout = 'std430'\n})\n\n-- a buffer using a variable from a shader:\nlovr.graphics.newBuffer(shader:getBufferFormat('transforms'))"
            }
          },
          notes = "The format table can contain a list of `DataType`s or a list of tables to provide extra information about each field.  Each inner table has the following keys:\n\n- `type` is the `DataType` of the field and is required.\n- `name` is the name of the field.  The field name is used to match table keys up to buffer\n  fields when writing table data to the Buffer, and is also used to match up buffer fields with\n  vertex attribute names declared in a `Shader`.  LÖVR has a set of <a\n  href=\"Shaders#vertex-attributes\">default vertex attributes</a> that shaders will automatically\n  use, allowing you to create a custom mesh without having to write shader code or add custom\n  vertex attributes in a shader.\n- `offset` is the byte offset of the field.  Any fields with a `nil` offset will be placed next\n  to each other sequentially in memory, subject to any padding required by the Buffer's layout.\n  In practice this means that you probably want to provide an `offset` for either all of the\n  fields or none of them.\n- `length` is the array size of the field (optional, leave as `nil` for non-arrays).\n- `stride` is the number of bytes between each item in an array (optional).\n\nAs a shorthand, the name, type, and optionally the length of a field can be provided as a list instead of using keys.\n\nIf no table or Blob is used to define the initial Buffer contents, its data will be undefined.",
          related = {
            "Shader:getBufferFormat"
          },
          variants = {
            {
              arguments = {
                {
                  name = "size",
                  type = "number",
                  description = "The size of the Buffer, in bytes."
                }
              },
              returns = {
                {
                  name = "buffer",
                  type = "Buffer",
                  description = "The new Buffer."
                }
              }
            },
            {
              arguments = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "A Blob with the initial contents of the Buffer."
                }
              },
              returns = {
                {
                  name = "buffer",
                  type = "Buffer",
                  description = "The new Buffer."
                }
              }
            },
            {
              arguments = {
                {
                  name = "format",
                  type = "table | DataType",
                  description = "A list of fields in the Buffer.  A `DataType` can also be used for buffers that are simple arrays.",
                  table = {
                    {
                      name = "layout",
                      type = "DataLayout",
                      description = "How to lay out the Buffer fields in memory.",
                      default = "packed"
                    },
                    {
                      name = "stride",
                      type = "number",
                      description = "The stride of the Buffer, in bytes.  When `nil`, the stride will be automatically computed based on the fields.  The stride can not be zero or smaller than the max byte occupied by one of the fields.  The layout of the Buffer may adjust the stride."
                    }
                  }
                },
                {
                  name = "length",
                  type = "number",
                  description = "The length of the Buffer.",
                  default = "1"
                }
              },
              returns = {
                {
                  name = "buffer",
                  type = "Buffer",
                  description = "The new Buffer."
                }
              }
            },
            {
              arguments = {
                {
                  name = "format",
                  type = "table | DataType",
                  description = "A list of fields in the Buffer.  A `DataType` can also be used for buffers that are simple arrays.",
                  table = {
                    {
                      name = "layout",
                      type = "DataLayout",
                      description = "How to lay out the Buffer fields in memory.",
                      default = "packed"
                    },
                    {
                      name = "stride",
                      type = "number",
                      description = "The stride of the Buffer, in bytes.  When `nil`, the stride will be automatically computed based on the fields.  The stride can not be zero or smaller than the max byte occupied by one of the fields.  The layout of the Buffer may adjust the stride."
                    }
                  }
                },
                {
                  name = "data",
                  type = "table | Blob",
                  description = "The initial data to put into the Buffer.  The length of the Buffer will be determined by the length of the table or the size of the Blob, combined with the format information."
                }
              },
              returns = {
                {
                  name = "buffer",
                  type = "Buffer",
                  description = "The new Buffer."
                }
              }
            }
          }
        },
        {
          name = "newFont",
          tag = "graphics-objects",
          summary = "Create a new Font.",
          description = "Creates a new Font.",
          key = "lovr.graphics.newFont",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.getDefaultFont",
            "lovr.data.newRasterizer",
            "Pass:text"
          },
          variants = {
            {
              description = "Creates a new Font from a font file.",
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing a TTF or BMFont file."
                },
                {
                  name = "size",
                  type = "number",
                  description = "The size of the Font in pixels (TTF only).  Larger sizes are slower to initialize and use more memory, but have better quality.",
                  default = "32"
                },
                {
                  name = "spread",
                  type = "number",
                  description = "For signed distance field fonts (currently all fonts), the width of the SDF, in pixels.  The greater the distance the font is viewed from, the larger this value needs to be for the font to remain properly antialiased.  Increasing this will have a performance penalty similar to increasing the size of the font.",
                  default = "4"
                }
              },
              returns = {
                {
                  name = "font",
                  type = "Font",
                  description = "The new Font."
                }
              }
            },
            {
              description = "Creates a new Font using the default typeface (Varela Round).",
              arguments = {
                {
                  name = "size",
                  type = "number",
                  description = "The size of the Font in pixels (TTF only).  Larger sizes are slower to initialize and use more memory, but have better quality.",
                  default = "32"
                },
                {
                  name = "spread",
                  type = "number",
                  description = "For signed distance field fonts (currently all fonts), the width of the SDF, in pixels.  The greater the distance the font is viewed from, the larger this value needs to be for the font to remain properly antialiased.  Increasing this will have a performance penalty similar to increasing the size of the font.",
                  default = "4"
                }
              },
              returns = {
                {
                  name = "font",
                  type = "Font",
                  description = "The new Font."
                }
              }
            },
            {
              description = "Creates a new Font from an existing Rasterizer.",
              arguments = {
                {
                  name = "rasterizer",
                  type = "Rasterizer",
                  description = "An existing Rasterizer to use to load glyph images."
                },
                {
                  name = "spread",
                  type = "number",
                  description = "For signed distance field fonts (currently all fonts), the width of the SDF, in pixels.  The greater the distance the font is viewed from, the larger this value needs to be for the font to remain properly antialiased.  Increasing this will have a performance penalty similar to increasing the size of the font.",
                  default = "4"
                }
              },
              returns = {
                {
                  name = "font",
                  type = "Font",
                  description = "The new Font."
                }
              }
            }
          }
        },
        {
          name = "newMaterial",
          tag = "graphics-objects",
          summary = "Create a new Material.",
          description = "Creates a new Material from a table of properties and textures.  All fields are optional.  Once a Material is created, its properties can not be changed.  Instead, a new Material should be created with the updated properties.",
          key = "lovr.graphics.newMaterial",
          module = "lovr.graphics",
          notes = "The non-texture material properties can be accessed in shaders using `Material.<property>`, where the property is the same as the Lua table key.  The textures use capitalized names in shader code, e.g. `ColorTexture`.",
          variants = {
            {
              arguments = {
                {
                  name = "properties",
                  type = "table",
                  description = "Material properties.",
                  table = {
                    {
                      name = "color",
                      type = "Vec4",
                      description = "The base color of the surface.  Can be a `Vec3`, `Vec4`, table of numbers, or hexcode. Can be toggled in shaders using the `materialColor` flag, which defaults to `true`.",
                      default = "{ 1, 1, 1, 1 }"
                    },
                    {
                      name = "glow",
                      type = "Vec4",
                      description = "The glow color of the surface, sometimes called \"emissive\".  The glow is not affected by lighting, so it's a good fit for e.g. headlights on a car or LED lights on a panel.  The alpha of the glow color is used as the glow strength.  Can be a `Vec3`, `Vec4`, table of numbers, or hexcode.  Can be toggled in shaders using the `glow` flag, which defaults to `false`.",
                      default = "{ 0, 0, 0, 0 }"
                    },
                    {
                      name = "uvShift",
                      type = "Vec2",
                      description = "An offset to apply to the UV coordinates used to sample textures.  The offset is not affected by `uvScale`.  This can be used to map UV coordinates to a sub-rectangle of a texture atlas.  Can be a `Vec2`, table of numbers, or a single number which gets assigned to both axes.  Can be toggled in shaders using the `uvTransform` flag, which defaults to `true`.",
                      default = "{ 0, 0 }"
                    },
                    {
                      name = "uvScale",
                      type = "Vec2",
                      description = "A scale factor to apply to the UV coordinates used to sample textures.  The scale is not affected by `uvOffset`.  This can be used to map UV coordinates to a sub-rectangle of a texture atlas, or repeat a texture multiple times across a surface.  Can be a `Vec2`, table of numbers, or a single number which gets assigned to both axes. Can be toggled in shaders using the `uvTransform` flag, which defaults to `true`.",
                      default = "{ 1, 1 }"
                    },
                    {
                      name = "metalness",
                      type = "number",
                      description = "The metalness the surface, used for physically-based rendering.  1.0 means the surface is metallic (conductor), and 0.0 means the surface is non-metallic (dielectric).  Values in between are seldom used and are only used in textures to transition between a metallic and non-metallic surface.  Metals reflect light differently than non-metals. Used by the lighting helper functions `initSurface` and `getLighting`.",
                      default = "0"
                    },
                    {
                      name = "roughness",
                      type = "number",
                      description = "The roughness of the surface, used for physically-based rendering.  1.0 means the surface is rough (blurry reflections), and 0.0 means the surface is smooth (sharp reflections).  Used by the lighting helper functions `initSurface` and `getLighting`.",
                      default = "0"
                    },
                    {
                      name = "clearcoat",
                      type = "number",
                      description = "The clearcoat factor.  Not currently used by LÖVR.",
                      default = "0"
                    },
                    {
                      name = "clearcoatRoughness",
                      type = "number",
                      description = "The roughness of the clearcoat layer.  Not currently used by LÖVR.",
                      default = "0"
                    },
                    {
                      name = "occlusionStrength",
                      type = "number",
                      description = "The strength of the ambient occlusion effect.  Ambient occlusion only affects indirect lighting.  Used by the lighting helper functions `initSurface` and `getIndirectLighting`.  Can be toggled in shaders using the `ambientOcclusion` flag, which defaults to `true`.",
                      default = "1"
                    },
                    {
                      name = "normalScale",
                      type = "number",
                      description = "The strength of the normal map.  Used by the `initSurface` function to bend the surface normal.  Can be toggled in shaders using the `normalMap` flag, which defaults to `false`.",
                      default = "1"
                    },
                    {
                      name = "alphaCutoff",
                      type = "number",
                      description = "The alpha cutoff.  At the end of the fragment shader, if the alpha of the final color is below the alpha cutoff, then the pixel will be \"discarded\" which means that it won't write a depth value.  Often used for transparent textures, especially with the \"alpha to coverage\" state set by `Pass:setAlphaToCoverage`.  Can be toggled in shaders using the `alphaCutoff` flag, which defaults to `false`.",
                      default = "0"
                    },
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The base color texture.  In shaders this gets multiplied with the `color` property to get the base color of the pixel.  Can be toggled in shaders using the `colorTexture` flag, which defaults to `true`."
                    },
                    {
                      name = "glowTexture",
                      type = "Texture",
                      description = "The glow color texture.  In shaders, samples from this texture get multiplied with the `glow` property to get the glow color of the pixel.  Can be toggled in shaders using the `glowTexture` flag, which defaults to `true` (also requires the `glow` flag to be enabled)."
                    },
                    {
                      name = "metalnessTexture",
                      type = "Texture",
                      description = "The metalness texture.  In shaders, samples from the blue channel of this texture get multiplied with the `metalness` property to get the metalness value of the pixel.  Can be toggled in shaders using the `metalnessTexture` flag, which defaults to `true`."
                    },
                    {
                      name = "roughnessTexture",
                      type = "Texture",
                      description = "The roughness texture.  In shaders, samples from the green channel of this texture get multiplied with the `roughness` property to get the roughness value of the pixel.  Can be toggled in shaders using the `roughnessTexture` flag, which defaults to `true`."
                    },
                    {
                      name = "clearcoatTexture",
                      type = "Texture",
                      description = "Not currently used by LÖVR."
                    },
                    {
                      name = "occlusionTexture",
                      type = "Texture",
                      description = "The ambient occlusion texture.  In shaders, samples from the red channel of this texture get multiplied with the `occlusionStrength` property to get the ambient occlusion value of the pixel. Used by the lighting helper functions `initSurface` and `getIndirectLighting`.  Can be toggled in shaders using the `ambientOcclusion` flag, which defaults to `true`."
                    },
                    {
                      name = "normalTexture",
                      type = "Texture",
                      description = "The normal map, used to apply details to a surface without adding mesh geometry.  The `normalScale` property can be used to control how strong the effect is.  Can be toggled in shaders using the `normalMap` flag, which defaults to `false`."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "material",
                  type = "Material",
                  description = "The new material."
                }
              }
            }
          }
        },
        {
          name = "newMesh",
          tag = "graphics-objects",
          summary = "Create a new Mesh.",
          description = "Creates a Mesh.  The capacity of the Mesh must be provided upfront, using either a vertex count or the vertex data itself.  A custom vertex format can be given to specify the set of attributes in each vertex, which get sent to the vertex shader.  If the format isn't given, the default vertex format will be used:\n\n    {\n      { 'VertexPosition', 'vec3' },\n      { 'VertexNormal', 'vec3' },\n      { 'VertexUV', 'vec2' }\n    }",
          key = "lovr.graphics.newMesh",
          module = "lovr.graphics",
          examples = {
            {
              code = "function lovr.load()\n  mesh = lovr.graphics.newMesh({\n    { 'VertexPosition', 'vec3' },\n    { 'VertexColor', 'vec4' }\n  }, {\n    {   0,  .4, 0 , 1, 0, 0, 1 },\n    { -.5, -.4, 0 , 0, 1, 0, 1 },\n    {  .5, -.4, 0 , 0, 0, 1, 1 }\n  })\nend\n\nfunction lovr.draw(pass)\n  pass:draw(mesh, 0, 1.7, -1)\nend"
            }
          },
          notes = "The Mesh will always use the `gpu` storage mode if it's created from a vertex buffer.",
          related = {
            "lovr.graphics.newBuffer",
            "lovr.graphics.newModel"
          },
          variants = {
            {
              arguments = {
                {
                  name = "count",
                  type = "number",
                  description = "The number of vertices in the Mesh."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "vertices",
                  type = "table",
                  description = "A table of vertices, formatted according to the vertex format.  The length of the table will be used to set the vertex count of the Mesh."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "blob",
                  type = "Blob",
                  description = "A Blob containing vertex data, formatted according to the vertex format.  The size of the Blob will be used to set the vertex count of the Mesh, and must be a multiple of the vertex size."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "format",
                  type = "table",
                  description = "A table of attributes describing the format of each vertex.  Each attribute is a table that must have `name` and `type` keys, where the name is a string and the type is a `DataType`. Attributes can also have an `offset` key, which is a byte offset relative to the start of the vertex.  As a shorthand, the name and type can be given as a pair without keys. Additionally, the format can have a `stride` key to set the number of bytes between subsequent vertices."
                },
                {
                  name = "count",
                  type = "number",
                  description = "The number of vertices in the Mesh."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "format",
                  type = "table",
                  description = "A table of attributes describing the format of each vertex.  Each attribute is a table that must have `name` and `type` keys, where the name is a string and the type is a `DataType`. Attributes can also have an `offset` key, which is a byte offset relative to the start of the vertex.  As a shorthand, the name and type can be given as a pair without keys. Additionally, the format can have a `stride` key to set the number of bytes between subsequent vertices."
                },
                {
                  name = "vertices",
                  type = "table",
                  description = "A table of vertices, formatted according to the vertex format.  The length of the table will be used to set the vertex count of the Mesh."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "format",
                  type = "table",
                  description = "A table of attributes describing the format of each vertex.  Each attribute is a table that must have `name` and `type` keys, where the name is a string and the type is a `DataType`. Attributes can also have an `offset` key, which is a byte offset relative to the start of the vertex.  As a shorthand, the name and type can be given as a pair without keys. Additionally, the format can have a `stride` key to set the number of bytes between subsequent vertices."
                },
                {
                  name = "blob",
                  type = "Blob",
                  description = "A Blob containing vertex data, formatted according to the vertex format.  The size of the Blob will be used to set the vertex count of the Mesh, and must be a multiple of the vertex size."
                },
                {
                  name = "storage",
                  type = "MeshStorage",
                  description = "The storage mode of the Mesh.",
                  default = "'cpu'"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            },
            {
              arguments = {
                {
                  name = "buffer",
                  type = "Buffer",
                  description = "A Buffer containing vertex data.  Its length will be used as the vertex count, and its format will be used as the vertex format."
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "Mesh",
                  description = "The new Mesh."
                }
              }
            }
          }
        },
        {
          name = "newModel",
          tag = "graphics-objects",
          summary = "Create a new Model.",
          description = "Loads a 3D model from a file.  Currently, OBJ, glTF, and binary STL files are supported.",
          key = "lovr.graphics.newModel",
          module = "lovr.graphics",
          notes = "Currently, the following features are not supported by the model importer:\n\n- glTF: Only the default scene is loaded.\n- glTF: Currently, each skin in a Model can have up to 256 joints.\n- glTF: Meshes can't appear multiple times in the node hierarchy with different skins, they need\n  to use 1 skin consistently.\n- glTF: `KHR_texture_transform` is supported, but all textures in a material will use the same\n  transform.\n- STL: ASCII STL files are not supported.\n\nDiffuse and emissive textures will be loaded using sRGB encoding, all other textures will be loaded as linear.\n\nLoading a model file will fail if the asset references textures or other files using absolute paths.  Relative paths should be used instead, and will be relative to the model file within the virtual filesystem.",
          related = {
            "lovr.data.newModelData",
            "Pass:draw"
          },
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing 3D model data to import."
                },
                {
                  name = "options",
                  type = "table",
                  description = "An optional table of Model options.",
                  default = "nil",
                  table = {
                    {
                      name = "mipmaps",
                      type = "boolean",
                      description = "Whether the textures created for the Model should have mipmaps generated.",
                      default = "true"
                    },
                    {
                      name = "materials",
                      type = "boolean",
                      description = "Whether the textures and materials in the Model should be loaded.  When false, the model will use the material set with `Pass:setMaterial`, although it will apply to all nodes.",
                      default = "true"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "model",
                  type = "Model",
                  description = "The new Model."
                }
              }
            },
            {
              arguments = {
                {
                  name = "modelData",
                  type = "ModelData",
                  description = "An existing ModelData object to use for the Model."
                },
                {
                  name = "options",
                  type = "table",
                  description = "An optional table of Model options.",
                  default = "nil",
                  table = {
                    {
                      name = "mipmaps",
                      type = "boolean",
                      description = "Whether the textures created for the Model should have mipmaps generated.",
                      default = "true"
                    },
                    {
                      name = "materials",
                      type = "boolean",
                      description = "Whether the textures and materials in the Model should be loaded.  When false, the model will use the material set with `Pass:setMaterial`, although it will apply to all nodes.",
                      default = "true"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "model",
                  type = "Model",
                  description = "The new Model."
                }
              }
            }
          }
        },
        {
          name = "newPass",
          tag = "graphics-objects",
          summary = "Create a new Pass.",
          description = "Creates and returns a new Pass object.  The canvas (the set of textures the Pass renders to) can be specified when creating the Pass, or later using `Pass:setCanvas`.",
          key = "lovr.graphics.newPass",
          module = "lovr.graphics",
          notes = "Fun facts about render passes:\n\n- Textures must have been created with the `render` `TextureUsage`.\n- Textures must have the same dimensions, layer counts, and sample counts.\n- When rendering to textures with multiple layers, each draw will be broadcast to all layers.\n  Render passes have multiple \"views\" (cameras), and each layer uses a corresponding view,\n  allowing each layer to be rendered from a different viewpoint.  This enables fast stereo\n  rendering, but can also be used to efficiently render to cubemaps.  The `ViewIndex` variable\n  can also be used in shaders to set up any desired per-view behavior.\n- Mipmaps will automatically be generated for textures at the end of the render pass.\n- It's okay to have zero color textures, but in this case there must be a depth texture.\n- It's possible to render to a specific mipmap level of a Texture, or a subset of its layers, by\n  rendering to texture views, see `lovr.graphics.newTextureView`.",
          related = {
            "lovr.graphics.submit",
            "lovr.graphics.getWindowPass",
            "lovr.headset.getPass"
          },
          variants = {
            {
              description = "Create a pass that renders to a set of textures.",
              arguments = {
                {
                  name = "...textures",
                  type = "Texture",
                  description = "One or more textures the pass will render to.  This can be changed later using `Pass:setCanvas`."
                }
              },
              returns = {
                {
                  name = "pass",
                  type = "Pass",
                  description = "The new Pass."
                }
              }
            },
            {
              description = "Create a pass, with extra canvas settings.",
              arguments = {
                {
                  name = "canvas",
                  type = "table",
                  description = "Render target configuration.  Up to 4 textures can be provided in table keys 1 through 4, as well as the following keys:",
                  table = {
                    {
                      name = "depth",
                      type = "table",
                      description = "Depth/stencil buffer settings.  In addition to a table, it can be a `Texture`, a `TextureFormat`, or `false` to disable the depth buffer.",
                      table = {
                        {
                          name = "format",
                          type = "TextureFormat",
                          description = "The format of the depth buffer texture, which must be a depth format (the ones that start with `d`).  LÖVR will create or reuse an internal depth buffer with this format.",
                          default = "'d32f'"
                        },
                        {
                          name = "texture",
                          type = "Texture",
                          description = "A Texture to use as the depth buffer.  Takes precedence over `format`."
                        }
                      }
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of multisamples to use.  Can be 4 for antialiasing, or 1 to disable antialiasing.",
                      default = "4"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "pass",
                  type = "Pass",
                  description = "The new Pass."
                }
              }
            },
            {
              description = "Create an empty Pass without a canvas.",
              arguments = {},
              returns = {
                {
                  name = "pass",
                  type = "Pass",
                  description = "The new Pass."
                }
              }
            }
          }
        },
        {
          name = "newSampler",
          tag = "graphics-objects",
          summary = "Create a new Sampler.",
          description = "Creates a new Sampler.  Samplers are immutable, meaning their parameters can not be changed after the sampler is created.  Instead, a new sampler should be created with the updated properties.",
          key = "lovr.graphics.newSampler",
          module = "lovr.graphics",
          related = {
            "Pass:setSampler"
          },
          variants = {
            {
              arguments = {
                {
                  name = "parameters",
                  type = "table",
                  description = "Parameters for the sampler.",
                  table = {
                    {
                      name = "filter",
                      type = "table",
                      description = "How the sampler smooths texture pixels.  Can be a table of 3 FilterModes, or a single FilterMode to use for all three.",
                      default = "'linear'",
                      table = {
                        {
                          name = "[1]",
                          type = "FilterMode",
                          description = "The filter mode to use when minifying a texture (drawing it at a smaller size than its native pixel resolution)."
                        },
                        {
                          name = "[2]",
                          type = "FilterMode",
                          description = "The filter mode to use when magnifying a texture (drawing it at a larger size than its native pixel resolution)."
                        },
                        {
                          name = "[3]",
                          type = "FilterMode",
                          description = "The filter mode used to smooth between mipmap levels in a texture."
                        }
                      }
                    },
                    {
                      name = "wrap",
                      type = "table",
                      description = "How the sampler behaves when wrapping UVs outside the 0-1 range.  Can be a table of 3 WrapModes, or a single WrapMode to use for all three axes.",
                      default = "'repeat'",
                      table = {
                        {
                          name = "[1]",
                          type = "WrapMode",
                          description = "The horizontal wrap mode."
                        },
                        {
                          name = "[2]",
                          type = "WrapMode",
                          description = "The vertical wrap mode."
                        },
                        {
                          name = "[3]",
                          type = "WrapMode",
                          description = "The \"z\" wrap mode for 3D textures."
                        }
                      }
                    },
                    {
                      name = "compare",
                      type = "CompareMode",
                      description = "The compare mode of the sampler (for shadow samplers).",
                      default = "'none'"
                    },
                    {
                      name = "anisotropy",
                      type = "number",
                      description = "The maximum amount of anisotropic filtering to use.",
                      default = "1"
                    },
                    {
                      name = "mipmaprange",
                      type = "table",
                      description = "A table of 2 mipmap levels the sampler will clamp to."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "sampler",
                  type = "Sampler",
                  description = "The new sampler."
                }
              }
            }
          }
        },
        {
          name = "newShader",
          tag = "graphics-objects",
          summary = "Create a new Shader.",
          description = "Creates a Shader, which is a small program that runs on the GPU.\n\nShader code is usually written in GLSL and compiled to SPIR-V bytecode.  SPIR-V is faster to load but requires a build step.  Either form can be used to create a shader.\n\nBy default, the provided shader code is expected to implement a `vec4 lovrmain() { ... }` function that is called for each vertex or fragment.  If the `raw` option is set to `true`, the code is treated as a raw shader and the `lovrmain` function is not required. In this case, the shader code is expected to implement its own `main` function.",
          key = "lovr.graphics.newShader",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.compileShader",
            "ShaderType",
            "ShaderStage"
          },
          variants = {
            {
              description = "Create a graphics shader.  It has a vertex stage that computes vertex positions, and a fragment stage that computes pixel colors.",
              arguments = {
                {
                  name = "vertex",
                  type = "string | DefaultShader | Blob",
                  description = "A string, path to a file, or Blob containing GLSL or SPIR-V code for the vertex stage.  Can also be a `DefaultShader` to use that shader's vertex code."
                },
                {
                  name = "fragment",
                  type = "string | DefaultShader | Blob",
                  description = "A string, path to a file, or Blob containing GLSL or SPIR-V code for the fragment stage. Can also be a `DefaultShader` to use that shader's fragment code."
                },
                {
                  name = "options",
                  type = "table",
                  description = "An optional table of Shader options.",
                  default = "nil",
                  table = {
                    {
                      name = "flags",
                      type = "table",
                      description = "A table of shader flags.  The keys of the table should be flag names or flag ID numbers. The values can be numbers or booleans, depending on the type of the flag as declared in the shader."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label to use for the shader in debugging tools."
                    },
                    {
                      name = "raw",
                      type = "boolean",
                      description = "If set to true, the code is treated as a raw shader.  It will be compiled with none of the LÖVR helpers."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "shader",
                  type = "Shader",
                  description = "The new shader."
                }
              }
            },
            {
              description = "Create a compute shader.",
              arguments = {
                {
                  name = "compute",
                  type = "string | Blob",
                  description = "A string, path to a file, or Blob containing GLSL or SPIR-V code for the compute stage."
                },
                {
                  name = "options",
                  type = "table",
                  description = "An optional table of Shader options.",
                  default = "nil",
                  table = {
                    {
                      name = "flags",
                      type = "table",
                      description = "A table of shader flags.  The keys of the table should be flag names or flag ID numbers. The values can be numbers or booleans, depending on the type of the flag as declared in the shader."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label to use for the shader in debugging tools."
                    },
                    {
                      name = "raw",
                      type = "boolean",
                      description = "If set to true, the code is treated as a raw shader.  It will be compiled with none of the LÖVR helpers."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "shader",
                  type = "Shader",
                  description = "The new shader."
                }
              }
            },
            {
              description = "Create a copy of one of the default shaders (used to provide different flags).",
              arguments = {
                {
                  name = "defaultshader",
                  type = "DefaultShader",
                  description = "One of the default shaders to use."
                },
                {
                  name = "options",
                  type = "table",
                  description = "An optional table of Shader options.",
                  default = "nil",
                  table = {
                    {
                      name = "flags",
                      type = "table",
                      description = "A table of shader flags.  The keys of the table should be flag names or flag ID numbers. The values can be numbers or booleans, depending on the type of the flag as declared in the shader."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label to use for the shader in debugging tools."
                    },
                    {
                      name = "raw",
                      type = "boolean",
                      description = "If set to true, the code is treated as a raw shader.  It will be compiled with none of the LÖVR helpers."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "shader",
                  type = "Shader",
                  description = "The new shader."
                }
              }
            }
          }
        },
        {
          name = "newTexture",
          tag = "graphics-objects",
          summary = "Create a new Texture.",
          description = "Creates a new Texture.  Image filenames or `Image` objects can be used to provide the initial pixel data and the dimensions, format, and type.  Alternatively, dimensions can be provided, which will create an empty texture.",
          key = "lovr.graphics.newTexture",
          module = "lovr.graphics",
          notes = "If no `type` is provided in the options table, LÖVR will guess the `TextureType` of the Texture based on the number of layers:\n\n- If there's only 1 layer, the type will be `2d`.\n- If there are 6 images provided, the type will be `cube`.\n- Otherwise, the type will be `array`.\n\nNote that an Image can contain multiple layers and mipmaps.  When a single Image is provided, its layer count will be used as the Texture's layer count.\n\nIf multiple Images are used to initialize the Texture, they must all have a single layer, and their dimensions, format, and mipmap counts must match.\n\nWhen providing cubemap images in a table, they can be in one of the following forms:\n\n    { 'px.png', 'nx.png', 'py.png', 'ny.png', 'pz.png', 'nz.png' }\n    { right = 'px.png', left = 'nx.png', top = 'py.png', bottom = 'ny.png', back = 'pz.png', front = 'nz.png' }\n    { px = 'px.png', nx = 'nx.png', py = 'py.png', ny = 'ny.png', pz = 'pz.png', nz = 'nz.png' }\n\n(Where 'p' stands for positive and 'n' stands for negative).\n\nIf no `usage` is provided in the options table, LÖVR will guess the `TextureUsage` of the Texture.  The `sample` usage is always included, but if the texture was created without any images then the texture will have the `render` usage as well.\n\nThe supported image formats are png, jpg, hdr, dds, ktx1, ktx2, and astc.\n\nIf image data is provided, mipmaps will be generated for any missing mipmap levels.",
          related = {
            "lovr.graphics.newTextureView"
          },
          variants = {
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing an image file to load."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Texture options.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the texture."
                    },
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the texture (ignored when images are provided).",
                      default = "'rgba8'"
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the texture is in linear color space instead of sRGB.  Linear textures should be used for non-color data, like normal maps.",
                      default = "false"
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the texture, used for multisample antialiasing.  Currently must be 1 or 4.  Ignored when images are provided.",
                      default = "1"
                    },
                    {
                      name = "mipmaps",
                      type = "boolean | number",
                      description = "The number of mipmap levels in the texture, or a boolean.  If true, a full mipmap chain will be created.  If false, the texture will only have a single mipmap.",
                      default = "true"
                    },
                    {
                      name = "usage",
                      type = "{TextureUsage}",
                      description = "A list of `TextureUsage` indicating how the texture will be used."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label for the Texture that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "texture",
                  type = "Texture",
                  description = "The new Texture."
                }
              }
            },
            {
              arguments = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the Texture, in pixels."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the Texture, in pixels."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Texture options.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the texture."
                    },
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the texture (ignored when images are provided).",
                      default = "'rgba8'"
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the texture is in linear color space instead of sRGB.  Linear textures should be used for non-color data, like normal maps.",
                      default = "false"
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the texture, used for multisample antialiasing.  Currently must be 1 or 4.  Ignored when images are provided.",
                      default = "1"
                    },
                    {
                      name = "mipmaps",
                      type = "boolean | number",
                      description = "The number of mipmap levels in the texture, or a boolean.  If true, a full mipmap chain will be created.  If false, the texture will only have a single mipmap.",
                      default = "true"
                    },
                    {
                      name = "usage",
                      type = "{TextureUsage}",
                      description = "A list of `TextureUsage` indicating how the texture will be used."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label for the Texture that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "texture",
                  type = "Texture",
                  description = "The new Texture."
                }
              }
            },
            {
              arguments = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the Texture, in pixels."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the Texture, in pixels."
                },
                {
                  name = "layers",
                  type = "number",
                  description = "The number of layers in the Texture."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Texture options.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the texture."
                    },
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the texture (ignored when images are provided).",
                      default = "'rgba8'"
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the texture is in linear color space instead of sRGB.  Linear textures should be used for non-color data, like normal maps.",
                      default = "false"
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the texture, used for multisample antialiasing.  Currently must be 1 or 4.  Ignored when images are provided.",
                      default = "1"
                    },
                    {
                      name = "mipmaps",
                      type = "boolean | number",
                      description = "The number of mipmap levels in the texture, or a boolean.  If true, a full mipmap chain will be created.  If false, the texture will only have a single mipmap.",
                      default = "true"
                    },
                    {
                      name = "usage",
                      type = "{TextureUsage}",
                      description = "A list of `TextureUsage` indicating how the texture will be used."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label for the Texture that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "texture",
                  type = "Texture",
                  description = "The new Texture."
                }
              }
            },
            {
              arguments = {
                {
                  name = "image",
                  type = "string",
                  description = "An Image object holding pixel data to load into the Texture."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Texture options.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the texture."
                    },
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the texture (ignored when images are provided).",
                      default = "'rgba8'"
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the texture is in linear color space instead of sRGB.  Linear textures should be used for non-color data, like normal maps.",
                      default = "false"
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the texture, used for multisample antialiasing.  Currently must be 1 or 4.  Ignored when images are provided.",
                      default = "1"
                    },
                    {
                      name = "mipmaps",
                      type = "boolean | number",
                      description = "The number of mipmap levels in the texture, or a boolean.  If true, a full mipmap chain will be created.  If false, the texture will only have a single mipmap.",
                      default = "true"
                    },
                    {
                      name = "usage",
                      type = "{TextureUsage}",
                      description = "A list of `TextureUsage` indicating how the texture will be used."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label for the Texture that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "texture",
                  type = "Texture",
                  description = "The new Texture."
                }
              }
            },
            {
              arguments = {
                {
                  name = "images",
                  type = "{string | Blob | Image}",
                  description = "A table of filenames or Images to load into the Texture."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Texture options.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the texture."
                    },
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the texture (ignored when images are provided).",
                      default = "'rgba8'"
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the texture is in linear color space instead of sRGB.  Linear textures should be used for non-color data, like normal maps.",
                      default = "false"
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the texture, used for multisample antialiasing.  Currently must be 1 or 4.  Ignored when images are provided.",
                      default = "1"
                    },
                    {
                      name = "mipmaps",
                      type = "boolean | number",
                      description = "The number of mipmap levels in the texture, or a boolean.  If true, a full mipmap chain will be created.  If false, the texture will only have a single mipmap.",
                      default = "true"
                    },
                    {
                      name = "usage",
                      type = "{TextureUsage}",
                      description = "A list of `TextureUsage` indicating how the texture will be used."
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "A label for the Texture that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "texture",
                  type = "Texture",
                  description = "The new Texture."
                }
              }
            }
          }
        },
        {
          name = "newTextureView",
          tag = "graphics-objects",
          summary = "Create a texture view.",
          description = "Creates a new Texture view.  A texture view does not store any pixels on its own, but instead uses the pixel data of a \"parent\" Texture object.  The width, height, format, sample count, and usage flags all match the parent.  The view may have a different `TextureType`, and it may reference a subset of the parent texture's layers and mipmap levels.\n\nTexture views are used for:\n\n- Reinterpretation of texture contents.  For example, a cubemap can be treated as an array\n  texture.\n- Rendering to a particular array layer or mipmap level of a texture.\n- Binding a particular range of layers or mipmap levels to a shader.",
          key = "lovr.graphics.newTextureView",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.newTexture"
          },
          variants = {
            {
              arguments = {
                {
                  name = "parent",
                  type = "Texture",
                  description = "The parent Texture to create a view of."
                },
                {
                  name = "options",
                  type = "table",
                  description = "Options for the texture view.",
                  default = "nil",
                  table = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The texture type of the view.  Defaults to the type of the parent."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer referenced by the view.",
                      default = "1"
                    },
                    {
                      name = "layercount",
                      type = "number",
                      description = "The number of layers in the view.  Defaults to 1 if a layer index is provided, otherwise the view will reference all layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap referenced by the view.",
                      default = "1"
                    },
                    {
                      name = "mipmapcount",
                      type = "number",
                      description = "The number of mipmap levels in the view.  Defaults to 1 if a mipmap index is provided, otherwise the view will reference all mipmaps.",
                      default = "nil"
                    },
                    {
                      name = "label",
                      type = "string",
                      description = "An optional label for the view that will show up in debugging tools."
                    }
                  }
                }
              },
              returns = {
                {
                  name = "view",
                  type = "Texture",
                  description = "The new texture view."
                }
              }
            }
          }
        },
        {
          name = "present",
          tag = "work-submission",
          summary = "Update the desktop window contents.",
          description = "Presents the window texture to the desktop window.  This function is called automatically by the default implementation of `lovr.run`, so it normally does not need to be called.",
          key = "lovr.graphics.present",
          module = "lovr.graphics",
          notes = "This should be called after submitting the window pass (`lovr.graphics.getWindowPass`).  If the window texture has not been rendered to since the last present, this function does nothing.",
          related = {
            "lovr.graphics.submit",
            "lovr.graphics.getWindowPass"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "setBackgroundColor",
          tag = "graphics-global",
          summary = "Set the background color.",
          description = "Changes the global background color.  The textures in a render pass will be cleared to this color at the beginning of the pass if no other clear option is specified.  Additionally, the headset and window will be cleared to this color before rendering.",
          key = "lovr.graphics.setBackgroundColor",
          module = "lovr.graphics",
          notes = "Setting the background color in `lovr.draw` will apply on the following frame, since the default pass is cleared before `lovr.draw` is called.\n\nInternally, this color is applied to the default pass objects when retrieving one of them using `lovr.headset.getPass` or `lovr.graphics.getWindowPass`.  Both are called automatically by the default `lovr.run` implementation.\n\nUsing the background color to clear the display is expected to be more efficient than manually clearing after a render pass begins, especially on mobile GPUs.",
          related = {
            "lovr.graphics.newPass",
            "Pass:setClear",
            "Texture:clear",
            "Pass:fill"
          },
          variants = {
            {
              arguments = {
                {
                  name = "r",
                  type = "number",
                  description = "The red component of the background color."
                },
                {
                  name = "g",
                  type = "number",
                  description = "The green component of the background color."
                },
                {
                  name = "b",
                  type = "number",
                  description = "The blue component of the background color."
                },
                {
                  name = "a",
                  type = "number",
                  description = "The alpha component of the background color.",
                  default = "1.0"
                }
              },
              returns = {}
            },
            {
              arguments = {
                {
                  name = "hex",
                  type = "number",
                  description = "A hexcode (like `0xffffff`) to use for the background color (does not support alpha)."
                },
                {
                  name = "a",
                  type = "number",
                  description = "The alpha component of the background color.",
                  default = "1.0"
                }
              },
              returns = {}
            },
            {
              arguments = {
                {
                  name = "table",
                  type = "{number}",
                  description = "A table containing 3 or 4 color components."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setTimingEnabled",
          tag = "graphics-global",
          summary = "Enable or disable timing stats.",
          description = "Enables or disables timing stats.  When enabled, `Pass:getStats` will return `submitTime` and `gpuTime` durations.  Timing is enabled by default when `t.graphics.debug` is set in `lovr.conf`.  Timing has a small amount of overhead, so it should only be enabled when needed.",
          key = "lovr.graphics.setTimingEnabled",
          module = "lovr.graphics",
          related = {
            "Pass:getStats"
          },
          variants = {
            {
              arguments = {
                {
                  name = "enable",
                  type = "boolean",
                  description = "Whether timing should be enabled."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "submit",
          tag = "work-submission",
          summary = "Submit recorded graphics work to the GPU.",
          description = "Submits work to the GPU.",
          key = "lovr.graphics.submit",
          module = "lovr.graphics",
          notes = "The submitted `Pass` objects will run in the order specified.  Commands within a single Pass do not have any ordering guarantees.\n\nSubmitting work to the GPU is not thread safe.  No other `lovr.graphics` or `Pass` functions may run at the same time as `lovr.graphics.submit`.\n\nCalling this function will invalidate any temporary buffers or passes that were created during the frame.\n\nSubmitting work to the GPU is a relatively expensive operation.  It's a good idea to batch all `Pass` objects into 1 submission if possible, unless there's a good reason not to.  One such reason would be that the frame has so much work that some of it needs to be submitted early to prevent the GPU from running out of things to do.  Another would be for `Readback` objects.\n\nBy default, this function is called with the default pass at the end of `lovr.draw` and `lovr.mirror`.\n\nIt is valid to submit zero passes.  This will send an empty batch of work to the GPU.",
          related = {
            "lovr.graphics.wait"
          },
          variants = {
            {
              arguments = {
                {
                  name = "...",
                  type = "Pass | boolean | nil",
                  description = "The pass objects to submit.  Falsy values will be skipped."
                }
              },
              returns = {
                {
                  name = "true",
                  type = "boolean",
                  description = "Always returns true, for convenience when returning from `lovr.draw`."
                }
              }
            },
            {
              arguments = {
                {
                  name = "t",
                  type = "{Pass | boolean}",
                  description = "A table of passes to submit.  Falsy values will be skipped."
                }
              },
              returns = {
                {
                  name = "true",
                  type = "boolean",
                  description = "Always returns true, for convenience when returning from `lovr.draw`."
                }
              }
            }
          }
        },
        {
          name = "wait",
          tag = "work-submission",
          summary = "Stall the CPU until all submitted GPU work is finished.",
          description = "Waits for all submitted GPU work to finish.  A normal application that is trying to render graphics at a high framerate should never use this function, since waiting like this prevents the CPU from doing other useful work.  Otherwise, reasons to use this function might be for debugging or to force a `Readback` to finish immediately.",
          key = "lovr.graphics.wait",
          module = "lovr.graphics",
          related = {
            "lovr.graphics.submit"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        }
      },
      objects = {
        {
          name = "Buffer",
          summary = "A block of memory on the GPU.",
          description = "A Buffer is a block of memory on the GPU.  It's like a GPU version of a `Blob`.  Lua code can write data to the buffer which uploads to VRAM, and shaders read buffer data during rendering. Compute shaders can also write to buffers.\n\nThe **size** of a Buffer is the number of bytes of VRAM it occupies.  It's set when the Buffer is created and can't be changed afterwards.\n\nBuffers can optionally have a **format**, which defines the type of data stored in the buffer. The format determines how Lua values are converted into binary.  Like the size, it can't change after the buffer is created.  `Shader:getBufferFormat` returns the format of a variable in a `Shader`.\n\nWhen a Buffer has a format, it also has a **length**, which is the number of items it holds, and a **stride**, which is the number of bytes between each item.\n\n`Buffer:setData` is used to upload data to the Buffer.  `Buffer:clear` can also be used to efficiently zero out a Buffer.\n\n`Buffer:getData` can be used to download data from the Buffer, but be aware that it stalls the GPU until the download is complete, which is very slow!  `Buffer:newReadback` will instead download the data in the background, which avoids costly stalls.\n\nBuffers are often used for mesh data.  Vertices stored in buffers can be drawn using `Pass:mesh`.  `Mesh` objects can also be used, which wrap Buffers along with some extra metadata.\n\nBuffers can be \"bound\" to a variable in a Shader using `Pass:send`.  That means that the next time the shader runs, the data from the Buffer will be used for the stuff in the variable.\n\nIt's important to understand that data from a Buffer will only be used at the point when graphics commands are actually submitted.  This example records 2 draws, changing the buffer data between each one:\n\n    buffer:setData(data1)\n    pass:mesh(buffer)\n    buffer:setData(data2)\n    pass:mesh(buffer)\n    lovr.graphics.submit(pass)\n\n**Both** draws will use `data2` here!  That's because `lovr.graphics.submit` is where the draws actually get processed, so they both see the \"final\" state of the buffer.  The data in a Buffer can't be 2 things at once!  If you need multiple versions of data, it's best to use a bigger buffer with offsets (or multiple buffers).",
          key = "Buffer",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newBuffer"
          },
          extends = "Object",
          methods = {
            {
              name = "clear",
              tag = "buffer-transfer",
              summary = "Clear data in the Buffer.",
              description = "Clears a range of data in the Buffer to a value.",
              key = "Buffer:clear",
              module = "lovr.graphics",
              related = {
                "Texture:clear"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "The offset of the range of the Buffer to clear, in bytes.  Must be a multiple of 4.",
                      default = "0"
                    },
                    {
                      name = "extent",
                      type = "number",
                      description = "The number of bytes to clear.  If `nil`, clears to the end of the Buffer.  Must be a multiple of 4.",
                      default = "nil"
                    },
                    {
                      name = "value",
                      type = "number",
                      description = "The value to clear to.  This will be interpreted as a 32 bit number, which will be repeated across the clear range.",
                      default = "0x00000000"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "getData",
              tag = "buffer-transfer",
              summary = "Get the data in the Buffer.",
              description = "Downloads the Buffer's data from VRAM and returns it as a table.  This function is very very slow because it stalls the CPU until the data is finished downloading, so it should only be used for debugging or non-interactive scripts.  `Buffer:newReadback` is an alternative that returns a `Readback` object, which will not block the CPU.",
              key = "Buffer:getData",
              module = "lovr.graphics",
              notes = "The length of the table will equal the number of items read.  Here are some examples of how the table is formatted:\n\n    buffer = lovr.graphics.newBuffer('int', { 7 })\n    buffer:getData() --> returns { 7 }\n\n    buffer = lovr.graphics.newBuffer('vec3', { 7, 8, 9 })\n    buffer:getData() --> returns {{ 7, 8, 9 }}\n\n    buffer = lovr.graphics.newBuffer('int', { 1, 2, 3 })\n    buffer:getData() --> returns { 1, 2, 3 }\n\n    buffer = lovr.graphics.newBuffer({ 'vec2', 'vec2' }, {\n      vec2(1,2), vec2(3,4),\n      vec2(5,6), vec2(7,8)\n    })\n    buffer:getData() --> returns { { 1, 2, 3, 4 }, { 5, 6, 7, 8 } }\n\n    buffer = lovr.graphics.newBuffer({\n      { 'a', 'float' },\n      { 'b', 'float' }\n    }, { a = 1, b = 2 })\n    buffer:getData() --> returns { { 1, 2 } }\n\n    buffer = lovr.graphics.newBuffer({\n      { 'x', 'int', 3 }\n    }, { x = { 1, 2, 3 } })\n    buffer:getData() --> returns { { x = { 1, 2, 3 } } }\n\n    buffer = lovr.graphics.newBuffer({\n      { 'lights', {\n        { 'pos', 'vec3' },\n        { 'size', 'float' },\n      }, 10}\n    }, data)\n    buffer:getData() --> returns { { lights = { { pos = ..., size = ... }, ... } } }\n\nIn summary, each individual item is wrapped in a table, except if the format is a single number. If the format has nested types or arrays then the tables will be key-value, otherwise they will use numeric keys.",
              related = {
                "Buffer:newReadback",
                "Buffer:mapData",
                "Readback:getData"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the first item to read.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of items to read.  If nil, reads the remainder of the buffer.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "t",
                      type = "table",
                      description = "The table with the Buffer's data."
                    }
                  }
                }
              }
            },
            {
              name = "getFormat",
              tag = "buffer-metadata",
              summary = "Get the format of the Buffer.",
              description = "Returns the format the Buffer was created with.",
              key = "Buffer:getFormat",
              module = "lovr.graphics",
              examples = {
                {
                  code = "function lovr.load()\n  buffer = lovr.graphics.newBuffer({\n    { 'a', 'float' },\n    { 'b', 'un16x2' }\n  })\n\n  for i, field in ipairs(buffer:getFormat()) do\n    print(('%s: %s'):format(field.name, field.type))\n  end\n\n  -- prints the following:\n  -- a: f32\n  -- b: un16x2\nend"
                }
              },
              related = {
                "Buffer:getSize",
                "Buffer:getLength",
                "Buffer:getStride"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "format",
                      type = "table",
                      description = "A list of fields comprising the format.",
                      table = {
                        {
                          name = "[].name",
                          type = "string",
                          description = "The name of the field (if fields were created with names)."
                        },
                        {
                          name = "[].type",
                          type = "*",
                          description = "The `DataType` of the field, or a recursive table with the sub-format."
                        },
                        {
                          name = "[].offset",
                          type = "number",
                          description = "The offset of the field relative to its parent, in bytes."
                        },
                        {
                          name = "[].length",
                          type = "number",
                          description = "The array length of the field, or `nil` if it's not an array."
                        },
                        {
                          name = "[].stride",
                          type = "number",
                          description = "The stride of the field in bytes, or `nil` if it's not an array."
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              name = "getLength",
              tag = "buffer-metadata",
              summary = "Get the length of the Buffer.",
              description = "Returns the length of the Buffer, or `nil` if the Buffer was not created with a format.",
              key = "Buffer:getLength",
              module = "lovr.graphics",
              related = {
                "Buffer:getSize",
                "Buffer:getStride"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the Buffer."
                    }
                  }
                }
              }
            },
            {
              name = "getSize",
              tag = "buffer-metadata",
              summary = "Get the size of the Buffer, in bytes.",
              description = "Returns the size of the Buffer in VRAM, in bytes.  This is the same as `length * stride`.\n\nThe size of the Buffer can't change after it's created.",
              key = "Buffer:getSize",
              module = "lovr.graphics",
              related = {
                "Buffer:getLength",
                "Buffer:getStride"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "size",
                      type = "number",
                      description = "The size of the Buffer, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "getStride",
              tag = "buffer-metadata",
              summary = "Get the stride of the Buffer, in bytes.",
              description = "Returns the distance between each item in the Buffer, in bytes, or `nil` if the Buffer was not created with a format.",
              key = "Buffer:getStride",
              module = "lovr.graphics",
              notes = "When a Buffer is created, the stride can be set explicitly, otherwise it will be automatically computed based on the fields in the Buffer.\n\nStrides can not be zero, and can not be smaller than the size of a single item.",
              related = {
                "Buffer:getSize",
                "Buffer:getLength"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "stride",
                      type = "number",
                      description = "The stride of the Buffer, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "mapData",
              tag = "buffer-transfer",
              summary = "Get a writable pointer to the Buffer's memory.",
              description = "Returns a pointer to GPU memory and schedules a copy from this pointer to the buffer's data. The data in the pointer will replace the data in the buffer.  This is intended for use with the LuaJIT FFI or for passing to C libraries.",
              key = "Buffer:mapData",
              module = "lovr.graphics",
              notes = "The pointer remains valid until the next call to `lovr.graphics.submit`, during which the data in the pointer will be uploaded to the buffer.\n\nThe initial contents of the pointer are undefined.\n\nSpecial care should be taken when writing data:\n\n- Reading data from the pointer will be very slow on some systems, and should be avoided.\n- It is better to write data to the pointer sequentially.  Random access may be slower.",
              related = {
                "Blob:getPointer"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset in the buffer to write to.",
                      default = "0"
                    },
                    {
                      name = "extent",
                      type = "number",
                      description = "The number of bytes to replace.  If nil, writes to the rest of the buffer.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "pointer",
                      type = "lightuserdata",
                      description = "A pointer to the Buffer's memory."
                    }
                  }
                }
              }
            },
            {
              name = "newReadback",
              tag = "buffer-transfer",
              summary = "Read back the contents of the Buffer asynchronously.",
              description = "Creates and returns a new `Readback` that will download the data in the Buffer from VRAM. Once the readback is complete, `Readback:getData` returns the data as a table, or `Readback:getBlob` returns the data as a `Blob`.",
              key = "Buffer:newReadback",
              module = "lovr.graphics",
              notes = "The offset and extent arguments must be a multiple of the Buffer's stride (unless it was created without a format).",
              related = {
                "Buffer:getData",
                "Texture:newReadback"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset to read from.",
                      default = "0"
                    },
                    {
                      name = "extent",
                      type = "number",
                      description = "The number of bytes to read.  If nil, reads the rest of the buffer.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "readback",
                      type = "Readback",
                      description = "A new Readback object."
                    }
                  }
                }
              }
            },
            {
              name = "setData",
              tag = "buffer-transfer",
              summary = "Change the data in the Buffer.",
              description = "Copies data to the Buffer from either a table, `Blob`, or `Buffer`.",
              key = "Buffer:setData",
              module = "lovr.graphics",
              examples = {
                {
                  description = "Various examples of copying different formats.",
                  code = "function lovr.load()\n  buffer = lovr.graphics.newBuffer('int', 3)\n  buffer:setData({ 1, 2, 3 })\n\n  buffer = lovr.graphics.newBuffer('vec3', 2)\n  buffer:setData({ 1,2,3, 4,5,6 })\n  buffer:setData({ { 1, 2, 3 }, { 4, 5, 6 } })\n  buffer:setData({ vec3(1, 2, 3), vec3(4, 5, 6) })\n\n  -- When the Buffer's length is 1, wrapping in table is optional:\n  buffer = lovr.graphics.newBuffer('vec3')\n  buffer:setData(1, 2, 3)\n  buffer:setData(vec3(1, 2, 3))\n\n  -- Same for key-value structs\n  buffer = lovr.graphics.newBuffer({\n    { 'x', 'float' },\n    { 'y', 'float' }\n  })\n  buffer:setData({ x = 1, y = 2 })\n\n  -- Key/value formats\n  buffer = lovr.graphics.newBuffer({\n    { 'x', 'float' },\n    { 'y', 'float' }\n  }, 3)\n  buffer:setData({\n    { x = 1, y = 2 },\n    { x = 3, y = 4 },\n    { x = 5, y = 6 }\n  })\n  buffer:setData({ 1, 2, 3, 4, 5, 6 })\n  buffer:setData({ { 1, 2 }, { 3, 4 }, { 5, 6 } })\n\n  -- Nested formats\n  buffer = lovr.graphics.newBuffer({\n    { 'a', {\n      {'b', {\n        'c', 'float'\n      }}\n    }}\n  })\n  buffer:setData({ a = { b = { c = 42 } } })\n\n  -- Inner arrays\n  buffer = lovr.graphics.newBuffer({\n    { 'positions', 'vec3', 10 },\n    { 'sizes', 'float', 10 },\n    layout = 'std140'\n  })\n  local data = { positions = {}, sizes = {} }\n  for i = 1, buffer:getLength() do\n    data.positions[i] = vec3(i, i, i)\n    data.sizes[i] = i\n  end\n  buffer:setData(data)\nend"
                }
              },
              notes = "One gotcha is that unspecified fields will be set to zero.  Here's an example:\n\n    buffer = lovr.graphics.newBuffer({{ 'x', 'int' }, { 'y', 'int' }})\n    buffer:setData({ x = 1, y = 1 }) -- set the data\n    buffer:setData({ x = 1 }) -- set the data, partially\n    -- buffer data is now {x=1, y=0}!\n\nThis doesn't apply to separate items in the buffer.  For example, if the Buffer's length is 2 and only the 1st item is set, the second item will remain undisturbed:\n\n    buffer = lovr.graphics.newBuffer({{ 'x', 'int' }, { 'y', 'int' }}, 2)\n    buffer:setData({{ x = 1, y = 1 }, { x = 2, y = 2 }}) -- set the data\n    buffer:setData({{ x = 1 }}) -- set one item, partially\n    -- buffer data is now {{x=1, y=0}, {x=2, y=2}}",
              variants = {
                {
                  arguments = {
                    {
                      name = "table",
                      type = "table",
                      description = "A flat or nested table of items to copy to the Buffer (see notes for format)."
                    },
                    {
                      name = "destinationIndex",
                      type = "number",
                      description = "The index of the first value in the Buffer to update.",
                      default = "1"
                    },
                    {
                      name = "sourceIndex",
                      type = "number",
                      description = "The index in the table to copy from.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of items to copy.  `nil` will copy as many items as possible, based on the lengths of the source and destination.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Copies a single field to a buffer with numbers (buffer length must be 0).",
                  arguments = {
                    {
                      name = "...numbers",
                      type = "number",
                      description = "Numerical components to copy to the buffer."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Copies a single vector to a buffer (buffer length must be 0).",
                  arguments = {
                    {
                      name = "vector",
                      type = "*",
                      description = "Vector objects to copy to the buffer."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob to copy data from."
                    },
                    {
                      name = "destinationOffset",
                      type = "number",
                      description = "The byte offset to copy to.",
                      default = "0"
                    },
                    {
                      name = "sourceOffset",
                      type = "number",
                      description = "The byte offset to copy from.",
                      default = "0"
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes to copy.  If nil, copies as many bytes as possible.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The Buffer to copy data from."
                    },
                    {
                      name = "destinationOffset",
                      type = "number",
                      description = "The byte offset to copy to.",
                      default = "0"
                    },
                    {
                      name = "sourceOffset",
                      type = "number",
                      description = "The byte offset to copy from.",
                      default = "0"
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The number of bytes to copy.  If nil, copies as many bytes as possible.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Metadata",
              tag = "buffer-metadata"
            },
            {
              name = "Transfers",
              tag = "buffer-transfer"
            }
          }
        },
        {
          name = "Font",
          summary = "A Font used to render text.",
          description = "Font objects are used to render text with `Pass:text`.  The active font can be changed using `Pass:setFont`.  The default font is Varela Round, which is used when no font is active, and can be retrieved using `lovr.graphics.getDefaultFont`.  Custom fonts can be loaded from TTF and BMFont files using `lovr.graphics.newFont`.\n\nEach Font uses a `Rasterizer` to load the font and create images for each glyph. As text is drawn, the Font uploads images from the Rasterizer to a GPU texture atlas as needed.  The Font also performs text layout and mesh generation for strings of text.\n\nFor TTF fonts, LÖVR uses a text rendering technique called \"multichannel signed distance fields\" (MSDF), which makes the font rendering remain crisp when text is viewed up close.",
          key = "Font",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newFont",
            "lovr.graphics.getDefaultFont"
          },
          extends = "Object",
          methods = {
            {
              name = "getAscent",
              summary = "Get the ascent of the Font.",
              description = "Returns the ascent of the font.  The ascent is the maximum amount glyphs ascend above the baseline.  The units depend on the font's pixel density.  With the default density, the units correspond to meters.",
              key = "Font:getAscent",
              module = "lovr.graphics",
              related = {
                "Rasterizer:getAscent",
                "Font:getDescent",
                "Font:getHeight",
                "Font:getKerning",
                "Font:getWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "ascent",
                      type = "number",
                      description = "The ascent of the font."
                    }
                  }
                }
              }
            },
            {
              name = "getDescent",
              summary = "Get the descent of the Font.",
              description = "Returns the descent of the font.  The descent is the maximum amount glyphs descend below the baseline.  The units depend on the font's pixel density.  With the default density, the units correspond to meters.",
              key = "Font:getDescent",
              module = "lovr.graphics",
              related = {
                "Rasterizer:getDescent",
                "Font:getAscent",
                "Font:getHeight",
                "Font:getKerning",
                "Font:getWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "descent",
                      type = "number",
                      description = "The descent of the font."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              summary = "Get the height of the Font.",
              description = "Returns the height of the font, sometimes also called the leading.  This is the full height of a line of text, including the space between lines.  Each line of a multiline string is separated on the y axis by this height, multiplied by the font's line spacing.  The units depend on the font's pixel density.  With the default density, the units correspond to meters.",
              key = "Font:getHeight",
              module = "lovr.graphics",
              related = {
                "Rasterizer:getLeading",
                "Font:getLineSpacing",
                "Font:setLineSpacing",
                "Font:getAscent",
                "Font:getDescent",
                "Font:getKerning",
                "Font:getWidth",
                "Font:getLines"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the font."
                    }
                  }
                }
              }
            },
            {
              name = "getKerning",
              summary = "Get the kerning between 2 glyphs.",
              description = "Returns the kerning between 2 glyphs.  Kerning is a slight horizontal adjustment between 2 glyphs to improve the visual appearance.  It will often be negative.  The units depend on the font's pixel density.  With the default density, the units correspond to meters.",
              key = "Font:getKerning",
              module = "lovr.graphics",
              related = {
                "Rasterizer:getKerning",
                "Font:getAscent",
                "Font:getDescent",
                "Font:getHeight",
                "Font:getWidth"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "first",
                      type = "string | number",
                      description = "The first character or codepoint."
                    },
                    {
                      name = "second",
                      type = "string | number",
                      description = "The second character or codepoint."
                    }
                  },
                  returns = {
                    {
                      name = "keming",
                      type = "number",
                      description = "The kerning between the two glyphs."
                    }
                  }
                }
              }
            },
            {
              name = "getLineSpacing",
              summary = "Get the line spacing of the Font.",
              description = "Returns the line spacing of the Font.  When spacing out lines, the height of the font is multiplied the line spacing to get the final spacing value.  The default is 1.0.",
              key = "Font:getLineSpacing",
              module = "lovr.graphics",
              related = {
                "Font:getHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "spacing",
                      type = "number",
                      description = "The line spacing of the font."
                    }
                  }
                }
              }
            },
            {
              name = "getLines",
              summary = "Wrap a string into a sequence of lines.",
              description = "Returns a table of wrapped lines for a piece of text, given a line length limit.\n\nBy default the units for `limit` are in meters.  If text is being drawn with scale applied, make sure the scale is also applied to the `limit`.",
              key = "Font:getLines",
              module = "lovr.graphics",
              notes = "The font's pixel density is incorporated into the limit.  So if the font's pixel density is changed to 1 (changing the font's units to pixels), the `limit` will be in pixels as well.",
              related = {
                "Font:getWidth",
                "Font:getHeight",
                "Pass:text"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "string",
                      type = "string",
                      description = "The text to wrap."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The line length to wrap at."
                    }
                  },
                  returns = {
                    {
                      name = "lines",
                      type = "{string}",
                      description = "A table of strings, one for each wrapped line."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "strings",
                      type = "table",
                      description = "A table of colored strings, each given as a `{ color, string }` pair.  The color can be a `Vec3`, `Vec4`, table, or hexcode."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The line length to wrap at."
                    }
                  },
                  returns = {
                    {
                      name = "lines",
                      type = "{string}",
                      description = "A table of strings, one for each wrapped line."
                    }
                  }
                }
              }
            },
            {
              name = "getPixelDensity",
              summary = "Get the pixel density of the Font.",
              description = "Returns the pixel density of the font.  The density is a \"pixels per world unit\" factor that controls how the pixels in the font's texture are mapped to units in the coordinate space.\n\nThe default pixel density is set to the height of the font.  This means that lines of text rendered with a scale of 1.0 come out to 1 unit (meter) tall.  However, if this font was drawn to a 2D texture where the units are in pixels, the font would still be drawn 1 unit (pixel) tall!  Scaling the coordinate space or the size of the text by the height of the font would fix this.  However, a more convenient option is to set the pixel density of the font to 1.0 when doing 2D rendering to make the font's size match up with the pixels of the canvas.",
              key = "Font:getPixelDensity",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "density",
                      type = "number",
                      description = "The pixel density of the font."
                    }
                  }
                }
              }
            },
            {
              name = "getRasterizer",
              summary = "Get the Font's Rasterizer.",
              description = "Returns the Rasterizer object backing the Font.",
              key = "Font:getRasterizer",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newFont",
                "lovr.data.newRasterizer"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "rasterizer",
                      type = "Rasterizer",
                      description = "The Rasterizer."
                    }
                  }
                }
              }
            },
            {
              name = "getVertices",
              summary = "Get the vertices for a piece of text.",
              description = "Returns a table of vertices for a piece of text, along with a Material to use when rendering it. The Material returned by this function may not be the same if the Font's texture atlas needs to be recreated with a bigger size to make room for more glyphs.",
              key = "Font:getVertices",
              module = "lovr.graphics",
              notes = "Each vertex is a table of 4 floating point numbers with the following data:\n\n    { x, y, u, v }\n\nThese could be placed in a vertex buffer using the following buffer format:\n\n    {\n      { 'VertexPosition', 'vec2' },\n      { 'VertexUV', 'vec2' }\n    }",
              variants = {
                {
                  arguments = {
                    {
                      name = "string",
                      type = "string",
                      description = "The text to render."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum line length.  The units depend on the pixel density of the font, but are in meters by default.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal align."
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical align."
                    }
                  },
                  returns = {
                    {
                      name = "vertices",
                      type = "{number}",
                      description = "The table of vertices.  See below for the format of each vertex."
                    },
                    {
                      name = "material",
                      type = "Material",
                      description = "A Material to use when rendering the vertices."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "strings",
                      type = "table",
                      description = "A table of colored strings, each given as a `{ color, string }` pair.  The color can be a `Vec3`, `Vec4`, table, or hexcode."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum line length.  The units depend on the pixel density of the font, but are in meters by default.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal align."
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical align."
                    }
                  },
                  returns = {
                    {
                      name = "vertices",
                      type = "{number}",
                      description = "The table of vertices.  See below for the format of each vertex."
                    },
                    {
                      name = "material",
                      type = "Material",
                      description = "A Material to use when rendering the vertices."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              summary = "Get the width of rendered text.",
              description = "Returns the maximum width of a piece of text.  This function does not perform wrapping but does respect newlines in the text.",
              key = "Font:getWidth",
              module = "lovr.graphics",
              related = {
                "Font:getAscent",
                "Font:getDescent",
                "Font:getHeight",
                "Font:getKerning",
                "Font:getLines"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "string",
                      type = "string",
                      description = "The text to measure."
                    }
                  },
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The maximum width of the text."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "strings",
                      type = "table",
                      description = "A table of colored strings, each given as a `{ color, string }` pair.  The color can be a `Vec3`, `Vec4`, table, or hexcode."
                    }
                  },
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The maximum width of the text."
                    }
                  }
                }
              }
            },
            {
              name = "setLineSpacing",
              summary = "Set the line spacing of the Font.",
              description = "Sets the line spacing of the Font.  When spacing out lines, the height of the font is multiplied by the line spacing to get the final spacing value.  The default is 1.0.",
              key = "Font:setLineSpacing",
              module = "lovr.graphics",
              related = {
                "Font:getHeight"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "spacing",
                      type = "number",
                      description = "The new line spacing."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPixelDensity",
              summary = "Set the pixel density of the Font.",
              description = "Sets the pixel density of the font.  The density is a \"pixels per world unit\" factor that controls how the pixels in the font's texture are mapped to units in the coordinate space.\n\nThe default pixel density is set to the height of the font.  This means that lines of text rendered with a scale of 1.0 come out to 1 unit (meter) tall.  However, if this font was drawn to a 2D texture where the units are in pixels, the font would still be drawn 1 unit (pixel) tall!  Scaling the coordinate space or the size of the text by the height of the font would fix this.  However, a more convenient option is to set the pixel density of the font to 1.0 when doing 2D rendering to make the font's size match up with the pixels of the canvas.",
              key = "Font:setPixelDensity",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "density",
                      type = "number",
                      description = "The new pixel density of the font."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Resets the pixel density to the default, which is given by `Font:getHeight`.",
                  arguments = {},
                  returns = {}
                }
              }
            }
          },
          notes = "MSDF text requires a special shader to work.  LÖVR will automatically switch to this shader if no shader is active on the `Pass`.  This font shader is also available as a `DefaultShader`."
        },
        {
          name = "Material",
          summary = "A set of properties and textures that define the properties of a surface.",
          description = "Materials are a set of properties and textures that define the properties of a surface, like what color it is, how bumpy or shiny it is, etc. `Shader` code can use the data from a material to compute lighting.\n\nMaterials are immutable, and can't be changed after they are created.  Instead, a new Material should be created with the updated properties.\n\n`Pass:setMaterial` changes the active material, causing it to affect rendering until the active material is changed again.\n\nUsing material objects is optional.  `Pass:setMaterial` can take a `Texture`, and `Pass:setColor` can change the color of objects, so basic tinting and texturing of surfaces does not require a full material to be created.  Also, a custom material system could be developed by sending textures and other data to shaders manually.\n\n`Model` objects will create materials for all of the materials defined in the model file.\n\nIn shader code, non-texture material properties can be accessed as `Material.<property>`, and material textures can be accessed as `<Type>Texture`, e.g. `RoughnessTexture`.",
          key = "Material",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newMaterial"
          },
          extends = "Object",
          methods = {
            {
              name = "getProperties",
              summary = "Get the properties of the Material.",
              description = "Returns the properties of the Material in a table.",
              key = "Material:getProperties",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "properties",
                      type = "table",
                      description = "The Material properties."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Mesh",
          summary = "A drawable triangle mesh.",
          description = "Meshes store arbitrary geometry data, and can be drawn with `Pass:draw`.\n\nMeshes hold a list of **vertices**.  The number of vertices is declared upfront when the Mesh is created, and it can not be resized afterwards.\n\nThe Mesh has a **vertex format**, which is a set of **attributes** comprising each vertex, like a `position`, `color`, etc.\n\nThe **vertex indices** in the Mesh describe the order that the vertices are rendered in.  This is an optimization that allows vertices to be reused if they are used for multiple triangles, without duplicating all of their data.\n\nThe Mesh has a **draw mode**, which controls how the vertices are connected together to create pixels.  It can either be `points`, `lines`, or `triangles`.\n\nThe Mesh can have a `Material` applied, which defines colors, textures, and other properties of its surface.\n\nThe **draw range** of the Mesh defines a subset of the vertices to render when the Mesh is drawn.\n\nThe **bounding box** of the Mesh allows LÖVR to skip rendering it when it's out of view.",
          key = "Mesh",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newMesh"
          },
          extends = "Object",
          methods = {
            {
              name = "computeBoundingBox",
              summary = "Compute the bounding box of the Mesh.",
              description = "Computes the axis-aligned bounding box of the Mesh from its vertices.\n\nIf the Mesh was created with the `gpu` storage mode, this function will do nothing and return `false`.\n\nIf the Mesh does not have an attribute named `VertexPosition` with the `f32x3` (aka `vec3`) type, this function will do nothing and return `false`.\n\nOtherwise, the bounding box will be set and the return value will be `true`.\n\nThe bounding box can also be assigned manually using `Mesh:setBoundingBox`, which can be used to set the bounding box on a `gpu` mesh or for cases where the bounding box is already known.\n\nPasses will use the bounding box of a Mesh to cull it against the cameras when `Pass:setViewCull` is enabled, which avoids rendering it when it's out of view.",
              key = "Mesh:computeBoundingBox",
              module = "lovr.graphics",
              related = {
                "Mesh:getBoundingBox",
                "Mesh:setBoundingBox",
                "Pass:setViewCull",
                "Collider:getAABB",
                "Shape:getAABB",
                "Model:getBoundingBox",
                "ModelData:getBoundingBox"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "updated",
                      type = "boolean",
                      description = "Whether the bounding box was updated."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingBox",
              summary = "Get the bounding box of the Mesh.",
              description = "Returns the axis-aligned bounding box of the Mesh, or `nil` if the Mesh doesn't have a bounding box.\n\nMeshes with the `cpu` storage mode can compute their bounding box automatically using `Mesh:computeBoundingBox`.  The bounding box can also be set manually using `Mesh:setBoundingBox`.\n\nPasses will use the bounding box of a Mesh to cull it against the cameras when `Pass:setViewCull` is enabled, which avoids rendering it when it's out of view.",
              key = "Mesh:getBoundingBox",
              module = "lovr.graphics",
              related = {
                "Mesh:computeBoundingBox",
                "Pass:setViewCull",
                "Collider:getAABB",
                "Shape:getAABB",
                "Model:getBoundingBox",
                "ModelData:getBoundingBox"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the bounding box."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the bounding box."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the bounding box."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the bounding box."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the bounding box."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the bounding box."
                    }
                  }
                }
              }
            },
            {
              name = "getDrawMode",
              summary = "Get the draw mode of the Mesh.",
              description = "Returns the `DrawMode` of the mesh, which controls how the vertices in the Mesh are connected together to create pixels.  The default is `triangles`.",
              key = "Mesh:getDrawMode",
              module = "lovr.graphics",
              related = {
                "Pass:setMeshMode"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mode",
                      type = "DrawMode",
                      description = "The current draw mode."
                    }
                  }
                }
              }
            },
            {
              name = "getDrawRange",
              summary = "Get the range of vertices drawn by the Mesh.",
              description = "Returns the range of vertices drawn by the Mesh.  If different sets of mesh data are stored in a single Mesh object, the draw range can be used to select different sets of vertices to render.",
              key = "Mesh:getDrawRange",
              module = "lovr.graphics",
              related = {
                "Mesh:setIndices"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "start",
                      type = "number",
                      description = "The index of the first vertex that will be drawn (or the first index, if the Mesh has vertex indices)."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices that will be drawn (or indices, if the Mesh has vertex indices)."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "When the Mesh has vertex indices, an offset that will be added to the index values before fetching the corresponding vertex.  This is ignored if the Mesh does not have vertex indices."
                    }
                  }
                },
                {
                  description = "This function returns nothing if no draw range is set.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getIndexBuffer",
              summary = "Get the Buffer backing the vertex indices of the Mesh.",
              description = "Returns the `Buffer` object that holds the data for the vertex indices in the Mesh.\n\nThis can be `nil` if the Mesh doesn't have any indices.\n\nIf a Mesh uses the `cpu` storage mode, the index buffer is internal to the `Mesh` and this function will return `nil`.  This ensures that the CPU data for the Mesh does not get out of sync with the GPU data in the Buffer.",
              key = "Mesh:getIndexBuffer",
              module = "lovr.graphics",
              related = {
                "Mesh:getIndices",
                "Mesh:setIndices",
                "Mesh:getVertexBuffer"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The index buffer."
                    }
                  }
                }
              }
            },
            {
              name = "getIndices",
              summary = "Get the vertex indices in the Mesh.",
              description = "Returns a table with the Mesh's vertex indices.",
              key = "Mesh:getIndices",
              module = "lovr.graphics",
              notes = "This function will be very very slow if the Mesh's storage is `gpu`, because the data needs to be downloaded from the GPU.",
              related = {
                "Mesh:getIndexBuffer",
                "Mesh:setIndexBuffer"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table of numbers with the 1-based vertex indices."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterial",
              summary = "Get the Material applied to the Mesh.",
              description = "Returns the `Material` applied to the Mesh.",
              key = "Mesh:getMaterial",
              module = "lovr.graphics",
              related = {
                "Pass:setMaterial",
                "Model:getMaterial",
                "lovr.graphics.newMaterial"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "material",
                      type = "Material",
                      description = "The material."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexBuffer",
              summary = "Get the Buffer backing the vertices of the Mesh.",
              description = "Returns the `Buffer` object that holds the data for the vertices in the Mesh.\n\nIf a Mesh uses the `cpu` storage mode, the vertex buffer is internal to the `Mesh` and this function will return `nil`.  This ensures that the CPU data for the Mesh does not get out of sync with the GPU data in the Buffer.",
              key = "Mesh:getVertexBuffer",
              module = "lovr.graphics",
              related = {
                "Mesh:getVertices",
                "Mesh:setVertices",
                "Mesh:getIndexBuffer"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The vertex buffer."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexCount",
              summary = "Get the number of vertices in the Mesh.",
              description = "Returns the number of vertices in the Mesh.  The vertex count is set when the Mesh is created and can't change afterwards.",
              key = "Mesh:getVertexCount",
              module = "lovr.graphics",
              related = {
                "Mesh:getVertexStride",
                "Mesh:getVertexFormat",
                "lovr.graphics.newMesh",
                "Model:getMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices in the Mesh."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexFormat",
              summary = "Get the vertex format of the Mesh.",
              description = "Returns the vertex format of the Mesh, which is a list of \"attributes\" that make up the data for each vertex (position, color, UV, etc.).",
              key = "Mesh:getVertexFormat",
              module = "lovr.graphics",
              notes = "If no vertex format is given when the Mesh is created, it will use a default format:\n\n    {\n      { 'VertexPosition', 'vec3', 0 },\n      { 'VertexNormal', 'vec3', 12 },\n      { 'VertexUV', 'vec2', 24 }\n    }\n\nThe name of the vertex attribute corresponds to an `in` input variable in a vertex shader.\n\nThere are a few built-in attributes that all shaders will understand and use by default:\n\n<table>\n  <thead>\n    <tr>\n      <td>Name</td>\n      <td>Description</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td><code>VertexPosition</code></td>\n      <td>The position of the vertex.</td>\n    </tr>\n    <tr>\n      <td><code>VertexNormal</code></td>\n      <td>The normal vector of the vertex.</td>\n    </tr>\n    <tr>\n      <td><code>VertexUV</code></td>\n      <td>The texture coordinate of the vertex.</td>\n    </tr>\n    <tr>\n      <td><code>VertexColor</code></td>\n      <td>The color of the vertex (linear color space).</td>\n    </tr>\n    <tr>\n      <td><code>VertexTangent</code></td>\n      <td>The tangent vector of the vertex.</td>\n    </tr>\n  </tbody> </table>\n\nSee the `Shaders` and `Meshes` guides for more info.",
              related = {
                "Mesh:getVertexCount",
                "Mesh:getVertexStride",
                "lovr.graphics.newMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "format",
                      type = "table",
                      description = "The vertex format.",
                      table = {
                        {
                          name = "[][1]",
                          type = "string",
                          description = "The name of the attribute."
                        },
                        {
                          name = "[][2]",
                          type = "DataType",
                          description = "The type of the attribute."
                        },
                        {
                          name = "[][3]",
                          type = "number",
                          description = "The byte offset of the attribute."
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              name = "getVertexStride",
              summary = "Get the size of each vertex in the Mesh.",
              description = "Returns the stride of the Mesh, which is the number of bytes used by each vertex.",
              key = "Mesh:getVertexStride",
              module = "lovr.graphics",
              related = {
                "Mesh:getVertexCount",
                "Mesh:getVertexFormat",
                "lovr.graphics.newMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "stride",
                      type = "number",
                      description = "The stride of the Mesh, in bytes."
                    }
                  }
                }
              }
            },
            {
              name = "getVertices",
              summary = "Get the vertices in the Mesh.",
              description = "Returns the vertices in the Mesh.",
              key = "Mesh:getVertices",
              module = "lovr.graphics",
              notes = "> **This function will be very very slow if the storage mode of the Mesh is `gpu`, because the\n> data will be downloaded from VRAM.  A better option is to call `Buffer:newReadback` on the\n> Mesh's underlying vertex buffer (`Mesh:getVertexBuffer`), which will download in the\n> background instead of waiting for it to complete.**",
              related = {
                "Mesh:getVertexBuffer",
                "Mesh:getVertexFormat",
                "Mesh:getIndices",
                "Mesh:setIndices"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the first vertex to return.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to return.  If nil, returns the \"rest\" of the vertices, based on the `index` argument.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "vertices",
                      type = "{{number}}",
                      description = "A table of vertices.  Each vertex is a table of numbers for each vertex attribute, given by the vertex format of the Mesh."
                    }
                  }
                }
              }
            },
            {
              name = "setBoundingBox",
              summary = "Set or remove the bounding box of the Mesh.",
              description = "Sets or removes the axis-aligned bounding box of the Mesh.\n\nMeshes with the `cpu` storage mode can compute their bounding box automatically using `Mesh:computeBoundingBox`.\n\nPasses will use the bounding box of a Mesh to cull it against the cameras when `Pass:setViewCull` is enabled, which avoids rendering it when it's out of view.",
              key = "Mesh:setBoundingBox",
              module = "lovr.graphics",
              related = {
                "Mesh:computeBoundingBox",
                "Pass:setViewCull",
                "Collider:getAABB",
                "Shape:getAABB",
                "Model:getBoundingBox",
                "ModelData:getBoundingBox"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the bounding box."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the bounding box."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the bounding box."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the bounding box."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the bounding box."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the bounding box."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Remove the bounding box.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setDrawMode",
              summary = "Set the draw mode of the Mesh.",
              description = "Changes the `DrawMode` of the mesh, which controls how the vertices in the Mesh are connected together to create pixels.  The default is `triangles`.",
              key = "Mesh:setDrawMode",
              module = "lovr.graphics",
              related = {
                "Pass:setMeshMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "DrawMode",
                      description = "The current draw mode."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDrawRange",
              summary = "Set the range of vertices drawn by the Mesh.",
              description = "Sets the range of vertices drawn by the Mesh.  If different sets of mesh data are stored in a single Mesh object, the draw range can be used to select different sets of vertices to render.",
              key = "Mesh:setDrawRange",
              module = "lovr.graphics",
              notes = "When using an index buffer, the draw range defines a range of indices to render instead of a range of vertices.  Additionally, a vertex offset can be set, which is added to the values in the index buffer before fetching the vertices.  This makes it easier to pack multiple sets of indexed mesh data in a single Mesh object, without having to manually offset the data in each index buffer.",
              related = {
                "Mesh:setIndices"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "start",
                      type = "number",
                      description = "The index of the first vertex that will be drawn (or the first index, if the Mesh has vertex indices)."
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices that will be drawn (or indices, if the Mesh has vertex indices)."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "When the Mesh has vertex indices, an offset that will be added to the index values before fetching the corresponding vertex.  This is ignored if the Mesh does not have vertex indices."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the draw range.  The Mesh will draw all of its vertices.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setIndexBuffer",
              summary = "Set a Buffer for the Mesh to use for vertex indices.",
              description = "Sets a `Buffer` object the Mesh will use for vertex indices.\n\nThis can only be used if the Mesh uses the `gpu` storage mode.\n\nThe Buffer must have a single field with the `u16`, `u32`, `index16`, or `index32` type.",
              key = "Mesh:setIndexBuffer",
              module = "lovr.graphics",
              examples = {
                {
                  description = "Use an index buffer to draw a plane.",
                  code = "function lovr.load()\n  mesh = lovr.graphics.newMesh({\n    { -1,  1, 0 }, -- upper left\n    {  1,  1, 0 }, -- upper right\n    { -1, -1, 0 }, -- lower left\n    {  1, -1, 0 }, -- lower right\n  }, 'gpu')\n\n  -- 2 triangles\n  local indices = { 1,3,2, 2,3,4 }\n\n  local indexBuffer = lovr.graphics.newBuffer('index16', indices)\n  mesh:setIndexBuffer(indexBuffer)\nend\n\nfunction lovr.draw(pass)\n  pass:draw(mesh, 0, 1.7, -2)\nend"
                }
              },
              notes = "The index buffer stores a list of numbers where each number is the index of a vertex in the Mesh.  When drawing the Mesh, the data from the vertex corresponding to the index is used.  This can be used to reorder or reuse vertices, which uses less data than repeating a vertex multiple times in the Mesh.",
              related = {
                "Mesh:getIndices",
                "Mesh:setIndices",
                "Mesh:getVertexBuffer"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The index buffer."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setIndices",
              summary = "Set the vertex indices of the Mesh.",
              description = "Sets or clears the vertex indices of the Mesh.  Vertex indices define the list of triangles in the mesh.  They allow vertices to be reused multiple times without duplicating all their data, which can save a lot of memory and processing time if a vertex is used for multiple triangles.\n\nIf a Mesh doesn't have vertex indices, then the vertices are rendered in order.",
              key = "Mesh:setIndices",
              module = "lovr.graphics",
              related = {
                "Mesh:getIndexBuffer",
                "Mesh:setIndexBuffer",
                "Mesh:setVertices"
              },
              variants = {
                {
                  description = "Set vertex indices using a table.",
                  arguments = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A list of numbers (1-based)."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set vertex indices using a Blob.",
                  arguments = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob with index data."
                    },
                    {
                      name = "type",
                      type = "DataType",
                      description = "The type of index data in the Blob.  Must be `u16` or `u32`."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable vertex indices.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMaterial",
              summary = "Set a Material to use when drawing the Mesh.",
              description = "Sets a `Material` to use when drawing the Mesh.",
              key = "Mesh:setMaterial",
              module = "lovr.graphics",
              related = {
                "Pass:setMaterial",
                "Model:getMaterial",
                "lovr.graphics.newMaterial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "material",
                      type = "Material",
                      description = "The material to use."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The texture to use as the material."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setVertices",
              summary = "Set vertices in the Mesh.",
              description = "Sets the data for vertices in the Mesh.",
              key = "Mesh:setVertices",
              module = "lovr.graphics",
              notes = "Note that a `Pass` that draws a Mesh will only \"see\" the vertices as they exist when the pass is submitted.  So, if this function is used to change vertices multiple times before submitting the Pass, only the final value of each vertex will be used.  Example:\n\n    function lovr.draw(pass)\n      -- Due to the second :setVertices call below, the Mesh\n      -- contains a sphere when this pass is submitted!  So\n      -- this code will actually draw 2 spheres!\n      mesh:setVertices(cube)\n      pass:draw(mesh, x1, y1, z1)\n\n      mesh:setVertices(sphere)\n      pass:draw(mesh, x2, y2, z2)\n    end\n\nIf you want multiple meshes, then use multiple Mesh objects!  Or, *append* vertices to the Mesh instead of replacing them, and use `Mesh:setDrawRange` to control which vertices are drawn for a particular draw call.\n\nCPU meshes will write the data to CPU memory and upload any changes to the GPU before the Mesh is drawn.  GPU meshes don't store this CPU copy of the data, and will immediately upload the new vertex data to VRAM.  This means that multiple calls to this function might be slower on a `gpu` mesh.",
              related = {
                "Mesh:getVertexBuffer",
                "Mesh:getVertexFormat",
                "Mesh:getIndices",
                "Mesh:setIndices"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "vertices",
                      type = "{{number}}",
                      description = "A table of vertices, where each vertex is a table of numbers matching the vertex format of the Mesh."
                    },
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the first vertex to set.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to set.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "A Blob containing binary vertex data."
                    },
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the first vertex to set.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to set.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Model",
          summary = "A 3D model.",
          description = "Models are 3D model assets loaded from files.  Currently, OBJ, glTF, and binary STL files are supported.\n\nA model can be drawn using `Pass:draw`.\n\nThe raw CPU data for a model is held in a `ModelData` object, which can be loaded on threads or reused for multiple Model instances.\n\nModels have a hierarchy of nodes which can have their transforms modified.  Meshes are attached to these nodes.  The same mesh can be attached to multiple nodes, allowing it to be drawn multiple times while only storing a single copy of its data.\n\nModels can have animations.  Animations have keyframes which affect the transforms of nodes. Right now each model can only be drawn with a single animated pose per frame.\n\nModels can have materials, which are collections of properties and textures that define how its surface is affected by lighting.  Each mesh in the model can use a single material.",
          key = "Model",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newModel",
            "lovr.headset.newModel"
          },
          extends = "Object",
          methods = {
            {
              name = "animate",
              summary = "Animate the Model.",
              description = "Animates a Model by setting or blending the transforms of nodes using data stored in the keyframes of an animation.\n\nThe animation from the model file is evaluated at the timestamp, resulting in a set of node properties.  These properties are then applied to the nodes in the model, using an optional blend factor.  If the animation doesn't have keyframes that target a given node, the node will remain unchanged.",
              key = "Model:animate",
              module = "lovr.graphics",
              notes = "If the timestamp is larger than the duration of the animation, it will wrap back around to zero, so looping an animation doesn't require using the modulo operator.\n\nTo change the speed of the animation, multiply the timestamp by a speed factor.\n\nFor each animated property in the animation, if the timestamp used for the animation is less than the timestamp of the first keyframe, the data of the first keyframe will be used.\n\nThis function can be called multiple times to layer and blend animations.  The model joints will be drawn in the final resulting pose.\n\n`Model:resetNodeTransforms` can be used to reset the model nodes to their initial transforms, which is helpful to ensure animating starts from a clean slate.",
              related = {
                "Model:resetNodeTransforms",
                "Model:getAnimationCount",
                "Model:getAnimationName",
                "Model:getAnimationDuration",
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodeTransform",
                "Model:setNodeTransform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string",
                      description = "The name or index of an animation in the model file."
                    },
                    {
                      name = "time",
                      type = "number",
                      description = "The timestamp to evaluate the keyframes at, in seconds."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "How much of the animation's pose to blend into the nodes, from 0 to 1.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "clone",
              summary = "Return a lightweight copy of the Model with its own animation state.",
              description = "Returns a lightweight copy of a Model.  Most of the data will be shared between the two copies of the model, like the materials, textures, and metadata.  However, the clone has its own set of node transforms, allowing it to be animated separately from its parent.  This allows a single model to be rendered in multiple different animation poses in a frame.",
              key = "Model:clone",
              module = "lovr.graphics",
              notes = "The node transforms of the clone will be reset to their initial setup poses.",
              related = {
                "lovr.graphics.newModel"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "model",
                      type = "Model",
                      description = "A genetically identical copy of the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationCount",
              summary = "Get the number of animations in the Model.",
              description = "Returns the number of animations in the Model.",
              key = "Model:getAnimationCount",
              module = "lovr.graphics",
              related = {
                "Model:getAnimationName",
                "Model:getAnimationDuration",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of animations in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationDuration",
              summary = "Get the duration of an animation in the Model.",
              description = "Returns the duration of an animation in the Model, in seconds.",
              key = "Model:getAnimationDuration",
              module = "lovr.graphics",
              notes = "The duration of an animation is calculated as the largest timestamp of all of its keyframes.",
              related = {
                "Model:getAnimationCount",
                "Model:getAnimationName",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "animation",
                      type = "string | number",
                      description = "The name or index of an animation."
                    }
                  },
                  returns = {
                    {
                      name = "duration",
                      type = "number",
                      description = "The duration of the animation, in seconds."
                    }
                  }
                }
              }
            },
            {
              name = "getAnimationName",
              summary = "Get the name of an animation in the Model.",
              description = "Returns the name of an animation in the Model.",
              key = "Model:getAnimationName",
              module = "lovr.graphics",
              related = {
                "Model:getAnimationCount",
                "Model:getAnimationDuration"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of an animation."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string | nil",
                      description = "The name of the animation, or `nil` if the animation doesn't have a name."
                    }
                  }
                }
              }
            },
            {
              name = "getBlendShapeCount",
              summary = "Get the number of blend shapes in the model.",
              description = "Returns the number of blend shapes in the model.",
              key = "Model:getBlendShapeCount",
              module = "lovr.graphics",
              related = {
                "Model:getBlendShapeName",
                "ModelData:getBlendShapeCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of blend shapes in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getBlendShapeName",
              summary = "Get the name of a blend shape in the model.",
              description = "Returns the name of a blend shape in the model.",
              key = "Model:getBlendShapeName",
              module = "lovr.graphics",
              notes = "This function will throw an error if the blend shape index is invalid.",
              related = {
                "Model:getBlendShapeCount",
                "ModelData:getBlendShapeName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of a blend shape."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the blend shape."
                    }
                  }
                }
              }
            },
            {
              name = "getBlendShapeWeight",
              summary = "Get the weight of a blend shape.",
              description = "Returns the weight of a blend shape.  A blend shape contains offset values for the vertices of one of the meshes in a Model.  Whenever the Model is drawn, the offsets are multiplied by the weight of the blend shape, allowing for smooth blending between different meshes.  A weight of zero won't apply any displacement and will skip processing of the blend shape.",
              key = "Model:getBlendShapeWeight",
              module = "lovr.graphics",
              notes = "The initial weights are declared in the model file.\n\nWeights can be any number, but usually they're kept between 0 and 1.\n\nThis function will throw an error if the blend shape name or index doesn't exist.",
              related = {
                "Model:getBlendShapeCount",
                "Model:getBlendShapeName",
                "Model:resetBlendShapes"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "blendshape",
                      type = "string | number",
                      description = "The name or index of a blend shape."
                    }
                  },
                  returns = {
                    {
                      name = "weight",
                      type = "number",
                      description = "The weight of the blend shape."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingBox",
              summary = "Get the bounding box of the Model.",
              description = "Returns the 6 values of the Model's axis-aligned bounding box.",
              key = "Model:getBoundingBox",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getHeight",
                "Model:getDepth",
                "Model:getDimensions",
                "Model:getCenter",
                "Model:getBoundingSphere",
                "ModelData:getBoundingBox",
                "Collider:getAABB"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the vertices in the Model."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the vertices in the Model."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the vertices in the Model."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the vertices in the Model."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the vertices in the Model."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the vertices in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getBoundingSphere",
              summary = "Get the bounding sphere of the Model.",
              description = "Returns a sphere approximately enclosing the vertices in the Model.",
              key = "Model:getBoundingSphere",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getHeight",
                "Model:getDepth",
                "Model:getDimensions",
                "Model:getCenter",
                "Model:getBoundingBox",
                "ModelData:getBoundingSphere"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the position of the sphere."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the position of the sphere."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the position of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the bounding sphere."
                    }
                  }
                }
              }
            },
            {
              name = "getCenter",
              summary = "Get the center of the Model's bounding box.",
              description = "Returns the center of the Model's axis-aligned bounding box, relative to the Model's origin.",
              key = "Model:getCenter",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getHeight",
                "Model:getDepth",
                "Model:getDimensions",
                "Model:getBoundingBox",
                "ModelData:getCenter"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x offset of the center of the bounding box."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y offset of the center of the bounding box."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z offset of the center of the bounding box."
                    }
                  }
                }
              }
            },
            {
              name = "getData",
              summary = "Get the ModelData backing the Model.",
              description = "Returns the ModelData this Model was created from.",
              key = "Model:getData",
              module = "lovr.graphics",
              related = {
                "lovr.data.newModelData"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "data",
                      type = "ModelData",
                      description = "The ModelData."
                    }
                  }
                }
              }
            },
            {
              name = "getDepth",
              summary = "Get the depth of the Model.",
              description = "Returns the depth of the Model, computed from its axis-aligned bounding box.",
              key = "Model:getDepth",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getHeight",
                "Model:getDimensions",
                "Model:getCenter",
                "Model:getBoundingBox",
                "ModelData:getDepth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              summary = "Get the dimensions of the Model.",
              description = "Returns the width, height, and depth of the Model, computed from its axis-aligned bounding box.",
              key = "Model:getDimensions",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getHeight",
                "Model:getDepth",
                "Model:getCenter",
                "Model:getBoundingBox",
                "ModelData:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Model."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Model."
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              summary = "Get the height of the Model.",
              description = "Returns the height of the Model, computed from its axis-aligned bounding box.",
              key = "Model:getHeight",
              module = "lovr.graphics",
              related = {
                "Model:getWidth",
                "Model:getDepth",
                "Model:getDimensions",
                "Model:getCenter",
                "Model:getBoundingBox",
                "ModelData:getHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getIndexBuffer",
              summary = "Get a Buffer containing the triangle indices in the Model.",
              description = "Returns the index buffer used by the Model.  The index buffer describes the order used to draw the vertices in each mesh.",
              key = "Model:getIndexBuffer",
              module = "lovr.graphics",
              related = {
                "Model:getVertexBuffer",
                "Model:getMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The index buffer."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterial",
              summary = "Get a Material from the Model.",
              description = "Returns a `Material` loaded from the Model.",
              key = "Model:getMaterial",
              module = "lovr.graphics",
              related = {
                "Model:getMaterialCount",
                "Model:getMaterialName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "which",
                      type = "string | number",
                      description = "The name or index of the Material to return."
                    }
                  },
                  returns = {
                    {
                      name = "material",
                      type = "Material",
                      description = "The material."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterialCount",
              summary = "Get the number of materials in the Model.",
              description = "Returns the number of materials in the Model.",
              key = "Model:getMaterialCount",
              module = "lovr.graphics",
              related = {
                "Model:getMaterialName",
                "Model:getMaterial"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of materials in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getMaterialName",
              summary = "Get the name of a material in the Model.",
              description = "Returns the name of a material in the Model.",
              key = "Model:getMaterialName",
              module = "lovr.graphics",
              related = {
                "Model:getMaterialCount",
                "Model:getMaterial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of a material."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the material."
                    }
                  }
                }
              }
            },
            {
              name = "getMesh",
              summary = "Get a Mesh from the Model.",
              description = "Returns a `Mesh` from the Model.",
              key = "Model:getMesh",
              module = "lovr.graphics",
              related = {
                "Model:getMeshCount",
                "lovr.graphics.newMesh"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the Mesh to return."
                    }
                  },
                  returns = {
                    {
                      name = "mesh",
                      type = "Mesh",
                      description = "The mesh object."
                    }
                  }
                }
              }
            },
            {
              name = "getMeshCount",
              summary = "Get the number of meshes in the Model.",
              description = "Returns the number of meshes in the Model.",
              key = "Model:getMeshCount",
              module = "lovr.graphics",
              related = {
                "Model:getMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of meshes in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getMetadata",
              summary = "Get extra information from the model file.",
              description = "Returns extra information stored in the model file.  Currently this is only implemented for glTF models and returns the JSON string from the glTF or glb file.  The metadata can be used to get application-specific data or add support for glTF extensions not supported by LÖVR.",
              key = "Model:getMetadata",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "metadata",
                      type = "string",
                      description = "The metadata from the model file."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeChildren",
              summary = "Get the children of a node.",
              description = "Given a parent node, this function returns a table with the indices of its children.",
              key = "Model:getNodeChildren",
              module = "lovr.graphics",
              notes = "If the node does not have any children, this function returns an empty table.",
              related = {
                "Model:getNodeParent",
                "Model:getRootNode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of the parent node."
                    }
                  },
                  returns = {
                    {
                      name = "children",
                      type = "{number}",
                      description = "A table containing the node index of each child of the parent node."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeCount",
              summary = "Get the number of nodes in the model.",
              description = "Returns the number of nodes in the model.",
              key = "Model:getNodeCount",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of nodes in the model."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeName",
              summary = "Get the name of a node in the Model.",
              description = "Returns the name of a node.",
              key = "Model:getNodeName",
              module = "lovr.graphics",
              related = {
                "Model:getNodeCount",
                "Model:getAnimationName",
                "Model:getMaterialName"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the node."
                    }
                  },
                  returns = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the node."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeOrientation",
              summary = "Get the orientation of a node.",
              description = "Returns the orientation of a node.",
              key = "Model:getNodeOrientation",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "origin",
                      type = "OriginType",
                      description = "Whether the orientation should be returned relative to the root node or the node's parent.",
                      default = "'root'"
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeParent",
              summary = "Get the parent of a node.",
              description = "Given a child node, this function returns the index of its parent.",
              key = "Model:getNodeParent",
              module = "lovr.graphics",
              related = {
                "Model:getNodeChildren",
                "Model:getRootNode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "number",
                      description = "The name or index of the child node."
                    }
                  },
                  returns = {
                    {
                      name = "parent",
                      type = "number",
                      description = "The index of the parent."
                    }
                  }
                }
              }
            },
            {
              name = "getNodePose",
              summary = "Get the pose of a node.",
              description = "Returns the pose (position and orientation) of a node.",
              key = "Model:getNodePose",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "origin",
                      type = "OriginType",
                      description = "Whether the pose should be returned relative to the root node or the node's parent.",
                      default = "'root'"
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the node."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the node."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the node."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getNodePosition",
              summary = "Get the position of a node.",
              description = "Returns the position of a node.",
              key = "Model:getNodePosition",
              module = "lovr.graphics",
              related = {
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "space",
                      type = "OriginType",
                      description = "Whether the position should be returned relative to the root node or the node's parent.",
                      default = "'root'"
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeScale",
              summary = "Get the scale of a node.",
              description = "Returns the scale of a node.",
              key = "Model:getNodeScale",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "origin",
                      type = "OriginType",
                      description = "Whether the scale should be returned relative to the root node or the node's parent.",
                      default = "'root'"
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x scale."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y scale."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z scale."
                    }
                  }
                }
              }
            },
            {
              name = "getNodeTransform",
              summary = "Get the transform of a node.",
              description = "Returns the transform (position, scale, and rotation) of a node.",
              key = "Model:getNodeTransform",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "origin",
                      type = "OriginType",
                      description = "Whether the transform should be returned relative to the root node or the node's parent.",
                      default = "'root'"
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the node."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the node."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the node."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x scale of the node."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y scale of the node."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z scale of the node."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getRootNode",
              summary = "Get the index of the root node.",
              description = "Returns the index of the model's root node.",
              key = "Model:getRootNode",
              module = "lovr.graphics",
              related = {
                "Model:getNodeCount",
                "Model:getNodeParent"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "root",
                      type = "number",
                      description = "The index of the root node."
                    }
                  }
                }
              }
            },
            {
              name = "getTexture",
              summary = "Get one of the textures in the Model.",
              description = "Returns one of the textures in the Model.",
              key = "Model:getTexture",
              module = "lovr.graphics",
              related = {
                "Model:getTextureCount",
                "Model:getMaterial"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the texture to get."
                    }
                  },
                  returns = {
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The texture."
                    }
                  }
                }
              }
            },
            {
              name = "getTextureCount",
              summary = "Get the number of textures in the Model.",
              description = "Returns the number of textures in the Model.",
              key = "Model:getTextureCount",
              module = "lovr.graphics",
              related = {
                "Model:getTexture"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of textures in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getTriangleCount",
              summary = "Get the total number of triangles in the Model.",
              description = "Returns the total number of triangles in the Model.",
              key = "Model:getTriangleCount",
              module = "lovr.graphics",
              notes = "This isn't always related to the length of the vertex buffer, since a mesh in the Model could be drawn by multiple nodes.",
              related = {
                "Model:getTriangles",
                "Model:getVertexCount",
                "ModelData:getTriangleCount",
                "Model:getMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The total number of triangles in the Model."
                    }
                  }
                }
              }
            },
            {
              name = "getTriangles",
              summary = "Get all the triangles in the Model.",
              description = "Returns 2 tables containing mesh data for the Model.\n\nThe first table is a list of vertex positions and contains 3 numbers for the x, y, and z coordinate of each vertex.  The second table is a list of triangles and contains 1-based indices into the first table representing the first, second, and third vertices that make up each triangle.\n\nThe vertex positions will be affected by node transforms.",
              key = "Model:getTriangles",
              module = "lovr.graphics",
              notes = "After this function is called on a Model once, the result is cached (in its ModelData).",
              related = {
                "Model:getTriangleCount",
                "Model:getVertexCount",
                "Model:getMesh",
                "ModelData:getTriangles"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "vertices",
                      type = "{number}",
                      description = "The triangle vertex positions, returned as a flat (non-nested) table of numbers.  The position of each vertex is given as an x, y, and z coordinate."
                    },
                    {
                      name = "indices",
                      type = "{number}",
                      description = "A list of numbers representing how to connect the vertices into triangles.  Each number is a 1-based index into the `vertices` table, and every 3 indices form a triangle."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexBuffer",
              summary = "Get a Buffer containing the vertices in the Model.",
              description = "Returns a `Buffer` that holds the vertices of all of the meshes in the Model.",
              key = "Model:getVertexBuffer",
              module = "lovr.graphics",
              related = {
                "Model:getIndexBuffer",
                "Model:getMesh"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The vertex buffer."
                    }
                  }
                }
              }
            },
            {
              name = "getVertexCount",
              summary = "Get the total vertex count of the Model.",
              description = "Returns the total vertex count of the Model.",
              key = "Model:getVertexCount",
              module = "lovr.graphics",
              notes = "This isn't always the same as the length of the vertex buffer, since a mesh in the Model could be drawn by multiple nodes.",
              related = {
                "Model:getTriangles",
                "Model:getTriangleCount",
                "ModelData:getVertexCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The total number of vertices."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              summary = "Get the width of the Model.",
              description = "Returns the width of the Model, computed from its axis-aligned bounding box.",
              key = "Model:getWidth",
              module = "lovr.graphics",
              related = {
                "Model:getHeight",
                "Model:getDepth",
                "Model:getDimensions",
                "Model:getCenter",
                "Model:getBoundingBox",
                "ModelData:getWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Model."
                    }
                  }
                }
              }
            },
            {
              name = "hasJoints",
              summary = "Check if the Model uses joints for skeletal animation.",
              description = "Returns whether the Model has any skeletal animations.",
              key = "Model:hasJoints",
              module = "lovr.graphics",
              notes = "This will return when there's at least one skin in the model, as returned by `ModelData:getSkinCount`.\n\nEven if this function returns true, the model could still have non-skeletal animations.\n\nRight now a model can only be drawn with one skeletal pose per frame.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "jointed",
                      type = "boolean",
                      description = "Whether the animation uses joint nodes for skeletal animation."
                    }
                  }
                }
              }
            },
            {
              name = "resetBlendShapes",
              summary = "Reset blend shape weights.",
              description = "Resets blend shape weights to the original ones defined in the model file.",
              key = "Model:resetBlendShapes",
              module = "lovr.graphics",
              related = {
                "Model:resetNodeTransforms",
                "Model:getBlendShapeWeight",
                "Model:setBlendShapeWeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "resetNodeTransforms",
              summary = "Reset node transforms.",
              description = "Resets node transforms to the original ones defined in the model file.",
              key = "Model:resetNodeTransforms",
              module = "lovr.graphics",
              related = {
                "Model:resetBlendShapes"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setBlendShapeWeight",
              summary = "Set the weight of a blend shape.",
              description = "Sets the weight of a blend shape.  A blend shape contains offset values for the vertices of one of the meshes in a Model.  Whenever the Model is drawn, the offsets are multiplied by the weight of the blend shape, allowing for smooth blending between different meshes.  A weight of zero won't apply any displacement and will skip processing of the blend shape.",
              key = "Model:setBlendShapeWeight",
              module = "lovr.graphics",
              notes = "The initial weights are declared in the model file.\n\nWeights can be any number, but usually they're kept between 0 and 1.\n\nThis function will throw an error if the blend shape name or index doesn't exist.",
              related = {
                "Model:getBlendShapeCount",
                "Model:getBlendShapeName",
                "Model:resetBlendShapes"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "blendshape",
                      type = "string | number",
                      description = "The name or index of a blend shape."
                    },
                    {
                      name = "weight",
                      type = "number",
                      description = "The new weight for the blend shape."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setNodeOrientation",
              summary = "Set or blend the orientation of a node.",
              description = "Sets or blends the orientation of a node to a new orientation.  This sets the local orientation of the node, relative to its parent.",
              key = "Model:setNodeOrientation",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node should be rotated around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target orientation to blend in.  A value of 0 will not change the node's orientation at all, whereas 1 will fully blend to the target orientation.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target orientation to blend in.  A value of 0 will not change the node's orientation at all, whereas 1 will fully blend to the target orientation.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setNodePose",
              summary = "Set or blend the pose of a node.",
              description = "Sets or blends the pose (position and orientation) of a node to a new pose.  This sets the local pose of the node, relative to its parent.  The scale will remain unchanged.",
              key = "Model:setNodePose",
              module = "lovr.graphics",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the position."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node should be rotated around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target pose to blend in.  A value of 0 will not change the node's pose at all, whereas 1 will fully blend to the target pose.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The target position.  Can also be provided as 3 numbers."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The target orientation.  Can also be provided as 4 numbers in angle-axis form."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target pose to blend in.  A value of 0 will not change the node's pose at all, whereas 1 will fully blend to the target pose.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setNodePosition",
              summary = "Set or blend the position of a node.",
              description = "Sets or blends the position of a node.  This sets the local position of the node, relative to its parent.",
              key = "Model:setNodePosition",
              module = "lovr.graphics",
              related = {
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the new position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the new position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the new position."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the new position to blend in.  A value of 0 will not change the node's position at all, whereas 1 will fully blend to the target position.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The new position."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the new position to blend in.  A value of 0 will not change the node's position at all, whereas 1 will fully blend to the target position.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setNodeScale",
              summary = "Set or blend the scale of a node.",
              description = "Sets or blends the scale of a node to a new scale.  This sets the local scale of the node, relative to its parent.",
              key = "Model:setNodeScale",
              module = "lovr.graphics",
              notes = "For best results when animating, it's recommended to keep the 3 scale components the same.",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:getNodeTransform",
                "Model:setNodeTransform",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z scale."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the new scale to blend in.  A value of 0 will not change the node's scale at all, whereas 1 will fully blend to the target scale.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The new scale."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the new scale to blend in.  A value of 0 will not change the node's scale at all, whereas 1 will fully blend to the target scale.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setNodeTransform",
              summary = "Set or blend the transform of a node.",
              description = "Sets or blends the transform of a node to a new transform.  This sets the local transform of the node, relative to its parent.",
              key = "Model:setNodeTransform",
              module = "lovr.graphics",
              notes = "For best results when animating, it's recommended to keep the 3 components of the scale the same.\n\nEven though the translation, scale, and rotation parameters are given in TSR order, they are applied in the normal TRS order.",
              related = {
                "Model:getNodePosition",
                "Model:setNodePosition",
                "Model:getNodeOrientation",
                "Model:setNodeOrientation",
                "Model:getNodeScale",
                "Model:setNodeScale",
                "Model:getNodePose",
                "Model:setNodePose",
                "Model:animate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the position."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x component of the scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y component of the scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z component of the scale."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the node should be rotated around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target transform to blend in.  A value of 0 will not change the node's transform at all, whereas 1 will fully blend to the target transform.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position."
                    },
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The scale."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target transform to blend in.  A value of 0 will not change the node's transform at all, whereas 1 will fully blend to the target transform.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "node",
                      type = "string | number",
                      description = "The name or index of a node."
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform."
                    },
                    {
                      name = "blend",
                      type = "number",
                      description = "A number from 0 to 1 indicating how much of the target transform to blend in.  A value of 0 will not change the node's transform at all, whereas 1 will fully blend to the target transform.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Pass",
          summary = "A stream of graphics commands.",
          description = "Pass objects record work for the GPU.  They contain a list of things to draw and a list of compute shaders to run.\n\nMethods like `Pass:sphere` will \"record\" a draw on the Pass, which adds it to the list.  Other methods like `Pass:setBlendMode` or `Pass:setShader` will change the way the next draws are processed.\n\nOnce all of the work has been recorded to a Pass, it can be sent to the GPU using `lovr.graphics.submit`, which will start processing all of the compute work and draws (in that order).\n\nA Pass can have a canvas, which is a set of textures that the draws will render to.\n\n`Pass:reset` is used to clear all of the computes and draws, putting the Pass in a fresh state.\n\n`lovr.draw` is called every frame with a `Pass` that is configured to render to either the headset or the window.  The Pass will automatically get submitted afterwards.",
          key = "Pass",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newPass",
            "lovr.graphics.getWindowPass",
            "lovr.headset.getPass"
          },
          extends = "Object",
          methods = {
            {
              name = "barrier",
              tag = "compute",
              summary = "Synchronize compute work.",
              description = "Synchronizes compute work.\n\nBy default, within a single Pass, multiple calls to `Pass:compute` can run on the GPU in any order, or all at the same time.  This is great because it lets the GPU process the work as efficiently as possible, but sometimes multiple compute dispatches need to be sequenced.\n\nCalling this function will insert a barrier.  All compute operations on the Pass after the barrier will only start once all of the previous compute operations on the Pass are finished.",
              key = "Pass:barrier",
              module = "lovr.graphics",
              examples = {
                {
                  code = "pass = lovr.graphics.newPass()\npass:setShader(computeShader)\n\npass:compute(x, y, z)\npass:compute(x, y, z)\npass:barrier()\npass:compute(x, y, z) --> waits for the previous 2 :computes to complete"
                }
              },
              notes = "It's only necessary to use a barrier if a compute shader is reading/writing the same bytes of memory that a previous compute operation in the same Pass read/wrote.\n\nBarriers will slow things down because they reduce parallelism by causing the GPU to wait. Strategic reordering of non-dependent :compute calls around the barrier can help.\n\nCalling this function before recording any :computes will do nothing, and calling it after the last :compute will do nothing.",
              related = {
                "Pass:compute"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "beginTally",
              tag = "tally",
              summary = "Begin a tally.",
              description = "Begins a new tally.  The tally will count the number of pixels touched by any draws that occur while the tally is active.  If a pixel fails the depth test or stencil test then it won't be counted, so the tally is a way to detect if objects are visible.\n\nThe results for all the tallies in the pass can be copied to a `Buffer` when the Pass finishes by setting a buffer with `Pass:setTallyBuffer`.",
              key = "Pass:beginTally",
              module = "lovr.graphics",
              notes = "There is currently a maximum of 256 tallies per pass.\n\nIf a tally is already active, this function will error.",
              related = {
                "Pass:finishTally"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the tally that was started."
                    }
                  }
                }
              }
            },
            {
              name = "box",
              tag = "drawing",
              summary = "Draw a box.",
              description = "Draw a box.  This is like `Pass:cube`, except it takes 3 separate values for the scale.",
              key = "Pass:box",
              module = "lovr.graphics",
              related = {
                "Pass:cube"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the box.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the box.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the box.",
                      default = "0"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box.",
                      default = "1"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box.",
                      default = "1"
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the box around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the box should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the box."
                    },
                    {
                      name = "size",
                      type = "Vec3",
                      description = "The size of the box."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the box."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the box should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the box."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the box should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "capsule",
              tag = "drawing",
              summary = "Draw a capsule.",
              description = "Draws a capsule.  A capsule is shaped like a cylinder with a hemisphere on each end.",
              key = "Pass:capsule",
              module = "lovr.graphics",
              notes = "The length of the capsule does not include the end caps.  The local origin of the capsule is in the center, and the local z axis points towards the end caps.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the capsule.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the capsule.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the capsule.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule.",
                      default = "1.0"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the capsule.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the capsule around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule.",
                      default = "1.0"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the capsule.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the capsule."
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the capsule."
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draws a capsule between two points.",
                  arguments = {
                    {
                      name = "p1",
                      type = "Vec3",
                      description = "The starting point of the capsule."
                    },
                    {
                      name = "p2",
                      type = "Vec3",
                      description = "The ending point of the capsule."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule.",
                      default = "1.0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "circle",
              tag = "drawing",
              summary = "Draw a circle.",
              description = "Draws a circle.",
              key = "Pass:circle",
              module = "lovr.graphics",
              notes = "The local origin of the circle is in its center.  The local z axis is perpendicular to the circle.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the circle.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the circle.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the circle.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the circle.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the circle around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the circle should be filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the circle."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the circle.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the circle."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the circle should be filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the circle."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the circle should be filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "compute",
              tag = "compute",
              summary = "Run a compute shader.",
              description = "Runs a compute shader.  There must be an active compute shader set using `Pass:setShader`.\n\nAll of the compute shader dispatches in a Pass will run **before** all of the draws in the Pass (if any).  They will also run at the same time in parallel, unless `Pass:barrier` is used to control the order.",
              key = "Pass:compute",
              module = "lovr.graphics",
              examples = {
                {
                  description = "A compute shader that makes a texture grayscale.",
                  code = "function lovr.load()\n  shader = lovr.graphics.newShader([[\n    layout(local_size_x = 8, local_size_y = 8) in;\n    layout(rgba8) uniform image2D image;\n\n    void lovrmain() {\n      ivec2 size = imageSize(image);\n      ivec2 pixel = ivec2(GlobalThreadID.xy);\n\n      if (pixel.x >= size.x || pixel.y >= size.y) {\n        return;\n      }\n\n      vec4 color = imageLoad(image, pixel);\n      color.rgb = vec3(color.r * .2126 + color.g * .7512 + color.b * .0722);\n      imageStore(image, pixel, color);\n    }\n  ]])\n\n  texture = lovr.graphics.newTexture('image.png', {\n    usage = { 'storage', 'sample', 'transfer' },\n    linear = true -- srgb textures don't always support storage usage\n  })\n\n  local tw, th = texture:getDimensions()\n  local sx, sy = shader:getWorkgroupSize()\n  local gx, gy = math.ceil(tw / sx), math.ceil(th / sy)\n\n  local computer = lovr.graphics.newPass()\n\n  computer:setShader(shader)\n  computer:send('image', texture)\n  computer:compute(gx, gy)\n  lovr.graphics.submit(computer)\n\n  texture:generateMipmaps()\nend\n\nfunction lovr.draw(pass)\n  pass:draw(texture, 0, 1.7, -1)\nend"
                }
              },
              notes = "Compute shaders are usually run once for each pixel in an image, once per particle, once per object, etc.  The 3 arguments represent how many times to run, or \"dispatch\", the compute shader, in up to 3 dimensions.  Each element of this grid is called a **workgroup**.\n\nTo make things even more complicated, each workgroup itself is made up of a set of \"mini GPU threads\", which are called **local workgroups**.  Like workgroups, the local workgroup size can also be 3D.  It's declared in the shader code, like this:\n\n    layout(local_size_x = w, local_size_y = h, local_size_z = d) in;\n\nAll these 3D grids can get confusing, but the basic idea is to make the local workgroup size a small block of e.g. 32 particles or 8x8 pixels or 4x4x4 voxels, and then dispatch however many workgroups are needed to cover a list of particles, image, voxel field, etc.\n\nThe reason to do it this way is that the GPU runs its threads in little fixed-size bundles called subgroups.  Subgroups are usually 32 or 64 threads (the exact size is given by the `subgroupSize` property of `lovr.graphics.getDevice`) and all run together.  If the local workgroup size was `1x1x1`, then the GPU would only run 1 thread per subgroup and waste the other 31 or 63.  So for the best performance, be sure to set a local workgroup size bigger than 1!\n\nInside the compute shader, a few builtin variables can be used to figure out which workgroup is running:\n\n- `uvec3 WorkgroupCount` is the workgroup count per axis (the `Pass:compute` arguments).\n- `uvec3 WorkgroupSize` is the local workgroup size (declared in the shader).\n- `uvec3 WorkgroupID` is the index of the current (global) workgroup.\n- `uvec3 LocalThreadID` is the index of the local workgroup inside its workgroup.\n- `uint LocalThreadIndex` is a 1D version of `LocalThreadID`.\n- `uvec3 GlobalThreadID` is the unique identifier for a thread within all workgroups in a\n  dispatch. It's equivalent to `WorkgroupID * WorkgroupSize + LocalThreadID` (usually what you\n  want!)\n\nThere are limits to the number of workgroups that can be dispatched, see the `workgroupCount` limit in `lovr.graphics.getLimits`.  The local workgroup size is also limited by the `workgroupSize` and `totalWorkgroupSize` limits.\n\nIndirect compute dispatches are useful to \"chain\" compute shaders together, while keeping all of the data on the GPU.  The first dispatch can do some computation and write some results to buffers, then the second indirect dispatch can use the data in those buffers to know how many times it should run.  An example would be a compute shader that does some sort of object culling, writing the number of visible objects to a buffer along with the IDs of each one. Subsequent compute shaders can be indirectly dispatched to perform extra processing on the visible objects.  Finally, an indirect draw can be used to render them.",
              related = {
                "Pass:barrier",
                "Pass:setShader",
                "Pass:send",
                "lovr.graphics.getLimits"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The number of workgroups to dispatch in the x dimension.",
                      default = "1"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The number of workgroups to dispatch in the y dimension.",
                      default = "1"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The number of workgroups to dispatch in the z dimension.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Perform an \"indirect\" dispatch.  Instead of passing in the workgroup counts directly from Lua, the workgroup counts are read from a `Buffer` object at a particular byte offset. Each count should be a 4-byte integer, so in total 12 bytes will be read from the buffer.",
                  arguments = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "A Buffer object containing the x, y, and z workgroup counts, stored as 4 byte unsigned integers."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "The byte offset to read the workgroup counts from in the Buffer.",
                      default = "0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "cone",
              tag = "drawing",
              summary = "Draw a cone.",
              description = "Draws a cone.",
              key = "Pass:cone",
              module = "lovr.graphics",
              notes = "The local origin is at the center of the base of the cone, and the negative z axis points towards the tip.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the base of the cone.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the base of the cone.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the base of the cone.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cone.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cone.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the cone around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments in the cone.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the base of the cone."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cone.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cone.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the cone."
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments in the cone.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the cone."
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments in the cone.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "p1",
                      type = "Vec3",
                      description = "The position of the base of the cone."
                    },
                    {
                      name = "p2",
                      type = "Vec3",
                      description = "The position of the tip of the cone."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cone.",
                      default = "1"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of segments in the cone.",
                      default = "64"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "cube",
              tag = "drawing",
              summary = "Draw a cube.",
              description = "Draws a cube.",
              key = "Pass:cube",
              module = "lovr.graphics",
              notes = "The local origin is in the center of the cube.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the cube.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the cube.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the cube.",
                      default = "0"
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The size of the cube.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the cube around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the cube should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the cube."
                    },
                    {
                      name = "size",
                      type = "number",
                      description = "The size of the cube.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the cube."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the cube should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the cube."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the cube should be drawn filled or outlined.",
                      default = "'fill'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "cylinder",
              tag = "drawing",
              summary = "Draw a cylinder.",
              description = "Draws a cylinder.",
              key = "Pass:cylinder",
              module = "lovr.graphics",
              notes = "The local origin is in the center of the cylinder, and the length of the cylinder is along the z axis.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the cylinder.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the cylinder.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the cylinder.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cylinder.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the cylinder around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "capped",
                      type = "boolean",
                      description = "Whether the tops and bottoms of the cylinder should be rendered.",
                      default = "true"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the cylinder."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cylinder.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the cylinder."
                    },
                    {
                      name = "capped",
                      type = "boolean",
                      description = "Whether the tops and bottoms of the cylinder should be rendered.",
                      default = "true"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the cylinder."
                    },
                    {
                      name = "capped",
                      type = "boolean",
                      description = "Whether the tops and bottoms of the cylinder should be rendered.",
                      default = "true"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "p1",
                      type = "Vec3",
                      description = "The starting point of the cylinder."
                    },
                    {
                      name = "p2",
                      type = "Vec3",
                      description = "The ending point of the cylinder."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder.",
                      default = "1"
                    },
                    {
                      name = "capped",
                      type = "boolean",
                      description = "Whether the tops and bottoms of the cylinder should be rendered.",
                      default = "true"
                    },
                    {
                      name = "angle1",
                      type = "number",
                      description = "The angle of the beginning of the arc.",
                      default = "0"
                    },
                    {
                      name = "angle2",
                      type = "number",
                      description = "angle of the end of the arc.",
                      default = "2 * math.pi"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to render.",
                      default = "64"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "draw",
              tag = "drawing",
              summary = "Draw a Model, Mesh, or Texture.",
              description = "Draws a `Model`, `Mesh`, or `Texture`.",
              key = "Pass:draw",
              module = "lovr.graphics",
              notes = "`Model:getMesh` can be used to draw individual meshes of a model.\n\nTextures ignore the `instances` parameter.\n\nWhen drawing a Texture, the plane will be 1 meter wide at 1.0 scale and the height will be adjusted based on the Texture's aspect ratio.",
              variants = {
                {
                  arguments = {
                    {
                      name = "object",
                      type = "Model | Mesh | Texture",
                      description = "The object to draw."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate to draw the object at.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate to draw the object at.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate to draw the object at.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the object.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the object around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of instances to draw.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "object",
                      type = "Model | Mesh | Texture",
                      description = "The object to draw."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to draw the object at."
                    },
                    {
                      name = "scale3",
                      type = "Vec3",
                      description = "The scale of the object, as a vector."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the object."
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of instances to draw.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "object",
                      type = "Model | Mesh | Texture",
                      description = "The object to draw."
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the object."
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of instances to draw.",
                      default = "1"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "fill",
              tag = "drawing",
              summary = "Draw a fullscreen triangle.",
              description = "Draws a fullscreen triangle.  The `fill` shader is used, which stretches the triangle across the screen.",
              key = "Pass:fill",
              module = "lovr.graphics",
              notes = "This function has some special behavior for array textures:\n\n- Filling a single-layer texture to a multi-layer canvas will mirror the texture to all layers,\n  just like regular drawing.\n- Filling a 2-layer texture to a mono canvas will render the 2 layers side-by-side.\n- Filling a multi-layer texture to a multi-layer canvas will do a layer-by-layer fill (the layer\n  counts must match).",
              variants = {
                {
                  arguments = {
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The texture to fill.  If nil, the texture from the active material is used."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "finishTally",
              tag = "tally",
              summary = "Finish a tally.",
              description = "Finishes a tally that was previously started with `Pass:beginTally`.  This will stop counting the number of pixels affected by draws.\n\nThe results for all the tallies in the pass can be copied to a `Buffer` when the Pass finishes by setting a buffer with `Pass:setTallyBuffer`.",
              key = "Pass:finishTally",
              module = "lovr.graphics",
              notes = "There is currently a maximum of 256 tallies per pass.\n\nIf no tally is active, this function will error.",
              related = {
                "Pass:beginTally"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the tally that was finished."
                    }
                  }
                }
              }
            },
            {
              name = "getCanvas",
              tag = "canvas",
              summary = "Get the Pass's canvas.",
              description = "Returns the Pass's canvas, or `nil` if the Pass doesn't have a canvas.  The canvas is a set of textures that the Pass will draw to when it's submitted.",
              key = "Pass:getCanvas",
              module = "lovr.graphics",
              notes = "If the Pass has multiple color textures, a fragment shader should be used to write a different color to each texture.  Here's an example that writes red to the first texture and blue to the second texture:\n\n    // Declare an output variable for the second texture\n    layout(location = 1) out vec4 secondColor;\n\n    vec4 lovrmain() {\n      secondColor = vec4(0, 0, 1, 1);\n      return vec4(1, 0, 0, 1);\n    }",
              related = {
                "Pass:getClear",
                "Pass:setClear",
                "Pass:getWidth",
                "Pass:getHeight",
                "Pass:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "canvas",
                      type = "table",
                      description = "The canvas.  Numeric keys will contain the color Textures, along with the following keys:",
                      table = {
                        {
                          name = "depth",
                          type = "*",
                          description = "A `Texture` or `TextureFormat` with the depth buffer."
                        },
                        {
                          name = "samples",
                          type = "number",
                          description = "The number of multisamples used for antialiasing (either 1 or 4)."
                        }
                      }
                    }
                  }
                },
                {
                  description = "This function returns nil when a canvas hasn't been set.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getClear",
              tag = "canvas",
              summary = "Return the clear values of the Pass.",
              description = "Returns the clear values of the pass.",
              key = "Pass:getClear",
              module = "lovr.graphics",
              notes = "The default clear color is transparent black.",
              related = {
                "Pass:getCanvas"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "clears",
                      type = "table",
                      description = "The clear values for the pass.  Each color texture's clear value is stored at its index, as either a 4-number rgba table or a boolean.  If the pass has a depth texture, there will also be a `depth` key with its clear value as a number or boolean."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              tag = "canvas",
              summary = "Get the dimensions of the Pass's canvas.",
              description = "Returns the dimensions of the textures of the Pass's canvas, in pixels.",
              key = "Pass:getDimensions",
              module = "lovr.graphics",
              notes = "If the pass doesn't have a canvas, this function returns zeros.",
              related = {
                "Pass:getWidth",
                "Pass:getHeight",
                "Pass:getViewCount",
                "Pass:getCanvas",
                "Pass:setCanvas",
                "lovr.system.getWindowDimensions",
                "lovr.headset.getDisplayDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The texture width."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The texture height."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              tag = "canvas",
              summary = "Get the height of the Pass's canvas.",
              description = "Returns the height of the textures of the Pass's canvas, in pixels.",
              key = "Pass:getHeight",
              module = "lovr.graphics",
              notes = "If the pass doesn't have a canvas, this function returns zero.",
              related = {
                "Pass:getWidth",
                "Pass:getDimensions",
                "Pass:getViewCount",
                "Pass:getCanvas",
                "Pass:setCanvas",
                "lovr.system.getWindowHeight",
                "lovr.headset.getDisplayHeight"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The texture height."
                    }
                  }
                }
              }
            },
            {
              name = "getLabel",
              tag = "pass-misc",
              summary = "Get the debug label of the Pass.",
              description = "Returns the debug label of the Pass, which will show up when the Pass is printed and in some graphics debugging tools.  This is set when the Pass is created, and can't be changed afterwards.",
              key = "Pass:getLabel",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newPass",
                "Texture:getLabel",
                "Shader:getLabel"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "label",
                      type = "string",
                      description = "The label, or nil if none was set."
                    }
                  }
                }
              }
            },
            {
              name = "getProjection",
              tag = "camera",
              summary = "Get the field of view.",
              description = "Returns the projection for a single view.",
              key = "Pass:getProjection",
              module = "lovr.graphics",
              related = {
                "lovr.headset.getViewAngles",
                "lovr.headset.getViewCount",
                "Pass:getViewPose",
                "Pass:setViewPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The view index."
                    }
                  },
                  returns = {
                    {
                      name = "left",
                      type = "number",
                      description = "The left field of view angle, in radians."
                    },
                    {
                      name = "right",
                      type = "number",
                      description = "The right field of view angle, in radians."
                    },
                    {
                      name = "up",
                      type = "number",
                      description = "The top field of view angle, in radians."
                    },
                    {
                      name = "down",
                      type = "number",
                      description = "The bottom field of view angle, in radians."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The view index."
                    },
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "The matrix to fill with the projection."
                    }
                  },
                  returns = {
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "The matrix containing the projection."
                    }
                  }
                }
              }
            },
            {
              name = "getStats",
              tag = "pass-misc",
              summary = "Get statistics for the Pass.",
              description = "Returns statistics for the Pass.",
              key = "Pass:getStats",
              module = "lovr.graphics",
              examples = {
                {
                  description = "See how long it takes the GPU to render a cube.",
                  code = "lovr.graphics.setTimingEnabled(true)\n\nfunction lovr.draw(pass)\n  pass:cube(0, 1.7, -1, .5, lovr.timer.getTime() * .2, 0, 1, 0)\n\n  local stats = pass:getStats()\n  print(('Rendering a cube takes %f microseconds'):format(stats.gpuTime * 1e6))\nend"
                }
              },
              related = {
                "lovr.graphics.isTimingEnabled",
                "lovr.graphics.setTimingEnabled",
                "Pass:setViewCull"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "stats",
                      type = "table",
                      description = "A table with statistics.",
                      table = {
                        {
                          name = "draws",
                          type = "number",
                          description = "The number of draws added to the Pass."
                        },
                        {
                          name = "computes",
                          type = "number",
                          description = "The number of compute calls added to the Pass."
                        },
                        {
                          name = "drawsCulled",
                          type = "number",
                          description = "The number of draw calls that were culled the last time the Pass was submitted."
                        },
                        {
                          name = "cpuMemoryReserved",
                          type = "number",
                          description = "The amount of CPU memory the Pass has reserved, in bytes."
                        },
                        {
                          name = "cpuMemoryUsed",
                          type = "number",
                          description = "The amount of CPU memory the Pass is currently using, in bytes."
                        },
                        {
                          name = "submitTime",
                          type = "number",
                          description = "The amount of time taken on the CPU to submit the Pass the last time it was submitted, in seconds.  Only updates when timing stats have been enabled with `lovr.graphics.setTimingEnabled`, and has a few frames of delay."
                        },
                        {
                          name = "gpuTime",
                          type = "number",
                          description = "The amount of time taken on the GPU to process the Pass, in seconds.  Only updates when timing stats have been enabled with `lovr.graphics.setTimingEnabled`, and has a few frames of delay."
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              name = "getTallyBuffer",
              tag = "tally",
              summary = "Get the Buffer that tally results will be written to.",
              description = "Returns the Buffer that tally results will be written to.  Each time the render pass finishes, the results of all the tallies will be copied to the Buffer at the specified offset.  The buffer can be used in a later pass in a compute shader, or the data in the buffer can be read back using e.g. `Buffer:newReadback`.\n\nIf no buffer has been set, this function will return `nil`.",
              key = "Pass:getTallyBuffer",
              module = "lovr.graphics",
              related = {
                "Pass:beginTally",
                "Pass:finishTally"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The buffer."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "An offset in the buffer where results will be written."
                    }
                  }
                }
              }
            },
            {
              name = "getViewCount",
              tag = "camera",
              summary = "Returns the view count of a render pass.",
              description = "Returns the view count of a render pass.  This is the layer count of the textures it is rendering to.",
              key = "Pass:getViewCount",
              module = "lovr.graphics",
              notes = "A render pass has one \"camera\" for each view.  Whenever something is drawn, it is broadcast to each view (layer) of each texture, using the corresponding camera.",
              related = {
                "Pass:getViewPose",
                "Pass:setViewPose",
                "Pass:getProjection",
                "Pass:setProjection",
                "lovr.headset.getViewCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "views",
                      type = "number",
                      description = "The view count."
                    }
                  }
                }
              }
            },
            {
              name = "getViewPose",
              tag = "camera",
              summary = "Get the camera pose.",
              description = "Get the pose of a single view.",
              key = "Pass:getViewPose",
              module = "lovr.graphics",
              related = {
                "lovr.headset.getViewPose",
                "lovr.headset.getViewCount",
                "Pass:getProjection",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The view index."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the viewer, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the viewer, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the viewer, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the viewer is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The view index."
                    },
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "The matrix to fill with the view pose."
                    },
                    {
                      name = "invert",
                      type = "boolean",
                      description = "Whether the matrix should be inverted."
                    }
                  },
                  returns = {
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "The matrix containing the view pose."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              tag = "canvas",
              summary = "Get the width of the Pass's canvas.",
              description = "Returns the width of the textures of the Pass's canvas, in pixels.",
              key = "Pass:getWidth",
              module = "lovr.graphics",
              notes = "If the pass doesn't have a canvas, this function returns zero.",
              related = {
                "Pass:getHeight",
                "Pass:getDimensions",
                "Pass:getViewCount",
                "Pass:getCanvas",
                "Pass:setCanvas",
                "lovr.system.getWindowWidth",
                "lovr.headset.getDisplayWidth"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The texture width."
                    }
                  }
                }
              }
            },
            {
              name = "line",
              tag = "drawing",
              summary = "Draw a line.",
              description = "Draws a line between points.  `Pass:mesh` can also be used to draw line segments using the `line` `DrawMode`.",
              key = "Pass:line",
              module = "lovr.graphics",
              notes = "There is currently no way to increase line thickness.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the first point."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the first point."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the first point."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the next point."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the next point."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the next point."
                    },
                    {
                      name = "...numbers",
                      type = "number",
                      description = "More points to add to the line."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number | Vec3}",
                      description = "A table of numbers or `Vec3` objects (not a mix) representing points of the line."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "v1",
                      type = "Vec3",
                      description = "A vector containing the position of the first point of the line."
                    },
                    {
                      name = "v2",
                      type = "Vec3",
                      description = "A vector containing the position of the next point on the line."
                    },
                    {
                      name = "...vectors",
                      type = "Vec3",
                      description = "More points to add to the line."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "mesh",
              tag = "drawing",
              summary = "Draw a mesh.",
              description = "Draws a mesh.",
              key = "Pass:mesh",
              module = "lovr.graphics",
              examples = {
                {
                  code = "function lovr.load()\n  local vertices = {\n    { vec3(  0,  .4, 0), vec4(1, 0, 0, 1) },\n    { vec3(-.5, -.4, 0), vec4(0, 1, 0, 1) },\n    { vec3( .5, -.4, 0), vec4(0, 0, 1, 1) }\n  }\n\n  local format = {\n    { name = 'VertexPosition', type = 'vec3' },\n    { name = 'VertexColor', type = 'vec4' }\n  }\n\n  triangle = lovr.graphics.newBuffer(format, vertices)\nend\n\nfunction lovr.draw(pass)\n  pass:mesh(triangle, 0, 1.7, -1)\nend"
                }
              },
              notes = "The index buffer defines the order the vertices are drawn in.  It can be used to reorder, reuse, or omit vertices from the mesh.\n\nWhen drawing without a vertex buffer, the `VertexIndex` variable can be used in shaders to compute the position of each vertex, possibly by reading data from other `Buffer` or `Texture` resources.\n\nThe active `DrawMode` controls whether the vertices are drawn as points, lines, or triangles.\n\nThe active `Material` is applied to the mesh.",
              related = {
                "Pass:setMeshMode"
              },
              variants = {
                {
                  description = "Draw a range of vertices from a Buffer, using numbers for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the mesh.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the mesh is rotated around its rotational axis.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draw a range of vertices from a Buffer, using vector types for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to draw the mesh at."
                    },
                    {
                      name = "scales",
                      type = "Vec3",
                      description = "The scale of the mesh."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the mesh."
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draw a range of vertices from a Buffer, using a matrix for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform to apply to the mesh."
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draw a mesh using a vertex buffer and an index buffer, using numbers for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "indices",
                      type = "Buffer",
                      description = "The buffer containing the vertex indices to draw."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the position to draw the mesh at.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the mesh.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the mesh is rotated around its rotational axis.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    },
                    {
                      name = "base",
                      type = "number",
                      description = "A base offset to apply to vertex indices.",
                      default = "0"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draw a mesh using a vertex buffer and an index buffer, using vector types for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "indices",
                      type = "Buffer",
                      description = "The buffer containing the vertex indices to draw."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to draw the mesh at."
                    },
                    {
                      name = "scales",
                      type = "Vec3",
                      description = "The scale of the mesh."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the mesh."
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    },
                    {
                      name = "base",
                      type = "number",
                      description = "A base offset to apply to vertex indices.",
                      default = "0"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Draw a mesh using a vertex buffer and an index buffer, using a matrix for the transform.",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "indices",
                      type = "Buffer",
                      description = "The buffer containing the vertex indices to draw."
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform to apply to the mesh."
                    },
                    {
                      name = "start",
                      type = "number",
                      description = "The 1-based index of the first vertex to render from the vertex buffer (or the first index, when using an index buffer).",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of vertices to render (or the number of indices, when using an index buffer). When `nil`, as many vertices or indices as possible will be drawn (based on the length of the Buffers and `start`).",
                      default = "nil"
                    },
                    {
                      name = "instances",
                      type = "number",
                      description = "The number of copies of the mesh to render.",
                      default = "1"
                    },
                    {
                      name = "base",
                      type = "number",
                      description = "A base offset to apply to vertex indices.",
                      default = "0"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Perform indirect draws by specifying a `draws` command buffer.  This allows for the drawing of instanced geometry to be orchestrated by a compute shader that writes to the `draws` buffer.  The `draws` buffer contains one or more commands that define how to draw instances. The `stride` determines the number of bytes between each draw command.  By default the draws are assumed to be tightly packed, with 20 bytes between indexed draws and 16 bytes for non-indexed draws.\n\nThe `draws` buffer should use one of these formats:\n\n    { -- drawing with vertices and indices\n      { name = 'indexCount', type = 'u32' },\n      { name = 'instanceCount', type = 'u32' },\n      { name = 'firstIndex', type = 'u32' },\n      { name = 'vertexOffset', type = 'i32' },\n      { name = 'firstInstance', type = 'u32' }\n    }\n\n    { -- drawing with vertices; indices = nil\n      { name = 'vertexCount', type = 'u32' },\n      { name = 'instanceCount', type = 'u32' },\n      { name = 'firstVertex', type = 'u32' },\n      { name = 'firstInstance', type = 'u32' }\n    }",
                  arguments = {
                    {
                      name = "vertices",
                      type = "Buffer",
                      description = "The buffer containing the vertices to draw.",
                      default = "nil"
                    },
                    {
                      name = "indices",
                      type = "Buffer",
                      description = "The buffer containing the vertex indices to draw."
                    },
                    {
                      name = "draws",
                      type = "Buffer",
                      description = "The buffer containing indirect draw commands."
                    },
                    {
                      name = "drawcount",
                      type = "number",
                      description = "The number of indirect draws to draw.",
                      default = "1"
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset into the draw buffer.",
                      default = "0"
                    },
                    {
                      name = "stride",
                      type = "number",
                      description = "The number of bytes between consecutive elements in the draw buffer.  When zero or nil, the stride is autodetected, and will be 20 bytes when an index buffer is provided and 16 bytes otherwise.",
                      default = "0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "origin",
              tag = "transform",
              summary = "Reset the transform to the origin.",
              description = "Resets the transform back to the origin.",
              key = "Pass:origin",
              module = "lovr.graphics",
              related = {
                "Pass:translate",
                "Pass:rotate",
                "Pass:scale",
                "Pass:transform",
                "Pass:push",
                "Pass:pop"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "plane",
              tag = "drawing",
              summary = "Draw a plane.",
              description = "Draws a plane.",
              key = "Pass:plane",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the plane.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the plane.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the plane.",
                      default = "0"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the plane.",
                      default = "1"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the plane.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the plane around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the plane should be drawn filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "columns",
                      type = "number",
                      description = "The number of horizontal segments in the plane.",
                      default = "1"
                    },
                    {
                      name = "rows",
                      type = "number",
                      description = "The number of vertical segments in the plane.",
                      default = "columns"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the plane."
                    },
                    {
                      name = "size",
                      type = "Vec2",
                      description = "The size of the plane."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the plane."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the plane should be drawn filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "columns",
                      type = "number",
                      description = "The number of horizontal segments in the plane.",
                      default = "1"
                    },
                    {
                      name = "rows",
                      type = "number",
                      description = "The number of vertical segments in the plane.",
                      default = "columns"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the plane."
                    },
                    {
                      name = "style",
                      type = "DrawStyle",
                      description = "Whether the plane should be drawn filled or outlined.",
                      default = "'fill'"
                    },
                    {
                      name = "columns",
                      type = "number",
                      description = "The number of horizontal segments in the plane.",
                      default = "1"
                    },
                    {
                      name = "rows",
                      type = "number",
                      description = "The number of vertical segments in the plane.",
                      default = "columns"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "points",
              tag = "drawing",
              summary = "Draw points.",
              description = "Draws points.  `Pass:mesh` can also be used to draw points using a `Buffer`.",
              key = "Pass:points",
              module = "lovr.graphics",
              notes = "To change the size of points, set the `pointSize` shader flag in `lovr.graphics.newShader` or write to the `PointSize` variable in the vertex shader.  Points are always the same size on the screen, regardless of distance, and the units are in pixels.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the first point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the first point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the first point."
                    },
                    {
                      name = "...",
                      type = "*",
                      description = "More points."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number | Vec3}",
                      description = "A table of numbers or Vec3 objects (not both) representing point positions."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "A vector containing the position of the first point to draw."
                    },
                    {
                      name = "...",
                      type = "*",
                      description = "More points."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "polygon",
              tag = "drawing",
              summary = "Draw a polygon.",
              description = "Draws a polygon.  The 3D vertices must be coplanar (all lie on the same plane), and the polygon must be convex (does not intersect itself or have any angles between vertices greater than 180 degrees), otherwise rendering artifacts may occur.",
              key = "Pass:polygon",
              module = "lovr.graphics",
              notes = "Currently, the polygon will not have normal vectors.\n\n`Mesh` objects can also be used to draw arbitrary triangle meshes.",
              related = {
                "Pass:points",
                "Pass:line",
                "Pass:draw"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the first vertex."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the first vertex."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the first vertex."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the next vertex."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the next vertex."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the next vertex."
                    },
                    {
                      name = "...",
                      type = "*",
                      description = "More vertices to add to the polygon."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number | Vec3}",
                      description = "A table of numbers or `Vec3` objects (not a mix) representing vertices of the polygon."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "v1",
                      type = "Vec3",
                      description = "A vector containing the position of the first vertex of the polygon."
                    },
                    {
                      name = "v2",
                      type = "Vec3",
                      description = "A vector containing the position of the next vertex on the polygon."
                    },
                    {
                      name = "...",
                      type = "*",
                      description = "More vertices to add to the polygon."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "pop",
              tag = "transform",
              summary = "Pop one of the stacks.",
              description = "Pops the transform or render state stack, restoring it to the state it was in when it was last pushed.",
              key = "Pass:pop",
              module = "lovr.graphics",
              notes = "If a stack is popped without a corresponding push, the stack \"underflows\" which causes an error.",
              related = {
                "Pass:push",
                "StackType"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "stack",
                      type = "StackType",
                      description = "The type of stack to pop.",
                      default = "'transform'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "push",
              tag = "transform",
              summary = "Push state onto a stack.",
              description = "Saves a copy of the transform or render states.  Further changes can be made to the transform or render states, and afterwards `Pass:pop` can be used to restore the original state.  Pushes and pops can be nested, but it's an error to pop without a corresponding push.",
              key = "Pass:push",
              module = "lovr.graphics",
              notes = "Each stack has a limit of the number of copies it can store.  There can be 16 transforms and 4 render states saved.\n\nThe `state` stack does not save the camera info or shader variables changed with `Pass:send`.",
              related = {
                "Pass:pop",
                "StackType"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "stack",
                      type = "StackType",
                      description = "The type of stack to push.",
                      default = "'transform'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "reset",
              tag = "pass-misc",
              summary = "Reset the Pass.",
              description = "Resets the Pass, clearing all of its draws and computes and resetting all of its state to the default values.",
              key = "Pass:reset",
              module = "lovr.graphics",
              notes = "The following things won't be reset:\n\n- Pass canvas, set with `Pass:setCanvas`.\n- Pass clears, set with `Pass:setClear`.\n- The tally buffer, set with `Pass:setTallyBuffer`.",
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "rotate",
              tag = "transform",
              summary = "Rotate the coordinate system.",
              description = "Rotates the coordinate system.",
              key = "Pass:rotate",
              module = "lovr.graphics",
              related = {
                "Pass:translate",
                "Pass:scale",
                "Pass:transform",
                "Pass:origin",
                "Pass:push",
                "Pass:pop"
              },
              variants = {
                {
                  description = "Rotate the coordinate system using numbers.",
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount to rotate the coordinate system by, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Rotate the coordinate system using a quaternion.",
                  arguments = {
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "A quaternion containing the rotation to apply."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "roundrect",
              tag = "drawing",
              summary = "Draw a rounded rectangle.",
              description = "Draws a rounded rectangle.",
              key = "Pass:roundrect",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the rectangle.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the rectangle.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the rectangle.",
                      default = "0"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the rectangle.",
                      default = "1"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the rectangle.",
                      default = "1"
                    },
                    {
                      name = "thickness",
                      type = "number",
                      description = "The thickness of the rectangle.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the rectangle around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the rectangle corners.  If the radius is zero or negative, the rectangle will have sharp corners.",
                      default = "0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to use for each corner.  This increases the smoothness, but increases the number of vertices in the mesh.",
                      default = "8"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the rectangle."
                    },
                    {
                      name = "size",
                      type = "Vec3",
                      description = "The size of the rectangle (width, height, thickness)."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the rectangle."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the rectangle corners.  If the radius is zero or negative, the rectangle will have sharp corners.",
                      default = "0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to use for each corner.  This increases the smoothness, but increases the number of vertices in the mesh.",
                      default = "8"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the rectangle."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the rectangle corners.  If the radius is zero or negative, the rectangle will have sharp corners.",
                      default = "0"
                    },
                    {
                      name = "segments",
                      type = "number",
                      description = "The number of circular segments to use for each corner.  This increases the smoothness, but increases the number of vertices in the mesh.",
                      default = "8"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "scale",
              tag = "transform",
              summary = "Scale the coordinate system.",
              description = "Scales the coordinate system.",
              key = "Pass:scale",
              module = "lovr.graphics",
              related = {
                "Pass:translate",
                "Pass:rotate",
                "Pass:transform",
                "Pass:origin",
                "Pass:push",
                "Pass:pop"
              },
              variants = {
                {
                  description = "Scale the coordinate system using numbers.",
                  arguments = {
                    {
                      name = "sx",
                      type = "number",
                      description = "The x component of the scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y component of the scale.",
                      default = "sx"
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z component of the scale.",
                      default = "sx"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Scale the coordinate system using a vector.",
                  arguments = {
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The scale to apply."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "send",
              tag = "shaders",
              summary = "Set the value of a shader variable.",
              description = "Sends a value to a variable in the Pass's active `Shader`.  The active shader is changed using `Pass:setShader`.",
              key = "Pass:send",
              module = "lovr.graphics",
              examples = {
                {
                  code = "function lovr.load()\n  shader = lovr.graphics.newShader([[\n    uniform sampler mySampler;\n    uniform Colors { vec4 colors[256]; };\n    uniform texture2D rocks;\n    uniform uint constant;\n\n    vec4 lovrmain() {\n      return DefaultPosition;\n    }\n  ]], 'unlit')\n\n  clampler = lovr.graphics.newSampler({ wrap = 'clamp' })\n  colorBuffer = lovr.graphics.newBuffer(256, 'vec4')\n  rockTexture = lovr.graphics.newTexture('rocks.jpg')\nend\n\nfunction lovr.draw(pass)\n  pass:setShader(shader)\n  pass:send('mySampler', clampler)\n  pass:send('Colors', colorBuffer)\n  pass:send('rocks', rockTexture)\n  pass:send('constant', 42)\n  -- Draw\nend"
                }
              },
              notes = "The new value will persist until a new shader is set that uses a different \"type\" for the binding number of the variable.  See `Pass:setShader` for more details.",
              variants = {
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the Shader variable."
                    },
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The Buffer to assign."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "An offset from the start of the buffer where data will be read, in bytes.",
                      default = "0"
                    },
                    {
                      name = "extent",
                      type = "number",
                      description = "The number of bytes that will be available for reading.  If zero, as much data as possible will be bound, depending on the offset, buffer size, and the `uniformBufferRange` or `storageBufferRange` limit.",
                      default = "0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the Shader variable."
                    },
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The Texture to assign."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the Shader variable."
                    },
                    {
                      name = "sampler",
                      type = "Sampler",
                      description = "The Sampler to assign."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the Shader variable."
                    },
                    {
                      name = "data",
                      type = "*",
                      description = "Numbers, booleans, vectors, or tables to assign to the data or uniform buffer."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setAlphaToCoverage",
              tag = "pipeline",
              summary = "Enable or disable alpha to coverage.",
              description = "Sets whether alpha to coverage is enabled.  Alpha to coverage factors the alpha of a pixel into antialiasing calculations.  It can be used to get antialiased edges on textures with transparency.  It's often used for foliage.",
              key = "Pass:setAlphaToCoverage",
              module = "lovr.graphics",
              notes = "By default, alpha to coverage is disabled.",
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether alpha to coverage should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setBlendMode",
              tag = "pipeline",
              summary = "Set the blend mode.",
              description = "Sets the blend mode.  When a pixel is drawn, the blend mode controls how it is mixed with the color and alpha of the pixel underneath it.",
              key = "Pass:setBlendMode",
              module = "lovr.graphics",
              notes = "The default blend mode is `alpha` with the `alphamultiply` alpha mode.",
              variants = {
                {
                  description = "Sets the blend mode for all canvas textures.",
                  arguments = {
                    {
                      name = "blend",
                      type = "BlendMode",
                      description = "The blend mode."
                    },
                    {
                      name = "alphaBlend",
                      type = "BlendAlphaMode",
                      description = "The alpha blend mode, used to control premultiplied alpha."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disables blending.  When something is drawn, its pixel colors will replace any existing color in the target texture.  This can work okay for opaque objects, but won't render text or transparency properly.",
                  arguments = {},
                  returns = {}
                },
                {
                  description = "Sets the blend mode for a single canvas texture.",
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the canvas texture that will use the new blend mode."
                    },
                    {
                      name = "blend",
                      type = "BlendMode",
                      description = "The blend mode."
                    },
                    {
                      name = "alphaBlend",
                      type = "BlendAlphaMode",
                      description = "The alpha blend mode, used to control premultiplied alpha."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disables blending for a single canvas texture.",
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the canvas texture that will use the new blend mode."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setCanvas",
              tag = "canvas",
              summary = "Set the Pass's canvas.",
              description = "Sets the Pass's canvas.  The canvas is a set of textures that the Pass will draw to when it's submitted, along with configuration for the depth buffer and antialiasing.",
              key = "Pass:setCanvas",
              module = "lovr.graphics",
              notes = "Changing the canvas will reset the pass, as though `Pass:reset` was called.\n\nAll textures must have the same dimensions, layer counts, and multisample counts.  They also must have been created with the `render` usage flag.\n\nThe number of layers in the textures determines how many views (cameras) the pass has.  Each draw will be rendered to all texture layers, as seen from the corresponding camera.  For example, VR rendering will use a canvas texture with 2 layers, one for each eye.\n\nTo render to a specific mipmap level or layer of a texture, use texture views (`lovr.graphics.newTextureView`).\n\nMipmaps will be regenerated for all of canvas textures at the end of a render pass.\n\nIf the Pass has multiple color textures, a fragment shader should be used to write a different color to each texture.  Here's an example that writes red to the first texture and blue to the second texture:\n\n    // Declare an output variable for the second texture\n    layout(location = 1) out vec4 secondColor;\n\n    vec4 lovrmain() {\n      secondColor = vec4(0, 0, 1, 1);\n      return vec4(1, 0, 0, 1);\n    }",
              related = {
                "Pass:getClear",
                "Pass:setClear",
                "Pass:getWidth",
                "Pass:getHeight",
                "Pass:getDimensions"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "...textures",
                      type = "Texture",
                      description = "One or more color textures the pass will render to."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "canvas",
                      type = "table",
                      description = "The canvas.  Each numeric key is a color texture to render to (up to 4), along with the following keys to control depth buffer and antialiasing settings:",
                      table = {
                        {
                          name = "depth",
                          type = "*",
                          description = "A `Texture` or `TextureFormat` with the depth buffer.",
                          default = "d32f"
                        },
                        {
                          name = "samples",
                          type = "number",
                          description = "The number of multisamples used for antialiasing (either 1 or 4).",
                          default = "4"
                        }
                      }
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the canvas.  Any draws in the Pass will be skipped when it is submitted (compute shaders will still run though).",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setClear",
              tag = "canvas",
              summary = "Set the clear values of the Pass.",
              description = "Sets the clear values of the pass.  This controls the initial colors of the canvas texture pixels at the beginning of the render pass.  For each color texture, it can be one of the following:\n\n- A specific RGBA color value (or number for the depth texture).\n- `true`, to do a \"fast clear\" to undefined values.  This is useful if the pass is going to end\n  up drawing to all of the texture's pixels.\n- `false`, to avoid clearing and load the texture's existing pixels.  This can be slow on mobile\n  GPUs.",
              key = "Pass:setClear",
              module = "lovr.graphics",
              notes = "If the depth clear is not given, it will be set to 0.\n\nAll clear colors will default to transparent black (all zeros) when the Pass is created.",
              related = {
                "Pass:setCanvas",
                "Texture:clear"
              },
              variants = {
                {
                  description = "Set the clear color for all color textures, using a hexcode.",
                  arguments = {
                    {
                      name = "hex",
                      type = "number",
                      description = "A hexcode color to clear all color textures to."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the clear color for all color textures, using numbers.",
                  arguments = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the clear color."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the clear color."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the clear color."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the clear color.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the clear color for all color textures, using a boolean.",
                  arguments = {
                    {
                      name = "clear",
                      type = "boolean",
                      description = "Whether color textures should be cleared."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the clear color for all color textures using a table, or set clear values for individual textures.",
                  arguments = {
                    {
                      name = "t",
                      type = "table",
                      description = "A table of clear values.  This can be a table of 4 numbers to use for all color textures, or it can be a list of boolean and/or RGBA tables to use for each individual color texture.  It can also have a `depth` key with a boolean/number for the depth texture's clear."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setColor",
              tag = "pipeline",
              summary = "Set the color.",
              description = "Sets the color used for drawing.  Color components are from 0 to 1.",
              key = "Pass:setColor",
              module = "lovr.graphics",
              notes = "The default color is `(1, 1, 1, 1)`.",
              variants = {
                {
                  arguments = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the color."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the color."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the color."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the color.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table of 3 or 4 color components."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "hex",
                      type = "number",
                      description = "A hexcode."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the color.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setColorWrite",
              tag = "pipeline",
              summary = "Change the color channels affected by drawing.",
              description = "Sets the color channels affected by drawing, on a per-channel basis.  Disabling color writes is often used to render to the depth or stencil buffer without affecting existing pixel colors.",
              key = "Pass:setColorWrite",
              module = "lovr.graphics",
              notes = "By default, color writes are enabled for all channels.",
              related = {
                "Pass:setDepthWrite",
                "Pass:setStencilWrite"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether all color components should be affected by draws."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "r",
                      type = "boolean",
                      description = "Whether the red component should be affected by draws."
                    },
                    {
                      name = "g",
                      type = "boolean",
                      description = "Whether the green component should be affected by draws."
                    },
                    {
                      name = "b",
                      type = "boolean",
                      description = "Whether the blue component should be affected by draws."
                    },
                    {
                      name = "a",
                      type = "boolean",
                      description = "Whether the alpha component should be affected by draws."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the canvas texture to update."
                    },
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether all color components should be affected by draws."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the canvas texture to update."
                    },
                    {
                      name = "r",
                      type = "boolean",
                      description = "Whether the red component should be affected by draws."
                    },
                    {
                      name = "g",
                      type = "boolean",
                      description = "Whether the green component should be affected by draws."
                    },
                    {
                      name = "b",
                      type = "boolean",
                      description = "Whether the blue component should be affected by draws."
                    },
                    {
                      name = "a",
                      type = "boolean",
                      description = "Whether the alpha component should be affected by draws."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setCullMode",
              tag = "pipeline",
              summary = "Control triangle face culling.",
              description = "Sets whether the front or back faces of triangles are culled.",
              key = "Pass:setCullMode",
              module = "lovr.graphics",
              deprecated = "This function has been replaced by `Pass:setFaceCull`.",
              notes = "By default, face culling is disabled.",
              related = {
                "Pass:setViewCull",
                "Pass:setWinding"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "CullMode",
                      description = "Whether `front` faces, `back` faces, or `none` of the faces should be culled."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable face culling.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setDepthClamp",
              tag = "pipeline",
              summary = "Enable or disable depth clamp.",
              description = "Enables or disables depth clamp.  Normally, when pixels fall outside of the clipping planes, they are clipped (not rendered).  Depth clamp will instead render these pixels, clamping their depth on to the clipping planes.",
              key = "Pass:setDepthClamp",
              module = "lovr.graphics",
              notes = "This isn\\'t supported on all GPUs.  Use the `depthClamp` feature of `lovr.graphics.getFeatures` to check for support.  If depth clamp is enabled when unsupported, it will silently fall back to depth clipping.\n\nDepth clamping is not enabled by default.",
              related = {
                "Pass:setDepthTest",
                "Pass:setDepthWrite",
                "Pass:setDepthOffset"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether depth clamp should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDepthOffset",
              tag = "pipeline",
              summary = "Configure the depth offset.",
              description = "Set the depth offset.  This is a constant offset added to the depth value of pixels, as well as a \"sloped\" depth offset that is scaled based on the \"slope\" of the depth at the pixel.\n\nThis can be used to fix Z fighting when rendering decals or other nearly-overlapping objects, and is also useful for shadow biasing when implementing shadow mapping.",
              key = "Pass:setDepthOffset",
              module = "lovr.graphics",
              notes = "The default depth offset is zero for both values.\n\nThis only applies to triangles, not points or lines.\n\nThe units for these offsets aren't specified very well -- they depend on the format of the depth texture, and the GPU can use them slightly differently for its depth calculations.  However, an `offset` of 1 will roughly correspond to the smallest-possible depth difference (e.g. 2^-16 for a `d16` depth texture).\n\nThe sloped depth scale is multiplied by the slope of the depth of the triangle.  For example, if pixels in the triangle all have the same depth (i.e. the triangle is facing the camera), then the slope of the depth will be zero and the sloped depth offset won't have any effect.  As the triangle starts to face away from the camera, the slope of the depth will increase and the sloped depth offset will begin to apply.  This can also be thought of corresponding to the normal vector of the triangle relative to the camera.\n\nNote that the offsets can be negative.  With LÖVR's default projection matrix, depth values of zero are far away and one are close up, so positive depth offsets will push depth values \"closer\" to the viewer.  With flipped projection matrices (a depth test of `lequal`), negative depth offsets would be used instead.",
              related = {
                "Pass:setDepthTest",
                "Pass:setDepthWrite"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "offset",
                      type = "number",
                      description = "The depth offset.",
                      default = "0.0"
                    },
                    {
                      name = "sloped",
                      type = "number",
                      description = "The sloped depth offset.",
                      default = "0.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDepthTest",
              tag = "pipeline",
              summary = "Configure the depth test.",
              description = "Sets the depth test.",
              key = "Pass:setDepthTest",
              module = "lovr.graphics",
              notes = "When using LÖVR's default projection (reverse Z with infinite far plane) the default depth test is `gequal`, depth values of 0.0 are on the far plane and depth values of 1.0 are on the near plane, closer to the camera.\n\nThe near and far clipping planes are set with `Pass:setProjection`.  The default is set with `lovr.headset.setClipDistance`.\n\nA depth buffer must be present to use the depth test, but this is enabled by default.",
              related = {
                "Pass:setDepthWrite",
                "Pass:setDepthOffset",
                "Pass:setDepthClamp",
                "Pass:setStencilTest",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "test",
                      type = "CompareMode",
                      description = "The new depth test to use."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the depth test.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setDepthWrite",
              tag = "pipeline",
              summary = "Set whether draws write to the depth buffer.",
              description = "Sets whether draws write to the depth buffer.  When a pixel is drawn, if depth writes are enabled and the pixel passes the depth test, the depth buffer will be updated with the pixel's depth value.",
              key = "Pass:setDepthWrite",
              module = "lovr.graphics",
              notes = "The default depth write is `true`.",
              related = {
                "Pass:setStencilWrite",
                "Pass:setColorWrite",
                "Pass:setDepthTest"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "write",
                      type = "boolean",
                      description = "Whether the depth buffer should be affected by draws."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setFaceCull",
              tag = "pipeline",
              summary = "Control triangle face culling.",
              description = "Sets whether the front or back faces of triangles are culled.",
              key = "Pass:setFaceCull",
              module = "lovr.graphics",
              notes = "By default, face culling is disabled.",
              related = {
                "Pass:setViewCull",
                "Pass:setWinding"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "CullMode",
                      description = "Whether `front` faces, `back` faces, or `none` of the faces should be culled."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable face culling.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setFont",
              tag = "pipeline",
              summary = "Set the font.",
              description = "Sets the font used for `Pass:text`.",
              key = "Pass:setFont",
              module = "lovr.graphics",
              related = {
                "Pass:text",
                "lovr.graphics.newFont",
                "lovr.graphics.getDefaultFont"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "font",
                      type = "Font",
                      description = "The Font to use when rendering text."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMaterial",
              tag = "pipeline",
              summary = "Set the material.",
              description = "Sets the material.  This will apply to most drawing, except for text, skyboxes, and models, which use their own materials.",
              key = "Pass:setMaterial",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "material",
                      type = "Texture | Material",
                      description = "The texture or material to apply to surfaces."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Use the default material.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMeshMode",
              tag = "pipeline",
              summary = "Change the way vertices are connected together.",
              description = "Changes the way vertices are connected together when drawing using `Pass:mesh`.",
              key = "Pass:setMeshMode",
              module = "lovr.graphics",
              notes = "The default mesh mode is `triangles`.",
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "DrawMode",
                      description = "The mesh mode to use."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setProjection",
              tag = "camera",
              summary = "Set the field of view.",
              description = "Sets the projection for a single view.  4 field of view angles can be used, similar to the field of view returned by `lovr.headset.getViewAngles`.  Alternatively, a projection matrix can be used for other types of projections like orthographic, oblique, etc.\n\nUp to 6 views are supported.  The Pass returned by `lovr.headset.getPass` will have its views automatically configured to match the headset.",
              key = "Pass:setProjection",
              module = "lovr.graphics",
              notes = "A far clipping plane of 0.0 can be used for an infinite far plane with reversed Z range.  This is the default because it improves depth precision and reduces Z fighting.  Using a non-infinite far plane requires the depth buffer to be cleared to 1.0 instead of 0.0 and the default depth test to be changed to `lequal` instead of `gequal`.\n\nBy default, the projection is set by the headset.  Each HMD has a specific field of view given by `lovr.headset.getViewAngles`, and the clipping planes can be customized with `lovr.headset.setClipDistance`.",
              related = {
                "lovr.headset.getViewAngles",
                "lovr.headset.getViewCount",
                "Pass:getViewPose",
                "Pass:setViewPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The index of the view to update."
                    },
                    {
                      name = "left",
                      type = "number",
                      description = "The left field of view angle, in radians."
                    },
                    {
                      name = "right",
                      type = "number",
                      description = "The right field of view angle, in radians."
                    },
                    {
                      name = "up",
                      type = "number",
                      description = "The top field of view angle, in radians."
                    },
                    {
                      name = "down",
                      type = "number",
                      description = "The bottom field of view angle, in radians."
                    },
                    {
                      name = "near",
                      type = "number",
                      description = "The near clipping plane distance, in meters.",
                      default = ".01"
                    },
                    {
                      name = "far",
                      type = "number",
                      description = "The far clipping plane distance, in meters.",
                      default = "0.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The index of the view to update."
                    },
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "The projection matrix for the view."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSampler",
              tag = "pipeline",
              summary = "Set the sampler.",
              description = "Sets the default `Sampler` to use when sampling textures.  It is also possible to send a custom sampler to a shader using `Pass:send` and use that instead, which allows customizing the sampler on a per-texture basis.",
              key = "Pass:setSampler",
              module = "lovr.graphics",
              examples = {
                {
                  code = "function lovr.draw(pass)\n  pass:setSampler('nearest') -- activate minecraft mode\n  pass:setMaterial(rock)\n  pass:cube(x, y, z)\nend"
                }
              },
              notes = "The `getPixel` shader helper function will use this sampler.\n\nWhen a Pass is reset, its sampler will be reset to `linear`.\n\nThe sampler applies to all draws in the pass on submit, regardless of when the sampler is set.\n\nIf you need different samplers for each draw, currently you have to send a `Sampler` object to a Shader (this is not ideal).",
              variants = {
                {
                  arguments = {
                    {
                      name = "sampler",
                      type = "Sampler | FilterMode",
                      description = "The Sampler shaders will use when reading from textures.  It can also be a `FilterMode`, for convenience (other sampler settings will use their defaults).",
                      default = "'linear'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setScissor",
              tag = "camera",
              summary = "Set the scissor rectangle.",
              description = "Sets the scissor rectangle.  Any pixels outside the scissor rectangle will not be drawn.",
              key = "Pass:setScissor",
              module = "lovr.graphics",
              notes = "`x` and `y` can not be negative.  `w` and `h` must be positive.\n\nBy default, the scissor covers the entire canvas.",
              related = {
                "Pass:setViewport"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the upper-left corner of the scissor rectangle."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the upper-left corner of the scissor rectangle."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The width of the scissor rectangle."
                    },
                    {
                      name = "h",
                      type = "number",
                      description = "The height of the scissor rectangle."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the scissor.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setShader",
              tag = "shaders",
              summary = "Set the active Shader.",
              description = "Sets the active shader.  The Shader will affect all drawing operations until it is changed again.",
              key = "Pass:setShader",
              module = "lovr.graphics",
              notes = "Changing the shader will preserve variable values (the ones set using `Pass:send`) **unless** the new shader declares a variable with the same as one in the old shader, but a different type. The variable \"type\" means one of the following:\n\n- Uniform buffer (`uniform`).\n- Storage buffer (`buffer`).\n- Sampled texture, (`uniform texture<type>`).\n- Storage texture, (`uniform image<type>`).\n- Sampler (`uniform sampler`).\n\nIf there's a clash in types, the variable will be reset to use a default resource:\n\n- Buffer variables do not have well-defined behavior when they are reset like this, and may\n  return random data or even crash the GPU.\n- Texture variable will use a default texture with a single white pixel.\n- Sampler variables will use a default sampler with a `linear` filter mode and `repeat` wrap\n  mode.\n\nUniform variables with basic types like `float`, `vec3`, `mat4`, etc. will have their data preserved as long as both shaders declare the variable with the same name and type.",
              related = {
                "Pass:send",
                "Pass:compute"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "shader",
                      type = "Shader | DefaultShader",
                      description = "The shader to use."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Switch back to using an automatic shader for drawing.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setStencilTest",
              tag = "pipeline",
              summary = "Configure the stencil test.",
              description = "Sets the stencil test.  Any pixels that fail the stencil test won't be drawn.  For example, setting the stencil test to `('equal', 1)` will only draw pixels that have a stencil value of 1. The stencil buffer can be modified by drawing while stencil writes are enabled with `lovr.graphics.setStencilWrite`.",
              key = "Pass:setStencilTest",
              module = "lovr.graphics",
              notes = "The stencil test is disabled by default.\n\nSetting the stencil test requires the `Pass` to have a depth texture with the `d24s8` or `d32fs8` format (the `s` means \"stencil\").  The `t.graphics.stencil` and `t.headset.stencil` flags in `lovr.conf` can be used to request a stencil format for the default window and headset passes, respectively.",
              related = {
                "Pass:setStencilWrite",
                "Pass:setDepthTest"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "test",
                      type = "CompareMode",
                      description = "The new stencil test to use."
                    },
                    {
                      name = "value",
                      type = "number",
                      description = "The stencil value to compare against."
                    },
                    {
                      name = "mask",
                      type = "number",
                      description = "An optional mask to apply to stencil values before the comparison.",
                      default = "0xff"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the stencil test.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setStencilWrite",
              tag = "pipeline",
              summary = "Set whether draws write to the stencil buffer.",
              description = "Sets or disables stencil writes.  When stencil writes are enabled, any pixels drawn will update the values in the stencil buffer using the `StencilAction` set.",
              key = "Pass:setStencilWrite",
              module = "lovr.graphics",
              notes = "By default, stencil writes are disabled.\n\nSetting the stencil test requires the `Pass` to have a depth texture with the `d24s8` or `d32fs8` format (the `s` means \"stencil\").  The `t.graphics.stencil` and `t.headset.stencil` flags in `lovr.conf` can be used to request a stencil format for the default window and headset passes, respectively.",
              related = {
                "Pass:setStencilTest",
                "Pass:setDepthTest"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "action",
                      type = "StencilAction | {StencilAction}",
                      description = "How pixels should update the stencil buffer when they are drawn.  Can also be a list of 3 stencil actions, used when a pixel fails the stencil test, fails the depth test, or passes the stencil test, respectively."
                    },
                    {
                      name = "value",
                      type = "number",
                      description = "When using the 'replace' action, this is the value to replace with.",
                      default = "1"
                    },
                    {
                      name = "mask",
                      type = "number",
                      description = "An optional mask to apply to stencil values before writing.",
                      default = "0xff"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disables stencil writing.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setTallyBuffer",
              tag = "tally",
              summary = "Set the Buffer that tally results will be written to.",
              description = "Sets the Buffer where tally results will be written to.  Each time the render pass finishes, the results of all the tallies will be copied to the Buffer at the specified offset.  The buffer can be used in a later pass in a compute shader, or the data in the buffer can be read back using e.g. `Buffer:newReadback`.",
              key = "Pass:setTallyBuffer",
              module = "lovr.graphics",
              notes = "Each tally result is a 4-byte unsigned integer with the number of samples that passed the depth and stencil tests.\n\nIf the buffer doesn't have enough room to store all the tallies, the number of tallies copied will be clamped to the minimum number that will fit.",
              related = {
                "Pass:beginTally",
                "Pass:finishTally"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "buffer",
                      type = "Buffer",
                      description = "The buffer."
                    },
                    {
                      name = "offset",
                      type = "number",
                      description = "A byte offset where results will be written.  Must be a multiple of 4."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Unset the tally buffer.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setViewCull",
              tag = "pipeline",
              summary = "Enable or disable view frustum culling.",
              description = "Enables or disables view frustum culling.  When enabled, if an object is drawn outside of the camera view, the draw will be skipped.  This can improve performance.",
              key = "Pass:setViewCull",
              module = "lovr.graphics",
              notes = "View frustum culling is disabled by default.\n\nObjects will be culled against all views in the Pass.  The pose and projection for these views is controlled using `Pass:setViewPose` and `Pass:setProjection`.\n\nView frustum culling will increase CPU usage, but will reduce GPU usage depending on how many objects get culled and how many vertices they have.\n\nFor most scenes that draw objects all around the camera, frustum culling will usually result in large speedups.  However, it's always good to measure to be sure.  For example, if every object drawn is in view, then frustum culling will only make things slower, because LÖVR will spend time checking if objects are in view without actually culling any of them.\n\n`Pass:getStats` will return `draws` and `drawsCulled` fields.  The `submitTime` and `gpuTime` fields (with `lovr.graphics.setTimingEnabled`) are a good way to measure the impact of culling.\n\nTo cull an object against a view frustum, LÖVR needs to know the object's bounding box.  The following types of draws have bounding boxes:\n\n- `Pass:plane`\n- `Pass:roundrect`\n- `Pass:cube`\n- `Pass:box`\n- `Pass:circle`\n- `Pass:sphere`\n- `Pass:cylinder`\n- `Pass:cone`\n- `Pass:capsule`\n- `Pass:torus`\n- `Pass:draw` (see notes below for `Model` and `Mesh` objects)\n\nThe following draws do **not** currently have bounding boxes, and will not be culled:\n\n- `Pass:points`\n- `Pass:line`\n- `Pass:text`\n- `Pass:skybox`\n- `Pass:fill`\n- `Pass:mesh`\n\n`Model` objects only compute their bounding box when they're loaded, using the initial node transforms.  If a model is animated, then the bounding box will become out of sync and culling will not work properly.  View culling should be disabled when rendering animated models.\n\n`Mesh` objects will not have a bounding box by default.  Meshes with a storage type of `cpu` can compute their bounding boxes using `Mesh:computeBoundingBox`, which should be called after creating the Mesh or whenever its vertices change.  Any type of Mesh can have its bounding box set manually using `Mesh:setBoundingBox`.  This can be faster than `Mesh:computeBoundingBox` if the bounding box is already known, and is the only way to give a `gpu` Mesh a bounding box.",
              related = {
                "Pass:setCullMode",
                "Mesh:computeBoundingBox",
                "Mesh:setBoundingBox",
                "Pass:setViewPose",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether frustum culling should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setViewPose",
              tag = "camera",
              summary = "Set the camera pose.",
              description = "Sets the pose for a single view.  Objects rendered in this view will appear as though the camera is positioned using the given pose.\n\nUp to 6 views are supported.  When rendering to the headset, views are changed to match the eye positions.  These view poses are also available using `lovr.headset.getViewPose`.",
              key = "Pass:setViewPose",
              module = "lovr.graphics",
              related = {
                "lovr.headset.getViewPose",
                "lovr.headset.getViewCount",
                "Pass:getProjection",
                "Pass:setProjection"
              },
              variants = {
                {
                  description = "Set the pose of the view using numbers.",
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The index of the view to update."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the viewer, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the viewer, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the viewer, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the viewer is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the pose of the view using vectors.",
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The index of the view to update."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the viewer, in meters."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the viewer."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the pose of the view using a matrix.",
                  arguments = {
                    {
                      name = "view",
                      type = "number",
                      description = "The index of the view to update."
                    },
                    {
                      name = "matrix",
                      type = "Mat4",
                      description = "A matrix containing the viewer pose."
                    },
                    {
                      name = "inverted",
                      type = "boolean",
                      description = "Whether the matrix is an inverted pose (a view matrix)."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setViewport",
              tag = "camera",
              summary = "Set the viewport.",
              description = "Sets the viewport.  Everything rendered will get mapped to the rectangle defined by the viewport.  More specifically, this defines the transformation from normalized device coordinates to pixel coordinates.",
              key = "Pass:setViewport",
              module = "lovr.graphics",
              notes = "The viewport rectangle can use floating point numbers.\n\nA negative viewport height (with a y coordinate equal to the bottom of the viewport) can be used to flip the rendering vertically.\n\nThe default viewport extends from `(0, 0)` to the dimensions of the canvas, with min depth and max depth respectively set to 0 and 1.",
              related = {
                "Pass:setScissor",
                "Pass:getDimensions"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The width of the viewport.  Must be positive."
                    },
                    {
                      name = "h",
                      type = "number",
                      description = "The height of the viewport.  May be negative."
                    },
                    {
                      name = "dmin",
                      type = "number",
                      description = "The min component of the depth range, between 0 and 1.",
                      default = "0.0"
                    },
                    {
                      name = "dmax",
                      type = "number",
                      description = "The max component of the depth range, between 0 and 1.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the viewport.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setWinding",
              tag = "pipeline",
              summary = "Set the winding direction of triangle vertices.",
              description = "Sets whether vertices in the clockwise or counterclockwise order vertices are considered the \"front\" face of a triangle.  This is used for culling with `Pass:setCullMode`.",
              key = "Pass:setWinding",
              module = "lovr.graphics",
              notes = "The default winding is counterclockwise.  LÖVR's builtin shapes are wound counterclockwise.",
              related = {
                "Pass:setCullMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "winding",
                      type = "Winding",
                      description = "Whether triangle vertices are ordered `clockwise` or `counterclockwise`."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setWireframe",
              tag = "pipeline",
              summary = "Enable or disable wireframe rendering.",
              description = "Enables or disables wireframe rendering.  This will draw all triangles as lines while active. It's intended to be used for debugging, since it usually has a performance cost.",
              key = "Pass:setWireframe",
              module = "lovr.graphics",
              notes = "Wireframe rendering is disabled by default.\n\nThere is currently no way to change the thickness of the lines.",
              related = {
                "Pass:setMeshMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether wireframe rendering should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "skybox",
              tag = "drawing",
              summary = "Draw a skybox.",
              description = "Draws a skybox.",
              key = "Pass:skybox",
              module = "lovr.graphics",
              notes = "The skybox will be rotated based on the camera rotation.\n\nThe skybox is drawn using a fullscreen triangle.\n\nThe skybox uses a custom shader, so set the shader to `nil` before calling this function (unless explicitly using a custom shader).",
              variants = {
                {
                  arguments = {
                    {
                      name = "skybox",
                      type = "Texture",
                      description = "The skybox to render.  Its `TextureType` can be `cube` to render as a cubemap, or `2d` to render as an equirectangular (spherical) 2D image."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "sphere",
              tag = "drawing",
              summary = "Draw a sphere.",
              description = "Draws a sphere",
              key = "Pass:sphere",
              module = "lovr.graphics",
              notes = "The local origin of the sphere is in its center.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the sphere.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the sphere.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the sphere.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the sphere around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "longitudes",
                      type = "number",
                      description = "The number of \"horizontal\" segments.",
                      default = "48"
                    },
                    {
                      name = "latitudes",
                      type = "number",
                      description = "The number of \"vertical\" segments.",
                      default = "longitudes / 2"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere.",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the sphere."
                    },
                    {
                      name = "longitudes",
                      type = "number",
                      description = "The number of \"horizontal\" segments.",
                      default = "48"
                    },
                    {
                      name = "latitudes",
                      type = "number",
                      description = "The number of \"vertical\" segments.",
                      default = "longitudes / 2"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the sphere."
                    },
                    {
                      name = "longitudes",
                      type = "number",
                      description = "The number of \"horizontal\" segments.",
                      default = "48"
                    },
                    {
                      name = "latitudes",
                      type = "number",
                      description = "The number of \"vertical\" segments.",
                      default = "longitudes / 2"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "text",
              tag = "drawing",
              summary = "Draw text.",
              description = "Draws text.  The font can be changed using `Pass:setFont`.",
              key = "Pass:text",
              module = "lovr.graphics",
              notes = "UTF-8 encoded strings are supported.\n\nNewlines will start a new line of text.  Tabs will be rendered as four spaces.  Carriage returns are ignored.\n\nWith the default font pixel density, a scale of 1.0 makes the text height 1 meter.\n\nThe wrap value does not take into account the text's scale.\n\nText rendering requires a special shader, which will only be automatically used when the active shader is set to `nil`.\n\nBlending should be enabled when rendering text (it's on by default).\n\nThis function can draw up to 16384 visible characters at a time, and will currently throw an error if the string is too long.",
              related = {
                "Pass:setFont",
                "lovr.graphics.getDefaultFont",
                "Pass:setShader",
                "Font:getWidth",
                "Font:getHeight",
                "Font:getLines",
                "Font:getVertices",
                "Font"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "text",
                      type = "string",
                      description = "The text to render."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the text (with the default pixel density, units are meters).",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the text around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "text",
                      type = "string",
                      description = "The text to render."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the text."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the text (with the default pixel density, units are meters).",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the text."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "text",
                      type = "string",
                      description = "The text to render."
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the text."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Renders multicolor text.",
                  arguments = {
                    {
                      name = "colortext",
                      type = "table",
                      description = "A table of strings with colors to render, in the form `{ color1, string1, color2, string2 }`, where color is a `Vec3`, `Vec4`, hexcode, or table of numbers."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the text origin.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the text (with the default pixel density, units are meters).",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the text around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Renders multicolor text.",
                  arguments = {
                    {
                      name = "colortext",
                      type = "table",
                      description = "A table of strings with colors to render, in the form `{ color1, string1, color2, string2 }`, where color is a `Vec3`, `Vec4`, hexcode, or table of numbers."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the text."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale of the text (with the default pixel density, units are meters).",
                      default = "1"
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the text."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Renders multicolor text.",
                  arguments = {
                    {
                      name = "colortext",
                      type = "table",
                      description = "A table of strings with colors to render, in the form `{ color1, string1, color2, string2 }`, where color is a `Vec3`, `Vec4`, hexcode, or table of numbers."
                    },
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the text."
                    },
                    {
                      name = "wrap",
                      type = "number",
                      description = "The maximum width of each line in meters (before scale is applied).  When zero, the text will not wrap.",
                      default = "0"
                    },
                    {
                      name = "halign",
                      type = "HorizontalAlign",
                      description = "The horizontal alignment relative to the text origin.",
                      default = "'center'"
                    },
                    {
                      name = "valign",
                      type = "VerticalAlign",
                      description = "The vertical alignment relative to the text origin.",
                      default = "'middle'"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "torus",
              tag = "drawing",
              summary = "Draw a donut.",
              description = "Draws a torus.",
              key = "Pass:torus",
              module = "lovr.graphics",
              notes = "The local origin is in the center of the torus, and the torus forms a circle around the local Z axis.",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the torus.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the torus.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the torus.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the torus.",
                      default = "1"
                    },
                    {
                      name = "thickness",
                      type = "number",
                      description = "The thickness of the torus.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the torus around its rotation axis, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "tsegments",
                      type = "number",
                      description = "The number of toroidal (circular) segments to render.",
                      default = "64"
                    },
                    {
                      name = "psegments",
                      type = "number",
                      description = "The number of poloidal (tubular) segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the torus."
                    },
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The size of the torus (x and y scale the radius, z is the thickness)."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the torus."
                    },
                    {
                      name = "tsegments",
                      type = "number",
                      description = "The number of toroidal (circular) segments to render.",
                      default = "64"
                    },
                    {
                      name = "psegments",
                      type = "number",
                      description = "The number of poloidal (tubular) segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "The transform of the torus."
                    },
                    {
                      name = "tsegments",
                      type = "number",
                      description = "The number of toroidal (circular) segments to render.",
                      default = "64"
                    },
                    {
                      name = "psegments",
                      type = "number",
                      description = "The number of poloidal (tubular) segments to render.",
                      default = "32"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "transform",
              tag = "transform",
              summary = "Apply a general transform to the coordinate system.",
              description = "Transforms the coordinate system.",
              key = "Pass:transform",
              module = "lovr.graphics",
              related = {
                "Pass:translate",
                "Pass:rotate",
                "Pass:scale",
                "Pass:origin",
                "Pass:push",
                "Pass:pop"
              },
              variants = {
                {
                  description = "Transform the coordinate system using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x component of the scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y component of the scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z component of the scale."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount to rotate the coordinate system by, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Transform the coordinate system using vector types.",
                  arguments = {
                    {
                      name = "translation",
                      type = "Vec3",
                      description = "The translation to apply."
                    },
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The scale to apply."
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "A quaternion containing the rotation to apply."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Transform the coordinate system using a matrix.",
                  arguments = {
                    {
                      name = "transform",
                      type = "Mat4",
                      description = "A matrix containing the transformation to apply."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "translate",
              tag = "transform",
              summary = "Translate the coordinate system.",
              description = "Translates the coordinate system.",
              key = "Pass:translate",
              module = "lovr.graphics",
              notes = "Order matters when scaling, translating, and rotating the coordinate system.",
              related = {
                "Pass:rotate",
                "Pass:scale",
                "Pass:transform",
                "Pass:origin",
                "Pass:push",
                "Pass:pop"
              },
              variants = {
                {
                  description = "Translate the coordinate system using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Translate the coordinate system using a vector.",
                  arguments = {
                    {
                      name = "translation",
                      type = "Vec3",
                      description = "The translation."
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Drawing",
              tag = "drawing",
              description = "Draw objects and shapes."
            },
            {
              name = "Coordinate System",
              tag = "transform",
              description = "Manipulate the 3D coordinate system."
            },
            {
              name = "Render States",
              tag = "pipeline",
              description = "Set render states that change the way draws appear.  Render states can be saved and restored using `Pass:push` and `Pass:pop`."
            },
            {
              name = "Shaders",
              tag = "shaders",
              description = "Change the shader used for draws or computes, and set variables in the active shader."
            },
            {
              name = "Compute",
              tag = "compute"
            },
            {
              name = "Tally",
              tag = "tally",
              description = "Tallies count the number of pixels that were visible for a draw."
            },
            {
              name = "Camera",
              tag = "camera"
            },
            {
              name = "Canvas",
              tag = "canvas"
            },
            {
              name = "Miscellaneous",
              tag = "pass-misc"
            }
          }
        },
        {
          name = "Readback",
          summary = "An asynchronous read of a GPU resource.",
          description = "Readbacks track the progress of an asynchronous read of a `Buffer` or `Texture`.  The Readback can be polled for completion or the CPU with `Readback:isComplete`, or you can wait for it to finish using `Readback:wait`.",
          key = "Readback",
          module = "lovr.graphics",
          constructors = {
            "Buffer:newReadback",
            "Texture:newReadback"
          },
          extends = "Object",
          methods = {
            {
              name = "getBlob",
              summary = "Get Readback's data as a Blob.",
              description = "Returns the Readback's data as a Blob.",
              key = "Readback:getBlob",
              module = "lovr.graphics",
              notes = "If the Readback is reading back a Texture, returns `nil`.",
              related = {
                "Readback:getData",
                "Readback:getImage"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "blob",
                      type = "Blob",
                      description = "The Blob."
                    }
                  }
                }
              }
            },
            {
              name = "getData",
              summary = "Get Readback's data as a table.",
              description = "Returns the data from the Readback, as a table.  See `Buffer:getData` for the way the table is structured.",
              key = "Readback:getData",
              module = "lovr.graphics",
              notes = "This returns `nil` for readbacks of `Texture` objects.",
              related = {
                "Readback:getBlob",
                "Readback:getImage"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "data",
                      type = "table",
                      description = "A table containing the data that was read back."
                    }
                  }
                }
              }
            },
            {
              name = "getImage",
              summary = "Get Readback's data as an Image.",
              description = "Returns the Readback's data as an Image.",
              key = "Readback:getImage",
              module = "lovr.graphics",
              notes = "If the Readback is not reading back a Texture, returns `nil`.",
              related = {
                "Readback:getData",
                "Readback:getBlob"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "image",
                      type = "Image",
                      description = "The Image."
                    }
                  }
                }
              }
            },
            {
              name = "isComplete",
              summary = "Check if a Readback is complete.",
              description = "Returns whether the Readback has completed on the GPU and its data is available.",
              key = "Readback:isComplete",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "complete",
                      type = "boolean",
                      description = "Whether the readback is complete."
                    }
                  }
                }
              }
            },
            {
              name = "wait",
              summary = "Wait for the Readback to finish.",
              description = "Blocks the CPU until the Readback is finished on the GPU.",
              key = "Readback:wait",
              module = "lovr.graphics",
              notes = "If `lovr.graphics.submit` or `lovr.graphics.wait` has not been called since the readback was created, the readback has not been submitted yet, so no wait will occur and this function will return `false`.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "waited",
                      type = "boolean",
                      description = "Whether the CPU had to be blocked for waiting."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Sampler",
          summary = "An object that controls how texture pixels are read.",
          description = "Samplers are objects that control how pixels are read from a texture.  They can control whether the pixels are smoothed, whether the texture wraps at the edge of its UVs, and more.\n\nEach `Pass` has a default sampler that will be used by default, which can be changed using `Pass:setSampler`.  Also, samplers can be declared in shaders using the following syntax:\n\n    uniform sampler mySampler;\n\nA Sampler can be sent to the variable using `Pass:send('mySampler', sampler)`.\n\nThe properties of a Sampler are immutable, and can't be changed after it's created.",
          key = "Sampler",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newSampler"
          },
          extends = "Object",
          methods = {
            {
              name = "getAnisotropy",
              summary = "Get the anisotropy level of the Sampler.",
              description = "Returns the anisotropy level of the Sampler.  Anisotropy smooths out a texture's appearance when viewed at grazing angles.",
              key = "Sampler:getAnisotropy",
              module = "lovr.graphics",
              notes = "Not all GPUs support anisotropy.  The maximum anisotropy level is given by the `anisotropy` limit of `lovr.graphics.getLimits`, which may be zero.  It's very common for the maximum to be 16, however.",
              related = {
                "Sampler:getFilter",
                "Sampler:getWrap",
                "Sampler:getCompareMode",
                "Sampler:getMipmapRange"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "anisotropy",
                      type = "number",
                      description = "The anisotropy level of the sampler."
                    }
                  }
                }
              }
            },
            {
              name = "getCompareMode",
              summary = "Get the compare mode of the Sampler.",
              description = "Returns the compare mode of the Sampler.  This is a feature typically only used for shadow mapping.  Using a sampler with a compare mode requires it to be declared in a shader as a `samplerShadow` instead of a `sampler` variable, and used with a texture that has a depth format.  The result of sampling a depth texture with a shadow sampler is a number between 0 and 1, indicating the percentage of sampled pixels that passed the comparison.",
              key = "Sampler:getCompareMode",
              module = "lovr.graphics",
              related = {
                "Sampler:getFilter",
                "Sampler:getWrap",
                "Sampler:getAnisotropy",
                "Sampler:getMipmapRange"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "compare",
                      type = "CompareMode",
                      description = "The compare mode of the sampler."
                    }
                  }
                }
              }
            },
            {
              name = "getFilter",
              summary = "Get the filter mode of the Sampler.",
              description = "Returns the filter mode of the Sampler.",
              key = "Sampler:getFilter",
              module = "lovr.graphics",
              related = {
                "Sampler:getWrap",
                "Sampler:getCompareMode",
                "Sampler:getAnisotropy",
                "Sampler:getMipmapRange"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "min",
                      type = "FilterMode",
                      description = "The filter mode used when the texture is minified."
                    },
                    {
                      name = "mag",
                      type = "FilterMode",
                      description = "The filter mode used when the texture is magnified."
                    },
                    {
                      name = "mip",
                      type = "FilterMode",
                      description = "The filter mode used to select a mipmap level."
                    }
                  }
                }
              }
            },
            {
              name = "getMipmapRange",
              summary = "Get the mipmap range of the Sampler.",
              description = "Returns the mipmap range of the Sampler.  This is used to clamp the range of mipmap levels that can be accessed from a texture.",
              key = "Sampler:getMipmapRange",
              module = "lovr.graphics",
              related = {
                "Sampler:getFilter",
                "Sampler:getWrap",
                "Sampler:getCompareMode",
                "Sampler:getAnisotropy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum mipmap level that will be sampled (0 is the largest image)."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum mipmap level that will be sampled."
                    }
                  }
                }
              }
            },
            {
              name = "getWrap",
              summary = "Get the wrap mode of the Sampler.",
              description = "Returns the wrap mode of the sampler, used to wrap or clamp texture coordinates when the extend outside of the 0-1 range.",
              key = "Sampler:getWrap",
              module = "lovr.graphics",
              related = {
                "Sampler:getFilter",
                "Sampler:getCompareMode",
                "Sampler:getAnisotropy",
                "Sampler:getMipmapRange"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "WrapMode",
                      description = "The wrap mode used in the horizontal direction."
                    },
                    {
                      name = "y",
                      type = "WrapMode",
                      description = "The wrap mode used in the vertical direction."
                    },
                    {
                      name = "z",
                      type = "WrapMode",
                      description = "The wrap mode used in the \"z\" direction, for 3D textures only."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Shader",
          summary = "GPU program.",
          description = "Shaders are small GPU programs.  See the `Shaders` guide for a full introduction to Shaders.",
          key = "Shader",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newShader",
            "Shader:clone"
          },
          extends = "Object",
          methods = {
            {
              name = "clone",
              summary = "Clone a Shader.",
              description = "Clones a shader.  This creates an inexpensive copy of it with different flags.  It can be used to create several variants of a shader with different behavior.",
              key = "Shader:clone",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "source",
                      type = "Shader",
                      description = "The Shader to clone."
                    },
                    {
                      name = "flags",
                      type = "table",
                      description = "The flags used by the clone."
                    }
                  },
                  returns = {
                    {
                      name = "shader",
                      type = "Shader",
                      description = "The new Shader."
                    }
                  }
                }
              }
            },
            {
              name = "getBufferFormat",
              summary = "Get the format of a buffer in the Shader.",
              description = "Returns the format of a buffer declared in shader code.  The return type matches the same syntax used by `lovr.graphics.newBuffer` and `Buffer:getFormat`, so it can be used to quickly create a Buffer that matches a variable from a Shader.",
              key = "Shader:getBufferFormat",
              module = "lovr.graphics",
              examples = {
                {
                  code = "shader = lovr.graphics.newShader([[\n  uniform Transforms {\n    mat4 transforms[32];\n  };\n\n  vec4 lovrmain() {\n    return Projection * View * transforms[InstanceIndex] * VertexPosition;\n  }\n]], 'unlit')\n\nlocal format, length = shader:getBufferFormat('Transforms')\nprint(length) --> 32\nprint(format[1].name) --> 'transforms'\nprint(format[1].type) --> 'mat4'\n\n-- Can pass the 2 results directly to newBuffer:\ntransforms = lovr.graphics.newBuffer(shader:getBufferFormat('Transforms'))\n\n-- Or override the length with some initial data:\ntransforms = lovr.graphics.newBuffer(shader:getBufferFormat('Transforms'), objects)"
                }
              },
              notes = "If the buffer only has a single array field, the format will be \"unwrapped\" to an array instead of a single-field struct with an array in it.  Example:\n\n    shader = lovr.graphics.newShader([[\n      buffer Numbers {\n        uint numbers[64];\n      };\n\n      void lovrmain(){}\n    ]])\n\n    shader:getBufferFormat('Numbers')\n    -- returns {{ name = 'numbers', type = 'u32' }}, 64\n    -- not     {{ name = 'numbers', type = 'u32', length = 64 }}, 1\n\nSimilarly, if the buffer only has a single struct field, the format will be \"unwrapped\" to the inner struct.  This lets you use a struct for a Buffer's data without having to wrap everything in an extra namespace.  Example:\n\n    shader = lovr.graphics.newShader([[\n      struct HandParams {\n        vec3 pos;\n        float grip;\n      };\n\n      buffer Hand {\n        HandParams params;\n      };\n\n      void lovrmain(){}\n    ]])\n\n    shader:getBufferFormat('Hand')\n    -- returns {{ name = 'pos', type = 'vec3' }, { name = 'grip', type = 'float' }}, 1\n    -- not     {{ name = 'params', type = {...}}}, 1",
              related = {
                "lovr.graphics.newBuffer",
                "Buffer:getFormat"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the buffer variable to return the format of."
                    }
                  },
                  returns = {
                    {
                      name = "format",
                      type = "table",
                      description = "A list of fields that match the type declaration of the buffer in the shader code.  Each field has `name`, `type`, and `offset` keys.  If the field is an array, it will have `length` and `stride` keys as well.  The top-level table also has a `stride` key.  Offsets and strides are in bytes."
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The number of items in the buffer (or 1 if the buffer is not an array)."
                    }
                  }
                }
              }
            },
            {
              name = "getLabel",
              summary = "Get the debug label of the Shader.",
              description = "Returns the debug label of the Shader, which will show up when the Shader is printed and in some graphics debugging tools.  This is set when the Shader is created, and can't be changed afterwards.",
              key = "Shader:getLabel",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newShader",
                "Texture:getLabel",
                "Pass:getLabel"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "label",
                      type = "string",
                      description = "The label, or nil if none was set."
                    }
                  }
                }
              }
            },
            {
              name = "getType",
              summary = "Get the type of the Shader.",
              description = "Returns whether the shader is a graphics or compute shader.",
              key = "Shader:getType",
              module = "lovr.graphics",
              related = {
                "Shader:hasStage",
                "lovr.graphics.newShader"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "type",
                      type = "ShaderType",
                      description = "The type of the Shader."
                    }
                  }
                }
              }
            },
            {
              name = "getWorkgroupSize",
              summary = "Get the workgroup size of a compute shader.",
              description = "Returns the workgroup size of a compute shader.  The workgroup size defines how many times a compute shader is invoked for each workgroup dispatched by `Pass:compute`.",
              key = "Shader:getWorkgroupSize",
              module = "lovr.graphics",
              notes = "For example, if the workgroup size is `8x8x1` and `16x16x16` workgroups are dispatched, then the compute shader will run `16 * 16 * 16 * (8 * 8 * 1) = 262144` times.\n\nThe maximum workgroup size is hardware-specific, and is given by the `workgroupSize` and `totalWorkgroupSize` limit in `lovr.graphics.getLimits`.",
              related = {
                "Pass:compute",
                "lovr.graphics.getLimits"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x size of a workgroup."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y size of a workgroup."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z size of a workgroup."
                    }
                  }
                }
              }
            },
            {
              name = "hasAttribute",
              summary = "Check if the Shader has a given vertex attribute.",
              description = "Returns whether the Shader has a vertex attribute, by name or location.",
              key = "Shader:hasAttribute",
              module = "lovr.graphics",
              examples = {
                {
                  code = "function lovr.load()\n  shader = lovr.graphics.newShader([[\n    in uint coolAttribute;\n\n    vec4 lovrmain() {\n      return DefaultPosition;\n    }\n  ]], [[\n    vec4 lovrmain() {\n      return DefaultColor;\n    }\n  ]])\n\n  print(shader:hasAttribute('coolAttribute')) --> true\nend"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of an attribute."
                    }
                  },
                  returns = {
                    {
                      name = "exists",
                      type = "boolean",
                      description = "Whether the Shader has the attribute."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "location",
                      type = "number",
                      description = "The location of an attribute."
                    }
                  },
                  returns = {
                    {
                      name = "exists",
                      type = "boolean",
                      description = "Whether the Shader has the attribute."
                    }
                  }
                }
              }
            },
            {
              name = "hasStage",
              summary = "Check if the Shader has a given stage.",
              description = "Returns whether the Shader has a given stage.",
              key = "Shader:hasStage",
              module = "lovr.graphics",
              related = {
                "Shader:getType"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "stage",
                      type = "ShaderStage",
                      description = "The stage."
                    }
                  },
                  returns = {
                    {
                      name = "exists",
                      type = "boolean",
                      description = "Whether the Shader has the stage."
                    }
                  }
                }
              }
            },
            {
              name = "hasVariable",
              summary = "Check if the Shader has a variable.",
              description = "Returns whether the Shader has a variable.",
              key = "Shader:hasVariable",
              module = "lovr.graphics",
              examples = {
                {
                  code = "for key, texture in pairs(textures) do\n  if shader:hasVariable(key) then\n    pass:send(key, texture)\n  end\nend"
                }
              },
              notes = "This will return true if the variable is a buffer, texture, sampler, or other uniform variable (anything that can be sent with `Pass:send`).",
              related = {
                "Pass:send"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "name",
                      type = "string",
                      description = "The name of the variable to check."
                    }
                  },
                  returns = {
                    {
                      name = "exists",
                      type = "boolean",
                      description = "Whether the Shader has the variable."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Texture",
          summary = "A multidimensional block of memory on the GPU.",
          description = "Textures are multidimensional blocks of memory on the GPU, contrasted with `Buffer` objects which are one-dimensional.  Textures are used as the destination for rendering operations, and textures loaded from images provide surface data to `Material` objects.",
          key = "Texture",
          module = "lovr.graphics",
          constructors = {
            "lovr.graphics.newTexture",
            "lovr.graphics.newTextureView"
          },
          extends = "Object",
          methods = {
            {
              name = "clear",
              tag = "texture-transfer",
              summary = "Clear the Texture to a color.",
              description = "Clears layers and mipmaps in a texture to a given color.\n\nWhen a Texture is being used as a canvas for a `Pass`, the clear color can be set with `Pass:setClear`, which a more efficient way to clear the texture before rendering.",
              key = "Texture:clear",
              module = "lovr.graphics",
              notes = "The texture must have been created with the `transfer` usage to clear it.\n\nThe clear color will be interpreted as a linear color for sRGB formats.",
              related = {
                "Buffer:clear",
                "Texture:setPixels",
                "Pass:setClear"
              },
              variants = {
                {
                  description = "Clear the whole texture to zero (transparent black).",
                  arguments = {},
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "hex",
                      type = "number",
                      description = "The hexcode color to clear to."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer to clear.",
                      default = "1"
                    },
                    {
                      name = "layerCount",
                      type = "number",
                      description = "The number of layers to clear.  If nil, clears the rest of the layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap to clear.",
                      default = "1"
                    },
                    {
                      name = "mipmapCount",
                      type = "number",
                      description = "The number of mipmaps to clear.  If nil, clears the rest of the mipmaps.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the clear color."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the clear color."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the clear color."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the clear color."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer to clear.",
                      default = "1"
                    },
                    {
                      name = "layerCount",
                      type = "number",
                      description = "The number of layers to clear.  If nil, clears the rest of the layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap to clear.",
                      default = "1"
                    },
                    {
                      name = "mipmapCount",
                      type = "number",
                      description = "The number of mipmaps to clear.  If nil, clears the rest of the mipmaps.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table with color components."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer to clear.",
                      default = "1"
                    },
                    {
                      name = "layerCount",
                      type = "number",
                      description = "The number of layers to clear.  If nil, clears the rest of the layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap to clear.",
                      default = "1"
                    },
                    {
                      name = "mipmapCount",
                      type = "number",
                      description = "The number of mipmaps to clear.  If nil, clears the rest of the mipmaps.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "v3",
                      type = "Vec3",
                      description = "A vec3 with the clear color."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer to clear.",
                      default = "1"
                    },
                    {
                      name = "layerCount",
                      type = "number",
                      description = "The number of layers to clear.  If nil, clears the rest of the layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap to clear.",
                      default = "1"
                    },
                    {
                      name = "mipmapCount",
                      type = "number",
                      description = "The number of mipmaps to clear.  If nil, clears the rest of the mipmaps.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "v4",
                      type = "Vec4",
                      description = "A vec4 with the clear color."
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the first layer to clear.",
                      default = "1"
                    },
                    {
                      name = "layerCount",
                      type = "number",
                      description = "The number of layers to clear.  If nil, clears the rest of the layers.",
                      default = "nil"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the first mipmap to clear.",
                      default = "1"
                    },
                    {
                      name = "mipmapCount",
                      type = "number",
                      description = "The number of mipmaps to clear.  If nil, clears the rest of the mipmaps.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "generateMipmaps",
              tag = "texture-transfer",
              summary = "Regenerate mipmaps for a Texture.",
              description = "Regenerates mipmap levels of a texture.  This downscales pixels from the texture to progressively smaller sizes and saves them.  If the texture is drawn at a smaller scale later, the mipmaps are used, which smooths out the appearance and improves performance.",
              key = "Texture:generateMipmaps",
              module = "lovr.graphics",
              notes = "Mipmaps will automatically be regenerated for textures after rendering to them in a `Pass`. This can be disabled by rendering to a single-level texture view instead.\n\nThe texture must have been created with the `transfer` usage to mipmap it.\n\nThe texture can not be multisampled.\n\nTexture views can not currently be mipmapped.",
              related = {
                "Texture:setPixels",
                "Texture:getMipmapCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "base",
                      type = "number",
                      description = "The base mipmap level which will be used to generate subsequent mipmaps.",
                      default = "1"
                    },
                    {
                      name = "count",
                      type = "number",
                      description = "The number of mipmap levels to generate.  If nil, the rest of the mipmaps will be generated.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "getDimensions",
              tag = "texture-metadata",
              summary = "Get the dimensions of the Texture.",
              description = "Returns the width, height, and depth of the Texture.",
              key = "Texture:getDimensions",
              module = "lovr.graphics",
              related = {
                "Texture:getWidth",
                "Texture:getHeight",
                "Texture:getLayerCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Texture."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Texture."
                    },
                    {
                      name = "layers",
                      type = "number",
                      description = "The number of layers in the Texture."
                    }
                  }
                }
              }
            },
            {
              name = "getFormat",
              tag = "texture-metadata",
              summary = "Get the format of the Texture.",
              description = "Returns the format of the texture.",
              key = "Texture:getFormat",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "format",
                      type = "TextureFormat",
                      description = "The format of the Texture."
                    },
                    {
                      name = "linear",
                      type = "boolean",
                      description = "Whether the format is linear or srgb."
                    }
                  }
                }
              }
            },
            {
              name = "getHeight",
              tag = "texture-metadata",
              summary = "Get the height of the Texture, in pixels.",
              description = "Returns the height of the Texture, in pixels.",
              key = "Texture:getHeight",
              module = "lovr.graphics",
              related = {
                "Texture:getWidth",
                "Texture:getLayerCount",
                "Texture:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the Texture, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getLabel",
              tag = "texture-metadata",
              summary = "Get the debug label of the Texture.",
              description = "Returns the debug label of the Texture, which will show up when the Texture is printed and in some graphics debugging tools.  This is set when the Texture is created, and can't be changed afterwards.",
              key = "Texture:getLabel",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newTexture",
                "Shader:getLabel",
                "Pass:getLabel"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "label",
                      type = "string",
                      description = "The label, or nil if none was set."
                    }
                  }
                }
              }
            },
            {
              name = "getLayerCount",
              tag = "texture-metadata",
              summary = "Get the layer count of the Texture.",
              description = "Returns the layer count of the Texture.  2D textures always have 1 layer and cubemaps always have a layer count divisible by 6.  3D and array textures have a variable number of layers.",
              key = "Texture:getLayerCount",
              module = "lovr.graphics",
              related = {
                "Texture:getWidth",
                "Texture:getHeight",
                "Texture:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "layers",
                      type = "number",
                      description = "The layer count of the Texture."
                    }
                  }
                }
              }
            },
            {
              name = "getMipmapCount",
              tag = "texture-metadata",
              summary = "Get the number of mipmap levels in the Texture.",
              description = "Returns the number of mipmap levels in the Texture.",
              key = "Texture:getMipmapCount",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newTexture",
                "Sampler:getMipmapRange",
                "Texture:generateMipmaps"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mipmaps",
                      type = "number",
                      description = "The number of mipmap levels in the Texture."
                    }
                  }
                }
              }
            },
            {
              name = "getPixels",
              tag = "texture-transfer",
              summary = "Get the pixels of the Texture.",
              description = "Creates and returns a new `Image` object with the current pixels of the Texture.  This function is very very slow because it stalls the CPU until the download is complete.  It should only be used for debugging, non-interactive scripts, etc.  For an asynchronous version that doesn't stall the CPU, see `Texture:newReadback`.",
              key = "Texture:getPixels",
              module = "lovr.graphics",
              notes = "The texture must have been created with the `transfer` usage.\n\nMultisampled textures can not be read back.\n\nIt is not currently possible to read back a texture view.",
              related = {
                "Texture:newReadback"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x offset of the region to download.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y offset of the region to download.",
                      default = "0"
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the layer to download.",
                      default = "1"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the mipmap level to download.",
                      default = "1"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the pixel rectangle to download.  If nil, the \"rest\" of the width will be used, based on the texture width and x offset.",
                      default = "nil"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the pixel rectangle to download.  If nil, the \"rest\" of the height will be used, based on the texture height and y offset.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "image",
                      type = "Image",
                      description = "The new image with the pixels."
                    }
                  }
                }
              }
            },
            {
              name = "getSampleCount",
              tag = "texture-metadata",
              summary = "Get the number of MSAA samples in the Texture.",
              description = "Returns the number of samples in the texture.  Multiple samples are used for multisample antialiasing when rendering to the texture.  Currently, the sample count is either 1 (not antialiased) or 4 (antialiased).",
              key = "Texture:getSampleCount",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newTexture",
                "Pass:setCanvas"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples in the Texture."
                    }
                  }
                }
              }
            },
            {
              name = "getSampler",
              tag = "texture-sampler",
              summary = "Get the Sampler assigned to the Texture.",
              description = "Returns the Sampler object previously assigned with `Texture:setSampler`.\n\nThis API is experimental, and subject to change in the future!",
              key = "Texture:getSampler",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "sampler",
                      type = "Sampler",
                      description = "The Sampler object."
                    }
                  }
                }
              }
            },
            {
              name = "getType",
              tag = "texture-metadata",
              summary = "Get the type of the Texture.",
              description = "Returns the type of the texture.",
              key = "Texture:getType",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "type",
                      type = "TextureType",
                      description = "The type of the Texture."
                    }
                  }
                }
              }
            },
            {
              name = "getWidth",
              tag = "texture-metadata",
              summary = "Get the width of the Texture, in pixels.",
              description = "Returns the width of the Texture, in pixels.",
              key = "Texture:getWidth",
              module = "lovr.graphics",
              related = {
                "Texture:getHeight",
                "Texture:getLayerCount",
                "Texture:getDimensions"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the Texture, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "hasUsage",
              tag = "texture-metadata",
              summary = "Check if a Texture was created with a set of usage flags.",
              description = "Returns whether a Texture was created with a set of `TextureUsage` flags.  Usage flags are specified when the Texture is created, and restrict what you can do with a Texture object.  By default, only the `sample` usage is enabled.  Applying a smaller set of usage flags helps LÖVR optimize things better.",
              key = "Texture:hasUsage",
              module = "lovr.graphics",
              related = {
                "lovr.graphics.newTexture"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "...",
                      type = "TextureUsage",
                      description = "One or more usage flags."
                    }
                  },
                  returns = {
                    {
                      name = "supported",
                      type = "boolean",
                      description = "Whether the Texture has all the provided usage flags."
                    }
                  }
                }
              }
            },
            {
              name = "newReadback",
              tag = "texture-transfer",
              summary = "Read back the contents of the Texture asynchronously.",
              description = "Creates and returns a new `Readback` that will download the pixels in the Texture from VRAM. Once the readback is complete, `Readback:getImage` returns an `Image` with a CPU copy of the data.",
              key = "Texture:newReadback",
              module = "lovr.graphics",
              examples = {
                {
                  description = "Take a screenshot when pressing a key.  This uses an intermediate texture and render pass, to work around the fact that the window/headset textures don't support transfers.",
                  code = "local screenshot = false\nlocal readback\nlocal texture\nlocal pass\n\nfunction lovr.keypressed(key)\n  if key == 'p' then screenshot = true end\nend\n\nfunction lovr.load()\n  local width, height = lovr.headset.getDisplayDimensions()\n\n  texture = lovr.graphics.newTexture(width, height, {\n    usage = { 'render', 'transfer', 'sample' }\n  })\n\n  pass = lovr.graphics.newPass(texture)\nend\n\nfunction lovr.update()\n  pass:reset()\n  for i = 1, lovr.headset.getViewCount() do\n    pass:setViewPose(i, lovr.headset.getViewPose(i))\n    pass:setProjection(i, lovr.headset.getViewAngles(i))\n  end\n  pass:text('hellooo', 0, 1.7, -1, .1)\n  lovr.graphics.submit(pass)\n\n  if screenshot and not readback then\n    readback = texture:newReadback()\n    screenshot = false\n  end\n\n  if readback and readback:isComplete() then\n    local filename = 'screenshot.png'\n    lovr.filesystem.write(filename, readback:getImage():encode())\n    print('saved screenshot to ' .. filename)\n    readback = nil\n  end\nend\n\nfunction lovr.draw(p)\n  p:fill(texture)\nend"
                }
              },
              notes = "The texture must have been created with the `transfer` usage.\n\nMultisampled textures can not be read back.\n\nIt is not currently possible to read back a texture view.",
              related = {
                "Texture:getPixels",
                "Buffer:newReadback"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x offset of the region to download.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y offset of the region to download.",
                      default = "0"
                    },
                    {
                      name = "layer",
                      type = "number",
                      description = "The index of the layer to download.",
                      default = "1"
                    },
                    {
                      name = "mipmap",
                      type = "number",
                      description = "The index of the mipmap level to download.",
                      default = "1"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the pixel rectangle to download.  If nil, the \"rest\" of the width will be used, based on the texture width and x offset.",
                      default = "nil"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the pixel rectangle to download.  If nil, the \"rest\" of the height will be used, based on the texture height and y offset.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "readback",
                      type = "Readback",
                      description = "A new Readback object."
                    }
                  }
                }
              }
            },
            {
              name = "setPixels",
              tag = "texture-transfer",
              summary = "Replace pixels in the Texture.",
              description = "Sets pixels in the texture.  The source data can be an `Image` with the pixels to upload, or another `Texture` object to copy from.",
              key = "Texture:setPixels",
              module = "lovr.graphics",
              notes = "Note that calling `Texture:setPixels(Image)` will only update the first mipmap of the texture, leaving the other mipmaps as-is.  You may want to regenerate the texture's mipmaps afterwards by calling `Texture:generateMipmaps`, or disable mipmaps entirely by setting `mipmaps` to false in `lovr.graphics.newTexture`.\n\nThe destination and source textures must have been created with the `transfer` usage.\n\nImages can't be copied to multisample textures.  Multisample textures can be copied between each other as long as there isn't any scaling.\n\nCopying between textures requires them to have the same format.\n\nWhen using different region sizes in a texture-to-texture copy:\n\n- It is not possible to mix 3D with non-3D textures.\n- Not every texture format is supported, use `lovr.graphics.isFormatSupported` to check.\n- The formats do not need to match, unless they're depth formats.",
              related = {
                "Texture:newReadback",
                "Texture:generateMipmaps",
                "Image:paste"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "source",
                      type = "Texture | Image",
                      description = "The source texture or image to copy to this texture."
                    },
                    {
                      name = "dstx",
                      type = "number",
                      description = "The x offset to copy to.",
                      default = "0"
                    },
                    {
                      name = "dsty",
                      type = "number",
                      description = "The y offset to copy to.",
                      default = "0"
                    },
                    {
                      name = "dstlayer",
                      type = "number",
                      description = "The index of the layer to copy to.",
                      default = "1"
                    },
                    {
                      name = "dstmipmap",
                      type = "number",
                      description = "The index of the mipmap level to copy to.",
                      default = "1"
                    },
                    {
                      name = "srcx",
                      type = "number",
                      description = "The x offset to copy from.",
                      default = "0"
                    },
                    {
                      name = "srcy",
                      type = "number",
                      description = "The y offset to copy from.",
                      default = "0"
                    },
                    {
                      name = "srclayer",
                      type = "number",
                      description = "The index of the layer to copy from.",
                      default = "1"
                    },
                    {
                      name = "srcmipmap",
                      type = "number",
                      description = "The index of the mipmap level to copy from.",
                      default = "1"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the region of pixels to copy.  If nil, the maximum possible width will be used, based on the widths of the source/destination and the offset parameters.",
                      default = "nil"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the region of pixels to copy.  If nil, the maximum possible height will be used, based on the heights of the source/destination and the offset parameters.",
                      default = "nil"
                    },
                    {
                      name = "layers",
                      type = "number",
                      description = "The number of layers to copy.  If nil, copies as many layers as possible.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSampler",
              tag = "texture-sampler",
              summary = "Set sampler settings for the Texture.",
              description = "Sets sampler settings for the texture.  This can either be a `FilterMode` like `nearest`, or a `Sampler` object, which allows configuring all of the filtering and wrapping settings.\n\nThere are other ways of using custom samplers for a texture, but they have disadvantages:\n\n- `Sampler` objects can be sent to shaders and used to sample from the texture, but this\n  requires writing custom shader code and sending sampler objects with `Pass:send`, which is\n  inconvenient.\n- `Pass:setSampler` exists, but it applies to all textures in all draws in the Pass.  It doesn't\n  allow for changing filtering settings on a per-texture basis.\n\nThis API is experimental, and subject to change in the future!",
              key = "Texture:setSampler",
              module = "lovr.graphics",
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "FilterMode",
                      description = "The FilterMode shaders will use when reading pixels from the texture."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "sampler",
                      type = "Sampler",
                      description = "The Sampler object shaders will use when reading pixels from the texture."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Remove the texture's sampler, instead using the one set by `Pass:setSampler`.",
                  arguments = {},
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Metadata",
              tag = "texture-metadata"
            },
            {
              name = "Transfers",
              tag = "texture-transfer"
            },
            {
              name = "Sampler",
              tag = "texture-sampler"
            }
          }
        }
      },
      sections = {
        {
          name = "Objects",
          tag = "graphics-objects"
        },
        {
          name = "Global State",
          tag = "graphics-global"
        },
        {
          name = "Work Submission",
          tag = "work-submission",
          description = "The only way to get the GPU to do anything is to submit `Pass` objects to it.  LÖVR submits the default pass automatically at the end of `lovr.draw`, but work can also be submitted manually."
        },
        {
          name = "System Info",
          tag = "graphics-misc",
          description = "Information about the GPU hardware and the features it supports."
        }
      }
    },
    {
      name = "headset",
      tag = "modules",
      summary = "Connects to VR hardware.",
      description = "The `lovr.headset` module is where all the magical VR functionality is.  With it, you can access connected VR hardware and get information about the available space the player has.  Note that all units are reported in meters.  Position `(0, 0, 0)` is on the floor in the center of the play area.",
      key = "lovr.headset",
      enums = {
        {
          name = "Device",
          summary = "Different types of input devices supported by the `lovr.headset` module.",
          description = "Different types of input devices supported by the `lovr.headset` module.",
          key = "Device",
          module = "lovr.headset",
          notes = "The `grip` pose is used to render an object held in the user's hand.  It's positioned at the surface of the palm.  The X axis of the grip orientation is perpendicular to the palm, pointing away from the left palm or into the right palm.  If you imagine the hand holding a stick, the Z axis will be parallel to the stick.\n\n<img src=\"/img/grip.svg\" width=\"600\" alt=\"Hand Grip Pose\" class=\"flat\"/>\n\n*Image from the [OpenXR Specification](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_grip_pose)*\n\n---\n\nThe `point` pose is used to aim or point at objects.  It's usually positioned slightly in front of the hand or controller, and is oriented so the -Z axis points in a natural forward direction.\n\n<img src=\"/img/aim.svg\" width=\"600\" alt=\"Hand Point Pose\" class=\"flat\"/>\n\n*Image from the [OpenXR Specification](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_aim_pose)*\n\n---\n\nThe `pinch` pose is a stable point between the thumb and index finger on a hand, or a point slightly in front of a controller.  The -Z axis will point forward, away from the hand.  It's good for precise, close-range interaction.\n\n<img src=\"/img/pinch.svg\" width=\"600\" alt=\"Hand Pinch Pose\" class=\"flat\"/>\n\n*Image from the [OpenXR Specification](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_pinch_pose)*\n\n---\n\nThe `poke` pose is a position located at the tip of the index finger, or a point slightly in front of a controller.  The -Z axis will point forward out of the tip of the finger, the +Y axis will be perpendicular to the fingernail.\n\n<img src=\"/img/poke.svg\" width=\"600\" alt=\"Hand Poke Pose\" class=\"flat\"/>\n\n*Image from the [OpenXR Specification](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_poke_pose)*\n\n---\n\nThese \"hand pose devices\" do not report any button input with e.g. `lovr.headset.isDown`.  The main `hand/left` and `hand/right` devices should be used for buttons and haptics.",
          related = {
            "DeviceAxis",
            "DeviceButton",
            "lovr.headset.getPose",
            "lovr.headset.getPosition",
            "lovr.headset.getOrientation",
            "lovr.headset.getVelocity",
            "lovr.headset.getAngularVelocity",
            "lovr.headset.getSkeleton",
            "lovr.headset.isTracked",
            "lovr.headset.isDown",
            "lovr.headset.isTouched",
            "lovr.headset.wasPressed",
            "lovr.headset.wasReleased",
            "lovr.headset.getAxis",
            "lovr.headset.vibrate",
            "lovr.headset.animate"
          },
          values = {
            {
              name = "head",
              description = "The headset."
            },
            {
              name = "floor",
              description = "A device representing the floor, at the center of the play area.  The pose of this device in physical space will remain constant, even after recentering."
            },
            {
              name = "left",
              description = "A shorthand for hand/left."
            },
            {
              name = "right",
              description = "A shorthand for hand/right."
            },
            {
              name = "hand/left",
              description = "The left hand."
            },
            {
              name = "hand/right",
              description = "The right hand."
            },
            {
              name = "hand/left/grip",
              description = "The left hand grip pose, used for held objects."
            },
            {
              name = "hand/right/grip",
              description = "The right hand grip pose, used for held objects."
            },
            {
              name = "hand/left/point",
              description = "The left hand pointer pose, used for pointing or aiming."
            },
            {
              name = "hand/right/point",
              description = "The right hand pointer pose, used for pointing or aiming."
            },
            {
              name = "hand/left/pinch",
              description = "The left hand pinch pose between the thumb and index fingers, used for precise, close-range interactions."
            },
            {
              name = "hand/right/pinch",
              description = "The right hand pinch pose between the thumb and index fingers, used for precise, close-range interactions."
            },
            {
              name = "hand/left/poke",
              description = "The left hand poke pose, on the tip of the index finger or in front of a controller."
            },
            {
              name = "hand/right/poke",
              description = "The right hand poke pose, on the tip of the index finger or in front of a controller."
            },
            {
              name = "elbow/left",
              description = "A device tracking the left elbow."
            },
            {
              name = "elbow/right",
              description = "A device tracking the right elbow."
            },
            {
              name = "shoulder/left",
              description = "A device tracking the left shoulder."
            },
            {
              name = "shoulder/right",
              description = "A device tracking the right shoulder."
            },
            {
              name = "chest",
              description = "A device tracking the chest."
            },
            {
              name = "waist",
              description = "A device tracking the waist."
            },
            {
              name = "knee/left",
              description = "A device tracking the left knee."
            },
            {
              name = "knee/right",
              description = "A device tracking the right knee."
            },
            {
              name = "foot/left",
              description = "A device tracking the left foot or ankle."
            },
            {
              name = "foot/right",
              description = "A device tracking the right foot or ankle."
            },
            {
              name = "camera",
              description = "A camera device, often used for recording \"mixed reality\" footage."
            },
            {
              name = "keyboard",
              description = "A tracked keyboard."
            },
            {
              name = "stylus",
              description = "A tracked pen or pointer."
            },
            {
              name = "eye/left",
              description = "The left eye."
            },
            {
              name = "eye/right",
              description = "The right eye."
            },
            {
              name = "eye/gaze",
              description = "The combined eye gaze pose.  The position is between the eyes.  The orientation aligns the\n-Z axis in the direction the user is looking and the +Y axis to the head's \"up\" vector. This provides more accurate eye tracking information compared to using the individual eye devices."
            }
          }
        },
        {
          name = "DeviceAxis",
          summary = "Different axes on an input device.",
          description = "Axes on an input device.",
          key = "DeviceAxis",
          module = "lovr.headset",
          related = {
            "lovr.headset.getAxis",
            "DeviceButton"
          },
          values = {
            {
              name = "trigger",
              description = "A trigger (1D)."
            },
            {
              name = "thumbstick",
              description = "A thumbstick (2D)."
            },
            {
              name = "thumbrest",
              description = "A rest (1D, pressure sensitivity, also available as a `DeviceButton`)."
            },
            {
              name = "touchpad",
              description = "A touchpad (2D)."
            },
            {
              name = "grip",
              description = "A grip button or grab gesture (1D)."
            },
            {
              name = "nib",
              description = "The pressure sensitivity of the nib (tip) of a `stylus` device.  Also available on the `hand/left` and `hand/right` devices for the stylus nibs on touch pro controllers."
            }
          }
        },
        {
          name = "DeviceButton",
          summary = "Different buttons on an input device.",
          description = "Buttons on an input device.",
          key = "DeviceButton",
          module = "lovr.headset",
          values = {
            {
              name = "trigger",
              description = "The trigger button."
            },
            {
              name = "thumbstick",
              description = "The thumbstick."
            },
            {
              name = "thumbrest",
              description = "The thumbrest."
            },
            {
              name = "touchpad",
              description = "The touchpad."
            },
            {
              name = "grip",
              description = "The grip button."
            },
            {
              name = "menu",
              description = "The menu button."
            },
            {
              name = "a",
              description = "The A button."
            },
            {
              name = "b",
              description = "The B button."
            },
            {
              name = "x",
              description = "The X button."
            },
            {
              name = "y",
              description = "The Y button."
            },
            {
              name = "nib",
              description = "The nib (tip) of the `stylus` device.  Also available on `hand/left` and `hand/right` devices for the stylus tips on touch pro controllers."
            }
          }
        },
        {
          name = "FoveationLevel",
          summary = "Different foveation levels.",
          description = "The different levels of foveation supported by `lovr.headset.setFoveation`.",
          key = "FoveationLevel",
          module = "lovr.headset",
          values = {
            {
              name = "low",
              description = "Low foveation."
            },
            {
              name = "medium",
              description = "Medium foveation."
            },
            {
              name = "high",
              description = "High foveation."
            }
          }
        },
        {
          name = "HeadsetDriver",
          summary = "VR APIs.",
          description = "These are all of the supported VR APIs that LÖVR can use to power the lovr.headset module.  You can change the order of headset drivers using `lovr.conf` to prefer or exclude specific VR APIs.\n\nAt startup, LÖVR searches through the list of drivers in order.",
          key = "HeadsetDriver",
          module = "lovr.headset",
          values = {
            {
              name = "simulator",
              description = "A VR simulator using keyboard/mouse."
            },
            {
              name = "openxr",
              description = "OpenXR."
            }
          }
        },
        {
          name = "HeadsetOrigin",
          summary = "Different types of coordinate space origins.",
          description = "Represents the different types of origins for coordinate spaces.  An origin of \"floor\" means that the origin is on the floor in the middle of a room-scale play area.  An origin of \"head\" means that no positional tracking is available, and consequently the origin is always at the position of the headset.",
          key = "HeadsetOrigin",
          module = "lovr.headset",
          values = {
            {
              name = "head",
              description = "The origin is at the head."
            },
            {
              name = "floor",
              description = "The origin is on the floor."
            }
          }
        },
        {
          name = "PassthroughMode",
          summary = "Passthrough modes.",
          description = "Different passthrough modes, set using `lovr.headset.setPassthrough`.\n\nFor best results, the `blend` and `add` modes should use a transparent background color, which can be changed with `lovr.graphics.setBackgroundColor`.",
          key = "PassthroughMode",
          module = "lovr.headset",
          related = {
            "lovr.headset.getPassthrough",
            "lovr.headset.setPassthrough",
            "lovr.headset.getPassthroughModes"
          },
          values = {
            {
              name = "opaque",
              description = "The headset display will not blend with anything behind it.  Most VR headsets use this mode."
            },
            {
              name = "blend",
              description = "The real world will blend with the headset display using the alpha channel.  This is supported on VR headsets with camera passthrough, as well as some AR displays."
            },
            {
              name = "add",
              description = "Color values from virtual content will be added to the real world.  This is the most common mode used for AR.  Notably, black pixels will not show up at all."
            }
          }
        }
      },
      functions = {
        {
          name = "animate",
          tag = "controller-models",
          summary = "Animate a model to match its Device input state.",
          description = "Animates a model to match its input state.  The buttons and joysticks on a controller will move as they're pressed/moved and hand models will move to match hand tracking joints.\n\nThe model must have been created using `lovr.headset.newModel` with the `animated` flag set to `true`.",
          key = "lovr.headset.animate",
          module = "lovr.headset",
          examples = {
            {
              code = "function lovr.load()\n  models = {\n    left = lovr.headset.newModel('hand/left'),\n    right = lovr.headset.newModel('hand/right')\n  }\nend\n\nfunction lovr.draw(pass)\n  for hand, model in pairs(models) do\n    if lovr.headset.isTracked(hand) then\n      lovr.headset.animate(model)\n      pass:draw(model, mat4(lovr.headset.getPose(hand)))\n    end\n  end\n\n  if not next(models) then\n    pass:text('No models loaded', 0, 1.7, -1, .1)\n  end\nend"
            }
          },
          notes = "It's possible to animate a custom hand model by retargeting joint poses, see the `Interaction/Custom_Hand_Rig` example.",
          related = {
            "lovr.headset.newModel",
            "Model:animate"
          },
          variants = {
            {
              arguments = {
                {
                  name = "model",
                  type = "Model",
                  description = "The model to animate."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the animation was applied successfully to the Model.  If the Model was not compatible or animation data for the device was not available, this will be `false`."
                }
              }
            },
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to use for the animation data.",
                  default = "'head'"
                },
                {
                  name = "model",
                  type = "Model",
                  description = "The model to animate."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the animation was applied successfully to the Model.  If the Model was not compatible or animation data for the device was not available, this will be `false`."
                }
              },
              deprecated = true
            }
          }
        },
        {
          name = "getAngularVelocity",
          tag = "input",
          summary = "Get the angular velocity of a device.",
          description = "Returns the current angular velocity of a device.",
          key = "lovr.headset.getAngularVelocity",
          module = "lovr.headset",
          notes = "If the device isn't tracked, all zeroes will be returned.",
          related = {
            "lovr.headset.getVelocity",
            "lovr.headset.getPosition",
            "lovr.headset.getOrientation"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the velocity of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x component of the angular velocity."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y component of the angular velocity."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z component of the angular velocity."
                }
              }
            }
          }
        },
        {
          name = "getAxis",
          tag = "input",
          summary = "Get the state of an analog axis on a device.",
          description = "Get the current state of an analog axis on a device.  Some axes are multidimensional, for example a 2D touchpad or thumbstick with x/y axes.  For multidimensional axes, this function will return multiple values, one number for each axis.  In these cases, it can be useful to use the `select` function built in to Lua to select a particular axis component.",
          key = "lovr.headset.getAxis",
          module = "lovr.headset",
          notes = "The axis values will be between 0 and 1 for 1D axes, and between -1 and 1 for each component of a multidimensional axis.\n\nWhen hand tracking is active, pinch strength will be mapped to the `trigger` axis.",
          related = {
            "DeviceAxis",
            "lovr.headset.isDown"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device."
                },
                {
                  name = "axis",
                  type = "DeviceAxis",
                  description = "The axis."
                }
              },
              returns = {
                {
                  name = "...",
                  type = "number | nil",
                  description = "The current state of the components of the axis, or `nil` if the device does not have any information about the axis."
                }
              }
            }
          }
        },
        {
          name = "getBoundsDepth",
          tag = "playArea",
          summary = "Get the depth of the play area.",
          description = "Returns the depth of the play area, in meters.",
          key = "lovr.headset.getBoundsDepth",
          module = "lovr.headset",
          notes = "If the VR system is not roomscale, this will return zero.",
          related = {
            "lovr.headset.getBoundsWidth",
            "lovr.headset.getBoundsDimensions"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "depth",
                  type = "number",
                  description = "The depth of the play area, in meters."
                }
              }
            }
          }
        },
        {
          name = "getBoundsDimensions",
          tag = "playArea",
          summary = "Get the size of the play area.",
          description = "Returns the size of the play area, in meters.",
          key = "lovr.headset.getBoundsDimensions",
          module = "lovr.headset",
          notes = "If the VR system is not roomscale, this will return zero.",
          related = {
            "lovr.headset.getBoundsWidth",
            "lovr.headset.getBoundsDepth",
            "lovr.headset.getBoundsGeometry"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the play area, in meters."
                },
                {
                  name = "depth",
                  type = "number",
                  description = "The depth of the play area, in meters."
                }
              }
            }
          }
        },
        {
          name = "getBoundsGeometry",
          tag = "playArea",
          summary = "Get a list of points that make up the play area boundary.",
          description = "Returns a list of points representing the boundaries of the play area, or `nil` if the current headset driver does not expose this information.",
          key = "lovr.headset.getBoundsGeometry",
          module = "lovr.headset",
          related = {
            "lovr.headset.getBoundsDimensions"
          },
          variants = {
            {
              arguments = {
                {
                  name = "t",
                  type = "table",
                  description = "A table to fill with the points.  If `nil`, a new table will be created.",
                  default = "nil"
                }
              },
              returns = {
                {
                  name = "points",
                  type = "table",
                  description = "A flat table of 3D points representing the play area boundaries."
                }
              }
            }
          }
        },
        {
          name = "getBoundsWidth",
          tag = "playArea",
          summary = "Get the width of the play area.",
          description = "Returns the width of the play area, in meters.",
          key = "lovr.headset.getBoundsWidth",
          module = "lovr.headset",
          notes = "If the VR system is not roomscale, this will return zero.",
          related = {
            "lovr.headset.getBoundsDepth",
            "lovr.headset.getBoundsDimensions"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the play area, in meters."
                }
              }
            }
          }
        },
        {
          name = "getClipDistance",
          tag = "headset",
          summary = "Get the near and far clipping planes of the headset.",
          description = "Returns the near and far clipping planes used to render to the headset.  Objects closer than the near clipping plane or further than the far clipping plane will be clipped out of view.",
          key = "lovr.headset.getClipDistance",
          module = "lovr.headset",
          notes = "The default near and far clipping planes are 0.01 meters and 0.0 meters.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "near",
                  type = "number",
                  description = "The distance to the near clipping plane, in meters."
                },
                {
                  name = "far",
                  type = "number",
                  description = "The distance to the far clipping plane, in meters, or 0 for an infinite far clipping plane with a reversed Z range."
                }
              }
            }
          }
        },
        {
          name = "getDeltaTime",
          tag = "headset-misc",
          summary = "Get the predicted delta time.",
          description = "Returns the headset delta time, which is the difference between the current and previous predicted display times.  When the headset is active, this will be the `dt` value passed in to `lovr.update`.",
          key = "lovr.headset.getDeltaTime",
          module = "lovr.headset",
          related = {
            "lovr.headset.getTime",
            "lovr.timer.getTime",
            "lovr.timer.getDelta"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "dt",
                  type = "number",
                  description = "The delta time."
                }
              }
            }
          }
        },
        {
          name = "getDirection",
          tag = "input",
          summary = "Get the direction a device is pointing.",
          description = "Returns the direction a device is pointing.  It will always be normalized.",
          key = "lovr.headset.getDirection",
          module = "lovr.headset",
          notes = "If the device isn't tracked, all zeroes will be returned.\n\nThis is the same as `quat(lovr.headset.getOrientation(device)):direction():unpack()`.",
          related = {
            "lovr.headset.getPose",
            "lovr.headset.getOrientation",
            "lovr.headset.getVelocity",
            "lovr.headset.getAngularVelocity",
            "lovr.headset.isTracked",
            "lovr.headset.getDriver"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the direction of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x component of the direction."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y component of the direction."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z component of the direction."
                }
              }
            }
          }
        },
        {
          name = "getDisplayDimensions",
          tag = "headset",
          summary = "Get the dimensions of the headset display.",
          description = "Returns the texture dimensions of the headset display (for one eye), in pixels.",
          key = "lovr.headset.getDisplayDimensions",
          module = "lovr.headset",
          related = {
            "lovr.headset.getDisplayWidth",
            "lovr.headset.getDisplayHeight"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the display."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the display."
                }
              }
            }
          }
        },
        {
          name = "getDisplayHeight",
          tag = "headset",
          summary = "Get the height of the headset display.",
          description = "Returns the height of the headset display (for one eye), in pixels.",
          key = "lovr.headset.getDisplayHeight",
          module = "lovr.headset",
          related = {
            "lovr.headset.getDisplayWidth",
            "lovr.headset.getDisplayDimensions"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "height",
                  type = "number",
                  description = "The height of the display."
                }
              }
            }
          }
        },
        {
          name = "getDisplayWidth",
          tag = "headset",
          summary = "Get the width of the headset display.",
          description = "Returns the width of the headset display (for one eye), in pixels.",
          key = "lovr.headset.getDisplayWidth",
          module = "lovr.headset",
          related = {
            "lovr.headset.getDisplayHeight",
            "lovr.headset.getDisplayDimensions"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the display."
                }
              }
            }
          }
        },
        {
          name = "getDriver",
          tag = "headset-misc",
          summary = "Get the VR API currently in use for a device.",
          description = "Returns the `HeadsetDriver` that is currently in use, plus the name of the VR runtime.  The order of headset drivers can be changed using `lovr.conf`.",
          key = "lovr.headset.getDriver",
          module = "lovr.headset",
          related = {
            "lovr.headset.getName"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "driver",
                  type = "HeadsetDriver",
                  description = "The current headset backend, e.g. `openxr` or `simulator`."
                },
                {
                  name = "runtime",
                  type = "string",
                  description = "The name of the VR runtime, e.g. `SteamVR/OpenXR`."
                }
              }
            }
          }
        },
        {
          name = "getFeatures",
          tag = "headset-misc",
          summary = "Get the supported headset features.",
          description = "Returns a table of features that are supported by the current headset runtime.",
          key = "lovr.headset.getFeatures",
          module = "lovr.headset",
          related = {
            "lovr.headset.getName"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "features",
                  type = "table",
                  description = "",
                  table = {
                    {
                      name = "overlay",
                      type = "boolean",
                      description = "Whether LÖVR is able to run as an overlay on top of other VR applications.  When unsupported, the `t.headset.overlay` option in `lovr.conf` will be ignored.  Currently this will also be false if `t.headset.overlay` is false."
                    },
                    {
                      name = "proximity",
                      type = "boolean",
                      description = "Whether the headset provides access to its proximity sensor.  When unsupported, `lovr.headset.isMounted` will always return true and `lovr.mount` will never be called."
                    },
                    {
                      name = "passthrough",
                      type = "boolean",
                      description = "Whether the headset supports one of the non-opaque passthrough modes.  When unsupported, `lovr.headset.getPassthroughModes` will only return 'opaque'."
                    },
                    {
                      name = "refreshRate",
                      type = "boolean",
                      description = "Whether the headset display supports querying and changing the refresh rate.  When unsupported, `lovr.headset.getRefreshRate` will always return nil and `lovr.headset.setRefreshRate` will always return false."
                    },
                    {
                      name = "depthSubmission",
                      type = "boolean",
                      description = "Whether `t.headset.submitdepth` in `lovr.conf` is active and supported."
                    },
                    {
                      name = "eyeTracking",
                      type = "boolean",
                      description = "Whether the headset supports eye gaze tracking.  When unsupported, the `eye/*` devices will always be untracked."
                    },
                    {
                      name = "handTracking",
                      type = "boolean",
                      description = "Whether hand tracking is supported.  When false, `lovr.headset.getSkeleton` will always return nil."
                    },
                    {
                      name = "handTrackingElbow",
                      type = "boolean",
                      description = "Whether the hand tracker is able to return data for the `elbow/*` devices."
                    },
                    {
                      name = "keyboardTracking",
                      type = "boolean",
                      description = "Whether the system supports tracked keyboards for the `keyboard` device."
                    },
                    {
                      name = "viveTrackers",
                      type = "boolean",
                      description = "Whether the system supports Vive trackers."
                    },
                    {
                      name = "handModel",
                      type = "boolean",
                      description = "Whether `lovr.headset.newModel` is able to load models for the user\\'s hands."
                    },
                    {
                      name = "controllerModel",
                      type = "boolean",
                      description = "Whether `lovr.headset.newModel` supports loading controller models."
                    },
                    {
                      name = "controllerSkeleton",
                      type = "boolean",
                      description = "Whether the `t.headset.controllerskeleton` option in `lovr.conf` is supported and whether the `controller` key in the `lovr.headset.getSkeleton` table is supported.  When this is false, it is not possible to determine whether hand tracking data is coming from the user's actual hands or if it's estimated from controller button inputs."
                    },
                    {
                      name = "cubeBackground",
                      type = "boolean",
                      description = "Whether `lovr.headset.setBackground` supports cubemap textures."
                    },
                    {
                      name = "equirectBackground",
                      type = "boolean",
                      description = "Whether `lovr.headset.setBackground` supports equirectangular textures."
                    },
                    {
                      name = "layerColor",
                      type = "boolean",
                      description = "Whether `Layer:setColor` is supported."
                    },
                    {
                      name = "layerCurve",
                      type = "boolean",
                      description = "Whether `Layer:setCurve` is supported."
                    },
                    {
                      name = "layerDepthTest",
                      type = "boolean",
                      description = "Whether Layers are able to depth sort with the rest of the 3D scene, and with each other.  When unsupported, layers will always render on top of the 3D scene and any layers that come before them in the layer list."
                    },
                    {
                      name = "layerFilter",
                      type = "boolean",
                      description = "Whether the `filter` option is supported for Layers."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "getFoveation",
          tag = "headset",
          summary = "Get the current foveation settings.",
          description = "Returns the current foveation settings, previously set by `lovr.headset.setFoveation`.'",
          key = "lovr.headset.getFoveation",
          module = "lovr.headset",
          notes = "Foveation is disabled by default.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "level",
                  type = "FoveationLevel",
                  description = "The foveation level (or the maximum level when dynamic foveation is active)."
                },
                {
                  name = "dynamic",
                  type = "boolean",
                  description = "Whether dynamic foveation is active, allowing the system to reduce foveation based on GPU load."
                }
              }
            }
          }
        },
        {
          name = "getHandles",
          tag = "headset-misc",
          summary = "Get native pointers to OpenXR objects.",
          description = "Returns pointers to the OpenXR instance and session objects.\n\nThis can be used with FFI or other native plugins to integrate with other OpenXR code.",
          key = "lovr.headset.getHandles",
          module = "lovr.headset",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "instance",
                  type = "lightuserdata",
                  description = "The OpenXR instance handle (`XrInstance`)."
                },
                {
                  name = "session",
                  type = "lightuserdata",
                  description = "The OpenXR session handle (`XrSession`)."
                }
              }
            }
          }
        },
        {
          name = "getHands",
          tag = "input",
          summary = "Get a list of currently tracked hand devices.",
          description = "Returns a table with all of the currently tracked hand devices.",
          key = "lovr.headset.getHands",
          module = "lovr.headset",
          examples = {
            {
              code = "function lovr.update(dt)\n  for i, hand in ipairs(lovr.headset.getHands()) do\n    print(hand, lovr.headset.getPose(hand))\n  end\nend"
            }
          },
          notes = "The hand paths will *always* be either `hand/left` or `hand/right`.",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "hands",
                  type = "{Device}",
                  description = "The currently tracked hand devices.",
                  arguments = {},
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "getLayers",
          tag = "layers",
          summary = "Get the list of active layers.",
          description = "Returns the list of active `Layer` objects.  These are the layers that will be rendered in the headset's display.  They are rendered in order.",
          key = "lovr.headset.getLayers",
          module = "lovr.headset",
          notes = "Currently some VR systems are able to sort the layers by their Z depth, but on others layers later in the list will render on top of previous layers, regardless of depth.\n\nThere is currently a maximum of 10 layers.",
          related = {
            "lovr.headset.newLayer",
            "Layer"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "layers",
                  type = "{Layer}",
                  description = "The list of layers."
                }
              }
            }
          }
        },
        {
          name = "getName",
          tag = "headset-misc",
          summary = "Get the name of the connected headset display.",
          description = "Returns the name of the headset as a string.  The exact string that is returned depends on the hardware and VR SDK that is currently in use.",
          key = "lovr.headset.getName",
          module = "lovr.headset",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "name",
                  type = "string",
                  description = "The name of the headset as a string."
                }
              }
            }
          }
        },
        {
          name = "getOrientation",
          tag = "input",
          summary = "Get the orientation of a device.",
          description = "Returns the current orientation of a device, in angle/axis form.",
          key = "lovr.headset.getOrientation",
          module = "lovr.headset",
          notes = "If the device isn't tracked, all zeroes will be returned.",
          related = {
            "lovr.headset.getPose",
            "lovr.headset.getPosition",
            "lovr.headset.getDirection",
            "lovr.headset.getVelocity",
            "lovr.headset.getAngularVelocity",
            "lovr.headset.isTracked",
            "lovr.headset.getDriver"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the orientation of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "angle",
                  type = "number",
                  description = "The amount of rotation around the axis of rotation, in radians."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              }
            }
          }
        },
        {
          name = "getPass",
          tag = "headset-misc",
          summary = "Get a Pass that renders to the headset.",
          description = "Returns a `Pass` that renders to the headset display.",
          key = "lovr.headset.getPass",
          module = "lovr.headset",
          notes = "The same Pass will be returned until `lovr.headset.submit` is called.\n\nThe first time this function is called during a frame, the views of the Pass will be initialized with the headset view poses and view angles.\n\nThe pass will be cleared to the background color, which can be changed using `lovr.graphics.setBackgroundColor`.\n\nThe pass will have a depth buffer.  If `t.headset.stencil` was set to a truthy value in `lovr.conf`, the depth buffer will use the `d32fs8` format, otherwise `d32f` will be used.\n\nIf `t.headset.antialias` was set to a truthy value in `lovr.conf`, the pass will be multisampled.",
          related = {
            "lovr.graphics.newPass",
            "lovr.graphics.getWindowPass",
            "lovr.conf"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "pass",
                  type = "Pass | nil",
                  description = "The pass."
                }
              }
            }
          }
        },
        {
          name = "getPassthrough",
          tag = "headset",
          summary = "Get the current passthrough mode.",
          description = "Returns the current passthrough mode.",
          key = "lovr.headset.getPassthrough",
          module = "lovr.headset",
          related = {
            "lovr.headset.getPassthroughModes"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "mode",
                  type = "PassthroughMode",
                  description = "The current passthrough mode."
                }
              }
            }
          }
        },
        {
          name = "getPassthroughModes",
          tag = "headset",
          summary = "Get the supported passthrough modes.",
          description = "Returns the set of supported passthrough modes.",
          key = "lovr.headset.getPassthroughModes",
          module = "lovr.headset",
          related = {
            "lovr.headset.getPassthrough",
            "lovr.headset.setPassthrough"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "modes",
                  type = "table",
                  description = "The set of supported passthrough modes.  Keys will be `PassthroughMode` strings, and values will be booleans indicating whether the mode is supported."
                }
              }
            }
          }
        },
        {
          name = "getPose",
          tag = "input",
          summary = "Get the pose of a device.",
          description = "Returns the current position and orientation of a device.",
          key = "lovr.headset.getPose",
          module = "lovr.headset",
          notes = "Units are in meters.\n\nIf the device isn't tracked, all zeroes will be returned.",
          related = {
            "lovr.headset.getPosition",
            "lovr.headset.getOrientation",
            "lovr.headset.getVelocity",
            "lovr.headset.getAngularVelocity",
            "lovr.headset.getSkeleton",
            "lovr.headset.isTracked",
            "lovr.headset.getDriver"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the pose of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position."
                },
                {
                  name = "angle",
                  type = "number",
                  description = "The amount of rotation around the axis of rotation, in radians."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation."
                }
              }
            }
          }
        },
        {
          name = "getPosition",
          tag = "input",
          summary = "Get the position of a device.",
          description = "Returns the current position of a device, in meters, relative to the play area.",
          key = "lovr.headset.getPosition",
          module = "lovr.headset",
          notes = "If the device isn't tracked, all zeroes will be returned.",
          related = {
            "lovr.headset.getPose",
            "lovr.headset.getOrientation",
            "lovr.headset.getVelocity",
            "lovr.headset.getAngularVelocity",
            "lovr.headset.isTracked",
            "lovr.headset.getDriver"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the position of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the device."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the device."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the device."
                }
              }
            }
          }
        },
        {
          name = "getRefreshRate",
          tag = "headset",
          summary = "Get the refresh rate of the headset display.",
          description = "Returns the refresh rate of the headset display, in Hz.",
          key = "lovr.headset.getRefreshRate",
          module = "lovr.headset",
          related = {
            "lovr.headset.getRefreshRates"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "rate",
                  type = "number | nil",
                  description = "The refresh rate of the display, or `nil` if I have no idea what it is."
                }
              }
            }
          }
        },
        {
          name = "getRefreshRates",
          tag = "headset",
          summary = "Get the list of refresh rates supported by the display.",
          description = "Returns a table with all the refresh rates supported by the headset display, in Hz.",
          key = "lovr.headset.getRefreshRates",
          module = "lovr.headset",
          related = {
            "lovr.headset.getRefreshRate",
            "lovr.headset.setRefreshRate"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "rates",
                  type = "table | nil",
                  description = "A flat table of the refresh rates supported by the headset display, or nil if not supported."
                }
              }
            }
          }
        },
        {
          name = "getSkeleton",
          tag = "input",
          summary = "Get skeletal joint transforms tracked by a device.",
          description = "Returns a list of joint transforms tracked by a device.  Currently, only hand devices are able to track joints.",
          key = "lovr.headset.getSkeleton",
          module = "lovr.headset",
          examples = {
            {
              code = "function lovr.draw(pass)\n  for _, hand in ipairs({ 'left', 'right' }) do\n    for _, joint in ipairs(lovr.headset.getSkeleton(hand) or {}) do\n      pass:points(unpack(joint, 1, 3))\n    end\n  end\nend"
            }
          },
          notes = "If the Device does not support tracking joints or the transforms are unavailable, this function returns `nil`.\n\nThe joint orientation is similar to the graphics coordinate system: -Z is the forwards direction, pointing towards the fingertips.  The +Y direction is \"up\", pointing out of the back of the hand.  The +X direction is to the right, perpendicular to X and Z.\n\nHere's a picture, courtesy of Khronos Group:\n\n![Hand Skeleton Joints](https://lovr.org/img/hand-skeleton.png)\n\nHand joints are returned in the following order:\n\n<table>\n  <thead>\n    <tr>\n      <td colspan=\"2\">Joint</td>\n      <td>Index</td>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <td colspan=\"2\">Palm</td>\n      <td>1</td>\n    </tr>\n    <tr>\n      <td colspan=\"2\">Wrist</td>\n      <td>2</td>\n    </tr>\n    <tr>\n      <td rowspan=\"4\">Thumb</td>\n      <td>Metacarpal</td>\n      <td>3</td>\n    </tr>\n    <tr>\n      <td>Proximal</td>\n      <td>4</td>\n    </tr>\n    <tr>\n      <td>Distal</td>\n      <td>5</td>\n    </tr>\n    <tr>\n      <td>Tip</td>\n      <td>6</td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">Index</td>\n      <td>Metacarpal</td>\n      <td>7</td>\n    </tr>\n    <tr>\n      <td>Proximal</td>\n      <td>8</td>\n    </tr>\n    <tr>\n      <td>Intermediate</td>\n      <td>9</td>\n    </tr>\n    <tr>\n      <td>Distal</td>\n      <td>10</td>\n    </tr>\n    <tr>\n      <td>Tip</td>\n      <td>11</td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">Middle</td>\n      <td>Metacarpal</td>\n      <td>12</td>\n    </tr>\n    <tr>\n      <td>Proximal</td>\n      <td>13</td>\n    </tr>\n    <tr>\n      <td>Intermediate</td>\n      <td>14</td>\n    </tr>\n    <tr>\n      <td>Distal</td>\n      <td>15</td>\n    </tr>\n    <tr>\n      <td>Tip</td>\n      <td>16</td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">Ring</td>\n      <td>Metacarpal</td>\n      <td>17</td>\n    </tr>\n    <tr>\n      <td>Proximal</td>\n      <td>18</td>\n    </tr>\n    <tr>\n      <td>Intermediate</td>\n      <td>19</td>\n    </tr>\n    <tr>\n      <td>Distal</td>\n      <td>20</td>\n    </tr>\n    <tr>\n      <td>Tip</td>\n      <td>21</td>\n    </tr>\n    <tr>\n      <td rowspan=\"5\">Pinky</td>\n      <td>Metacarpal</td>\n      <td>22</td>\n    </tr>\n    <tr>\n      <td>Proximal</td>\n      <td>23</td>\n    </tr>\n    <tr>\n      <td>Intermediate</td>\n      <td>24</td>\n    </tr>\n    <tr>\n      <td>Distal</td>\n      <td>25</td>\n    </tr>\n    <tr>\n      <td>Tip</td>\n      <td>26</td>\n    </tr>\n  </tbody> </table>",
          related = {
            "lovr.headset.getPose",
            "lovr.headset.animate"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The hand device to query (`left` or `right`)."
                }
              },
              returns = {
                {
                  name = "transforms",
                  type = "{{number}} | nil",
                  description = "A list of joint transforms for the device.  Each transform is a table with 3 numbers for the position of the joint, 1 number for the joint radius (in meters), and 4 numbers for the angle/axis orientation of the joint.  There is also a `radius` key with the radius of the joint as well."
                }
              }
            },
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The hand device to query (`left` or `right`)."
                },
                {
                  name = "t",
                  type = "table",
                  description = "A table to fill with the joint transforms, instead of allocating a new one."
                }
              },
              returns = {
                {
                  name = "transforms",
                  type = "{{number}} | nil",
                  description = "A list of joint transforms for the device.  Each transform is a table with 3 numbers for the position of the joint, 1 number for the joint radius (in meters), and 4 numbers for the angle/axis orientation of the joint.  There is also a `radius` key with the radius of the joint as well."
                }
              }
            }
          }
        },
        {
          name = "getTexture",
          tag = "headset-misc",
          summary = "Get the Texture for the headset display.",
          description = "Returns a Texture that will be submitted to the headset display.  This will be the render target used in the headset's render pass.  The texture is not guaranteed to be the same every frame, and must be called every frame to get the current texture.",
          key = "lovr.headset.getTexture",
          module = "lovr.headset",
          notes = "This function may return `nil` if the headset is not being rendered to this frame.",
          related = {
            "lovr.headset.getPass",
            "lovr.mirror"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "texture",
                  type = "Texture | nil",
                  description = "The headset texture."
                }
              }
            }
          }
        },
        {
          name = "getTime",
          tag = "headset-misc",
          summary = "Get the predicted display time.",
          description = "Returns the estimated time in the future at which the light from the pixels of the current frame will hit the eyes of the user.\n\nThis can be used as a replacement for `lovr.timer.getTime` for timestamps that are used for rendering to get a smoother result that is synchronized with the display of the headset.",
          key = "lovr.headset.getTime",
          module = "lovr.headset",
          notes = "This has a different epoch than `lovr.timer.getTime`, so it is not guaranteed to be close to that value.",
          related = {
            "lovr.headset.getDeltaTime",
            "lovr.timer.getTime"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "time",
                  type = "number",
                  description = "The predicted display time, in seconds."
                }
              }
            }
          }
        },
        {
          name = "getVelocity",
          tag = "input",
          summary = "Get the linear velocity of a device.",
          description = "Returns the current linear velocity of a device, in meters per second.",
          key = "lovr.headset.getVelocity",
          module = "lovr.headset",
          notes = "If the device isn't tracked, all zeroes will be returned.",
          related = {
            "lovr.headset.getAngularVelocity",
            "lovr.headset.getPose",
            "lovr.headset.getPosition",
            "lovr.headset.getOrientation"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the velocity of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "vx",
                  type = "number",
                  description = "The x component of the linear velocity."
                },
                {
                  name = "vy",
                  type = "number",
                  description = "The y component of the linear velocity."
                },
                {
                  name = "vz",
                  type = "number",
                  description = "The z component of the linear velocity."
                }
              }
            }
          }
        },
        {
          name = "getViewAngles",
          tag = "headset",
          summary = "Get the field of view angles of a view.",
          description = "Returns the view angles of one of the headset views.\n\nThese can be used with `Mat4:fov` to create a projection matrix.\n\nIf tracking data is unavailable for the view or the index is invalid, `nil` is returned.",
          key = "lovr.headset.getViewAngles",
          module = "lovr.headset",
          related = {
            "lovr.headset.getViewCount",
            "lovr.headset.getViewPose"
          },
          variants = {
            {
              arguments = {
                {
                  name = "view",
                  type = "number",
                  description = "The view index."
                }
              },
              returns = {
                {
                  name = "left",
                  type = "number | nil",
                  description = "The left view angle, in radians."
                },
                {
                  name = "right",
                  type = "number | nil",
                  description = "The right view angle, in radians."
                },
                {
                  name = "top",
                  type = "number | nil",
                  description = "The top view angle, in radians."
                },
                {
                  name = "bottom",
                  type = "number | nil",
                  description = "The bottom view angle, in radians."
                }
              }
            }
          }
        },
        {
          name = "getViewCount",
          tag = "headset",
          summary = "Get the number of views used for rendering.",
          description = "Returns the number of views used for rendering.  Each view consists of a pose in space and a set of angle values that determine the field of view.\n\nThis is usually 2 for stereo rendering configurations, but it can also be different.  For example, one way of doing foveated rendering uses 2 views for each eye -- one low quality view with a wider field of view, and a high quality view with a narrower field of view.",
          key = "lovr.headset.getViewCount",
          module = "lovr.headset",
          related = {
            "lovr.headset.getViewPose",
            "lovr.headset.getViewAngles"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "count",
                  type = "number",
                  description = "The number of views."
                }
              }
            }
          }
        },
        {
          name = "getViewPose",
          tag = "headset",
          summary = "Get the pose of one of the views.",
          description = "Returns the pose of one of the headset views.  This info can be used to create view matrices or do other eye-dependent calculations.\n\nIf tracking data is unavailable for the view or the index is invalid, `nil` is returned.",
          key = "lovr.headset.getViewPose",
          module = "lovr.headset",
          related = {
            "lovr.headset.getViewCount",
            "lovr.headset.getViewAngles"
          },
          variants = {
            {
              arguments = {
                {
                  name = "view",
                  type = "number",
                  description = "The view index."
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number | nil",
                  description = "The x coordinate of the view position, in meters."
                },
                {
                  name = "y",
                  type = "number | nil",
                  description = "The y coordinate of the view position, in meters."
                },
                {
                  name = "z",
                  type = "number | nil",
                  description = "The z coordinate of the view position, in meters."
                },
                {
                  name = "angle",
                  type = "number | nil",
                  description = "The amount of rotation around the rotation axis, in radians."
                },
                {
                  name = "ax",
                  type = "number | nil",
                  description = "The x component of the axis of rotation."
                },
                {
                  name = "ay",
                  type = "number | nil",
                  description = "The y component of the axis of rotation."
                },
                {
                  name = "az",
                  type = "number | nil",
                  description = "The z component of the axis of rotation."
                }
              }
            }
          }
        },
        {
          name = "isActive",
          tag = "headset-misc",
          summary = "Check if the headset session is active.",
          description = "Returns whether a headset session is active.  When true, there is an active connection to the VR hardware.  When false, most headset methods will not work properly until `lovr.headset.start` is used to start a session.",
          key = "lovr.headset.isActive",
          module = "lovr.headset",
          related = {
            "lovr.headset.start",
            "lovr.headset.stop"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "active",
                  type = "boolean",
                  description = "Whether the headset session is active."
                }
              }
            }
          }
        },
        {
          name = "isDown",
          tag = "input",
          summary = "Get the state of a button on a device.",
          description = "Returns whether a button on a device is pressed.",
          key = "lovr.headset.isDown",
          module = "lovr.headset",
          notes = "When hand tracking is active, pinching will be mapped to the `trigger` button.",
          related = {
            "DeviceButton",
            "lovr.headset.wasPressed",
            "lovr.headset.wasReleased",
            "lovr.headset.isTouched",
            "lovr.headset.getAxis"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device."
                },
                {
                  name = "button",
                  type = "DeviceButton",
                  description = "The button."
                }
              },
              returns = {
                {
                  name = "down",
                  type = "boolean | nil",
                  description = "Whether the button on the device is currently pressed, or `nil` if the device does not have the specified button."
                }
              }
            }
          }
        },
        {
          name = "isFocused",
          tag = "headset-misc",
          summary = "Check if LÖVR has VR input focus.",
          description = "Returns whether LÖVR has VR input focus.  Focus is lost when the VR system menu is shown.  The `lovr.focus` callback can be used to detect when this changes.",
          key = "lovr.headset.isFocused",
          module = "lovr.headset",
          related = {
            "lovr.focus"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "focused",
                  type = "boolean",
                  description = "Whether the application is focused."
                }
              }
            }
          }
        },
        {
          name = "isMounted",
          tag = "headset-misc",
          summary = "Check if the headset is \"mounted\" (worn on a head).",
          description = "Returns whether the headset is mounted.  Usually this uses a proximity sensor on the headset to detect whether someone is wearing the headset.",
          key = "lovr.headset.isMounted",
          module = "lovr.headset",
          related = {
            "lovr.mount",
            "lovr.headset.isFocused",
            "lovr.headset.isVisible"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "mounted",
                  type = "boolean",
                  description = "Whether the headset is mounted."
                }
              }
            }
          }
        },
        {
          name = "isSeated",
          tag = "playArea",
          summary = "Check if the coordinate space is standing or seated.",
          description = "Returns whether the headset coordinate space is in seated mode.\n\nSeated mode is enabled by setting `t.headset.seated` to true in `lovr.conf`.  In seated mode, `y=0` will be at eye level, instead of on the floor like in standing-scale experiences.\n\nThe seated coordinate space can be more convenient for applications that are rendering a simple interface in front of the user (like a video player) instead of a roomscale 3D scene.  y=0 will also be at the correct height at startup, whether the user is sitting or standing.",
          key = "lovr.headset.isSeated",
          module = "lovr.headset",
          related = {
            "lovr.conf",
            "lovr.recenter"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "seated",
                  type = "boolean",
                  description = "Whether the experience is seated."
                }
              }
            }
          }
        },
        {
          name = "isTouched",
          tag = "input",
          summary = "Check if a button on a device is touched.",
          description = "Returns whether a button on a device is currently touched.",
          key = "lovr.headset.isTouched",
          module = "lovr.headset",
          related = {
            "DeviceButton",
            "lovr.headset.isDown",
            "lovr.headset.getAxis"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device."
                },
                {
                  name = "button",
                  type = "DeviceButton",
                  description = "The button."
                }
              },
              returns = {
                {
                  name = "touched",
                  type = "boolean | nil",
                  description = "Whether the button on the device is currently touched, or `nil` if the device does not have the button or it isn't touch-sensitive."
                }
              }
            }
          }
        },
        {
          name = "isTracked",
          tag = "input",
          summary = "Check if a device is currently tracked.",
          description = "Returns whether any active headset driver is currently returning pose information for a device.",
          key = "lovr.headset.isTracked",
          module = "lovr.headset",
          notes = "If a device is tracked, it is guaranteed to return a valid pose until the next call to `lovr.headset.update`.",
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to get the pose of.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "tracked",
                  type = "boolean",
                  description = "Whether the device is currently tracked."
                }
              }
            }
          }
        },
        {
          name = "isVisible",
          tag = "headset-misc",
          summary = "Check if content is being shown in the headset display.",
          description = "Returns whether LÖVR's content is being presented to the headset display.  Normally this will be true, but some VR runtimes allow applications to be hidden or \"minimized\", similar to desktop windows.",
          key = "lovr.headset.isVisible",
          module = "lovr.headset",
          notes = "`lovr.draw` may still be called even when the application is invisible, and apps should continue to render the scene normally because the VR system may use this for timing info.  If the VR system decides that the application no longer needs to render, LÖVR will stop calling `lovr.draw`.",
          related = {
            "lovr.visible",
            "lovr.headset.isFocused",
            "lovr.focus"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "visible",
                  type = "boolean",
                  description = "Whether the application is visible."
                }
              }
            }
          }
        },
        {
          name = "newLayer",
          tag = "layers",
          summary = "Create a new Layer.",
          description = "Creates a new `Layer`.",
          key = "lovr.headset.newLayer",
          module = "lovr.headset",
          related = {
            "lovr.headset.getLayers",
            "lovr.headset.setLayers"
          },
          variants = {
            {
              arguments = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the Layer texture, in pixels."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the Layer texture, in pixels."
                }
              },
              returns = {
                {
                  name = "layer",
                  type = "Layer",
                  description = "The new Layer."
                }
              }
            }
          }
        },
        {
          name = "newModel",
          tag = "controller-models",
          summary = "Load a model for an active device.",
          description = "Loads a new Model object for the specified model key.\n\nModel keys are lightuserdata values that act as an ID for a specific model.  Use `lovr.headset.getModelKeys` to retrieve a list of model keys for the currently connected hardware.\n\nIt is recommended to refresh the list of model keys in the `lovr.modelschanged` event, which gets fired whenever the list of keys changes.  `lovr.modelschanged` is also fired once at startup when the models are ready to load.  In the callback, you can get the new list of model keys and load models for any keys that haven't been loaded yet.\n\nThere isn't any correspondence between a model key and a `Device`, because there could be multiple models for a device, or some models that do not correspond to a device at all.  For example, the hand device could have a model for a controller, a wrist tracker, or a hand mesh.\n\nOnce a model is loaded, call `lovr.headset.isTracked` with the model to check if it should be visible, and `lovr.headset.getPose` to get the position and orientation to draw the model at.\n\nTo reposition the nodes in the model to match the current state of the buttons, joysticks, etc., call `lovr.headset.animate` with the model.",
          key = "lovr.headset.newModel",
          module = "lovr.headset",
          examples = {
            {
              code = "local models = {}\n\nfunction lovr.draw(pass)\n  for k, model in pairs(models) do\n    if lovr.headset.isTracked(model) then\n      lovr.headset.animate(model)\n\n      local x, y, z, angle, ax, ay, az = lovr.headset.getPose(model)\n      pass:draw(model, x, y, z, 1, angle, ax, ay, az)\n    end\n  end\nend\n\nfunction lovr.modelschanged()\n  local newModels = {}\n\n  for i, key in ipairs(lovr.headset.getModelKeys()) do\n    newModels[key] = models[key] or lovr.headset.newModel(key)\n  end\n\n  models = newModels\nend"
            }
          },
          related = {
            "lovr.headset.animate",
            "lovr.headset.isTracked",
            "lovr.modelschanged",
            "lovr.graphics.newModel"
          },
          variants = {
            {
              arguments = {
                {
                  name = "key",
                  type = "lightuserdata",
                  description = "A model key to load, previously obtained with `lovr.headset.getModelKeys`."
                }
              },
              returns = {
                {
                  name = "model",
                  type = "Model",
                  description = "The new Model, or `nil` if a model could not be loaded."
                }
              }
            },
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to load a model for.",
                  default = "'head'"
                }
              },
              returns = {
                {
                  name = "model",
                  type = "Model",
                  description = "The new Model, or `nil` if a model could not be loaded."
                }
              },
              deprecated = true
            }
          }
        },
        {
          name = "setBackground",
          tag = "layers",
          summary = "Set the background layer.",
          description = "Sets a background layer.  This will render behind any transparent pixels in the main 3D content. It works similarly to other `Layer` objects, but using a cubemap or equirectangular texture.\n\nThe background texture is sent to the VR runtime once, and the runtime is responsible for compositing it behind the rest of the scene.  This can improve performance greatly, since the background doesn't need to be re-rendered every frame.  It also ensures the background remains tracked smoothly even if LÖVR is struggling to render at a high frame rate.",
          key = "lovr.headset.setBackground",
          module = "lovr.headset",
          notes = "There is no `lovr.headset.getBackground` because LÖVR does not store the Image or Texture after setting it as a background, to save memory.",
          related = {
            "Layer",
            "Pass:skybox"
          },
          variants = {
            {
              arguments = {
                {
                  name = "background",
                  type = "Image | {Image} | Texture",
                  description = "The image(s) or texture to use for the background.  Backgrounds can either be cubemaps (6 images) or equirectangular (a single panoramic 2D image).\n\nTextures can have any color format, but it will be converted to `rgba8` before getting copied to the VR runtime.  Images currently have to be `rgba8`."
                }
              },
              returns = {}
            },
            {
              description = "Disables any previously set background.",
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "setClipDistance",
          tag = "headset",
          summary = "Set the near and far clipping planes of the headset.",
          description = "Sets the near and far clipping planes used to render to the headset.  Objects closer than the near clipping plane or further than the far clipping plane will be clipped out of view.",
          key = "lovr.headset.setClipDistance",
          module = "lovr.headset",
          notes = "The default clip distances are 0.01 and 0.0.",
          variants = {
            {
              arguments = {
                {
                  name = "near",
                  type = "number",
                  description = "The distance to the near clipping plane, in meters."
                },
                {
                  name = "far",
                  type = "number",
                  description = "The distance to the far clipping plane, in meters, or 0 for an infinite far clipping plane with a reversed Z range."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setFoveation",
          tag = "headset",
          summary = "Set foveated rendering settings.",
          description = "Sets foveated rendering settings.  Currently only fixed foveated rendering is supported.  This renders the edges of the screen at a lower resolution to improve GPU performance.  Higher foveation levels will save more GPU time, but make the edges of the screen more blocky.",
          key = "lovr.headset.setFoveation",
          module = "lovr.headset",
          notes = "Foveation is disabled by default.",
          variants = {
            {
              arguments = {
                {
                  name = "level",
                  type = "FoveationLevel",
                  description = "The foveation level (or the maximum level when dynamic foveation is active)."
                },
                {
                  name = "dynamic",
                  type = "boolean",
                  description = "Whether the system is allowed to dynamically adjust the foveation level based on GPU load.",
                  default = "true"
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether foveation was enabled successfully."
                }
              }
            },
            {
              description = "Disables foveation.",
              arguments = {},
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether foveation was enabled successfully."
                }
              }
            }
          }
        },
        {
          name = "setLayers",
          tag = "layers",
          summary = "Set the list of active layers.",
          description = "Sets the list of active `Layer` objects.  These are the layers that will be rendered in the headset's display.  They are rendered in order.",
          key = "lovr.headset.setLayers",
          module = "lovr.headset",
          notes = "Currently some VR systems are able to sort the layers by their Z depth, but on others layers later in the list will render on top of previous layers, regardless of depth.\n\nThere is currently a maximum of 10 layers.",
          related = {
            "lovr.headset.newLayer",
            "Layer"
          },
          variants = {
            {
              arguments = {
                {
                  name = "...layers",
                  type = "Layer",
                  description = "Zero or more layers to render in the headset."
                }
              },
              returns = {}
            },
            {
              arguments = {
                {
                  name = "t",
                  type = "table",
                  description = "A table with zero or more layers starting at index 1."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setPassthrough",
          tag = "headset",
          summary = "Change current passthrough mode.",
          description = "Sets a new passthrough mode.  Not all headsets support all passthrough modes.  Use `lovr.headset.getPassthroughModes` to see which modes are supported.",
          key = "lovr.headset.setPassthrough",
          module = "lovr.headset",
          notes = "When using one of the transparent passthrough modes, be sure to set the alpha of the background color to zero using `lovr.graphics.setBackgroundColor`, so the background shows through.\n\nQuest Link currently requires some extra steps to enable passthrough, see [this article](https://developers.meta.com/horizon/documentation/native/android/mobile-passthrough-over-link) for details.",
          related = {
            "lovr.headset.getPassthroughModes"
          },
          variants = {
            {
              arguments = {
                {
                  name = "mode",
                  type = "PassthroughMode",
                  description = "The passthrough mode to request."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the passthrough mode was supported and successfully enabled."
                }
              }
            },
            {
              arguments = {
                {
                  name = "transparent",
                  type = "boolean",
                  description = "Whether the headset should use a transparent passthrough mode.  When false, this will request the `opaque` mode.  When true, either `blend` or `add` will be requested, based on what the VR runtime supports."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the passthrough mode was supported and successfully enabled."
                }
              }
            },
            {
              description = "Switch to the headset's default passthrough mode.",
              arguments = {},
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the passthrough mode was supported and successfully enabled."
                }
              }
            }
          }
        },
        {
          name = "setRefreshRate",
          tag = "headset",
          summary = "Set the display refresh rate.",
          description = "Sets the display refresh rate, in Hz.",
          key = "lovr.headset.setRefreshRate",
          module = "lovr.headset",
          notes = "Changing the display refresh-rate usually also changes the frequency of lovr.update() and lovr.draw() as they depend on the refresh rate.  However, it's ultimately up to the VR runtime to decide how often the application gets to render, based on available resources.",
          related = {
            "lovr.headset.getRefreshRates"
          },
          variants = {
            {
              arguments = {
                {
                  name = "rate",
                  type = "number",
                  description = "The new refresh rate, in Hz."
                }
              },
              returns = {
                {
                  name = "success",
                  type = "boolean",
                  description = "Whether the display refresh rate was successfully set."
                }
              }
            }
          }
        },
        {
          name = "start",
          tag = "headset-misc",
          summary = "Starts the headset session.",
          description = "Starts the headset session.  This must be called after the graphics module is initialized. Normally it is called automatically by `boot.lua`, but this can be disabled by setting `t.headset.start` to false in `lovr.conf`.",
          key = "lovr.headset.start",
          module = "lovr.headset",
          related = {
            "lovr.headset.stop",
            "lovr.headset.isActive"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "stop",
          tag = "headset-misc",
          summary = "Stop the headset session.",
          description = "Stops the headset session.  This tears down the connection to the VR runtime and hardware. `lovr.draw` will instead start rendering to the desktop window, as though the headset module was disabled.  However, certain information about the headset can still be queried, such as its name, supported passthrough modes, display size, etc.  A headset session can be started later using `lovr.headset.start`.",
          key = "lovr.headset.stop",
          module = "lovr.headset",
          notes = "The headset module behaves in the following manner when there is no headset session:\n\n- `lovr.headset.isActive` returns `false`.\n- `lovr.headset.getPass` returns `nil`.\n- All devices will be untracked.",
          related = {
            "lovr.headset.start",
            "lovr.headset.isActive"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "stopVibration",
          tag = "input",
          summary = "Stop vibration on a device.",
          description = "Causes the device to stop any active haptics vibration.",
          key = "lovr.headset.stopVibration",
          module = "lovr.headset",
          related = {
            "lovr.headset.vibrate"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to stop the vibration on.",
                  default = "'head'"
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "submit",
          tag = "headset-misc",
          summary = "Submit a frame to the headset display.",
          description = "Submits the current headset texture to the VR display.  This should be called after calling `lovr.graphics.submit` with the headset render pass.  Normally this is taken care of by `lovr.run`.",
          key = "lovr.headset.submit",
          module = "lovr.headset",
          related = {
            "lovr.headset.getPass",
            "lovr.headset.getTexture"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "update",
          tag = "headset-misc",
          summary = "Update the headset module.",
          description = "Updates the headset module, blocking until it is time to start a new frame and polling new input states.  This should only be called once at the beginning of a frame, and is normally taken care of by the default `lovr.run` implementation.",
          key = "lovr.headset.update",
          module = "lovr.headset",
          related = {
            "lovr.headset.submit",
            "lovr.run"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "vibrate",
          tag = "input",
          summary = "Make a device go BZZZ!",
          description = "Causes the device to vibrate with a custom strength, duration, and frequency, if possible.",
          key = "lovr.headset.vibrate",
          module = "lovr.headset",
          related = {
            "lovr.headset.stopVibration"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device to vibrate.",
                  default = "'head'"
                },
                {
                  name = "strength",
                  type = "number",
                  description = "The strength of the vibration (amplitude), between 0 and 1.",
                  default = "1"
                },
                {
                  name = "duration",
                  type = "number",
                  description = "The duration of the vibration, in seconds.",
                  default = ".5"
                },
                {
                  name = "frequency",
                  type = "number",
                  description = "The frequency of the vibration, in hertz.  0 will use a default frequency.",
                  default = "0"
                }
              },
              returns = {
                {
                  name = "vibrated",
                  type = "boolean",
                  description = "Whether the vibration was successfully triggered by an active headset driver."
                }
              }
            }
          }
        },
        {
          name = "wasPressed",
          tag = "input",
          summary = "Check if a button was just pressed.",
          description = "Returns whether a button on a device was pressed this frame.",
          key = "lovr.headset.wasPressed",
          module = "lovr.headset",
          notes = "The internal `lovr.headset.update` function updates pressed/released status.",
          related = {
            "DeviceButton",
            "lovr.headset.isDown",
            "lovr.headset.wasReleased",
            "lovr.headset.isTouched",
            "lovr.headset.getAxis"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device."
                },
                {
                  name = "button",
                  type = "DeviceButton",
                  description = "The button to check."
                }
              },
              returns = {
                {
                  name = "pressed",
                  type = "boolean",
                  description = "Whether the button on the device was pressed this frame."
                }
              }
            }
          }
        },
        {
          name = "wasReleased",
          tag = "input",
          summary = "Check if a button was just released.",
          description = "Returns whether a button on a device was released this frame.",
          key = "lovr.headset.wasReleased",
          module = "lovr.headset",
          notes = "Some headset backends are not able to return pressed/released information.  These drivers will always return false for `lovr.headset.wasPressed` and `lovr.headset.wasReleased`.\n\nTypically the internal `lovr.headset.update` function will update pressed/released status.",
          related = {
            "DeviceButton",
            "lovr.headset.isDown",
            "lovr.headset.wasPressed",
            "lovr.headset.isTouched",
            "lovr.headset.getAxis"
          },
          variants = {
            {
              arguments = {
                {
                  name = "device",
                  type = "Device",
                  description = "The device."
                },
                {
                  name = "button",
                  type = "DeviceButton",
                  description = "The button to check."
                }
              },
              returns = {
                {
                  name = "released",
                  type = "boolean",
                  description = "Whether the button on the device was released this frame."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Layer",
          summary = "A quad in 3D space.",
          description = "A Layer is a textured plane placed in 3D space.  Layers are sent directly to the VR runtime and composited along with the rest of the 3D content.  This has several advantages compared to rendering the texture into the 3D scene with `Pass:draw`:\n\n- Better tracking.  The VR runtime composites the texture later in the rendering process, using a more accurate head pose.\n- Better resolution, less shimmery.  Regular 3D content must have lens distortion correction\n  applied to it, whereas layers are composited after distortion correction, meaning they have a\n  higher pixel density.  The layer can also use a higher resolution than the main headset\n  texture, allowing for extra resolution on the 2D content without having to supersample all of\n  the 3D rendering.\n- Supersampling and sharpening effects.  Some headset runtimes (currently just Quest) can also\n  supersample and sharpen layers.\n\nCombined, all of this makes a massive difference in quality when rendering 2D content on a Layer, especially improving text readability.\n\nNote that currently the VR simulator does not support layers.",
          key = "Layer",
          module = "lovr.headset",
          constructors = {
            "lovr.headset.newLayer"
          },
          extends = "Object",
          methods = {
            {
              name = "getColor",
              summary = "Get the color of the layer.",
              description = "Returns the color of the layer.  This will tint the contents of its texture.  It can be used to fade the layer without re-rendering its texture, which is especially useful for layers created with the `static` option.",
              key = "Layer:getColor",
              module = "lovr.headset",
              notes = "The default color is white (all 1s).\n\nNot every headset system supports layer colors.  See the `layerColor` property of `lovr.headset.getFeatures` to check for support.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the color."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the color."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the color."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the color."
                    }
                  }
                }
              }
            },
            {
              name = "getCurve",
              summary = "Get the curve of the layer.",
              description = "Returns the curve of the layer.  Curving a layer renders it on a piece of a cylinder instead of a plane. The radius of the cylinder is `1 / curve` meters, so increasing the curve decreases the radius of the cylinder.",
              key = "Layer:getCurve",
              module = "lovr.headset",
              notes = "When a layer is created, its curve is zero.\n\nNot every headset system supports curved layers.  See the `layerCurve` property of `lovr.headset.getFeatures` to check for support.\n\nNo matter what the curve is, the center of the layer texture will always get rendered at the layer's pose.\n\nThe largest possible curve is `2 * math.pi / width`, where `width` is the width of the layer in meters.  This would cause the cylinder to fully wrap around.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "curve",
                      type = "number",
                      description = "The curve of the layer."
                    }
                  }
                }
              }
            },
            {
              name = "getDimensions",
              summary = "Get the size of the layer.",
              description = "Returns the width and height of the layer.  This is the size of the Layer's plane in meters, not the resolution of the layer's texture in pixels.",
              key = "Layer:getDimensions",
              module = "lovr.headset",
              notes = "When a layer is created, its width and height are 1 meter.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the layer, in meters."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the layer, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getOrientation",
              summary = "Get the orientation of the layer.",
              description = "Returns the orientation of the layer.",
              key = "Layer:getOrientation",
              module = "lovr.headset",
              related = {
                "Layer:getPosition",
                "Layer:setPosition",
                "Layer:getPose",
                "Layer:setPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount of rotation around the axis of rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPass",
              summary = "Get the render pass for the layer.",
              description = "Returns the render pass for the layer.  This can be used to render to the layer.",
              key = "Layer:getPass",
              module = "lovr.headset",
              notes = "This function will reset the Layer's render pass when it is called, as though `Pass:reset` was called.\n\nThe Pass will have its background color cleared to the background color, set using `lovr.graphics.setBackgroundColor`.\n\nThe Pass will have its view matrix set to the origin, and its projection will be set to an orthographic matrix where the top left of the texture is at the origin and the bottom right of the texture will be at `(width, height)` in pixels.",
              related = {
                "Layer:getTexture"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "pass",
                      type = "Pass",
                      description = "The layer's render pass."
                    }
                  }
                }
              }
            },
            {
              name = "getPose",
              summary = "Get the pose of the layer.",
              description = "Returns the position and orientation of the layer.",
              key = "Layer:getPose",
              module = "lovr.headset",
              notes = "Units are in meters.",
              related = {
                "Layer:getPosition",
                "Layer:setPosition",
                "Layer:getOrientation",
                "Layer:setOrientation"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount of rotation around the axis of rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              summary = "Get the position of the layer.",
              description = "Returns the position of the layer, in meters.",
              key = "Layer:getPosition",
              module = "lovr.headset",
              related = {
                "Layer:getOrientation",
                "Layer:setOrientation",
                "Layer:getPose",
                "Layer:setPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the layer."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the layer."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the layer."
                    }
                  }
                }
              }
            },
            {
              name = "getTexture",
              summary = "Get the texture for the layer.",
              description = "Returns the texture for the layer.  This is the texture that will be pasted onto the layer.",
              key = "Layer:getTexture",
              module = "lovr.headset",
              notes = "This function may return a different `Texture` object each frame.  The return value should not be cached.\n\nThe texture will have the `rgba8` format, with `sample` and `render` usage flags.",
              related = {
                "Layer:getPass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "texture",
                      type = "Texture",
                      description = "The layer's texture."
                    }
                  }
                }
              }
            },
            {
              name = "getViewport",
              summary = "Get the viewport of the layer.",
              description = "Returns the viewport of the layer.  The viewport is a 2D region of pixels that the layer will display within its plane.",
              key = "Layer:getViewport",
              module = "lovr.headset",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The width of the viewport, in pixels."
                    },
                    {
                      name = "h",
                      type = "number",
                      description = "The height of the viewport, in pixels."
                    }
                  }
                }
              }
            },
            {
              name = "setColor",
              summary = "Set the color of the layer.",
              description = "Sets the color of the layer.  This will tint the contents of its texture.  It can be used to fade the layer without re-rendering its texture, which is especially useful for layers created with the `static` option.",
              key = "Layer:setColor",
              module = "lovr.headset",
              notes = "The default color is white (all 1s).\n\nNot every headset system supports layer colors.  See the `layerColor` property of `lovr.headset.getFeatures` to check for support.",
              variants = {
                {
                  arguments = {
                    {
                      name = "r",
                      type = "number",
                      description = "The red component of the color."
                    },
                    {
                      name = "g",
                      type = "number",
                      description = "The green component of the color."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The blue component of the color."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the color.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A table of 3 or 4 color components."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "hex",
                      type = "number",
                      description = "A hexcode."
                    },
                    {
                      name = "a",
                      type = "number",
                      description = "The alpha component of the color.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setCurve",
              summary = "Set the curve of the layer.",
              description = "Sets the curve of the layer.  Curving a layer renders it on a piece of a cylinder instead of a plane. The radius of the cylinder is `1 / curve` meters, so increasing the curve decreases the radius of the cylinder.",
              key = "Layer:setCurve",
              module = "lovr.headset",
              notes = "When a layer is created, its curve is zero.\n\nNot every headset system supports curved layers.  See the `layerCurve` property of `lovr.headset.getFeatures` to check for support.  If curved layers are not supported, this function will do nothing.\n\nNo matter what the curve is, the center of the layer texture will always get rendered at the layer's pose.\n\nThe largest possible curve is `2 * math.pi / width`, where `width` is the width of the layer in meters.  This would cause the cylinder to fully wrap around.",
              variants = {
                {
                  arguments = {
                    {
                      name = "curve",
                      type = "number",
                      description = "The curve of the layer.  Negative values or zero means no curve.",
                      default = "0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDimensions",
              summary = "Set the size of the layer.",
              description = "Sets the width and height of the layer.  This is the size of the Layer's plane in meters, not not the resolution of the layer's texture in pixels.",
              key = "Layer:setDimensions",
              module = "lovr.headset",
              notes = "When a layer is created, its width and height are 1 meter.",
              variants = {
                {
                  arguments = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the layer, in meters."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the layer, in meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setOrientation",
              summary = "Set the orientation of the layer.",
              description = "Sets the orientation of the layer.",
              key = "Layer:setOrientation",
              module = "lovr.headset",
              related = {
                "Layer:getPosition",
                "Layer:setPosition",
                "Layer:getPose",
                "Layer:setPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount of rotation around the axis of rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the layer."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPose",
              summary = "Set the pose of the layer.",
              description = "Sets the position and orientation of the layer.",
              key = "Layer:setPose",
              module = "lovr.headset",
              notes = "Units are in meters.",
              related = {
                "Layer:getPosition",
                "Layer:setPosition",
                "Layer:getOrientation",
                "Layer:setOrientation"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The amount of rotation around the axis of rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the layer."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the layer."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPosition",
              summary = "Set the position of the layer.",
              description = "Sets the position of the layer, in meters.",
              key = "Layer:setPosition",
              module = "lovr.headset",
              related = {
                "Layer:getOrientation",
                "Layer:setOrientation",
                "Layer:getPose",
                "Layer:setPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the layer."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the layer."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the layer."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setViewport",
              summary = "Set the viewport of the layer.",
              description = "Sets the viewport of the layer.  The viewport is a 2D region of pixels that the layer will display within its plane.",
              key = "Layer:setViewport",
              module = "lovr.headset",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the upper-left corner of the viewport."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The width of the viewport, in pixels."
                    },
                    {
                      name = "h",
                      type = "number",
                      description = "The height of the viewport, in pixels."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        }
      },
      sections = {
        {
          name = "Input",
          tag = "input",
          description = "Functions for accessing input devices, like controllers, hands, trackers, or gamepads."
        },
        {
          name = "Controller Models",
          tag = "controller-models"
        },
        {
          name = "Display",
          tag = "headset",
          description = "Functions that return information about the active head mounted display (HMD)."
        },
        {
          name = "Play area",
          tag = "playArea",
          description = "Retrieve information about the size and shape of the room the player is in, and provides information about the \"chaperone\", a visual indicator that appears whenever a player is about to run into a wall."
        },
        {
          name = "Layers",
          tag = "layers",
          description = "Layers are 2D textured quads that can be placed in 3D space.  They are higher quality than rendering regular planes in the 3D scene."
        },
        {
          name = "Miscellaneous",
          tag = "headset-misc",
          description = "Functions that are internal or return information about the VR session."
        }
      }
    },
    {
      name = "math",
      tag = "modules",
      summary = "Contains useful math helpers.",
      description = "The `lovr.math` module provides math helpers commonly used for 3D applications.",
      key = "lovr.math",
      enums = {},
      functions = {
        {
          name = "drain",
          tag = "vectors",
          summary = "Drain the temporary vector pool.",
          description = "Drains the temporary vector pool, invalidating existing temporary vectors.\n\nThis is called automatically at the end of each frame.",
          key = "lovr.math.drain",
          module = "lovr.math",
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "gammaToLinear",
          tag = "mathOther",
          summary = "Convert a color from gamma space to linear space.",
          description = "Converts a color from gamma space to linear space.",
          key = "lovr.math.gammaToLinear",
          module = "lovr.math",
          related = {
            "lovr.math.linearToGamma"
          },
          variants = {
            {
              arguments = {
                {
                  name = "gr",
                  type = "number",
                  description = "The red component of the gamma-space color."
                },
                {
                  name = "gg",
                  type = "number",
                  description = "The green component of the gamma-space color."
                },
                {
                  name = "gb",
                  type = "number",
                  description = "The blue component of the gamma-space color."
                }
              },
              returns = {
                {
                  name = "lr",
                  type = "number",
                  description = "The red component of the resulting linear-space color."
                },
                {
                  name = "lg",
                  type = "number",
                  description = "The green component of the resulting linear-space color."
                },
                {
                  name = "lb",
                  type = "number",
                  description = "The blue component of the resulting linear-space color."
                }
              }
            },
            {
              description = "A table can also be used.",
              arguments = {
                {
                  name = "color",
                  type = "{number}",
                  description = "A table containing the components of a gamma-space color."
                }
              },
              returns = {
                {
                  name = "lr",
                  type = "number",
                  description = "The red component of the resulting linear-space color."
                },
                {
                  name = "lg",
                  type = "number",
                  description = "The green component of the resulting linear-space color."
                },
                {
                  name = "lb",
                  type = "number",
                  description = "The blue component of the resulting linear-space color."
                }
              }
            },
            {
              description = "Convert a single color channel.",
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The color channel to convert."
                }
              },
              returns = {
                {
                  name = "y",
                  type = "number",
                  description = "The converted color channel."
                }
              }
            }
          }
        },
        {
          name = "getRandomSeed",
          tag = "random",
          summary = "Get the random seed.",
          description = "Get the seed used to initialize the random generator.",
          key = "lovr.math.getRandomSeed",
          module = "lovr.math",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "seed",
                  type = "number",
                  description = "The new seed."
                }
              }
            }
          }
        },
        {
          name = "linearToGamma",
          tag = "mathOther",
          summary = "Convert a color from linear space to gamma space.",
          description = "Converts a color from linear space to gamma space.",
          key = "lovr.math.linearToGamma",
          module = "lovr.math",
          related = {
            "lovr.math.gammaToLinear"
          },
          variants = {
            {
              arguments = {
                {
                  name = "lr",
                  type = "number",
                  description = "The red component of the linear-space color."
                },
                {
                  name = "lg",
                  type = "number",
                  description = "The green component of the linear-space color."
                },
                {
                  name = "lb",
                  type = "number",
                  description = "The blue component of the linear-space color."
                }
              },
              returns = {
                {
                  name = "gr",
                  type = "number",
                  description = "The red component of the resulting gamma-space color."
                },
                {
                  name = "gg",
                  type = "number",
                  description = "The green component of the resulting gamma-space color."
                },
                {
                  name = "gb",
                  type = "number",
                  description = "The blue component of the resulting gamma-space color."
                }
              }
            },
            {
              description = "A table can also be used.",
              arguments = {
                {
                  name = "color",
                  type = "{number}",
                  description = "A table containing the components of a linear-space color."
                }
              },
              returns = {
                {
                  name = "gr",
                  type = "number",
                  description = "The red component of the resulting gamma-space color."
                },
                {
                  name = "gg",
                  type = "number",
                  description = "The green component of the resulting gamma-space color."
                },
                {
                  name = "gb",
                  type = "number",
                  description = "The blue component of the resulting gamma-space color."
                }
              }
            },
            {
              description = "Convert a single color channel.",
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The color channel to convert."
                }
              },
              returns = {
                {
                  name = "y",
                  type = "number",
                  description = "The converted color channel."
                }
              }
            }
          }
        },
        {
          name = "mat4",
          tag = "vectors",
          summary = "Create a temporary Mat4.",
          description = "Creates a temporary 4D matrix.  This function takes the same arguments as `Mat4:set`.",
          key = "lovr.math.mat4",
          module = "lovr.math",
          related = {
            "lovr.math.newMat4",
            "Mat4",
            "Vectors"
          },
          variants = {
            {
              description = "Sets the matrix to the identity matrix.",
              arguments = {},
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              description = "Copies the values from an existing matrix.",
              arguments = {
                {
                  name = "n",
                  type = "Mat4",
                  description = "An existing matrix to copy the values from."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The translation of the matrix.",
                  default = "0, 0, 0"
                },
                {
                  name = "scale",
                  type = "Vec3",
                  description = "The scale of the matrix.",
                  default = "1, 1, 1"
                },
                {
                  name = "rotation",
                  type = "Quat",
                  description = "The rotation of the matrix.",
                  default = "0, 0, 0, 1"
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The translation of the matrix.",
                  default = "0, 0, 0"
                },
                {
                  name = "rotation",
                  type = "Quat",
                  description = "The rotation of the matrix.",
                  default = "0, 0, 0, 1"
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "...",
                  type = "number",
                  description = "16 numbers to use as the raw values of the matrix (column-major)."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              description = "Sets the diagonal values to a number and everything else to 0.",
              arguments = {
                {
                  name = "d",
                  type = "number",
                  description = "A number to use for the diagonal elements."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            }
          }
        },
        {
          name = "newCurve",
          tag = "mathOther",
          summary = "Create a new Curve.",
          description = "Creates a new `Curve` from a list of control points.",
          key = "lovr.math.newCurve",
          module = "lovr.math",
          variants = {
            {
              description = "Create a Curve from a set of initial control points.",
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x coordinate of the first control point."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y coordinate of the first control point."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z coordinate of the first control point."
                },
                {
                  name = "...",
                  type = "*",
                  description = "Additional control points."
                }
              },
              returns = {
                {
                  name = "curve",
                  type = "Curve",
                  description = "The new Curve."
                }
              }
            },
            {
              description = "Create a Curve from a set of initial control points, using vectors.",
              arguments = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The first control point."
                },
                {
                  name = "...",
                  type = "*",
                  description = "Additional control points."
                }
              },
              returns = {
                {
                  name = "curve",
                  type = "Curve",
                  description = "The new Curve."
                }
              }
            },
            {
              description = "Create a Curve from control points in a table.  The table values can be numbers or `Vec3` objects.",
              arguments = {
                {
                  name = "points",
                  type = "table",
                  description = "A table of control points, formatted as numbers or `Vec3` objects."
                }
              },
              returns = {
                {
                  name = "curve",
                  type = "Curve",
                  description = "The new Curve."
                }
              }
            },
            {
              description = "Create an empty Curve, reserving space ahead of time for a certain number of control points.",
              arguments = {
                {
                  name = "n",
                  type = "number",
                  description = "The number of points to reserve for the Curve."
                }
              },
              returns = {
                {
                  name = "curve",
                  type = "Curve",
                  description = "The new Curve."
                }
              }
            }
          }
        },
        {
          name = "newMat4",
          tag = "vectors",
          summary = "Create a new Mat4.",
          description = "Creates a new 4D matrix.  This function takes the same arguments as `Mat4:set`.",
          key = "lovr.math.newMat4",
          module = "lovr.math",
          related = {
            "lovr.math.mat4",
            "Mat4",
            "Vectors"
          },
          variants = {
            {
              description = "Sets the matrix to the identity matrix.",
              arguments = {},
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              description = "Copies the values from an existing matrix.",
              arguments = {
                {
                  name = "n",
                  type = "Mat4",
                  description = "An existing matrix to copy the values from."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The translation of the matrix.",
                  default = "0, 0, 0"
                },
                {
                  name = "scale",
                  type = "Vec3",
                  description = "The scale of the matrix.",
                  default = "1, 1, 1"
                },
                {
                  name = "rotation",
                  type = "Quat",
                  description = "The rotation of the matrix.",
                  default = "0, 0, 0, 1"
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "position",
                  type = "Vec3",
                  description = "The translation of the matrix.",
                  default = "0, 0, 0"
                },
                {
                  name = "rotation",
                  type = "Quat",
                  description = "The rotation of the matrix.",
                  default = "0, 0, 0, 1"
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              arguments = {
                {
                  name = "...",
                  type = "number",
                  description = "16 numbers to use as the raw values of the matrix (column-major)."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            },
            {
              description = "Sets the diagonal values to a number and everything else to 0.",
              arguments = {
                {
                  name = "d",
                  type = "number",
                  description = "A number to use for the diagonal elements."
                }
              },
              returns = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "The new matrix."
                }
              }
            }
          }
        },
        {
          name = "newQuat",
          tag = "vectors",
          summary = "Create a new Quat.",
          description = "Creates a new quaternion.  This function takes the same arguments as `Quat:set`.",
          key = "lovr.math.newQuat",
          module = "lovr.math",
          related = {
            "lovr.math.quat",
            "Quat",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "angle",
                  type = "number",
                  description = "An angle to use for the rotation, in radians.",
                  default = "0"
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "raw",
                  type = "boolean",
                  description = "Whether the components should be interpreted as raw `(x, y, z, w)` components.",
                  default = "false"
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              arguments = {
                {
                  name = "r",
                  type = "Quat",
                  description = "An existing quaternion to copy the values from."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Uses the direction of a vector.",
              arguments = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "A normalized direction vector."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Sets the rotation to represent the rotation between two vectors.",
              arguments = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "A normalized direction vector."
                },
                {
                  name = "u",
                  type = "Vec3",
                  description = "Another normalized direction vector."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              arguments = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "A matrix to use the rotation from."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Set the quaternion to the identity (0, 0, 0, 1).",
              arguments = {},
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            }
          }
        },
        {
          name = "newRandomGenerator",
          tag = "random",
          summary = "Create a new RandomGenerator.",
          description = "Creates a new `RandomGenerator`, which can be used to generate random numbers. If you just want some random numbers, you can use `lovr.math.random`. Individual RandomGenerator objects are useful if you need more control over the random sequence used or need a random generator isolated from other instances.",
          key = "lovr.math.newRandomGenerator",
          module = "lovr.math",
          variants = {
            {
              description = "Create a RandomGenerator with a default seed.",
              arguments = {},
              returns = {
                {
                  name = "randomGenerator",
                  type = "RandomGenerator",
                  description = "The new RandomGenerator."
                }
              }
            },
            {
              arguments = {
                {
                  name = "seed",
                  type = "number",
                  description = "The initial seed for the RandomGenerator."
                }
              },
              returns = {
                {
                  name = "randomGenerator",
                  type = "RandomGenerator",
                  description = "The new RandomGenerator."
                }
              }
            },
            {
              description = "This variant allows creation of random generators with precise 64-bit seed values, since Lua's number format loses precision with really big numbers.",
              arguments = {
                {
                  name = "low",
                  type = "number",
                  description = "The lower 32 bits of the seed."
                },
                {
                  name = "high",
                  type = "number",
                  description = "The upper 32 bits of the seed."
                }
              },
              returns = {
                {
                  name = "randomGenerator",
                  type = "RandomGenerator",
                  description = "The new RandomGenerator."
                }
              }
            }
          }
        },
        {
          name = "newVec2",
          tag = "vectors",
          summary = "Create a new Vec2.",
          description = "Creates a new 2D vector.  This function takes the same arguments as `Vec2:set`.",
          key = "lovr.math.newVec2",
          module = "lovr.math",
          related = {
            "lovr.math.vec2",
            "Vec2",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec2",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec2",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec2",
                  description = "The new vector."
                }
              }
            }
          }
        },
        {
          name = "newVec3",
          tag = "vectors",
          summary = "Create a new Vec3.",
          description = "Creates a new 3D vector.  This function takes the same arguments as `Vec3:set`.",
          key = "lovr.math.newVec3",
          module = "lovr.math",
          related = {
            "lovr.math.vec3",
            "Vec3",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec3",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "A matrix to use the position of."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "q",
                  type = "Quat",
                  description = "A quat to use the direction of."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            }
          }
        },
        {
          name = "newVec4",
          tag = "vectors",
          summary = "Create a new Vec4.",
          description = "Creates a new 4D vector.  This function takes the same arguments as `Vec4:set`.",
          key = "lovr.math.newVec4",
          module = "lovr.math",
          related = {
            "lovr.math.vec4",
            "Vec4",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z value of the vector.",
                  default = "x"
                },
                {
                  name = "w",
                  type = "number",
                  description = "The w value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec4",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec4",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec4",
                  description = "The new vector."
                }
              }
            }
          }
        },
        {
          name = "noise",
          tag = "random",
          summary = "Generate simplex noise.",
          description = "Returns a 1D, 2D, 3D, or 4D simplex noise value.  The number will be between 0 and 1.",
          key = "lovr.math.noise",
          module = "lovr.math",
          related = {
            "lovr.math.random"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x coordinate of the input."
                }
              },
              returns = {
                {
                  name = "noise",
                  type = "number",
                  description = "The noise value, between 0 and 1."
                }
              }
            },
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x coordinate of the input."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y coordinate of the input."
                }
              },
              returns = {
                {
                  name = "noise",
                  type = "number",
                  description = "The noise value, between 0 and 1."
                }
              }
            },
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x coordinate of the input."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y coordinate of the input."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z coordinate of the input."
                }
              },
              returns = {
                {
                  name = "noise",
                  type = "number",
                  description = "The noise value, between 0 and 1."
                }
              }
            },
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x coordinate of the input."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y coordinate of the input."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z coordinate of the input."
                },
                {
                  name = "w",
                  type = "number",
                  description = "The w coordinate of the input."
                }
              },
              returns = {
                {
                  name = "noise",
                  type = "number",
                  description = "The noise value, between 0 and 1."
                }
              }
            }
          }
        },
        {
          name = "quat",
          tag = "vectors",
          summary = "Create a temporary Quat.",
          description = "Creates a temporary quaternion.  This function takes the same arguments as `Quat:set`.",
          key = "lovr.math.quat",
          module = "lovr.math",
          related = {
            "lovr.math.newQuat",
            "Quat",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "angle",
                  type = "number",
                  description = "An angle to use for the rotation, in radians.",
                  default = "0"
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the axis of rotation.",
                  default = "0"
                },
                {
                  name = "raw",
                  type = "boolean",
                  description = "Whether the components should be interpreted as raw `(x, y, z, w)` components.",
                  default = "false"
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              arguments = {
                {
                  name = "r",
                  type = "Quat",
                  description = "An existing quaternion to copy the values from."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Uses the direction of a vector.",
              arguments = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "A normalized direction vector."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Sets the rotation to represent the rotation between two vectors.",
              arguments = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "A normalized direction vector."
                },
                {
                  name = "u",
                  type = "Vec3",
                  description = "Another normalized direction vector."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              arguments = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "A matrix to use the rotation from."
                }
              },
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            },
            {
              description = "Set the quaternion to the identity (0, 0, 0, 1).",
              arguments = {},
              returns = {
                {
                  name = "q",
                  type = "Quat",
                  description = "The new quaternion."
                }
              }
            }
          }
        },
        {
          name = "random",
          tag = "random",
          summary = "Get a random number.",
          description = "Returns a uniformly distributed pseudo-random number.  This function has improved randomness over Lua's `math.random` and also guarantees that the sequence of random numbers will be the same on all platforms (given the same seed).",
          key = "lovr.math.random",
          module = "lovr.math",
          notes = "You can set the random seed using `lovr.math.setRandomSeed`.",
          related = {
            "lovr.math.randomNormal",
            "RandomGenerator",
            "lovr.math.noise"
          },
          variants = {
            {
              description = "Generate a pseudo-random floating point number in the range `[0,1)`",
              arguments = {},
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "A pseudo-random number."
                }
              }
            },
            {
              description = "Generate a pseudo-random integer in the range `[1,high]`",
              arguments = {
                {
                  name = "high",
                  type = "number",
                  description = "The maximum number to generate."
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "A pseudo-random number."
                }
              }
            },
            {
              description = "Generate a pseudo-random integer in the range `[low,high]`",
              arguments = {
                {
                  name = "low",
                  type = "number",
                  description = "The minimum number to generate."
                },
                {
                  name = "high",
                  type = "number",
                  description = "The maximum number to generate."
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "A pseudo-random number."
                }
              }
            }
          }
        },
        {
          name = "randomNormal",
          tag = "random",
          summary = "Get a random number from a normal distribution.",
          description = "Returns a pseudo-random number from a normal distribution (a bell curve).  You can control the center of the bell curve (the mean value) and the overall width (sigma, or standard deviation).",
          key = "lovr.math.randomNormal",
          module = "lovr.math",
          related = {
            "lovr.math.random",
            "RandomGenerator"
          },
          variants = {
            {
              arguments = {
                {
                  name = "sigma",
                  type = "number",
                  description = "The standard deviation of the distribution.  This can be thought of how \"wide\" the range of numbers is or how much variability there is.",
                  default = "1"
                },
                {
                  name = "mu",
                  type = "number",
                  description = "The average value returned.",
                  default = "0"
                }
              },
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "A normally distributed pseudo-random number."
                }
              }
            }
          }
        },
        {
          name = "setRandomSeed",
          tag = "random",
          summary = "Set the random seed.",
          description = "Seed the random generator with a new seed.  Each seed will cause `lovr.math.random` and `lovr.math.randomNormal` to produce a unique sequence of random numbers.  This is done once automatically at startup by `lovr.run`.",
          key = "lovr.math.setRandomSeed",
          module = "lovr.math",
          variants = {
            {
              arguments = {
                {
                  name = "seed",
                  type = "number",
                  description = "The new seed."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "vec2",
          tag = "vectors",
          summary = "Create a temporary Vec2.",
          description = "Creates a temporary 2D vector.  This function takes the same arguments as `Vec2:set`.",
          key = "lovr.math.vec2",
          module = "lovr.math",
          related = {
            "lovr.math.newVec2",
            "Vec2",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec2",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec2",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec2",
                  description = "The new vector."
                }
              }
            }
          }
        },
        {
          name = "vec3",
          tag = "vectors",
          summary = "Create a temporary Vec3.",
          description = "Creates a temporary 3D vector.  This function takes the same arguments as `Vec3:set`.",
          key = "lovr.math.vec3",
          module = "lovr.math",
          related = {
            "lovr.math.newVec3",
            "Vec3",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec3",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "m",
                  type = "Mat4",
                  description = "A matrix to use the position of."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "q",
                  type = "Quat",
                  description = "A quat to use the direction of."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec3",
                  description = "The new vector."
                }
              }
            }
          }
        },
        {
          name = "vec4",
          tag = "vectors",
          summary = "Create a temporary Vec4.",
          description = "Creates a temporary 4D vector.  This function takes the same arguments as `Vec4:set`.",
          key = "lovr.math.vec4",
          module = "lovr.math",
          related = {
            "lovr.math.newVec4",
            "Vec4",
            "Vectors"
          },
          variants = {
            {
              arguments = {
                {
                  name = "x",
                  type = "number",
                  description = "The x value of the vector.",
                  default = "0"
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y value of the vector.",
                  default = "x"
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z value of the vector.",
                  default = "x"
                },
                {
                  name = "w",
                  type = "number",
                  description = "The w value of the vector.",
                  default = "x"
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec4",
                  description = "The new vector."
                }
              }
            },
            {
              arguments = {
                {
                  name = "u",
                  type = "Vec4",
                  description = "A vector to copy the values from."
                }
              },
              returns = {
                {
                  name = "v",
                  type = "Vec4",
                  description = "The new vector."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Curve",
          summary = "A Bézier curve.",
          description = "A Curve is an object that represents a Bézier curve in three dimensions.  Curves are defined by an arbitrary number of control points (note that the curve only passes through the first and last control point).\n\nOnce a Curve is created with `lovr.math.newCurve`, you can use `Curve:evaluate` to get a point on the curve or `Curve:render` to get a list of all of the points on the curve.  These points can be passed directly to `Pass:points` or `Pass:line` to render the curve.\n\nNote that for longer or more complicated curves (like in a drawing application) it can be easier to store the path as several Curve objects.",
          key = "Curve",
          module = "lovr.math",
          constructors = {
            "lovr.math.newCurve",
            "Curve:slice"
          },
          extends = "Object",
          methods = {
            {
              name = "addPoint",
              summary = "Add a new control point to the Curve.",
              description = "Inserts a new control point into the Curve at the specified index.",
              key = "Curve:addPoint",
              module = "lovr.math",
              notes = "An error will be thrown if the index is less than one or more than the number of control points.",
              related = {
                "Curve:getPointCount",
                "Curve:getPoint",
                "Curve:setPoint",
                "Curve:removePoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the control point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the control point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the control point."
                    },
                    {
                      name = "index",
                      type = "number",
                      description = "The index to insert the control point at.  If nil, the control point is added to the end of the list of control points.",
                      default = "nil"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "evaluate",
              summary = "Turn a number from 0 to 1 into a point on the Curve.",
              description = "Returns a point on the Curve given a parameter `t` from 0 to 1.  0 will return the first control point, 1 will return the last point, .5 will return a point in the \"middle\" of the Curve, etc.",
              key = "Curve:evaluate",
              module = "lovr.math",
              notes = "An error will be thrown if `t` is not between 0 and 1, or if the Curve has less than two points.",
              related = {
                "Curve:getTangent",
                "Curve:render",
                "Curve:slice"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "t",
                      type = "number",
                      description = "The parameter to evaluate the Curve at."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the point."
                    }
                  }
                }
              }
            },
            {
              name = "getPoint",
              summary = "Get a control point of the Curve.",
              description = "Returns a control point of the Curve.",
              key = "Curve:getPoint",
              module = "lovr.math",
              notes = "An error will be thrown if the index is less than one or more than the number of control points.",
              related = {
                "Curve:getPointCount",
                "Curve:setPoint",
                "Curve:addPoint",
                "Curve:removePoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index to retrieve."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the control point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the control point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the control point."
                    }
                  }
                }
              }
            },
            {
              name = "getPointCount",
              summary = "Get the number of control points in the Curve.",
              description = "Returns the number of control points in the Curve.",
              key = "Curve:getPointCount",
              module = "lovr.math",
              related = {
                "Curve:getPoint",
                "Curve:setPoint",
                "Curve:addPoint",
                "Curve:removePoint"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of control points."
                    }
                  }
                }
              }
            },
            {
              name = "getTangent",
              summary = "Get the direction of the Curve at a point.",
              description = "Returns a direction vector for the Curve given a parameter `t` from 0 to 1.  0 will return the direction at the first control point, 1 will return the direction at the last point, .5 will return the direction at the \"middle\" of the Curve, etc.",
              key = "Curve:getTangent",
              module = "lovr.math",
              notes = "The direction vector returned by this function will have a length of one.",
              related = {
                "Curve:evaluate",
                "Curve:render",
                "Curve:slice"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "t",
                      type = "number",
                      description = "Where on the Curve to compute the direction."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the point."
                    }
                  }
                }
              }
            },
            {
              name = "removePoint",
              summary = "Remove a control point from the Curve.",
              description = "Removes a control point from the Curve.",
              key = "Curve:removePoint",
              module = "lovr.math",
              notes = "An error will be thrown if the index is less than one or more than the number of control points.",
              related = {
                "Curve:getPointCount",
                "Curve:getPoint",
                "Curve:setPoint",
                "Curve:addPoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the control point to remove."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "render",
              summary = "Get a list of points on the Curve.",
              description = "Returns a list of points on the Curve.  The number of points can be specified to get a more or less detailed representation, and it is also possible to render a subsection of the Curve.",
              key = "Curve:render",
              module = "lovr.math",
              related = {
                "Curve:evaluate",
                "Curve:slice",
                "Pass:points",
                "Pass:line",
                "Pass:mesh"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "n",
                      type = "number",
                      description = "The number of points to use.",
                      default = "32"
                    },
                    {
                      name = "t1",
                      type = "number",
                      description = "How far along the curve to start rendering.",
                      default = "0"
                    },
                    {
                      name = "t2",
                      type = "number",
                      description = "How far along the curve to stop rendering.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "t",
                      type = "{number}",
                      description = "A (flat) table of 3D points along the curve."
                    }
                  }
                }
              }
            },
            {
              name = "setPoint",
              summary = "Set a control point of the Curve.",
              description = "Changes the position of a control point on the Curve.",
              key = "Curve:setPoint",
              module = "lovr.math",
              notes = "An error will be thrown if the index is less than one or more than the number of control points.",
              related = {
                "Curve:getPointCount",
                "Curve:getPoint",
                "Curve:addPoint",
                "Curve:removePoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index to modify."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The new x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The new y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The new z coordinate."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "slice",
              summary = "Get a new Curve from a slice of an existing one.",
              description = "Returns a new Curve created by slicing the Curve at the specified start and end points.",
              key = "Curve:slice",
              module = "lovr.math",
              notes = "The new Curve will have the same number of control points as the existing curve.\n\nAn error will be thrown if t1 or t2 are not between 0 and 1, or if the Curve has less than two points.",
              related = {
                "Curve:evaluate",
                "Curve:render"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "t1",
                      type = "number",
                      description = "The starting point to slice at."
                    },
                    {
                      name = "t2",
                      type = "number",
                      description = "The ending point to slice at."
                    }
                  },
                  returns = {
                    {
                      name = "curve",
                      type = "Curve",
                      description = "A new Curve."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Mat4",
          summary = "A 4x4 matrix.",
          description = "A `mat4` is a math type that holds 16 values in a 4x4 grid.",
          key = "Mat4",
          module = "lovr.math",
          constructors = {
            "lovr.math.newMat4",
            "lovr.math.mat4"
          },
          methods = {
            {
              name = "equals",
              summary = "Check if a matrix equals another matrix.",
              description = "Returns whether a matrix is approximately equal to another matrix.",
              key = "Mat4:equals",
              module = "lovr.math",
              related = {
                "Vec2:equals",
                "Vec3:equals",
                "Vec4:equals",
                "Quat:equals"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "n",
                      type = "Mat4",
                      description = "The other matrix."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 matrices approximately equal each other."
                    }
                  }
                }
              }
            },
            {
              name = "fov",
              summary = "Set a projection using raw field of view angles.",
              description = "Sets a projection matrix using raw projection angles and clipping planes.\n\nThis can be used for asymmetric or oblique projections.",
              key = "Mat4:fov",
              module = "lovr.math",
              related = {
                "Mat4:orthographic",
                "Mat4:perspective",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "left",
                      type = "number",
                      description = "The left half-angle of the projection, in radians."
                    },
                    {
                      name = "right",
                      type = "number",
                      description = "The right half-angle of the projection, in radians."
                    },
                    {
                      name = "up",
                      type = "number",
                      description = "The top half-angle of the projection, in radians."
                    },
                    {
                      name = "down",
                      type = "number",
                      description = "The bottom half-angle of the projection, in radians."
                    },
                    {
                      name = "near",
                      type = "number",
                      description = "The near plane of the projection."
                    },
                    {
                      name = "far",
                      type = "number",
                      description = "The far plane.  Zero is a special value that will set an infinite far plane with a reversed Z range, which improves depth buffer precision and is the default.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "getOrientation",
              summary = "Get the angle/axis rotation of the matrix.",
              description = "Returns the angle/axis rotation of the matrix.",
              key = "Mat4:getOrientation",
              module = "lovr.math",
              related = {
                "Mat4:getPosition",
                "Mat4:getScale",
                "Mat4:getPose",
                "Mat4:unpack",
                "Mat4:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the matrix rotates around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPose",
              summary = "Get the position and rotation of the matrix.",
              description = "Returns the position and rotation of the matrix.",
              key = "Mat4:getPose",
              module = "lovr.math",
              related = {
                "Mat4:getPosition",
                "Mat4:getOrientation",
                "Mat4:getScale",
                "Mat4:unpack",
                "Mat4:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z translation."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the matrix rotates around its rotation axis."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              summary = "Get the translation of the matrix.",
              description = "Returns the translation of the matrix.  This is the last column of the matrix.",
              key = "Mat4:getPosition",
              module = "lovr.math",
              related = {
                "Mat4:getOrientation",
                "Mat4:getScale",
                "Mat4:getPose",
                "Mat4:unpack",
                "Mat4:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z translation."
                    }
                  }
                }
              }
            },
            {
              name = "getScale",
              summary = "Get the scale factor of the matrix.",
              description = "Returns the scale factor of the matrix.",
              key = "Mat4:getScale",
              module = "lovr.math",
              related = {
                "Mat4:getPosition",
                "Mat4:getOrientation",
                "Mat4:getPose",
                "Mat4:unpack",
                "Mat4:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "sx",
                      type = "number",
                      description = "The x scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z scale."
                    }
                  }
                }
              }
            },
            {
              name = "identity",
              summary = "Reset the matrix to the identity.",
              description = "Resets the matrix to the identity, effectively setting its translation to zero, its scale to 1, and clearing any rotation.",
              key = "Mat4:identity",
              module = "lovr.math",
              related = {
                "Pass:origin"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "invert",
              summary = "Invert the matrix.",
              description = "Inverts the matrix, causing it to represent the opposite of its old transform.",
              key = "Mat4:invert",
              module = "lovr.math",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The inverted matrix."
                    }
                  }
                }
              }
            },
            {
              name = "lookAt",
              summary = "Create a view transform that looks from a position to target position.",
              description = "Sets a view transform matrix that moves and orients camera to look at a target point.\n\nThis is useful for changing camera position and orientation.\n\nThe lookAt() function produces same result as target() after matrix inversion.",
              key = "Mat4:lookAt",
              module = "lovr.math",
              examples = {
                {
                  code = "function lovr.draw(pass)\n  pass:setViewPose(1, mat4():lookAt(cameraPos, playerPos), true)\n\n  -- draw scene\nend"
                }
              },
              related = {
                "Mat4:target",
                "Quat:direction"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "from",
                      type = "Vec3",
                      description = "The position of the viewer."
                    },
                    {
                      name = "to",
                      type = "Vec3",
                      description = "The position of the target."
                    },
                    {
                      name = "up",
                      type = "Vec3",
                      description = "The up vector of the viewer.",
                      default = "Vec3(0, 1, 0)"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "mul",
              summary = "Multiply a matrix with another matrix or a vector.",
              description = "Multiplies this matrix by another value.  Multiplying by a matrix combines their two transforms together.  Multiplying by a vector applies the transformation from the matrix to the vector and returns the vector.",
              key = "Mat4:mul",
              module = "lovr.math",
              notes = "When multiplying by a vec4, the vector is treated as either a point if its w component is 1, or a direction vector if the w is 0 (the matrix translation won't be applied).",
              related = {
                "Mat4:translate",
                "Mat4:rotate",
                "Mat4:scale"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "n",
                      type = "Mat4",
                      description = "The matrix."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "v3",
                      type = "Vec3",
                      description = "A 3D vector, treated as a point."
                    }
                  },
                  returns = {
                    {
                      name = "v3",
                      type = "Vec3",
                      description = "The transformed vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "v4",
                      type = "Vec4",
                      description = "A 4D vector."
                    }
                  },
                  returns = {
                    {
                      name = "v4",
                      type = "Vec4",
                      description = "The transformed vector."
                    }
                  }
                }
              }
            },
            {
              name = "orthographic",
              summary = "Turn the matrix into an orthographic projection.",
              description = "Sets this matrix to represent an orthographic projection, useful for 2D/isometric rendering.\n\nThis can be used with `Pass:setProjection`, or it can be sent to a `Shader` for use in GLSL.",
              key = "Mat4:orthographic",
              module = "lovr.math",
              related = {
                "Mat4:perspective",
                "Mat4:fov",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "left",
                      type = "number",
                      description = "The left edge of the projection."
                    },
                    {
                      name = "right",
                      type = "number",
                      description = "The right edge of the projection."
                    },
                    {
                      name = "bottom",
                      type = "number",
                      description = "The bottom edge of the projection."
                    },
                    {
                      name = "top",
                      type = "number",
                      description = "The top edge of the projection."
                    },
                    {
                      name = "near",
                      type = "number",
                      description = "The position of the near clipping plane."
                    },
                    {
                      name = "far",
                      type = "number",
                      description = "The position of the far clipping plane."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the projection."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the projection."
                    },
                    {
                      name = "near",
                      type = "number",
                      description = "The position of the near clipping plane."
                    },
                    {
                      name = "far",
                      type = "number",
                      description = "The position of the far clipping plane."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "perspective",
              summary = "Turn the matrix into a perspective projection.",
              description = "Sets this matrix to represent a perspective projection.\n\nThis can be used with `Pass:setProjection`, or it can be sent to a `Shader` for use in GLSL.",
              key = "Mat4:perspective",
              module = "lovr.math",
              related = {
                "Mat4:orthographic",
                "Mat4:fov",
                "Pass:setProjection"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "fov",
                      type = "number",
                      description = "The vertical field of view (in radians)."
                    },
                    {
                      name = "aspect",
                      type = "number",
                      description = "The horizontal aspect ratio of the projection (width / height)."
                    },
                    {
                      name = "near",
                      type = "number",
                      description = "The near plane."
                    },
                    {
                      name = "far",
                      type = "number",
                      description = "The far plane.  Zero is a special value that will set an infinite far plane with a reversed Z range, which improves depth buffer precision and is the default.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "reflect",
              summary = "Create a matrix that reflects across a plane.",
              description = "Turns the matrix into a reflection matrix that transforms values as though they were reflected across a plane.",
              key = "Mat4:reflect",
              module = "lovr.math",
              variants = {
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the plane."
                    },
                    {
                      name = "normal",
                      type = "Vec3",
                      description = "The normal vector of the plane."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The reflected matrix."
                    }
                  }
                }
              }
            },
            {
              name = "rotate",
              summary = "Rotate the matrix.",
              description = "Rotates the matrix using a quaternion or an angle/axis rotation.",
              key = "Mat4:rotate",
              module = "lovr.math",
              related = {
                "Mat4:translate",
                "Mat4:scale",
                "Mat4:identity"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "q",
                      type = "Quat",
                      description = "The rotation to apply to the matrix."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The rotated matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle component of the angle/axis rotation (radians)."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The rotated matrix."
                    }
                  }
                }
              }
            },
            {
              name = "scale",
              summary = "Scale the matrix.",
              description = "Scales the matrix.",
              key = "Mat4:scale",
              module = "lovr.math",
              related = {
                "Mat4:translate",
                "Mat4:rotate",
                "Mat4:identity"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The 3D scale to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "sx",
                      type = "number",
                      description = "The x component of the scale to apply."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y component of the scale to apply.",
                      default = "sx"
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z component of the scale to apply.",
                      default = "sx"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "set",
              summary = "Set the components of the matrix.",
              description = "Sets the components of the matrix from separate position, rotation, and scale arguments or an existing matrix.",
              key = "Mat4:set",
              module = "lovr.math",
              related = {
                "Mat4:unpack"
              },
              variants = {
                {
                  description = "Resets the matrix to the identity matrix, without any translation, rotation, or scale.",
                  arguments = {},
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  description = "Copies the values from an existing matrix.",
                  arguments = {
                    {
                      name = "n",
                      type = "Mat4",
                      description = "An existing matrix to copy the values from."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  description = "Sets the position, scale, and rotation of the matrix using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation."
                    },
                    {
                      name = "sx",
                      type = "number",
                      description = "The x component of the scale."
                    },
                    {
                      name = "sy",
                      type = "number",
                      description = "The y component of the scale."
                    },
                    {
                      name = "sz",
                      type = "number",
                      description = "The z component of the scale."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle of the rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  description = "Sets the pose (position and orientation) of the matrix using numbers.  The scale is set to 1 on all axes.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle of the rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The translation of the matrix."
                    },
                    {
                      name = "scale",
                      type = "Vec3",
                      description = "The scale of the matrix."
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The rotation of the matrix."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The translation of the matrix."
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The rotation of the matrix."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  description = "Sets the raw components of the matrix using 16 numbers in column-major order.",
                  arguments = {
                    {
                      name = "...",
                      type = "number",
                      description = "The raw values of the matrix, in column-major order."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                },
                {
                  description = "Sets the diagonal values to a number and everything else to 0.",
                  arguments = {
                    {
                      name = "d",
                      type = "number",
                      description = "A number to use for the diagonal elements."
                    }
                  },
                  returns = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The input matrix."
                    }
                  }
                }
              }
            },
            {
              name = "target",
              summary = "Create a model transform that targets from a position to target position.",
              description = "Sets a model transform matrix that moves to `from` and orients model towards `to` point.\n\nThis is used when rendered model should always point towards a point of interest. The resulting Mat4 object can be used as model pose.\n\nThe target() function produces same result as lookAt() after matrix inversion.",
              key = "Mat4:target",
              module = "lovr.math",
              related = {
                "Mat4:lookAt",
                "Quat:direction"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "from",
                      type = "Vec3",
                      description = "The position of the viewer."
                    },
                    {
                      name = "to",
                      type = "Vec3",
                      description = "The position of the target."
                    },
                    {
                      name = "up",
                      type = "Vec3",
                      description = "The up vector of the viewer.",
                      default = "Vec3(0, 1, 0)"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The modified matrix."
                    }
                  }
                }
              }
            },
            {
              name = "translate",
              summary = "Translate the matrix.",
              description = "Translates the matrix.",
              key = "Mat4:translate",
              module = "lovr.math",
              related = {
                "Mat4:rotate",
                "Mat4:scale",
                "Mat4:identity"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The translation vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The translated matrix."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The translated matrix."
                    }
                  }
                }
              }
            },
            {
              name = "transpose",
              summary = "Transpose the matrix.",
              description = "Transposes the matrix, mirroring its values along the diagonal.",
              key = "Mat4:transpose",
              module = "lovr.math",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Mat4",
                      description = "The transposed matrix."
                    }
                  }
                }
              }
            },
            {
              name = "unpack",
              summary = "Get the individual components of the matrix.",
              description = "Returns the components of matrix, either as 10 separated numbers representing the position, scale, and rotation, or as 16 raw numbers representing the individual components of the matrix in column-major order.",
              key = "Mat4:unpack",
              module = "lovr.math",
              related = {
                "Mat4:set",
                "Mat4:getPosition",
                "Mat4:getOrientation",
                "Mat4:getScale",
                "Mat4:getPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "raw",
                      type = "boolean",
                      description = "Whether to return the 16 raw components.",
                      default = "false"
                    }
                  },
                  returns = {
                    {
                      name = "...",
                      type = "number",
                      description = "The requested components of the matrix."
                    }
                  }
                }
              }
            }
          },
          related = {
            "Vec3",
            "Quat",
            "Vectors"
          }
        },
        {
          name = "Quat",
          summary = "A quaternion.",
          description = "A `quat` is a math type that represents a 3D rotation, stored as four numbers.",
          key = "Quat",
          module = "lovr.math",
          constructors = {
            "lovr.math.newQuat",
            "lovr.math.quat"
          },
          methods = {
            {
              name = "conjugate",
              summary = "Conjugate (invert) the quaternion.",
              description = "Conjugates the input quaternion in place, returning the input.  If the quaternion is normalized, this is the same as inverting it.  It negates the (x, y, z) components of the quaternion.",
              key = "Quat:conjugate",
              module = "lovr.math",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The inverted quaternion."
                    }
                  }
                }
              }
            },
            {
              name = "direction",
              summary = "Get the direction of the quaternion.",
              description = "Creates a new temporary vec3 facing the forward direction, rotates it by this quaternion, and returns the vector.",
              key = "Quat:direction",
              module = "lovr.math",
              related = {
                "Mat4:lookAt"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The direction vector."
                    }
                  }
                }
              }
            },
            {
              name = "equals",
              summary = "Check if a quaternion equals another quaternion.",
              description = "Returns whether a quaternion is approximately equal to another quaternion.",
              key = "Quat:equals",
              module = "lovr.math",
              related = {
                "Vec2:equals",
                "Vec3:equals",
                "Vec4:equals",
                "Mat4:equals"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "r",
                      type = "Quat",
                      description = "The other quaternion."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 quaternions approximately equal each other."
                    }
                  }
                }
              }
            },
            {
              name = "getEuler",
              summary = "Get the euler angles of the quaternion.",
              description = "Returns the euler angles of the quaternion, in YXZ order.",
              key = "Quat:getEuler",
              module = "lovr.math",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "pitch",
                      type = "number",
                      description = "The pitch (x axis rotation)."
                    },
                    {
                      name = "yaw",
                      type = "number",
                      description = "The yaw (y axis rotation)."
                    },
                    {
                      name = "roll",
                      type = "number",
                      description = "The roll (z axis rotation)."
                    }
                  }
                }
              }
            },
            {
              name = "length",
              summary = "Get the length of the quaternion.",
              description = "Returns the length of the quaternion.",
              key = "Quat:length",
              module = "lovr.math",
              related = {
                "Quat:normalize"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the quaternion."
                    }
                  }
                }
              }
            },
            {
              name = "mul",
              summary = "Multiply a quaternion by another quaternion or a vector.",
              description = "Multiplies this quaternion by another value.  If the value is a quaternion, the rotations in the two quaternions are applied sequentially and the result is stored in the first quaternion.  If the value is a vector, then the input vector is rotated by the quaternion and returned.",
              key = "Quat:mul",
              module = "lovr.math",
              variants = {
                {
                  arguments = {
                    {
                      name = "r",
                      type = "Quat",
                      description = "A quaternion to combine with the original."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "v3",
                      type = "Vec3",
                      description = "A vector to rotate."
                    }
                  },
                  returns = {
                    {
                      name = "v3",
                      type = "Vec3",
                      description = "The rotated vector."
                    }
                  }
                }
              }
            },
            {
              name = "normalize",
              summary = "Normalize the length of the quaternion to 1.",
              description = "Adjusts the values in the quaternion so that its length becomes 1.",
              key = "Quat:normalize",
              module = "lovr.math",
              notes = "A common source of bugs with quaternions is to forget to normalize them after performing a series of operations on them.  Try normalizing a quaternion if some of the calculations aren't working quite right!",
              related = {
                "Quat:length"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The normalized quaternion."
                    }
                  }
                }
              }
            },
            {
              name = "set",
              summary = "Set the components of the quaternion.",
              description = "Sets the components of the quaternion.  There are lots of different ways to specify the new components, the summary is:\n\n- Four numbers can be used to specify an angle/axis rotation, similar to other LÖVR functions.\n- Four numbers plus the fifth `raw` flag can be used to set the raw values of the quaternion.\n- An existing quaternion can be passed in to copy its values.\n- A single direction vector can be specified to turn its direction (relative to the default\n  forward direction of \"negative z\") into a rotation.\n- Two direction vectors can be specified to set the quaternion equal to the rotation between the\n  two vectors.\n- A matrix can be passed in to extract the rotation of the matrix into a quaternion.",
              key = "Quat:set",
              module = "lovr.math",
              related = {
                "Quat:unpack"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to use for the rotation, in radians.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "raw",
                      type = "boolean",
                      description = "Whether the components should be interpreted as raw `(x, y, z, w)` components.",
                      default = "false"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "r",
                      type = "Quat",
                      description = "An existing quaternion to copy the values from."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  description = "Sets the values from a direction vector.",
                  arguments = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "A normalized direction vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  description = "Sets the values to represent the rotation between two vectors.",
                  arguments = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "A normalized direction vector."
                    },
                    {
                      name = "u",
                      type = "Vec3",
                      description = "Another normalized direction vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "A matrix to use the rotation from."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                },
                {
                  description = "Reset the quaternion to the identity (0, 0, 0, 1).",
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                }
              }
            },
            {
              name = "setEuler",
              summary = "Set the value of the quaternion using euler angles.",
              description = "Sets the value of the quaternion using euler angles.  The rotation order is YXZ.",
              key = "Quat:setEuler",
              module = "lovr.math",
              variants = {
                {
                  arguments = {
                    {
                      name = "pitch",
                      type = "number",
                      description = "The pitch (x axis rotation)."
                    },
                    {
                      name = "yaw",
                      type = "number",
                      description = "The yaw (y axis rotation)."
                    },
                    {
                      name = "roll",
                      type = "number",
                      description = "The roll (z axis rotation)."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion."
                    }
                  }
                }
              }
            },
            {
              name = "slerp",
              summary = "Moves this quaternion some amount towards another one.",
              description = "Performs a spherical linear interpolation between this quaternion and another one, which can be used for smoothly animating between two rotations.\n\nThe amount of interpolation is controlled by a parameter `t`.  A `t` value of zero leaves the original quaternion unchanged, whereas a `t` of one sets the original quaternion exactly equal to the target.  A value between `0` and `1` returns a rotation between the two based on the value.",
              key = "Quat:slerp",
              module = "lovr.math",
              related = {
                "Vec3:lerp"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "r",
                      type = "Quat",
                      description = "The quaternion to slerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Quat",
                      description = "The modified quaternion, containing the new lerped values."
                    }
                  }
                }
              }
            },
            {
              name = "unpack",
              summary = "Get the components of the quaternion.",
              description = "Returns the components of the quaternion as numbers, either in an angle/axis representation or as raw quaternion values.",
              key = "Quat:unpack",
              module = "lovr.math",
              related = {
                "Quat:set"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "raw",
                      type = "boolean",
                      description = "Whether the values should be returned as raw values instead of angle/axis.",
                      default = "false"
                    }
                  },
                  returns = {
                    {
                      name = "a",
                      type = "number",
                      description = "The angle in radians, or the x value."
                    },
                    {
                      name = "b",
                      type = "number",
                      description = "The x component of the rotation axis or the y value."
                    },
                    {
                      name = "c",
                      type = "number",
                      description = "The y component of the rotation axis or the z value."
                    },
                    {
                      name = "d",
                      type = "number",
                      description = "The z component of the rotation axis or the w value."
                    }
                  }
                }
              }
            }
          },
          related = {
            "Vec3",
            "Mat4",
            "Vectors"
          }
        },
        {
          name = "RandomGenerator",
          summary = "A pseudo-random number generator.",
          description = "A RandomGenerator is a standalone object that can be used to independently generate pseudo-random numbers. If you just need basic randomness, you can use `lovr.math.random` without needing to create a random generator.",
          key = "RandomGenerator",
          module = "lovr.math",
          constructors = {
            "lovr.math.newRandomGenerator"
          },
          extends = "Object",
          methods = {
            {
              name = "getSeed",
              summary = "Get the seed value of the RandomGenerator.",
              description = "Returns the seed used to initialize the RandomGenerator.",
              key = "RandomGenerator:getSeed",
              module = "lovr.math",
              notes = "Since the seed is a 64 bit integer, each 32 bits of the seed are returned separately to avoid precision issues.",
              related = {
                "lovr.math.newRandomGenerator"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "low",
                      type = "number",
                      description = "The lower 32 bits of the seed."
                    },
                    {
                      name = "high",
                      type = "number",
                      description = "The upper 32 bits of the seed."
                    }
                  }
                }
              }
            },
            {
              name = "getState",
              summary = "Get the current state of the RandomGenerator.",
              description = "Returns the current state of the RandomGenerator.  This can be used with `RandomGenerator:setState` to reliably restore a previous state of the generator.",
              key = "RandomGenerator:getState",
              module = "lovr.math",
              notes = "The seed represents the starting state of the RandomGenerator, whereas the state represents the current state of the generator.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "state",
                      type = "string",
                      description = "The serialized state."
                    }
                  }
                }
              }
            },
            {
              name = "random",
              summary = "Get a random number.",
              description = "Returns the next uniformly distributed pseudo-random number from the RandomGenerator's sequence.",
              key = "RandomGenerator:random",
              module = "lovr.math",
              related = {
                "lovr.math.random",
                "RandomGenerator:randomNormal"
              },
              variants = {
                {
                  description = "Generate a pseudo-random floating point number in the range `[0,1)`",
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "A pseudo-random number."
                    }
                  }
                },
                {
                  description = "Generate a pseudo-random integer in the range `[1,high]`",
                  arguments = {
                    {
                      name = "high",
                      type = "number",
                      description = "The maximum number to generate."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "A pseudo-random number."
                    }
                  }
                },
                {
                  description = "Generate a pseudo-random integer in the range `[low,high]`",
                  arguments = {
                    {
                      name = "low",
                      type = "number",
                      description = "The minimum number to generate."
                    },
                    {
                      name = "high",
                      type = "number",
                      description = "The maximum number to generate."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "A pseudo-random number."
                    }
                  }
                }
              }
            },
            {
              name = "randomNormal",
              summary = "Get a random number from a normal distribution.",
              description = "Returns a pseudo-random number from a normal distribution (a bell curve).  You can control the center of the bell curve (the mean value) and the overall width (sigma, or standard deviation).",
              key = "RandomGenerator:randomNormal",
              module = "lovr.math",
              related = {
                "lovr.math.randomNormal",
                "RandomGenerator:random"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "sigma",
                      type = "number",
                      description = "The standard deviation of the distribution.  This can be thought of how \"wide\" the range of numbers is or how much variability there is.",
                      default = "1"
                    },
                    {
                      name = "mu",
                      type = "number",
                      description = "The average value returned.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "A normally distributed pseudo-random number."
                    }
                  }
                }
              }
            },
            {
              name = "setSeed",
              summary = "Reinitialize the RandomGenerator with a new seed.",
              description = "Seed the RandomGenerator with a new seed.  Each seed will cause the RandomGenerator to produce a unique sequence of random numbers.",
              key = "RandomGenerator:setSeed",
              module = "lovr.math",
              notes = "For precise 64 bit seeds, you should specify the lower and upper 32 bits of the seed separately. Otherwise, seeds larger than 2^53 will start to lose precision.",
              variants = {
                {
                  arguments = {
                    {
                      name = "seed",
                      type = "number",
                      description = "The random seed."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "low",
                      type = "number",
                      description = "The lower 32 bits of the seed."
                    },
                    {
                      name = "high",
                      type = "number",
                      description = "The upper 32 bits of the seed."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setState",
              summary = "Set the state of the RandomGenerator.",
              description = "Sets the state of the RandomGenerator, as previously obtained using `RandomGenerator:getState`. This can be used to reliably restore a previous state of the generator.",
              key = "RandomGenerator:setState",
              module = "lovr.math",
              notes = "The seed represents the starting state of the RandomGenerator, whereas the state represents the current state of the generator.",
              variants = {
                {
                  arguments = {
                    {
                      name = "state",
                      type = "string",
                      description = "The serialized state."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Vec2",
          summary = "A 2D vector.",
          description = "A vector object that holds two numbers.",
          key = "Vec2",
          module = "lovr.math",
          constructors = {
            "lovr.math.newVec2",
            "lovr.math.vec2"
          },
          methods = {
            {
              name = "add",
              summary = "Add a vector or a number to the vector.",
              description = "Adds a vector or a number to the vector.",
              key = "Vec2:add",
              module = "lovr.math",
              related = {
                "Vec2:sub",
                "Vec2:mul",
                "Vec2:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to add to x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to add to y component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "angle",
              summary = "Get the angle to another vector.",
              description = "Returns the angle between vectors.",
              key = "Vec2:angle",
              module = "lovr.math",
              notes = "If any of the two vectors have a length of zero, the angle between them is not well defined.  In this case the function returns `math.pi / 2`.",
              related = {
                "Vec2:distance",
                "Vec2:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to the other vector, in radians."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to the other vector, in radians."
                    }
                  }
                }
              }
            },
            {
              name = "distance",
              summary = "Get the distance to another vector.",
              description = "Returns the distance to another vector.",
              key = "Vec2:distance",
              module = "lovr.math",
              related = {
                "Vec2:angle",
                "Vec2:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The vector to measure the distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to measure distance to."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to measure distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                }
              }
            },
            {
              name = "div",
              summary = "Divides the vector by a vector or a number.",
              description = "Divides the vector by a vector or a number.",
              key = "Vec2:div",
              module = "lovr.math",
              related = {
                "Vec2:add",
                "Vec2:sub",
                "Vec2:mul"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector to divide the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to divide x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to divide y component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "dot",
              summary = "Get the dot product with another vector.",
              description = "Returns the dot product between this vector and another one.",
              key = "Vec2:dot",
              module = "lovr.math",
              notes = "This is computed as:\n\n    dot = v.x * u.x + v.y * u.y\n\nThe vectors are not normalized before computing the dot product.",
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The vector to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to compute the dot product with."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                }
              }
            },
            {
              name = "equals",
              summary = "Check if a vector equals another vector.",
              description = "Returns whether a vector is approximately equal to another vector.",
              key = "Vec2:equals",
              module = "lovr.math",
              notes = "To handle floating point precision issues, this function returns true as long as the squared distance between the vectors is below `1e-10`.",
              related = {
                "Vec3:equals",
                "Vec4:equals",
                "Quat:equals",
                "Mat4:equals"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                }
              }
            },
            {
              name = "length",
              summary = "Get the length of the vector.",
              description = "Returns the length of the vector.",
              key = "Vec2:length",
              module = "lovr.math",
              notes = "The length is equivalent to this:\n\n    math.sqrt(v.x * v.x + v.y * v.y)",
              related = {
                "Vec2:normalize",
                "Vec2:distance"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the vector."
                    }
                  }
                }
              }
            },
            {
              name = "lerp",
              summary = "Moves this vector some amount towards another one.",
              description = "Performs a linear interpolation between this vector and another one, which can be used to smoothly animate between two vectors, based on a parameter value.  A parameter value of `0` will leave the vector unchanged, a parameter value of `1` will set the vector to be equal to the input vector, and a value of `.5` will set the components to be halfway between the two vectors.",
              key = "Vec2:lerp",
              module = "lovr.math",
              related = {
                "Quat:slerp"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The vector to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The interpolated vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to lerp towards."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The interpolated vector."
                    }
                  }
                }
              }
            },
            {
              name = "mul",
              summary = "Multiply the vector by a vector or a number.",
              description = "Multiplies the vector by a vector or a number.",
              key = "Vec2:mul",
              module = "lovr.math",
              related = {
                "Vec2:add",
                "Vec2:sub",
                "Vec2:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector to multiply the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to multiply x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to multiply y component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "normalize",
              summary = "Normalize the length of the vector to 1.",
              description = "Adjusts the values in the vector so that its direction stays the same but its length becomes 1.",
              key = "Vec2:normalize",
              module = "lovr.math",
              related = {
                "Vec2:length"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The normalized vector."
                    }
                  }
                }
              }
            },
            {
              name = "set",
              summary = "Set the components of the vector.",
              description = "Sets the components of the vector, either from numbers or an existing vector.",
              key = "Vec2:set",
              module = "lovr.math",
              related = {
                "Vec2:unpack"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The new x value of the vector.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The new y value of the vector.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec2",
                      description = "The input vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The vector to copy the values from."
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec2",
                      description = "The input vector."
                    }
                  }
                }
              }
            },
            {
              name = "sub",
              summary = "Subtract a vector or a number from the vector.",
              description = "Subtracts a vector or a number from the vector.",
              key = "Vec2:sub",
              module = "lovr.math",
              related = {
                "Vec2:add",
                "Vec2:mul",
                "Vec2:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec2",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to subtract from x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to subtract from y component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec2",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "unpack",
              summary = "Get the components of the vector.",
              description = "Returns the 2 components of the vector as numbers.",
              key = "Vec2:unpack",
              module = "lovr.math",
              related = {
                "Vec2:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x value."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y value."
                    }
                  }
                }
              }
            }
          },
          related = {
            "Vec3",
            "Vec4",
            "Vectors"
          }
        },
        {
          name = "Vec3",
          summary = "A 3D vector.",
          description = "A vector object that holds three numbers.",
          key = "Vec3",
          module = "lovr.math",
          constructors = {
            "lovr.math.newVec3",
            "lovr.math.vec3"
          },
          methods = {
            {
              name = "add",
              summary = "Add a vector or a number to the vector.",
              description = "Adds a vector or a number to the vector.",
              key = "Vec3:add",
              module = "lovr.math",
              related = {
                "Vec3:sub",
                "Vec3:mul",
                "Vec3:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to add to x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to add to y component.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to add to z component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "angle",
              summary = "Get the angle to another vector.",
              description = "Returns the angle between vectors.",
              key = "Vec3:angle",
              module = "lovr.math",
              notes = "If any of the two vectors have a length of zero, the angle between them is not well defined.  In this case the function returns `math.pi / 2`.",
              related = {
                "Vec3:distance",
                "Vec3:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to the other vector, in radians."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to the other vector, in radians."
                    }
                  }
                }
              }
            },
            {
              name = "cross",
              summary = "Get the cross product with another vector.",
              description = "Sets this vector to be equal to the cross product between this vector and another one.  The new `v` will be perpendicular to both the old `v` and `u`.",
              key = "Vec3:cross",
              module = "lovr.math",
              notes = "The vectors are not normalized before or after computing the cross product.",
              related = {
                "Vec3:dot"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The vector to compute the cross product with."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to compute cross product with."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to compute cross product with."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to compute cross product with."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "distance",
              summary = "Get the distance to another vector.",
              description = "Returns the distance to another vector.",
              key = "Vec3:distance",
              module = "lovr.math",
              related = {
                "Vec3:angle",
                "Vec3:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The vector to measure the distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to measure distance to."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to measure distance to."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to measure distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                }
              }
            },
            {
              name = "div",
              summary = "Divides the vector by a vector or a number.",
              description = "Divides the vector by a vector or a number.",
              key = "Vec3:div",
              module = "lovr.math",
              related = {
                "Vec3:add",
                "Vec3:sub",
                "Vec3:mul"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector to divide the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to divide x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to divide y component by.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to divide z component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "dot",
              summary = "Get the dot product with another vector.",
              description = "Returns the dot product between this vector and another one.",
              key = "Vec3:dot",
              module = "lovr.math",
              notes = "This is computed as:\n\n    dot = v.x * u.x + v.y * u.y + v.z * u.z\n\nThe vectors are not normalized before computing the dot product.",
              related = {
                "Vec3:cross"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The vector to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to compute the dot product with."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to compute the dot product with."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                }
              }
            },
            {
              name = "equals",
              summary = "Check if a vector equals another vector.",
              description = "Returns whether a vector is approximately equal to another vector.",
              key = "Vec3:equals",
              module = "lovr.math",
              notes = "To handle floating point precision issues, this function returns true as long as the squared distance between the vectors is below `1e-10`.",
              related = {
                "Vec2:equals",
                "Vec4:equals",
                "Quat:equals",
                "Mat4:equals"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                }
              }
            },
            {
              name = "length",
              summary = "Get the length of the vector.",
              description = "Returns the length of the vector.",
              key = "Vec3:length",
              module = "lovr.math",
              notes = "The length is equivalent to this:\n\n    math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)",
              related = {
                "Vec3:normalize",
                "Vec3:distance"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the vector."
                    }
                  }
                }
              }
            },
            {
              name = "lerp",
              summary = "Moves this vector some amount towards another one.",
              description = "Performs a linear interpolation between this vector and another one, which can be used to smoothly animate between two vectors, based on a parameter value.  A parameter value of `0` will leave the vector unchanged, a parameter value of `1` will set the vector to be equal to the input vector, and a value of `.5` will set the components to be halfway between the two vectors.",
              key = "Vec3:lerp",
              module = "lovr.math",
              related = {
                "Quat:slerp"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The vector to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The interpolated vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to lerp towards."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to lerp towards."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The interpolated vector."
                    }
                  }
                }
              }
            },
            {
              name = "mul",
              summary = "Multiply the vector by a vector or a number.",
              description = "Multiplies the vector by a vector or a number.",
              key = "Vec3:mul",
              module = "lovr.math",
              related = {
                "Vec3:add",
                "Vec3:sub",
                "Vec3:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector to multiply the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to multiply x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to multiply y component by.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to multiply z component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "normalize",
              summary = "Normalize the length of the vector to 1.",
              description = "Adjusts the values in the vector so that its direction stays the same but its length becomes 1.",
              key = "Vec3:normalize",
              module = "lovr.math",
              related = {
                "Vec3:length"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The normalized vector."
                    }
                  }
                }
              }
            },
            {
              name = "rotate",
              summary = "Apply a rotation to the vector.",
              description = "Applies a rotation to the vector, using a `Quat` or an angle/axis rotation.",
              key = "Vec3:rotate",
              module = "lovr.math",
              related = {
                "Quat:mul"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "q",
                      type = "Quat",
                      description = "The quaternion to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians to rotate."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis to rotate around."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis to rotate around."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis to rotate around."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "set",
              summary = "Set the components of the vector.",
              description = "Sets the components of the vector, either from numbers or an existing vector.",
              key = "Vec3:set",
              module = "lovr.math",
              related = {
                "Vec3:unpack"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The new x value of the vector.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The new y value of the vector.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The new z value of the vector.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The input vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The vector to copy the values from."
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The input vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "q",
                      type = "Quat",
                      description = "A quat to use the direction of."
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The input vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The matrix to use the position of."
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec3",
                      description = "The input vector."
                    }
                  }
                }
              }
            },
            {
              name = "sub",
              summary = "Subtract a vector or a number from the vector.",
              description = "Subtracts a vector or a number from the vector.",
              key = "Vec3:sub",
              module = "lovr.math",
              related = {
                "Vec3:add",
                "Vec3:mul",
                "Vec3:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec3",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to subtract from x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to subtract from y component.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to subtract from z component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "transform",
              summary = "Apply a transform to the vector.",
              description = "Applies a transform (translation, rotation, scale) to the vector using a `Mat4` or numbers. This is the same as multiplying the vector by a matrix.  This treats the vector as a point.",
              key = "Vec3:transform",
              module = "lovr.math",
              related = {
                "Mat4:mul",
                "Vec4:transform",
                "Vec3:rotate"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The matrix to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The original vector, with transformed components."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale factor.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians to rotate around the rotation axis.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The original vector, with transformed components."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "translation",
                      type = "Vec3",
                      description = "The translation to apply."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale factor.",
                      default = "1"
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The rotation to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec3",
                      description = "The original vector, with transformed components."
                    }
                  }
                }
              }
            },
            {
              name = "unpack",
              summary = "Get the components of the vector.",
              description = "Returns the 3 components of the vector as numbers.",
              key = "Vec3:unpack",
              module = "lovr.math",
              related = {
                "Vec3:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x value."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y value."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z value."
                    }
                  }
                }
              }
            }
          },
          related = {
            "Vec2",
            "Vec4",
            "Vectors"
          }
        },
        {
          name = "Vec4",
          summary = "A 4D vector.",
          description = "A vector object that holds four numbers.",
          key = "Vec4",
          module = "lovr.math",
          constructors = {
            "lovr.math.newVec4",
            "lovr.math.vec4"
          },
          methods = {
            {
              name = "add",
              summary = "Add a vector or a number to the vector.",
              description = "Adds a vector or a number to the vector.",
              key = "Vec4:add",
              module = "lovr.math",
              related = {
                "Vec4:sub",
                "Vec4:mul",
                "Vec4:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to add to x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to add to y component.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to add to z component.",
                      default = "x"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value to add to w component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "angle",
              summary = "Get the angle to another vector.",
              description = "Returns the angle between vectors.",
              key = "Vec4:angle",
              module = "lovr.math",
              notes = "If any of the two vectors have a length of zero, the angle between them is not well defined.  In this case the function returns `math.pi / 2`.",
              related = {
                "Vec4:distance",
                "Vec4:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to other vector, in radians."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the other vector."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The w component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle to other vector, in radians."
                    }
                  }
                }
              }
            },
            {
              name = "distance",
              summary = "Get the distance to another vector.",
              description = "Returns the distance to another vector.",
              key = "Vec4:distance",
              module = "lovr.math",
              related = {
                "Vec4:angle",
                "Vec4:length"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The vector to measure the distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to measure distance to."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to measure distance to."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to measure distance to."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value of w component to measure distance to."
                    }
                  },
                  returns = {
                    {
                      name = "distance",
                      type = "number",
                      description = "The distance to `u`."
                    }
                  }
                }
              }
            },
            {
              name = "div",
              summary = "Divides the vector by a vector or a number.",
              description = "Divides the vector by a vector or a number.",
              key = "Vec4:div",
              module = "lovr.math",
              related = {
                "Vec4:add",
                "Vec4:sub",
                "Vec4:mul"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector to divide the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to divide x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to divide y component by.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to divide z component by.",
                      default = "x"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value to divide w component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "dot",
              summary = "Get the dot product with another vector.",
              description = "Returns the dot product between this vector and another one.",
              key = "Vec4:dot",
              module = "lovr.math",
              notes = "This is computed as:\n\n    dot = v.x * u.x + v.y * u.y + v.z * u.z + v.w * u.w\n\nThe vectors are not normalized before computing the dot product.",
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The vector to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to compute the dot product with."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to compute the dot product with."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to compute the dot product with."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value of w component to compute the dot product with."
                    }
                  },
                  returns = {
                    {
                      name = "dot",
                      type = "number",
                      description = "The dot product between `v` and `u`."
                    }
                  }
                }
              }
            },
            {
              name = "equals",
              summary = "Check if a vector equals another vector.",
              description = "Returns whether a vector is approximately equal to another vector.",
              key = "Vec4:equals",
              module = "lovr.math",
              notes = "To handle floating point precision issues, this function returns true as long as the squared distance between the vectors is below `1e-10`.",
              related = {
                "Vec2:equals",
                "Vec3:equals",
                "Quat:equals",
                "Mat4:equals"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the other vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the other vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the other vector."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The w component of the other vector."
                    }
                  },
                  returns = {
                    {
                      name = "equal",
                      type = "boolean",
                      description = "Whether the 2 vectors approximately equal each other."
                    }
                  }
                }
              }
            },
            {
              name = "length",
              summary = "Get the length of the vector.",
              description = "Returns the length of the vector.",
              key = "Vec4:length",
              module = "lovr.math",
              notes = "The length is equivalent to this:\n\n    math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w)",
              related = {
                "Vec4:normalize",
                "Vec4:distance"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the vector."
                    }
                  }
                }
              }
            },
            {
              name = "lerp",
              summary = "Moves this vector some amount towards another one.",
              description = "Performs a linear interpolation between this vector and another one, which can be used to smoothly animate between two vectors, based on a parameter value.  A parameter value of `0` will leave the vector unchanged, a parameter value of `1` will set the vector to be equal to the input vector, and a value of `.5` will set the components to be halfway between the two vectors.",
              key = "Vec4:lerp",
              module = "lovr.math",
              related = {
                "Quat:slerp"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The vector to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The interpolated vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value of x component to lerp towards."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value of y component to lerp towards."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value of z component to lerp towards."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value of w component to lerp towards."
                    },
                    {
                      name = "t",
                      type = "number",
                      description = "The lerping parameter."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The interpolated vector."
                    }
                  }
                }
              }
            },
            {
              name = "mul",
              summary = "Multiply the vector by a vector or a number.",
              description = "Multiplies the vector by a vector or a number.",
              key = "Vec4:mul",
              module = "lovr.math",
              related = {
                "Vec4:add",
                "Vec4:sub",
                "Vec4:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector to multiply the components by."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to multiply x component by."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to multiply y component by.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to multiply z component by.",
                      default = "x"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value to multiply w component by.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "normalize",
              summary = "Normalize the length of the vector to 1.",
              description = "Adjusts the values in the vector so that its direction stays the same but its length becomes 1.",
              key = "Vec4:normalize",
              module = "lovr.math",
              related = {
                "Vec4:length"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The normalized vector."
                    }
                  }
                }
              }
            },
            {
              name = "set",
              summary = "Set the components of the vector.",
              description = "Sets the components of the vector, either from numbers or an existing vector.",
              key = "Vec4:set",
              module = "lovr.math",
              related = {
                "Vec4:unpack"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The new x value of the vector.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The new y value of the vector.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The new z value of the vector.",
                      default = "x"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The new w value of the vector.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec4",
                      description = "The input vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The vector to copy the values from."
                    }
                  },
                  returns = {
                    {
                      name = "v",
                      type = "Vec4",
                      description = "The input vector."
                    }
                  }
                }
              }
            },
            {
              name = "sub",
              summary = "Subtract a vector or a number from the vector.",
              description = "Subtracts a vector or a number from the vector.",
              key = "Vec4:sub",
              module = "lovr.math",
              related = {
                "Vec4:add",
                "Vec4:mul",
                "Vec4:div"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "u",
                      type = "Vec4",
                      description = "The other vector."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "A value to subtract from x component."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "A value to subtract from y component.",
                      default = "x"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "A value to subtract from z component.",
                      default = "x"
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "A value to subtract from w component.",
                      default = "x"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The modified vector."
                    }
                  }
                }
              }
            },
            {
              name = "transform",
              summary = "Apply a transform to the vector.",
              description = "Applies a transform (translation, rotation, scale) to the vector using a `Mat4` or numbers. This is the same as multiplying the vector by a matrix.",
              key = "Vec4:transform",
              module = "lovr.math",
              related = {
                "Mat4:mul",
                "Vec3:transform"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "m",
                      type = "Mat4",
                      description = "The matrix to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The original vector, with transformed components."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the translation.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the translation.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the translation.",
                      default = "0"
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale factor.",
                      default = "1"
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians to rotate around the rotation axis.",
                      default = "0"
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation.",
                      default = "0"
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation.",
                      default = "1"
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation.",
                      default = "0"
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The original vector, with transformed components."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "translation",
                      type = "Vec3",
                      description = "The translation to apply."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale factor.",
                      default = "1"
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The rotation to apply."
                    }
                  },
                  returns = {
                    {
                      name = "self",
                      type = "Vec4",
                      description = "The original vector, with transformed components."
                    }
                  }
                }
              }
            },
            {
              name = "unpack",
              summary = "Get the components of the vector.",
              description = "Returns the 4 components of the vector as numbers.",
              key = "Vec4:unpack",
              module = "lovr.math",
              related = {
                "Vec4:set"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x value."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y value."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z value."
                    },
                    {
                      name = "w",
                      type = "number",
                      description = "The w value."
                    }
                  }
                }
              }
            }
          },
          related = {
            "Vec2",
            "Vec3",
            "Vectors"
          }
        },
        {
          name = "Vectors",
          summary = "What is your vector victor.",
          description = "LÖVR has math objects for vectors, matrices, and quaternions, collectively called \"vector objects\".  Vectors are useful because they can represent a multidimensional quantity (like a 3D position) using just a single value.",
          key = "Vectors",
          module = "lovr.math",
          constructors = {
            "lovr.math.vec2",
            "lovr.math.vec3",
            "lovr.math.vec4",
            "lovr.math.quat",
            "lovr.math.mat4",
            "lovr.math.newVec2",
            "lovr.math.newVec3",
            "lovr.math.newVec4",
            "lovr.math.newQuat",
            "lovr.math.newMat4"
          },
          methods = {},
          notes = "Most LÖVR functions that accept positions, orientations, transforms, velocities, etc. also accept vector objects, so they can be used interchangeably with numbers:\n\n    function lovr.draw(pass)\n      -- position and size are vec3's, rotation is a quat\n      pass:box(position, size, rotation)\n    end\n\n### Temporary vs. Permanent\n\nVectors can be created in two different ways: **permanent** and **temporary**.\n\n**Permanent** vectors behave like normal Lua values.  They are individual objects that are garbage collected when no longer needed.  They're created using the usual `lovr.math.new<Type>` syntax:\n\n    self.position = lovr.math.newVec3(x, y, z)\n\n**Temporary** vectors are created from a shared pool of vector objects.  This makes them faster because they use temporary memory and do not need to be garbage collected.  To make a temporary vector, leave off the `new` prefix:\n\n    local position = lovr.math.vec3(x, y, z)\n\nAs a shortcut, vector constructors are placed on the global scope.  The uppercase name of the vector is a function that will create a permanent vector, and the lowercase name will create a temporary vector.  This can be disabled using the `t.math.globals` option in `lovr.conf`.\n\n    local position = vec3(x1, y1, z1) + vec3(x2, y2, z2)\n    local transform = Mat4()\n\nTemporary vectors, with all their speed, come with an important restriction: they can only be used during the frame in which they were created.  Saving them into variables and using them later on will throw an error:\n\n    local position = vec3(1, 2, 3)\n\n    function lovr.update(dt)\n      -- Reusing the temporary 'position' vector across frames will error:\n      position:add(vec3(dt))\n    end\n\nIt's possible to overflow the temporary vector pool.  If that happens, `lovr.math.drain` can be used to periodically drain the pool, invalidating any existing temporary vectors.\n\n### Metamethods\n\nVectors have metamethods, allowing them to be used using the normal math operators like `+`, `-`, `*`, `/`, etc.\n\n    print(vec3(2, 4, 6) * .5 + vec3(10, 20, 30))\n\nThese metamethods will create new temporary vectors.\n\n### Components and Swizzles\n\nThe raw components of a vector can be accessed like normal fields:\n\n    print(vec3(1, 2, 3).z) --> 3\n    print(mat4()[16]) --> 1\n\nAlso, multiple fields can be accessed and combined into a new (temporary) vector, called swizzling:\n\n    local position = vec3(10, 5, 1)\n    print(position.xy) --> vec2(10, 5)\n    print(position.xyy) --> vec3(10, 5, 5)\n    print(position.zyxz) --> vec4(1, 5, 10, 1)\n\nThe following fields are supported for vectors:\n\n- `x`, `y`, `z`, `w`\n- `r`, `g`, `b`, `a`\n- `s`, `t`, `p`, `q`\n\nQuaternions support `x`, `y`, `z`, and `w`.\n\nMatrices use numbers for accessing individual components in \"column-major\" order.\n\nAll fields can also be assigned to.\n\n    -- Swap the components of a 2D vector\n    v.xy = v.yx\n\nThe `unpack` function can be used (on any vector type) to access all of the individual components of a vector object.  For quaternions you can choose whether you want to unpack the angle/axis representation or the raw quaternion components.  Similarly, matrices support raw unpacking as well as decomposition into translation/scale/rotation values.\n\n### Vector Constants\n\nThe following vector constants are available.  They return new temporary vectors each time they are used:\n\n- `vec2.zero` (0, 0)\n- `vec2.one` (1, 1)\n- `vec3.zero` (0, 0, 0)\n- `vec3.one` (1, 1, 1)\n- `vec3.left` (-1, 0, 0)\n- `vec3.right` (1, 0, 0)\n- `vec3.up` (0, 1, 0)\n- `vec3.down` (0, -1, 0)\n- `vec3.back` (0, 0, 1)\n- `vec3.forward` (0, 0, -1)\n- `vec4.zero` (0, 0, 0, 0)\n- `vec4.one` (1, 1, 1, 1)\n- `quat.identity` (0, 0, 0, 1)"
        }
      },
      sections = {
        {
          name = "Randomization",
          tag = "random",
          description = "Functions for generating random numbers and noise."
        },
        {
          name = "Vectors",
          tag = "vectors",
          description = "A collection of vector objects.  Check out the `Vectors` guide for an introduction."
        },
        {
          name = "Other",
          tag = "mathOther",
          description = "Other miscellaneous math objects/helpers."
        }
      }
    },
    {
      name = "physics",
      tag = "modules",
      summary = "Simulates 3D physics.",
      description = "The `lovr.physics` module simulates 3D rigid body physics.",
      key = "lovr.physics",
      enums = {
        {
          name = "JointType",
          summary = "Types of physics joints.",
          description = "Represents the different types of physics Joints available.",
          key = "JointType",
          module = "lovr.physics",
          related = {
            "Joint",
            "BallJoint",
            "DistanceJoint",
            "HingeJoint",
            "SliderJoint"
          },
          values = {
            {
              name = "ball",
              description = "A BallJoint."
            },
            {
              name = "distance",
              description = "A DistanceJoint."
            },
            {
              name = "hinge",
              description = "A HingeJoint."
            },
            {
              name = "slider",
              description = "A SliderJoint."
            }
          }
        },
        {
          name = "MotorMode",
          summary = "The different states for joint motors.",
          description = "The different ways the motor on a joint can be used.",
          key = "MotorMode",
          module = "lovr.physics",
          related = {
            "HingeJoint:setMotorMode",
            "SliderJoint:setMotorMode"
          },
          values = {
            {
              name = "position",
              description = "The motor drives to a particular value."
            },
            {
              name = "velocity",
              description = "The motor drives to a particular speed."
            }
          }
        },
        {
          name = "ShapeType",
          summary = "Types of physics shapes.",
          description = "Represents the different types of physics Shapes available.",
          key = "ShapeType",
          module = "lovr.physics",
          related = {
            "Shape",
            "BoxShape",
            "SphereShape",
            "CapsuleShape",
            "CylinderShape",
            "ConvexShape",
            "MeshShape",
            "TerrainShape"
          },
          values = {
            {
              name = "box",
              description = "A box."
            },
            {
              name = "sphere",
              description = "A sphere."
            },
            {
              name = "capsule",
              description = "A capsule (cylinder with rounded ends)."
            },
            {
              name = "cylinder",
              description = "A cylinder."
            },
            {
              name = "convex",
              description = "A convex hull."
            },
            {
              name = "mesh",
              description = "A triangle mesh.  Colliders with this shape can not move."
            },
            {
              name = "terrain",
              description = "A heightfield.  Colliders with this shape can not move."
            }
          }
        }
      },
      functions = {
        {
          name = "newBallJoint",
          summary = "Create a new BallJoint.",
          description = "Creates a new BallJoint.",
          key = "lovr.physics.newBallJoint",
          module = "lovr.physics",
          notes = "A ball joint is like a ball and socket between the two colliders.  It tries to keep the distance between the colliders and the anchor position the same, but does not constrain the angle between them.\n\nIf the anchor is nil, the position of the first Collider is the anchor.  If the first collider is nil, then the position of the second Collider is the anchor.",
          related = {
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint",
            "lovr.physics.newWeldJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the joint anchor point, in world coordinates."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the joint anchor point, in world coordinates."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the joint anchor point, in world coordinates."
                }
              },
              returns = {
                {
                  name = "ball",
                  type = "BallJoint",
                  description = "The new BallJoint."
                }
              }
            },
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "anchor",
                  type = "Vec3",
                  description = "The joint anchor point, in world coordinates."
                }
              },
              returns = {
                {
                  name = "ball",
                  type = "BallJoint",
                  description = "The new BallJoint."
                }
              }
            }
          }
        },
        {
          name = "newBoxShape",
          summary = "Create a new BoxShape.",
          description = "Creates a new BoxShape.",
          key = "lovr.physics.newBoxShape",
          module = "lovr.physics",
          notes = "A Shape can be attached to a Collider using `Collider:addShape`.",
          related = {
            "BoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          },
          variants = {
            {
              arguments = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the box, in meters.",
                  default = "1"
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the box, in meters.",
                  default = "width"
                },
                {
                  name = "depth",
                  type = "number",
                  description = "The depth of the box, in meters.",
                  default = "width"
                }
              },
              returns = {
                {
                  name = "box",
                  type = "BoxShape",
                  description = "The new BoxShape."
                }
              }
            }
          }
        },
        {
          name = "newCapsuleShape",
          summary = "Create a new CapsuleShape.",
          description = "Creates a new CapsuleShape.  Capsules are cylinders with hemispheres on each end.",
          key = "lovr.physics.newCapsuleShape",
          module = "lovr.physics",
          notes = "A Shape can be attached to a Collider using `Collider:addShape`.",
          related = {
            "CapsuleShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          },
          variants = {
            {
              arguments = {
                {
                  name = "radius",
                  type = "number",
                  description = "The radius of the capsule, in meters.",
                  default = "1"
                },
                {
                  name = "length",
                  type = "number",
                  description = "The length of the capsule, not including the caps, in meters.",
                  default = "1"
                }
              },
              returns = {
                {
                  name = "capsule",
                  type = "CapsuleShape",
                  description = "The new CapsuleShape."
                }
              }
            }
          }
        },
        {
          name = "newConeJoint",
          summary = "Create a new ConeJoint.",
          description = "Creates a new ConeJoint.",
          key = "lovr.physics.newConeJoint",
          module = "lovr.physics",
          notes = "A ConeJoint is similar to a BallJoint, where the relative position between the colliders will be constrained to a single point.  However, the ConeJoint also limits the rotation away from the cone axis.  This can be useful for limb joints, ropes, etc.\n\nIf the anchor is nil, the position of the first Collider is the anchor.  If the first Collider is nil, the position of the second collider is the anchor.\n\nIf the axis is nil, it defaults to the direction between the anchor and the second Collider.",
          related = {
            "lovr.physics.newWeldJoint",
            "lovr.physics.newBallJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the joint anchor point, in world space."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the joint anchor point, in world space."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the joint anchor point, in world space."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the cone axis, in world space."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the cone axis, in world space."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the cone axis, in world space."
                }
              },
              returns = {
                {
                  name = "cone",
                  type = "ConeJoint",
                  description = "The new ConeJoint."
                }
              }
            },
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "anchor",
                  type = "Vec3",
                  description = "The joint anchor point, in world space."
                },
                {
                  name = "axis",
                  type = "Vec3",
                  description = "The cone axis, in world space."
                }
              },
              returns = {
                {
                  name = "cone",
                  type = "ConeJoint",
                  description = "The new ConeJoint."
                }
              }
            }
          }
        },
        {
          name = "newConvexShape",
          summary = "Create a new ConvexShape.",
          description = "Creates a new ConvexShape.",
          key = "lovr.physics.newConvexShape",
          module = "lovr.physics",
          related = {
            "ConvexShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          },
          variants = {
            {
              arguments = {
                {
                  name = "points",
                  type = "table",
                  description = "A list of vertices to compute a convex hull from.  Can be a table of tables (each with 3 numbers) or a table of numbers (every 3 numbers form a 3D point)."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the points.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "shape",
                  type = "ConvexShape",
                  description = "The new ConvexShape."
                }
              }
            },
            {
              arguments = {
                {
                  name = "object",
                  type = "ModelData | Model | Mesh",
                  description = "An object to use for the points of the convex hull."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the points.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "shape",
                  type = "ConvexShape",
                  description = "The new ConvexShape."
                }
              }
            },
            {
              description = "Clones an existing ConvexShape, which is faster than passing the same points multiple times. Clones can have their own scale.  The clone's scale doesn't get multiplied with the scale of the template.",
              arguments = {
                {
                  name = "template",
                  type = "ConvexShape",
                  description = "An existing ConvexShape to clone."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the points.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "shape",
                  type = "ConvexShape",
                  description = "The new ConvexShape."
                }
              }
            }
          }
        },
        {
          name = "newCylinderShape",
          summary = "Create a new CylinderShape.",
          description = "Creates a new CylinderShape.",
          key = "lovr.physics.newCylinderShape",
          module = "lovr.physics",
          notes = "A Shape can be attached to a Collider using `Collider:addShape`.",
          related = {
            "CylinderShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          },
          variants = {
            {
              arguments = {
                {
                  name = "radius",
                  type = "number",
                  description = "The radius of the cylinder, in meters.",
                  default = "1"
                },
                {
                  name = "length",
                  type = "number",
                  description = "The length of the cylinder, in meters.",
                  default = "1"
                }
              },
              returns = {
                {
                  name = "cylinder",
                  type = "CylinderShape",
                  description = "The new CylinderShape."
                }
              }
            }
          }
        },
        {
          name = "newDistanceJoint",
          summary = "Create a new DistanceJoint.",
          description = "Creates a new DistanceJoint.",
          key = "lovr.physics.newDistanceJoint",
          module = "lovr.physics",
          notes = "A distance joint tries to keep the two colliders a fixed distance apart.  The distance is determined by the initial distance between the anchor points.  The joint allows for rotation on the anchor points.\n\nIf no anchors are given, they default to the positions of the Colliders.",
          related = {
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint",
            "lovr.physics.newWeldJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "x1",
                  type = "number",
                  description = "The x position of the first anchor point, in world coordinates."
                },
                {
                  name = "y1",
                  type = "number",
                  description = "The y position of the first anchor point, in world coordinates."
                },
                {
                  name = "z1",
                  type = "number",
                  description = "The z position of the first anchor point, in world coordinates."
                },
                {
                  name = "x2",
                  type = "number",
                  description = "The x position of the second anchor point, in world coordinates."
                },
                {
                  name = "y2",
                  type = "number",
                  description = "The y position of the second anchor point, in world coordinates."
                },
                {
                  name = "z2",
                  type = "number",
                  description = "The z position of the second anchor point, in world coordinates."
                }
              },
              returns = {
                {
                  name = "joint",
                  type = "DistanceJoint",
                  description = "The new DistanceJoint."
                }
              }
            },
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "first",
                  type = "Vec3",
                  description = "The first anchor point, in world coordinates."
                },
                {
                  name = "second",
                  type = "Vec3",
                  description = "The second anchor point, in world coordinates."
                }
              },
              returns = {
                {
                  name = "joint",
                  type = "DistanceJoint",
                  description = "The new DistanceJoint."
                }
              }
            }
          }
        },
        {
          name = "newHingeJoint",
          summary = "Create a new HingeJoint.",
          description = "Creates a new HingeJoint.",
          key = "lovr.physics.newHingeJoint",
          module = "lovr.physics",
          notes = "A hinge joint constrains two colliders to allow rotation only around the hinge's axis.\n\nIf the anchor is nil, the position of the first Collider is the anchor.  If the first Collider is nil, the position of the second collider is the anchor.\n\nIf the axis is nil, it defaults to the direction between the anchor and the second Collider.",
          related = {
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newSliderJoint",
            "lovr.physics.newWeldJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the hinge anchor, in world coordinates."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the hinge anchor, in world coordinates."
                },
                {
                  name = "z",
                  type = "number",
                  description = "The z position of the hinge anchor, in world coordinates."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the hinge axis direction."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the hinge axis direction."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the hinge axis direction."
                }
              },
              returns = {
                {
                  name = "hinge",
                  type = "HingeJoint",
                  description = "The new HingeJoint."
                }
              }
            },
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "anchor",
                  type = "Vec3",
                  description = "The anchor point, in world coordinates."
                },
                {
                  name = "axis",
                  type = "Vec3",
                  description = "The hinge axis direction."
                }
              },
              returns = {
                {
                  name = "hinge",
                  type = "HingeJoint",
                  description = "The new HingeJoint."
                }
              }
            }
          }
        },
        {
          name = "newMeshShape",
          summary = "Create a new MeshShape.",
          description = "Creates a new MeshShape.",
          key = "lovr.physics.newMeshShape",
          module = "lovr.physics",
          related = {
            "MeshShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newTerrainShape",
            "Model:getTriangles"
          },
          variants = {
            {
              arguments = {
                {
                  name = "vertices",
                  type = "table",
                  description = "The table of vertices in the mesh.  Each vertex is a table with 3 numbers."
                },
                {
                  name = "indices",
                  type = "table",
                  description = "A table of triangle indices representing how the vertices are connected in the Mesh."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the mesh vertices.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "MeshShape",
                  description = "The new MeshShape."
                }
              }
            },
            {
              arguments = {
                {
                  name = "object",
                  type = "ModelData | Model | Mesh",
                  description = "An object to use the triangles from.  Meshes must use the `cpu` storage mode."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the mesh vertices.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "MeshShape",
                  description = "The new MeshShape."
                }
              }
            },
            {
              description = "Clones an existing MeshShape, which is faster than passing the same mesh multiple times. Clones can have their own scale.  The clone's scale doesn't get multiplied with the scale of the template.",
              arguments = {
                {
                  name = "template",
                  type = "MeshShape",
                  description = "An existing MeshShape to clone."
                },
                {
                  name = "scale",
                  type = "number",
                  description = "A scale to apply to the mesh vertices.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "mesh",
                  type = "MeshShape",
                  description = "The new MeshShape."
                }
              }
            }
          }
        },
        {
          name = "newSliderJoint",
          summary = "Create a new SliderJoint.",
          description = "Creates a new SliderJoint.",
          key = "lovr.physics.newSliderJoint",
          module = "lovr.physics",
          notes = "A slider joint constrains two colliders to only allow movement along the slider's axis.",
          related = {
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newWeldJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "ax",
                  type = "number",
                  description = "The x component of the slider axis."
                },
                {
                  name = "ay",
                  type = "number",
                  description = "The y component of the slider axis."
                },
                {
                  name = "az",
                  type = "number",
                  description = "The z component of the slider axis."
                }
              },
              returns = {
                {
                  name = "slider",
                  type = "SliderJoint",
                  description = "The new SliderJoint."
                }
              }
            },
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                },
                {
                  name = "axis",
                  type = "Vec3",
                  description = "The slider axis direction."
                }
              },
              returns = {
                {
                  name = "slider",
                  type = "SliderJoint",
                  description = "The new SliderJoint."
                }
              }
            }
          }
        },
        {
          name = "newSphereShape",
          summary = "Create a new SphereShape.",
          description = "Creates a new SphereShape.",
          key = "lovr.physics.newSphereShape",
          module = "lovr.physics",
          notes = "A Shape can be attached to a Collider using `Collider:addShape`.",
          related = {
            "SphereShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          },
          variants = {
            {
              arguments = {
                {
                  name = "radius",
                  type = "number",
                  description = "The radius of the sphere, in meters.",
                  default = "1"
                }
              },
              returns = {
                {
                  name = "sphere",
                  type = "SphereShape",
                  description = "The new SphereShape."
                }
              }
            }
          }
        },
        {
          name = "newTerrainShape",
          summary = "Create a new TerrainShape.",
          description = "Creates a new TerrainShape.",
          key = "lovr.physics.newTerrainShape",
          module = "lovr.physics",
          notes = "A Shape can be attached to a Collider using `Collider:addShape`. For immobile terrain use the `Collider:setKinematic`.",
          related = {
            "TerrainShape",
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.data.newImage"
          },
          variants = {
            {
              description = "Create a flat floor collider.",
              arguments = {
                {
                  name = "scale",
                  type = "number",
                  description = "The width and depth of the terrain, in meters."
                }
              },
              returns = {
                {
                  name = "terrain",
                  type = "TerrainShape",
                  description = "The new TerrainShape."
                }
              }
            },
            {
              description = "Create terrain from a heightmap image.",
              arguments = {
                {
                  name = "scale",
                  type = "number",
                  description = "The width and depth of the terrain, in meters."
                },
                {
                  name = "heightmap",
                  type = "Image",
                  description = "A heightmap image describing the terrain elevation at different points.  The red channel brightness of each pixel determines the elevation at corresponding coordinates."
                },
                {
                  name = "stretch",
                  type = "number",
                  description = "A vertical multiplier for height values to obtain terrain height.  When the image format has pixel values only in the 0 to 1 range, this can be used to scale the height to meters.",
                  default = "1.0"
                }
              },
              returns = {
                {
                  name = "terrain",
                  type = "TerrainShape",
                  description = "The new TerrainShape."
                }
              }
            },
            {
              description = "Create terrain defined with a callback function.",
              arguments = {
                {
                  name = "scale",
                  type = "number",
                  description = "The width and depth of the terrain, in meters."
                },
                {
                  name = "callback",
                  type = "function",
                  description = "A function that computes terrain height from x and z coordinates.  The x and z inputs will range from `-scale / 2` to `scale / 2`.",
                  arguments = {
                    {
                      name = "x",
                      type = "number"
                    },
                    {
                      name = "z",
                      type = "number"
                    }
                  },
                  returns = {
                    name = "height",
                    type = "number"
                  }
                },
                {
                  name = "samples",
                  type = "number",
                  description = "The number of samples taken across the x and z dimensions.  More samples will result in higher terrain fidelity, but use more CPU and memory.",
                  default = "100"
                }
              },
              returns = {
                {
                  name = "terrain",
                  type = "TerrainShape",
                  description = "The new TerrainShape."
                }
              }
            }
          }
        },
        {
          name = "newWeldJoint",
          summary = "Create a new WeldJoint.",
          description = "Creates a new WeldJoint.",
          key = "lovr.physics.newWeldJoint",
          module = "lovr.physics",
          notes = "The joint will try to keep the Colliders in the relative pose they were at when the joint was created.",
          related = {
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint"
          },
          variants = {
            {
              arguments = {
                {
                  name = "colliderA",
                  type = "Collider",
                  description = "The first collider to attach the Joint to, or `nil` to attach the joint to a fixed position in the World."
                },
                {
                  name = "colliderB",
                  type = "Collider",
                  description = "The second collider to attach the Joint to."
                }
              },
              returns = {
                {
                  name = "joint",
                  type = "WeldJoint",
                  description = "The new WeldJoint."
                }
              }
            }
          }
        },
        {
          name = "newWorld",
          summary = "Create a new World.",
          description = "Creates a new physics World.",
          key = "lovr.physics.newWorld",
          module = "lovr.physics",
          related = {
            "World:update"
          },
          variants = {
            {
              arguments = {
                {
                  name = "settings",
                  type = "table",
                  description = "An optional table with settings for the physics simulation.",
                  default = "nil",
                  table = {
                    {
                      name = "tags",
                      type = "table",
                      description = "The list of collision tags (strings).  Colliders can be assigned a tag, and collision can be enabled and disabled between different tags.  There is a maximum of 31 tags.",
                      default = "{}"
                    },
                    {
                      name = "staticTags",
                      type = "table",
                      description = "An optional list of collision tags that are \"static\".  Colliders with a static tag will not move, and the physics engine uses this for optimization.",
                      default = "{}"
                    },
                    {
                      name = "maxColliders",
                      type = "number",
                      description = "The maximum number of Colliders in the World.  Increasing this will use more memory. This can't be bigger than 2^23 (around 8 million).",
                      default = "16384"
                    },
                    {
                      name = "threadSafe",
                      type = "boolean",
                      description = "Whether the World and the objects it contains can be used from multiple threads.  This will use a set of locks to ensure only one thread can access a Collider at a given time. Disable this to potentially get a small performance boost when only using the World from a single Thread.",
                      default = "true"
                    },
                    {
                      name = "allowSleep",
                      type = "boolean",
                      description = "Whether colliders should be allowed to go to sleep when they come to rest.  Sleeping colliders don't need to simulate movement until something hits them.  This improves performance a lot for a typical physics scene where many objects are at rest.",
                      default = "true"
                    },
                    {
                      name = "stabilization",
                      type = "number",
                      description = "How quickly the physics engine corrects position error from collisions and joints, from 0 to 1.  If the value is too low, objects will be spongy, but if it's too high then physics will explode.  Values between .2 and .8 are recommended.",
                      default = "0.2"
                    },
                    {
                      name = "maxOverlap",
                      type = "number",
                      description = "The maximum amount that colliders are allowed to overlap, in meters.",
                      default = ".01"
                    },
                    {
                      name = "restitutionThreshold",
                      type = "number",
                      description = "A velocity below which restitution (bounciness) will not be applied, in meters per second.  If this is too low then objects may have trouble coming to rest.",
                      default = "1.0"
                    },
                    {
                      name = "velocitySteps",
                      type = "number",
                      description = "The number of solver velocity iterations to run per tick.  This must be at least 2. Larger values will increase accuracy but use more CPU.",
                      default = "10"
                    },
                    {
                      name = "positionSteps",
                      type = "number",
                      description = "The number of solver position iterations to run per tick.  Larger values will increase accuracy but use more CPU.",
                      default = "2"
                    }
                  }
                }
              },
              returns = {
                {
                  name = "world",
                  type = "World",
                  description = "A whole new World."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "BallJoint",
          summary = "A ball and socket joint.",
          description = "A BallJoint is a type of `Joint` that acts like a ball and socket between two colliders.  It allows the colliders to rotate freely around an anchor point, but does not allow the colliders' distance from the anchor point to change.",
          key = "BallJoint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newBallJoint"
          },
          extends = "Joint",
          methods = {},
          related = {
            "Collider"
          }
        },
        {
          name = "BoxShape",
          summary = "A box Shape.",
          description = "A type of `Shape` that can be used for cubes or boxes.",
          key = "BoxShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newBoxShape",
            "World:newBoxCollider"
          },
          extends = "Shape",
          methods = {
            {
              name = "getDimensions",
              summary = "Get the dimensions of the BoxShape.",
              description = "Returns the width, height, and depth of the BoxShape.",
              key = "BoxShape:getDimensions",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box, in meters."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box, in meters."
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "setDimensions",
              summary = "Set the dimensions of the BoxShape.",
              description = "Sets the width, height, and depth of the BoxShape.",
              key = "BoxShape:setDimensions",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              variants = {
                {
                  arguments = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box, in meters."
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box, in meters."
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box, in meters."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "CapsuleShape",
          summary = "A capsule Shape.",
          description = "A type of `Shape` that can be used for capsule-shaped things.",
          key = "CapsuleShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newCapsuleShape",
            "World:newCapsuleCollider"
          },
          extends = "Shape",
          methods = {
            {
              name = "getLength",
              summary = "Get the length of the CapsuleShape.",
              description = "Returns the length of the CapsuleShape, not including the caps.",
              key = "CapsuleShape:getLength",
              module = "lovr.physics",
              related = {
                "CapsuleShape:getRadius",
                "CapsuleShape:setRadius"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the capsule, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getRadius",
              summary = "Get the radius of the CapsuleShape.",
              description = "Returns the radius of the CapsuleShape.",
              key = "CapsuleShape:getRadius",
              module = "lovr.physics",
              related = {
                "CapsuleShape:getLength",
                "CapsuleShape:setLength"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "setLength",
              summary = "Set the length of the CapsuleShape.",
              description = "Sets the length of the CapsuleShape.",
              key = "CapsuleShape:setLength",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              related = {
                "CapsuleShape:getRadius",
                "CapsuleShape:setRadius"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "length",
                      type = "number",
                      description = "The new length, in meters, not including the caps."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setRadius",
              summary = "Set the radius of the CapsuleShape.",
              description = "Sets the radius of the CapsuleShape.",
              key = "CapsuleShape:setRadius",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              related = {
                "CapsuleShape:getLength",
                "CapsuleShape:setLength"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The new radius, in meters."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Collider",
          summary = "A single object in a physics simulation.",
          description = "Colliders represent a single rigid body in the physics simulation.",
          key = "Collider",
          module = "lovr.physics",
          constructors = {
            "World:newCollider",
            "World:newBoxCollider",
            "World:newSphereCollider",
            "World:newCapsuleCollider",
            "World:newCylinderCollider",
            "World:newConvexCollider",
            "World:newMeshCollider",
            "World:newTerrainCollider"
          },
          extends = "Object",
          methods = {
            {
              name = "addShape",
              summary = "Add a Shape to the Collider.",
              description = "Attaches a Shape to the collider.",
              key = "Collider:addShape",
              module = "lovr.physics",
              notes = "By default, LÖVR will recompute mass properties for the Collider as shapes are added and removed.  Use `Collider:setAutomaticMass` to enable or disable this behavior.\n\nShapes can only be attached to a single Collider.  Attempting to attach a shape to multiple colliders (or to a single collider multiple times) will error.  Use `Collider:removeShape` to remove shapes from their original collider before reattaching them.\n\nAdding a `MeshShape` or a `TerrainShape` will force the Collider to be immobile.  It will immediately become kinematic, and will not move via velocity or forces.  However, it can still be repositioned with methods like `Collider:setPosition`.",
              related = {
                "Collider:removeShape",
                "Collider:getShapes",
                "Collider:getShape",
                "Shape"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to attach."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "applyAngularImpulse",
              summary = "Apply an angular impulse to the Collider.",
              description = "Applies an angular impulse to the Collider.\n\nAn impulse is a single instantaneous push.  Impulses are independent of time, and are meant to only be applied once.  Use `Collider:applyTorque` for a time-dependent push that happens over multiple frames.",
              key = "Collider:applyAngularImpulse",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore forces.\n\nIf the Collider is asleep, this will wake it up.\n\nImpulses are accumulated and processed during `World:update`.",
              related = {
                "Collider:applyTorque",
                "Collider:applyForce",
                "Collider:applyLinearImpulse"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space impulse vector, in newton meter seconds."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space impulse vector, in newton meter seconds."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space impulse vector, in newton meter seconds."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "impulse",
                      type = "Vec3",
                      description = "The world-space impulse vector, in newton meter seconds."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "applyForce",
              summary = "Apply a force to the Collider.",
              description = "Applies a force to the Collider.",
              key = "Collider:applyForce",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore forces.\n\nIf the Collider is asleep, this will wake it up.\n\nForces are accumulated and processed during `World:update`.",
              related = {
                "Collider:applyLinearImpulse",
                "Collider:applyTorque",
                "Collider:applyAngularImpulse"
              },
              variants = {
                {
                  description = "Apply a force at the center of mass.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space force vector, in newtons."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space force vector, in newtons."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space force vector, in newtons."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply a force at a custom position.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space force vector, in newtons."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space force vector, in newtons."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space force vector, in newtons."
                    },
                    {
                      name = "px",
                      type = "number",
                      description = "The x position to apply the force at, in world space."
                    },
                    {
                      name = "py",
                      type = "number",
                      description = "The y position to apply the force at, in world space."
                    },
                    {
                      name = "pz",
                      type = "number",
                      description = "The z position to apply the force at, in world space."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply a force at the center of mass, using vector types.",
                  arguments = {
                    {
                      name = "force",
                      type = "Vec3",
                      description = "The world-space force vector, in newtons."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply a force at a custom position, using vector types.",
                  arguments = {
                    {
                      name = "force",
                      type = "Vec3",
                      description = "The world-space force vector, in newtons."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to apply the force at, in world space."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "applyLinearImpulse",
              summary = "Apply a linear impulse to the Collider.",
              description = "Applies a linear impulse to the Collider.\n\nAn impulse is a single instantaneous push.  Impulses are independent of time, and are meant to only be applied once.  Use `Collider:applyForce` for a time-dependent push that happens over multiple frames.",
              key = "Collider:applyLinearImpulse",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore forces.\n\nIf the Collider is asleep, this will wake it up.\n\nImpulses are accumulated and processed during `World:update`.",
              related = {
                "Collider:applyForce",
                "Collider:applyTorque",
                "Collider:applyAngularImpulse"
              },
              variants = {
                {
                  description = "Apply an impulse at the center of mass.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space impulse vector, in newton seconds."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply an impulse at a custom position.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "px",
                      type = "number",
                      description = "The x position to apply the impulse at, in world space."
                    },
                    {
                      name = "py",
                      type = "number",
                      description = "The y position to apply the impulse at, in world space."
                    },
                    {
                      name = "pz",
                      type = "number",
                      description = "The z position to apply the impulse at, in world space."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply an impulse at the center of mass, using vector types.",
                  arguments = {
                    {
                      name = "impulse",
                      type = "Vec3",
                      description = "The world-space impulse vector, in newton seconds."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Apply an impulse at a custom position, using vector types.",
                  arguments = {
                    {
                      name = "impulse",
                      type = "Vec3",
                      description = "The world-space impulse vector, in newton seconds."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to apply the impulse at, in world space."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "applyTorque",
              summary = "Apply torque to the Collider.",
              description = "Applies torque to the Collider.",
              key = "Collider:applyTorque",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore forces.\n\nIf the Collider is asleep, this will wake it up.\n\nForces are accumulated and processed during `World:update`.",
              related = {
                "Collider:applyAngularImpulse",
                "Collider:applyForce",
                "Collider:applyLinearImpulse"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the world-space torque vector, in newton meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the world-space torque vector, in newton meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the world-space torque vector, in newton meters."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "torque",
                      type = "Vec3",
                      description = "The world-space torque vector, in newton meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "destroy",
              summary = "Destroy the Collider.",
              description = "Destroys the Collider, removing it from the World and destroying all Shapes and Joints attached to it.",
              key = "Collider:destroy",
              module = "lovr.physics",
              notes = "After a Collider is destroyed, calling methods on it or passing it to a function will throw an error.",
              related = {
                "Collider:isDestroyed",
                "Collider:setEnabled",
                "World:destroy",
                "Shape:destroy",
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getAABB",
              summary = "Get the Collider's axis aligned bounding box.",
              description = "Returns the world-space axis-aligned bounding box of the Collider, computed from attached shapes.",
              key = "Collider:getAABB",
              module = "lovr.physics",
              related = {
                "Shape:getAABB",
                "World:queryBox"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the box."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the box."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the box."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the box."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the box."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the box."
                    }
                  }
                }
              }
            },
            {
              name = "getAngularDamping",
              summary = "Get the angular damping of the Collider.",
              description = "Returns the angular damping of the Collider.  Angular damping is similar to drag or air resistance, reducing the Collider's angular velocity over time.",
              key = "Collider:getAngularDamping",
              module = "lovr.physics",
              notes = "The default damping is .05, meaning the collider will lose approximately 5% of its angular velocity each second.  A damping value of zero means the Collider will not lose velocity over time.",
              related = {
                "Collider:getLinearDamping",
                "Collider:setLinearDamping",
                "Collider:getInertia",
                "Collider:setInertia"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The angular damping."
                    }
                  }
                }
              }
            },
            {
              name = "getAngularVelocity",
              summary = "Get the angular velocity of the Collider.",
              description = "Returns the angular velocity of the Collider.",
              key = "Collider:getAngularVelocity",
              module = "lovr.physics",
              related = {
                "Collider:getLinearVelocity",
                "Collider:setLinearVelocity",
                "Collider:applyTorque",
                "Collider:getOrientation",
                "Collider:setOrientation"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x component of the angular velocity."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y component of the angular velocity."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z component of the angular velocity."
                    }
                  }
                }
              }
            },
            {
              name = "getAutomaticMass",
              summary = "Get whether automatic mass is enabled.",
              description = "Returns whether automatic mass is enabled for the Collider.\n\nWhen enabled, the Collider's mass, inertia, and center of mass will be recomputed when:\n\n- A shape is added to or removed from the Collider.\n- A shape attached to the Collider changes shape (e.g. `SphereShape:setRadius`).\n- A shape attached to the Collider is moved using `Shape:setOffset`.\n- A shape attached to the Collider changes its density using `Shape:setDensity`.\n\nAdditionally, changing the center of mass of a Collider will automatically update its inertia when automatic mass is enabled.\n\nDisable this to manage the mass properties manually.  When automatic mass is disabled, `Collider:resetMassData` can still be used to reset the mass from attached shapes if needed.",
              key = "Collider:getAutomaticMass",
              module = "lovr.physics",
              related = {
                "Collider:resetMassData",
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether automatic mass is enabled."
                    }
                  }
                }
              }
            },
            {
              name = "getCenterOfMass",
              summary = "Get the Collider's local center of mass.",
              description = "Returns the Collider's center of mass, in the Collider's local coordinate space.",
              key = "Collider:getCenterOfMass",
              module = "lovr.physics",
              notes = "By default, the center of mass of the Collider is kept up to date automatically as the Collider's shapes change.  To disable this, use `Collider:setAutomaticMass`.\n\nUse `Collider:resetMassData` to reset the center of mass and other mass properties based on the Collider's shapes.",
              related = {
                "Shape:getCenterOfMass",
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the center of mass."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the center of mass."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the center of mass."
                    }
                  }
                }
              }
            },
            {
              name = "getDegreesOfFreedom",
              summary = "Get the enabled translation/rotation axes.",
              description = "Get the degrees of freedom of the Collider.",
              key = "Collider:getDegreesOfFreedom",
              module = "lovr.physics",
              notes = "The default state is `xyz` for both translation and rotation.\n\nThe physics engine does not support disabling all degrees of freedom.  At least one translation or rotation axis needs to be enabled.  To disable all movement for a collider, make it kinematic.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "translation",
                      type = "string",
                      description = "A string containing the world-space axes the Collider is allowed to move on.  The string will have 'x', 'y', and 'z' letters representing which axes are enabled.  If no axes are enabled then it will be an empty string."
                    },
                    {
                      name = "rotation",
                      type = "string",
                      description = "A string containing the world-space axes the Collider is allowed to rotate around.  The string will have 'x', 'y', and 'z' letters representing which axes are enabled.  If no axes are enabled then it will be an empty string."
                    }
                  }
                }
              }
            },
            {
              name = "getFriction",
              summary = "Get the friction of the Collider.",
              description = "Returns the friction of the Collider.  Friction determines how easy it is for two colliders to slide against each other.  Low friction makes it easier for a collider to slide, simulating a smooth surface.",
              key = "Collider:getFriction",
              module = "lovr.physics",
              notes = "The default friction is .2.\n\nWhen two colliders collide, their friction is combined using the geometric mean:\n\n    friction = (frictionA * frictionB) ^ .5",
              related = {
                "Contact:getFriction",
                "Contact:setFriction",
                "Collider:getRestitution",
                "Collider:setRestitution"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The friction of the Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getGravityScale",
              summary = "Get the gravity scale of the Collider.",
              description = "Returns the gravity scale of the Collider.  This is multiplied with the global gravity from the World, so 1.0 is regular gravity, 0.0 will ignore gravity, etc.",
              key = "Collider:getGravityScale",
              module = "lovr.physics",
              related = {
                "World:getGravity",
                "World:setGravity",
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The gravity scale."
                    }
                  }
                }
              }
            },
            {
              name = "getInertia",
              summary = "Get the inertia of the Collider.",
              description = "Returns the inertia of the Collider.\n\nInertia is kind of like \"angular mass\".  Regular mass determines how resistant the Collider is to linear forces (movement), whereas inertia determines how resistant the Collider is to torque (rotation).  Colliders with less inertia are more spinny.\n\nIn 3D, inertia is represented by a 3x3 matrix, called a tensor.  To make calculations easier, the physics engine stores the inertia using eigenvalue decomposition, splitting the matrix into a diagonal matrix and a rotation.  It's complicated!\n\nIn a realistic simulation, mass and inertia follow a linear relationship.  If the mass of an object increases, the diagonal part of its inertia should increase proportionally.",
              key = "Collider:getInertia",
              module = "lovr.physics",
              notes = "By default, the inertia of the Collider is kept up to date automatically as the Collider's shapes change.  To disable this, use `Collider:setAutomaticMass`.\n\nUse `Collider:resetMassData` to reset the inertia and other mass properties based on the Collider's shapes.\n\nIf the Collider is kinematic or all rotation axes are disabled, this returns zeroes.",
              related = {
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getInertia"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "dx",
                      type = "number",
                      description = "The x component of the diagonal matrix."
                    },
                    {
                      name = "dy",
                      type = "number",
                      description = "The y component of the diagonal matrix."
                    },
                    {
                      name = "dz",
                      type = "number",
                      description = "The z component of the diagonal matrix."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle of the inertia rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the inertia rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the inertia rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the inertia rotation axis."
                    }
                  }
                }
              }
            },
            {
              name = "getJoints",
              summary = "Get a list of Joints attached to the Collider.",
              description = "Returns a list of Joints attached to the Collider.",
              key = "Collider:getJoints",
              module = "lovr.physics",
              related = {
                "World:getJoints",
                "Joint:getColliders",
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "joints",
                      type = "table",
                      description = "A list of `Joint` objects attached to the Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getLinearDamping",
              summary = "Get the linear damping of the Collider.",
              description = "Returns the linear damping of the Collider.  Linear damping is similar to drag or air resistance, slowing the Collider down over time.",
              key = "Collider:getLinearDamping",
              module = "lovr.physics",
              notes = "The default damping is .05, meaning the collider will lose approximately 5% of its velocity each second.  A damping value of zero means the Collider will not lose velocity over time.",
              related = {
                "Collider:getAngularDamping",
                "Collider:setAngularDamping",
                "Collider:getGravityScale",
                "Collider:setGravityScale"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The linear damping."
                    }
                  }
                }
              }
            },
            {
              name = "getLinearVelocity",
              summary = "Get the linear velocity of the Collider.",
              description = "Returns the world-space linear velocity of the center of mass of the Collider, in meters per second.",
              key = "Collider:getLinearVelocity",
              module = "lovr.physics",
              notes = "Currently, velocity is clamped to 500 meters per second to improve stability of the simulation.",
              related = {
                "Collider:applyForce",
                "Collider:getLinearVelocityFromLocalPoint",
                "Collider:getLinearVelocityFromWorldPoint",
                "Collider:getAngularVelocity",
                "Collider:setAngularVelocity",
                "Collider:getPosition",
                "Collider:setPosition"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x component of the velocity."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y component of the velocity."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z component of the velocity."
                    }
                  }
                }
              }
            },
            {
              name = "getLinearVelocityFromLocalPoint",
              summary = "Get the linear velocity of a point on the Collider.",
              description = "Returns the linear velocity of a point on the Collider.  This includes the velocity of the center of mass plus the angular velocity at that point.",
              key = "Collider:getLinearVelocityFromLocalPoint",
              module = "lovr.physics",
              related = {
                "Collider:getLinearVelocity",
                "Collider:getLinearVelocityFromWorldPoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position in local space."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position in local space."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position in local space."
                    }
                  },
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x velocity of the point."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y velocity of the point."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z velocity of the point."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "point",
                      type = "Vec3",
                      description = "The local-space point."
                    }
                  },
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x velocity of the point."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y velocity of the point."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z velocity of the point."
                    }
                  }
                }
              }
            },
            {
              name = "getLinearVelocityFromWorldPoint",
              summary = "Get the linear velocity of the Collider at a world space point.",
              description = "Returns the linear velocity of a point on the Collider.  This includes the velocity of the center of mass plus the angular velocity at that point.",
              key = "Collider:getLinearVelocityFromWorldPoint",
              module = "lovr.physics",
              related = {
                "Collider:getLinearVelocity",
                "Collider:getLinearVelocityFromLocalPoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position in world space."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position in world space."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position in world space."
                    }
                  },
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x velocity of the point."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y velocity of the point."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z velocity of the point."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "point",
                      type = "Vec3",
                      description = "The world-space point."
                    }
                  },
                  returns = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x velocity of the point."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y velocity of the point."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z velocity of the point."
                    }
                  }
                }
              }
            },
            {
              name = "getLocalPoint",
              summary = "Transform a point from world space to collider space.",
              description = "Transforms a point from world coordinates into local coordinates relative to the Collider.",
              key = "Collider:getLocalPoint",
              module = "lovr.physics",
              related = {
                "Collider:getWorldPoint",
                "Collider:getLocalVector",
                "Collider:getWorldVector"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world point."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world point."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world point."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local point."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "point",
                      type = "Vec3",
                      description = "The world point."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local point."
                    }
                  }
                }
              }
            },
            {
              name = "getLocalVector",
              summary = "Transform a vector from world space to local space.",
              description = "Transforms a direction vector from world space to local space.",
              key = "Collider:getLocalVector",
              module = "lovr.physics",
              related = {
                "Collider:getWorldVector",
                "Collider:getLocalPoint",
                "Collider:getWorldPoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world vector."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world vector."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world vector."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "vector",
                      type = "Vec3",
                      description = "The world vector."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local vector."
                    }
                  }
                }
              }
            },
            {
              name = "getMass",
              summary = "Get the mass of the Collider.",
              description = "Returns the mass of the Collider.\n\nThe relative mass of colliders determines how they react when they collide.  A heavier collider has more momentum than a lighter collider moving the same speed, and will impart more force on the lighter collider.\n\nMore generally, heavier colliders react less to forces they receive, including forces applied with functions like `Collider:applyForce`.\n\nColliders with higher mass do not fall faster.  Use `Collider:setLinearDamping` to give a collider drag to make it fall slower or `Collider:setGravityScale` to change the way it reacts to gravity.",
              key = "Collider:getMass",
              module = "lovr.physics",
              notes = "By default, the mass of the Collider will be kept up to date automatically as shapes are added and removed from the Collider (or if the shapes change size or density).  Use `Collider:setAutomaticMass` to customize this.\n\nMass can be overridden with `Collider:setMass`, or recomputed from the attached shapes with `Collider:resetMassData`.\n\nIf the Collider is kinematic or all translation axes are disabled, this returns 0.",
              related = {
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getDensity",
                "Shape:setDensity",
                "Shape:getVolume",
                "Shape:getMass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mass",
                      type = "number",
                      description = "The mass of the Collider, in kilograms."
                    }
                  }
                }
              }
            },
            {
              name = "getOrientation",
              summary = "Get the orientation of the Collider.",
              description = "Returns the orientation of the Collider in angle/axis representation.",
              key = "Collider:getOrientation",
              module = "lovr.physics",
              notes = "If `World:interpolate` has been called, this returns an interpolated orientation between the last two physics updates.",
              related = {
                "Collider:applyTorque",
                "Collider:getAngularVelocity",
                "Collider:setAngularVelocity",
                "Collider:getPosition",
                "Collider:setPosition",
                "Collider:getPose",
                "Collider:setPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Collider is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPose",
              summary = "Get the pose of the Collider.",
              description = "Returns the position and orientation of the Collider.",
              key = "Collider:getPose",
              module = "lovr.physics",
              notes = "If `World:interpolate` has been called, this returns an interpolated pose between the last two physics updates.",
              related = {
                "Collider:getPosition",
                "Collider:getOrientation"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Collider, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Collider, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Collider, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Collider is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              summary = "Get the position of the Collider.",
              description = "Returns the position of the Collider.",
              key = "Collider:getPosition",
              module = "lovr.physics",
              notes = "If `World:interpolate` has been called, this returns an interpolated position between the last two physics updates.",
              related = {
                "Collider:applyForce",
                "Collider:getLinearVelocity",
                "Collider:setLinearVelocity",
                "Collider:getOrientation",
                "Collider:setOrientation",
                "Collider:getPose",
                "Collider:setPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Collider, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Collider, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Collider, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getRestitution",
              summary = "Get the bounciness of the Collider.",
              description = "Returns the restitution of the Collider.  Restitution makes a Collider bounce when it collides with other objects.  A restitution value of zero would result in an inelastic collision response, whereas 1.0 would result in an elastic collision that preserves all of the velocity. The restitution can be bigger than 1.0 to make the collision even more bouncy.",
              key = "Collider:getRestitution",
              module = "lovr.physics",
              notes = "To improve stability of the simulation and allow colliders to come to rest, restitution is only applied if the collider is moving above a certain speed.  This can be configured using the `restitutionThreshold` option in `lovr.physics.newWorld`.",
              related = {
                "Contact:getRestitution",
                "Contact:setRestitution",
                "Collider:getFriction",
                "Collider:setFriction"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "restitution",
                      type = "number",
                      description = "The restitution of the Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getShape",
              summary = "Get the first Shape attached to the Collider.",
              description = "Returns a Shape attached to the Collider.\n\nFor the common case where a Collider only has a single shape, this is more convenient and efficient than extracting it from the table returned by `Collider:getShapes`.  It is always equivalent to `Collider:getShapes()[1]`.",
              key = "Collider:getShape",
              module = "lovr.physics",
              examples = {
                {
                  code = "function drawBoxCollider(pass, collider)\n  local position = vec3(collider:getPosition())\n  local size = vec3(collider:getShape():getDimensions())\n  local orientation = quat(collider:getOrientation())\n  pass:box(position, size, orientation)\nend"
                }
              },
              related = {
                "Collider:getShapes",
                "Collider:addShape",
                "Collider:removeShape",
                "Shape"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "shape",
                      type = "Shape | nil",
                      description = "One of the `Shape` objects attached to the Collider, or `nil` if the Collider doesn't have any shapes attached to it."
                    }
                  }
                }
              }
            },
            {
              name = "getShapes",
              summary = "Get a list of Shapes attached to the Collider.",
              description = "Returns a list of Shapes attached to the Collider.",
              key = "Collider:getShapes",
              module = "lovr.physics",
              related = {
                "Collider:getShape",
                "Collider:addShape",
                "Collider:removeShape",
                "Shape"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "shapes",
                      type = "table",
                      description = "A list of `Shape` objects attached to the Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getTag",
              summary = "Get the Collider's tag.",
              description = "Returns the Collider's tag.\n\nTags are strings that represent the category of a collider.  Use `World:enableCollisionBetween` and `World:disableCollisionBetween` to control which pairs of tags should collide with each other.  Physics queries like `World:raycast` also use tags to filter their results.\n\nThe list of available tags is set in `lovr.physics.newWorld`.",
              key = "Collider:getTag",
              module = "lovr.physics",
              related = {
                "World:getTags",
                "World:disableCollisionBetween",
                "World:enableCollisionBetween",
                "World:isCollisionEnabledBetween",
                "lovr.physics.newWorld"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "tag",
                      type = "string | nil",
                      description = "The Collider's tag."
                    }
                  }
                }
              }
            },
            {
              name = "getUserData",
              summary = "Get the Lua value associated with the Collider.",
              description = "Returns the Lua value associated with the Collider.",
              key = "Collider:getUserData",
              module = "lovr.physics",
              notes = "The userdata is useful for linking a Collider with custom data:\n\n    local collider = world:raycast(origin, direction, 'enemy')\n\n    if collider then\n      -- Get the enemy object from its Collider\n      local enemy = collider:getUserData()\n      enemy.health = 0\n    end\n\nThe user data is not shared between threads.  Each thread has its own user data for the Collider.",
              related = {
                "Shape:getUserData",
                "Shape:setUserData",
                "Joint:getUserData",
                "Joint:setUserData"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value associated with the Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getWorld",
              summary = "Get the World the Collider is in.",
              description = "Returns the World the Collider is in.",
              key = "Collider:getWorld",
              module = "lovr.physics",
              notes = "Colliders can only ever be in the World that created them.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "world",
                      type = "World",
                      description = "The World the Collider is in."
                    }
                  }
                }
              }
            },
            {
              name = "getWorldPoint",
              summary = "Transform a point from local space to world space.",
              description = "Transforms a local point relative to the collider to a point in world coordinates.",
              key = "Collider:getWorldPoint",
              module = "lovr.physics",
              related = {
                "Collider:getLocalPoint",
                "Collider:getLocalVector",
                "Collider:getWorldVector"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local point."
                    }
                  },
                  returns = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world point."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world point."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world point."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "point",
                      type = "Vec3",
                      description = "The local point."
                    }
                  },
                  returns = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world point."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world point."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world point."
                    }
                  }
                }
              }
            },
            {
              name = "getWorldVector",
              summary = "Transform a vector from local space to world space.",
              description = "Transforms a direction vector from local space to world space.",
              key = "Collider:getWorldVector",
              module = "lovr.physics",
              related = {
                "Collider:getLocalVector",
                "Collider:getLocalPoint",
                "Collider:getWorldPoint"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the local vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the local vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the local vector."
                    }
                  },
                  returns = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world vector."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world vector."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "vector",
                      type = "Vec3",
                      description = "The local vector."
                    }
                  },
                  returns = {
                    {
                      name = "wx",
                      type = "number",
                      description = "The x component of the world vector."
                    },
                    {
                      name = "wy",
                      type = "number",
                      description = "The y component of the world vector."
                    },
                    {
                      name = "wz",
                      type = "number",
                      description = "The z component of the world vector."
                    }
                  }
                }
              }
            },
            {
              name = "isAwake",
              summary = "Check if the Collider is awake.",
              description = "Returns whether the Collider is awake.",
              key = "Collider:isAwake",
              module = "lovr.physics",
              notes = "See `Collider:setSleepingAllowed` for notes about sleeping.",
              related = {
                "Collider:isSleepingAllowed",
                "Collider:setSleepingAllowed"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "awake",
                      type = "boolean",
                      description = "Whether the Collider is finally awake."
                    }
                  }
                }
              }
            },
            {
              name = "isContinuous",
              summary = "Check if the Collider is using continuous collision detection.",
              description = "Returns whether the Collider uses continuous collision detection.\n\nNormally on each timestep a Collider will \"teleport\" to its new position based on its velocity. Usually this works fine, but if a Collider is going really fast relative to its size, then it might miss collisions with objects or pass through walls.  Enabling continuous collision detection means the Collider will check for obstacles along its path before moving to the new location.  This prevents the Collider from going through walls, but reduces performance.  It's usually used for projectiles, which tend to be small and really fast.",
              key = "Collider:isContinuous",
              module = "lovr.physics",
              notes = "The physics engine performs an optimization where continuous collision detection is only used if the Collider is moving faster than 75% of its size.  So it is not necessary to enable and disable continuous collision detection based on how fast the Collider is moving.\n\nColliders that are sensors are not able to use continuous collision detection.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "continuous",
                      type = "boolean",
                      description = "Whether the Collider uses continuous collision detection."
                    }
                  }
                }
              }
            },
            {
              name = "isDestroyed",
              summary = "Check if the Collider has been destroyed.",
              description = "Returns whether the collider has been destroyed.",
              key = "Collider:isDestroyed",
              module = "lovr.physics",
              notes = "After a Collider is destroyed, calling methods on it or passing it to a function will throw an error.",
              related = {
                "Collider:destroy",
                "World:destroy",
                "Shape:destroy",
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "destroyed",
                      type = "boolean",
                      description = "Whether the collider has been destroyed."
                    }
                  }
                }
              }
            },
            {
              name = "isEnabled",
              summary = "Check if the Collider is enabled.",
              description = "Returns whether the Collider is enabled.  When a Collider is disabled, it is removed from the World and does not impact the physics simulation in any way.  The Collider keeps all of its state and can be re-enabled to add it back to the World.",
              key = "Collider:isEnabled",
              module = "lovr.physics",
              notes = "Colliders are enabled when they are created.",
              related = {
                "Collider:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether the Collider is enabled."
                    }
                  }
                }
              }
            },
            {
              name = "isGravityIgnored",
              summary = "Check if the Collider ignores gravity.",
              description = "Returns whether the Collider is currently ignoring gravity.",
              key = "Collider:isGravityIgnored",
              module = "lovr.physics",
              deprecated = "This function has been replaced by `Collider:getGravityScale`.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "ignored",
                      type = "boolean",
                      description = "Whether gravity is ignored for this Collider."
                    }
                  }
                }
              }
            },
            {
              name = "isKinematic",
              summary = "Check if the Collider is kinematic.",
              description = "Returns whether the Collider is kinematic.\n\nKinematic colliders behave like they have infinite mass.  They ignore forces applied to them from gravity, joints, and collisions, but they can still move if given a velocity.  Kinematic colliders don't collide with other kinematic colliders.  They're useful for static environment objects in a level, or for objects that have their position managed outside of the physics system like tracked hands.",
              key = "Collider:isKinematic",
              module = "lovr.physics",
              notes = "If a Collider has a `MeshShape` or a `TerrainShape`, it will always be kinematic.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "kinematic",
                      type = "boolean",
                      description = "Whether the Collider is kinematic."
                    }
                  }
                }
              }
            },
            {
              name = "isSensor",
              summary = "Check if the Collider is a sensor.",
              description = "Returns whether the Collider is a sensor.  Sensors do not collide with other objects, but they can still sense collisions with the collision callbacks set by `World:setCallbacks`.  Use them to trigger gameplay behavior when an object is inside a region of space.",
              key = "Collider:isSensor",
              module = "lovr.physics",
              examples = {
                {
                  code = "danger = world:newBoxCollider(x, y, z, width, height, depth)\ndanger:setKinematic(true)\ndanger:setSensor(true)\n\nworld:setCallbacks({\n  enter = function(a, b)\n    if (a == danger and b == player) or (a == player and b == danger) then\n      damagePlayer()\n    end\n  end\n})"
                }
              },
              notes = "Sensors are still reported as hits when doing raycasts and other queries.  Use tags to ignore sensors if needed.\n\nWhen a World is created, a set of collision tags can be marked as \"static\", for performance. Sensors do not detect collision with colliders that have a static tag.  Also, if a sensor itself has a static tag, it will not be able to detect collisions with sleeping colliders.  If a Collider enters a static sensor and goes to sleep, the `exit` callback is called and the sensor is no longer able to detect that collider.\n\nSensors can not use continuous collision detection.\n\nSensors will never go to sleep.",
              related = {
                "Collider:setKinematic",
                "Collider:setEnabled",
                "World:overlapShape",
                "World:setCallbacks"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "sensor",
                      type = "boolean",
                      description = "Whether the Collider is a sensor."
                    }
                  }
                }
              }
            },
            {
              name = "isSleepingAllowed",
              summary = "Check if the Collider is allowed to sleep.",
              description = "Returns whether the Collider is allowed to automatically go to sleep.\n\nWhen enabled, the Collider will go to sleep if it hasn't moved in a while.  The physics engine does not simulate movement for colliders that are asleep, which saves a lot of CPU for a typical physics world where most objects are at rest at any given time.",
              key = "Collider:isSleepingAllowed",
              module = "lovr.physics",
              notes = "Sleeping is enabled by default.  Sleeping can be disabled globally using the `allowSleep` option in `lovr.physics.newWorld`.\n\nColliders can still be put to sleep manually with `Collider:setAwake`, even if automatic sleeping is disabled.\n\nSleeping colliders will wake up when:\n\n- Colliding with a moving collider\n- Awakened explicitly with `Collider:setAwake`\n- Changing position `Collider:setPosition` or `Collider:setOrientation`\n- Changing velocity (to something non-zero)\n- Applying force, torque, or an impulse\n- Enabling a joint connected to the sleeping collider\n\nNotably, the following will not wake up the collider:\n\n- Changing its kinematic state with `Collider:setKinematic`\n- Changing its shape with `Collider:addShape` or `Collider:removeShape`\n- Disabling or destroying a sleeping collider it is resting on\n\nSensors will never go to sleep.",
              related = {
                "Collider:isAwake",
                "Collider:setAwake"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "sleepy",
                      type = "boolean",
                      description = "Whether the Collider can go to sleep."
                    }
                  }
                }
              }
            },
            {
              name = "moveKinematic",
              summary = "TODO",
              description = "TODO",
              key = "Collider:moveKinematic",
              module = "lovr.physics",
              notes = "",
              related = {},
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "removeShape",
              summary = "Remove a Shape from the Collider.",
              description = "Removes a Shape from the Collider.",
              key = "Collider:removeShape",
              module = "lovr.physics",
              notes = "By default, LÖVR will recompute mass properties for the Collider as shapes are added and removed.  Use `Collider:setAutomaticMass` to enable or disable this behavior.\n\nIt is valid for a Collider to have zero shapes, but due to a limitation of the physics engine LÖVR substitutes in a 1mm sphere so that the Collider still has mass.  It isn't advisable to keep these tiny spheres around.  Instead, prefer to quickly attach other shapes, or disable the Collider with `Collider:setEnabled`.",
              related = {
                "Collider:addShape",
                "Collider:getShapes",
                "Shape"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to remove."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "resetMassData",
              summary = "Reset mass properties.",
              description = "Resets the mass, inertia, and center of mass of the Collider based on its attached shapes.\n\nIf automatic mass is enabled, these properties will be kept up to date automatically.  Use this function when automatic mass is disabled or if mass needs to be reset after being overridden.",
              key = "Collider:resetMassData",
              module = "lovr.physics",
              related = {
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setAngularDamping",
              summary = "Set the angular damping of the Collider.",
              description = "Sets the angular damping of the Collider.  Angular damping is similar to drag or air resistance, reducing the Collider's angular velocity over time.",
              key = "Collider:setAngularDamping",
              module = "lovr.physics",
              notes = "The default damping is .05, meaning the collider will lose approximately 5% of its velocity each second.  A damping value of zero means the Collider will not lose velocity over time.\n\nNegative damping is not meaningful and will be clamped to zero.",
              related = {
                "Collider:getLinearDamping",
                "Collider:setLinearDamping",
                "Collider:getInertia",
                "Collider:setInertia"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The angular damping."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setAngularVelocity",
              summary = "Set the angular velocity of the Collider.",
              description = "Sets the angular velocity of the Collider.",
              key = "Collider:setAngularVelocity",
              module = "lovr.physics",
              notes = "Although setting the velocity directly is useful sometimes, it can cause problems:\n\n- Velocity ignores mass, so it can lead to unnaturally sharp changes in motion.\n- If the velocity of a Collider is changed multiple times during a frame, only the last one is\n  going to have an effect, nullifying the other velocities that were set.\n- Setting the velocity of a Collider every frame can mess up collisions, since the forces used\n  to resolve a collision will get ignored by changing the velocity.\n\nUsing forces and impulses to move Colliders will avoid all of these issues.\n\nIf the Collider is asleep, setting the angular velocity to a non-zero value will wake it up.\n\nIf the Collider has a tag that was marked as static when the World was created, then the Collider can not move and this function will do nothing.",
              related = {
                "Collider:applyTorque",
                "Collider:applyAngularImpulse",
                "Collider:getLinearVelocity",
                "Collider:setLinearVelocity",
                "Collider:getOrientation",
                "Collider:setOrientation"
              },
              variants = {
                {
                  description = "Sets the angular velocity of the Collider using numbers.",
                  arguments = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x component of the angular velocity."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y component of the angular velocity."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z component of the angular velocity."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Sets the angular velocity of the Collider using a vector.",
                  arguments = {
                    {
                      name = "velocity",
                      type = "Vec3",
                      description = "The angular velocity of the Collider."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setAutomaticMass",
              summary = "Enable or disable automatic mass.",
              description = "Enables or disables automatic mass for the Collider.\n\nWhen enabled, the Collider's mass, inertia, and center of mass will be recomputed when:\n\n- A shape is added to or removed from the Collider.\n- A shape attached to the Collider changes shape (e.g. `SphereShape:setRadius`).\n- A shape attached to the Collider is moved using `Shape:setOffset`.\n- A shape attached to the Collider changes its density using `Shape:setDensity`.\n\nAdditionally, changing the center of mass of a Collider will automatically update its inertia when automatic mass is enabled.\n\nDisable this to manage the mass properties manually.  When automatic mass is disabled, `Collider:resetMassData` can still be used to reset the mass from attached shapes if needed.",
              key = "Collider:setAutomaticMass",
              module = "lovr.physics",
              related = {
                "Collider:resetMassData",
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether automatic mass should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setAwake",
              summary = "Put the Collider to sleep or wake it up.",
              description = "Puts the Collider to sleep or wakes it up manually.",
              key = "Collider:setAwake",
              module = "lovr.physics",
              notes = "This function can still be used to put a Collider to sleep even if automatic sleeping has been disabled with `Collider:setSleepingAllowed`.",
              related = {
                "Collider:isSleepingAllowed",
                "Collider:setSleepingAllowed"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "awake",
                      type = "boolean",
                      description = "Whether the Collider should be awake."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setCenterOfMass",
              summary = "Set the Collider's center of mass.",
              description = "Sets the Collider's center of mass, in the Collider's local coordinate space.\n\nThis does not change the Collider's position.",
              key = "Collider:setCenterOfMass",
              module = "lovr.physics",
              notes = "By default, the center of mass of the Collider is kept up to date automatically as the Collider's shapes change.  To disable this, use `Collider:setAutomaticMass`.\n\nUse `Collider:resetMassData` to reset the center and other mass properties based on the Collider's shapes.",
              related = {
                "Shape:getCenterOfMass",
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the center of mass."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the center of mass."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the center of mass."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "center",
                      type = "Vec3",
                      description = "The center of mass."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setContinuous",
              summary = "Set whether the Collider uses continuous collision detection.",
              description = "Sets whether the Collider uses continuous collision detection.\n\nNormally on each timestep a Collider will \"teleport\" to its new position based on its velocity. Usually this works fine, but if a Collider is going really fast relative to its size, then it might miss collisions with objects or pass through walls.  Enabling continuous collision detection means the Collider will check for obstacles along its path before moving to the new location.  This prevents the Collider from going through walls, but reduces performance.  It's usually used for projectiles, which tend to be small and really fast.",
              key = "Collider:setContinuous",
              module = "lovr.physics",
              notes = "The physics engine performs an optimization where continuous collision detection is only used if the Collider is moving faster than 75% of its size.  So it is not necessary to enable and disable continuous collision detection based on how fast the Collider is moving.\n\nColliders that are sensors are not able to use continuous collision detection.",
              variants = {
                {
                  arguments = {
                    {
                      name = "continuous",
                      type = "boolean",
                      description = "Whether the Collider uses continuous collision detection."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setDegreesOfFreedom",
              summary = "Set the enabled translation/rotation axes.",
              description = "Set the degrees of freedom of the Collider.",
              key = "Collider:setDegreesOfFreedom",
              module = "lovr.physics",
              notes = "The default state is `xyz` for both translation and rotation.\n\nThe physics engine does not support disabling all degrees of freedom.  At least one translation or rotation axis needs to be enabled.  To disable all movement for a collider, make it kinematic.\n\nWhen all translation axes are disabled, `Collider:getMass` will return 0.\n\nWhen all rotation axes are disabled, `Collider:getInertia` will return zero/identity.\n\nThis function does nothing if the Collider is kinematic.",
              variants = {
                {
                  arguments = {
                    {
                      name = "translation",
                      type = "string",
                      description = "A string containing the world-space axes the Collider is allowed to move on.  The string should have 'x', 'y', and 'z' letters representing the axes to enable.  Use nil or an empty string to disable all translation.",
                      default = "''"
                    },
                    {
                      name = "rotation",
                      type = "string",
                      description = "A string containing the world-space axes the Collider is allowed to rotate on.  The string should have 'x', 'y', and 'z' letters representing the axes to enable.  Use nil or an empty string to disable all rotation.",
                      default = "''"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setEnabled",
              summary = "Enable or disable the Collider.",
              description = "Enables or disables the Collider.  When a Collider is disabled, it is removed from the World and does not impact the physics simulation in any way.  The Collider keeps all of its state and can be re-enabled to add it back to the World.",
              key = "Collider:setEnabled",
              module = "lovr.physics",
              related = {
                "Collider:destroy"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether the Collider should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setFriction",
              summary = "Set the friction of the Collider.",
              description = "Sets the friction of the Collider.  Friction determines how easy it is for two colliders to slide against each other.  Low friction makes it easier for a collider to slide, simulating a smooth surface.",
              key = "Collider:setFriction",
              module = "lovr.physics",
              notes = "The default friction is .2.\n\nWhen two colliders collide, their friction is combined using the geometric mean:\n\n    friction = (frictionA * frictionB) ^ .5",
              related = {
                "Contact:getFriction",
                "Contact:setFriction",
                "Collider:getRestitution",
                "Collider:setRestitution"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The friction of the Collider."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setGravityIgnored",
              summary = "Set whether the Collider ignores gravity.",
              description = "Sets whether the Collider should ignore gravity.",
              key = "Collider:setGravityIgnored",
              module = "lovr.physics",
              deprecated = "This function has been replaced by `Collider:setGravityScale`.",
              variants = {
                {
                  arguments = {
                    {
                      name = "ignored",
                      type = "boolean",
                      description = "Whether gravity should be ignored."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setGravityScale",
              summary = "Set the gravity scale of the Collider.",
              description = "Sets the gravity scale of the Collider.  This is multiplied with the global gravity from the World, so 1.0 is regular gravity, 0.0 will ignore gravity, etc.",
              key = "Collider:setGravityScale",
              module = "lovr.physics",
              related = {
                "World:getGravity",
                "World:setGravity",
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The gravity scale."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setInertia",
              summary = "Set the inertia of the Collider.",
              description = "Sets the inertia of the Collider.\n\nInertia is kind of like \"angular mass\".  Regular mass determines how resistant the Collider is to linear forces (movement), whereas inertia determines how resistant the Collider is to torque (rotation).  Colliders with less inertia are more spinny.\n\nIn 3D, inertia is represented by a 3x3 matrix, called a tensor.  To make calculations easier, the physics engine stores the inertia using eigenvalue decomposition, splitting the matrix into a diagonal matrix and a rotation.  It's complicated!\n\nIn a realistic simulation, mass and inertia follow a linear relationship.  If the mass of an object increases, the diagonal part of its inertia should increase proportionally.",
              key = "Collider:setInertia",
              module = "lovr.physics",
              notes = "By default, the inertia of the Collider is kept up to date automatically as the Collider's shapes change.  To disable this, use `Collider:setAutomaticMass`.\n\nUse `Collider:resetMassData` to reset the inertia and other mass properties based on the Collider's shapes.\n\nIf the Collider is kinematic or all rotation axes are disabled, the collider behaves as though it has infinite inertia, and this function will do nothing.",
              related = {
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getInertia"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "dx",
                      type = "number",
                      description = "The x component of the diagonal matrix."
                    },
                    {
                      name = "dy",
                      type = "number",
                      description = "The y component of the diagonal matrix."
                    },
                    {
                      name = "dz",
                      type = "number",
                      description = "The z component of the diagonal matrix."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle of the inertia rotation, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the rotation axis."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "diagonal",
                      type = "Vec3",
                      description = "A vector containing the 3 elements of a diagonal matrix."
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The inertia rotation."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setKinematic",
              summary = "Set whether the Collider is kinematic.",
              description = "Sets whether the Collider is kinematic.\n\nKinematic colliders behave like they have infinite mass.  They ignore forces applied to them from gravity, joints, and collisions, but they can still move if given a velocity.  Kinematic colliders don't collide with other kinematic colliders.  They're useful for static environment objects in a level, or for objects that have their position managed outside of the physics system like tracked hands.",
              key = "Collider:setKinematic",
              module = "lovr.physics",
              notes = "If a Collider has a `MeshShape` or a `TerrainShape`, the collider will always be kinematic and this function will do nothing.",
              variants = {
                {
                  arguments = {
                    {
                      name = "kinematic",
                      type = "boolean",
                      description = "Whether the Collider should be kinematic."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLinearDamping",
              summary = "Set the linear damping of the Collider.",
              description = "Sets the linear damping of the Collider.  Linear damping is similar to drag or air resistance, slowing the Collider down over time.",
              key = "Collider:setLinearDamping",
              module = "lovr.physics",
              notes = "The default damping is .05, meaning the collider will lose approximately 5% of its velocity each second.  A damping value of zero means the Collider will not lose velocity over time.\n\nNegative damping is not meaningful and will be clamped to zero.",
              related = {
                "Collider:getAngularDamping",
                "Collider:setAngularDamping",
                "Collider:getGravityScale",
                "Collider:setGravityScale"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The linear damping."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLinearVelocity",
              summary = "Set the linear velocity of the Collider.",
              description = "Sets the world-space linear velocity of the center of mass of the Collider.",
              key = "Collider:setLinearVelocity",
              module = "lovr.physics",
              notes = "Although setting the velocity directly is useful sometimes, it can cause problems:\n\n- Velocity ignores mass, so it can lead to unnaturally sharp changes in motion.\n- If the velocity of a Collider is changed multiple times during a frame, only the last one is\n  going to have an effect, nullifying the other velocities that were set.\n- Setting the velocity of a Collider every frame can mess up collisions, since the forces used\n  to resolve a collision will get ignored by changing the velocity.\n\nUsing forces and impulses to move Colliders will avoid all of these issues.\n\nIf the Collider is asleep, setting the velocity to a non-zero value will wake it up.\n\nIf the Collider has a tag that was marked as static when the World was created, then the Collider can not move and this function will do nothing.\n\nCurrently, velocity is clamped to 500 meters per second to improve stability of the simulation.",
              related = {
                "Collider:applyForce",
                "Collider:applyLinearImpulse",
                "Collider:getLinearVelocityFromLocalPoint",
                "Collider:getLinearVelocityFromWorldPoint",
                "Collider:getAngularVelocity",
                "Collider:setAngularVelocity",
                "Collider:getPosition",
                "Collider:setPosition"
              },
              variants = {
                {
                  description = "Set the linear velocity of the collider using numbers.",
                  arguments = {
                    {
                      name = "vx",
                      type = "number",
                      description = "The x component of the new velocity, in meters per second."
                    },
                    {
                      name = "vy",
                      type = "number",
                      description = "The y component of the new velocity, in meters per second."
                    },
                    {
                      name = "vz",
                      type = "number",
                      description = "The z component of the new velocity, in meters per second."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the linear velocity of the collider using a vector.",
                  arguments = {
                    {
                      name = "velocity",
                      type = "Vec3",
                      description = "The new velocity, in meters per second."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMass",
              summary = "Set the mass of the Collider.",
              description = "Sets the mass of the Collider.\n\nThe relative mass of colliders determines how they react when they collide.  A heavier collider has more momentum than a lighter collider moving the same speed, and will impart more force on the lighter collider.\n\nMore generally, heavier colliders react less to forces they receive, including forces applied with functions like `Collider:applyForce`.\n\nColliders with higher mass do not fall faster.  Use `Collider:setLinearDamping` to give a collider drag to make it fall slower or `Collider:setGravityScale` to change the way it reacts to gravity.",
              key = "Collider:setMass",
              module = "lovr.physics",
              notes = "The mass must be positive.  Attempting to set a zero or negative mass will error.\n\nBy default, the mass of the Collider is kept up to date automatically as the Collider's shapes change.  Use `Collider:setAutomaticMass` to disable this.\n\nUse `Collider:resetMassData` to reset the mass based on the Collider's shapes.\n\nIf the Collider is kinematic or all translation axes are disabled, this function will do nothing.",
              related = {
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData",
                "Shape:getDensity",
                "Shape:setDensity",
                "Shape:getVolume",
                "Shape:getMass"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mass",
                      type = "number",
                      description = "The new mass for the Collider, in kilograms."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setOrientation",
              summary = "Set the orientation of the Collider.",
              description = "Sets the orientation of the Collider in angle/axis representation.",
              key = "Collider:setOrientation",
              module = "lovr.physics",
              related = {
                "Collider:applyTorque",
                "Collider:getAngularVelocity",
                "Collider:setAngularVelocity",
                "Collider:getPosition",
                "Collider:setPosition",
                "Collider:getPose",
                "Collider:setPose"
              },
              variants = {
                {
                  description = "Set the orientation of the Collider using numbers.",
                  arguments = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Collider is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the orientation of the Collider using a quaternion.",
                  arguments = {
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the Collider."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPose",
              summary = "Set the pose of the Collider.",
              description = "Sets the position and orientation of the Collider.",
              key = "Collider:setPose",
              module = "lovr.physics",
              related = {
                "Collider:setPosition",
                "Collider:setOrientation"
              },
              variants = {
                {
                  description = "Set the pose of the Collider using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Collider, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Collider, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Collider, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Collider is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the pose of the Collider using vector types.",
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the Collider, in meters."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the Collider."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPosition",
              summary = "Set the position of the Collider.",
              description = "Sets the position of the Collider.",
              key = "Collider:setPosition",
              module = "lovr.physics",
              related = {
                "Collider:applyForce",
                "Collider:getLinearVelocity",
                "Collider:setLinearVelocity",
                "Collider:getOrientation",
                "Collider:setOrientation",
                "Collider:getPose",
                "Collider:setPose"
              },
              variants = {
                {
                  description = "Set the position of the Collider using numbers.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Collider, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Collider, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Collider, in meters."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Set the position of the Collider using a vector.",
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the Collider, in meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setRestitution",
              summary = "Set the bounciness of the Collider.",
              description = "Sets the restitution of the Collider.  Restitution makes a Collider bounce when it collides with other objects.  A restitution value of zero would result in an inelastic collision response, whereas 1.0 would result in an elastic collision that preserves all of the velocity.",
              key = "Collider:setRestitution",
              module = "lovr.physics",
              notes = "To improve stability of the simulation and allow colliders to come to rest, restitution is only applied if the collider is moving above a certain speed.  This can be configured using the `restitutionThreshold` option in `lovr.physics.newWorld`.\n\nNegative restitution is not meaningful and is clamped to zero.",
              related = {
                "Contact:getRestitution",
                "Contact:setRestitution",
                "Collider:getFriction",
                "Collider:setFriction"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "restitution",
                      type = "number",
                      description = "The restitution of the Collider."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSensor",
              summary = "Set whether the Collider should be a sensor.",
              description = "Sets whether the Collider should be a sensor.  Sensors do not collide with other objects, but they can still sense collisions with the collision callbacks set by `World:setCallbacks`.  Use them to trigger gameplay behavior when an object is inside a region of space.",
              key = "Collider:setSensor",
              module = "lovr.physics",
              notes = "Sensors are still reported as hits when doing raycasts and other queries.  Use tags to ignore sensors if needed.\n\nWhen a World is created, a set of collision tags can be marked as \"static\", for performance. Sensors do not detect collision with colliders that have a static tag.  Also, if a sensor itself has a static tag, it will not be able to detect collisions with sleeping colliders.  If a Collider enters a static sensor and goes to sleep, the `exit` callback is called and the sensor is no longer able to detect that collider.\n\nSensors can not use continuous collision detection.\n\nSensors will never go to sleep.",
              related = {
                "Collider:setKinematic",
                "Collider:setEnabled",
                "World:overlapShape",
                "World:setCallbacks"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "sensor",
                      type = "boolean",
                      description = "Whether the Collider should be a sensor."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSleepingAllowed",
              summary = "Set whether the Collider is allowed to sleep.",
              description = "Sets whether the Collider is allowed to automatically go to sleep.\n\nWhen enabled, the Collider will go to sleep if it hasn't moved in a while.  The physics engine does not simulate movement for colliders that are asleep, which saves a lot of CPU for a typical physics world where most objects are at rest at any given time.",
              key = "Collider:setSleepingAllowed",
              module = "lovr.physics",
              notes = "Sleeping is enabled by default.  Sleeping can be disabled globally using the `allowSleep` option in `lovr.physics.newWorld`.\n\nColliders can still be put to sleep manually with `Collider:setAwake`, even if automatic sleeping is disabled.\n\nSleeping colliders will wake up when:\n\n- Colliding with a moving collider\n- Awakened explicitly with `Collider:setAwake`\n- Changing position `Collider:setPosition` or `Collider:setOrientation`\n- Changing velocity (to something non-zero)\n- Applying force, torque, or an impulse\n- Enabling a joint connected to the sleeping collider\n\nNotably, the following will not wake up the collider:\n\n- Changing its kinematic state with `Collider:setKinematic`\n- Changing its shape with `Collider:addShape` or `Collider:removeShape`\n- Disabling or destroying a sleeping collider it is resting on\n\nSensors will never go to sleep.",
              related = {
                "Collider:isAwake",
                "Collider:setAwake"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "sleepy",
                      type = "boolean",
                      description = "Whether the Collider can go to sleep."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setTag",
              summary = "Set the Collider's tag.",
              description = "Sets the Collider's tag.\n\nTags are strings that represent the category of a collider.  Use `World:enableCollisionBetween` and `World:disableCollisionBetween` to control which pairs of tags should collide with each other.  Physics queries like `World:raycast` also use tags to filter their results.\n\nThe list of available tags is set in `lovr.physics.newWorld`.",
              key = "Collider:setTag",
              module = "lovr.physics",
              related = {
                "World:getTags",
                "World:disableCollisionBetween",
                "World:enableCollisionBetween",
                "World:isCollisionEnabledBetween",
                "lovr.physics.newWorld"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "tag",
                      type = "string",
                      description = "The Collider's tag."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Clear the Collider's tag.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setUserData",
              summary = "Associate a Lua value with the Collider.",
              description = "Associates a Lua value with the Collider.",
              key = "Collider:setUserData",
              module = "lovr.physics",
              notes = "Set the user data to `nil` to clear any existing reference.\n\nThe userdata is useful for linking a Collider with custom data:\n\n    local collider = world:raycast(origin, direction, 'enemy')\n\n    if collider then\n      -- Get the enemy object from its Collider\n      local enemy = collider:getUserData()\n      enemy.health = 0\n    end\n\nThe user data is not shared between threads.  Each thread has its own user data for the Collider.",
              related = {
                "Shape:getUserData",
                "Shape:setUserData",
                "Joint:getUserData",
                "Joint:setUserData"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value to associate with the Collider."
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Motion",
              links = {
                "Collider:getPosition",
                "Collider:setPosition",
                "Collider:getOrientation",
                "Collider:setOrientation",
                "Collider:getPose",
                "Collider:setPose",
                "Collider:getLocalPoint",
                "Collider:getWorldPoint",
                "Collider:getLocalVector",
                "Collider:getWorldVector",
                "Collider:getAABB",
                "Collider:getLinearVelocity",
                "Collider:setLinearVelocity",
                "Collider:getAngularVelocity",
                "Collider:setAngularVelocity",
                "Collider:getLinearVelocityFromLocalPoint",
                "Collider:getLinearVelocityFromWorldPoint",
                "Collider:moveKinematic",
                "Collider:applyForce",
                "Collider:applyTorque",
                "Collider:applyLinearImpulse",
                "Collider:applyAngularImpulse",
                "Collider:getLinearDamping",
                "Collider:setLinearDamping",
                "Collider:getAngularDamping",
                "Collider:setAngularDamping",
                "Collider:isKinematic",
                "Collider:setKinematic",
                "Collider:isContinuous",
                "Collider:setContinuous",
                "Collider:getDegreesOfFreedom",
                "Collider:setDegreesOfFreedom",
                "Collider:getGravityScale",
                "Collider:setGravityScale",
                "Collider:isSleepingAllowed",
                "Collider:setSleepingAllowed",
                "Collider:isAwake",
                "Collider:setAwake"
              }
            },
            {
              name = "Collision",
              links = {
                "Collider:getTag",
                "Collider:setTag",
                "Collider:getShape",
                "Collider:getShapes",
                "Collider:addShape",
                "Collider:removeShape",
                "Collider:isSensor",
                "Collider:setSensor",
                "Collider:getFriction",
                "Collider:setFriction",
                "Collider:getRestitution",
                "Collider:setRestitution"
              }
            },
            {
              name = "Mass",
              links = {
                "Collider:getMass",
                "Collider:setMass",
                "Collider:getInertia",
                "Collider:setInertia",
                "Collider:getCenterOfMass",
                "Collider:setCenterOfMass",
                "Collider:getAutomaticMass",
                "Collider:setAutomaticMass",
                "Collider:resetMassData"
              }
            },
            {
              name = "Miscellaneous",
              links = {
                "Collider:getUserData",
                "Collider:setUserData",
                "Collider:isEnabled",
                "Collider:setEnabled",
                "Collider:getWorld",
                "Collider:getJoints",
                "Collider:destroy",
                "Collider:isDestroyed"
              }
            }
          }
        },
        {
          name = "ConeJoint",
          summary = "TODO",
          description = "TODO",
          key = "ConeJoint",
          module = "lovr.physics",
          extends = "Joint",
          methods = {
            {
              name = "getAxis",
              summary = "Get the axis of the cone.",
              description = "Returns the axis of the ConeJoint, in world space.  The axis is relative to the first Collider connected to the Joint, so it will rotate as the collider does.  The relative angle between the axis and the second collider will be constrained based on the ConeJoint's angle limit.",
              key = "ConeJoint:getAxis",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis."
                    }
                  }
                }
              }
            },
            {
              name = "getLimit",
              summary = "Get the angle limit of the ConeJoint.",
              description = "Returns the angle limit of the ConeJoint.  The relative angle between the ConeJoint's axis and the second Collider will be constrained to this limit.",
              key = "ConeJoint:getLimit",
              module = "lovr.physics",
              notes = "The default limit is zero, preventing any rotation away from the axis.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "limit",
                      type = "number",
                      description = "The angle limit, in radians."
                    }
                  }
                }
              }
            },
            {
              name = "setLimit",
              summary = "Set the angle limit of the ConeJoint.",
              description = "Sets the angle limit of the ConeJoint.  The relative angle between the ConeJoint's axis and the second Collider will be constrained to this limit.",
              key = "ConeJoint:setLimit",
              module = "lovr.physics",
              notes = "The default limit is zero, preventing any rotation away from the axis.",
              variants = {
                {
                  arguments = {
                    {
                      name = "limit",
                      type = "number",
                      description = "The new limit in radians, between 0 and pi."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "Contact",
          summary = "TODO",
          description = "TODO",
          key = "Contact",
          module = "lovr.physics",
          methods = {
            {
              name = "getColliders",
              summary = "Get the two Colliders that are in contact.",
              description = "Returns the two Colliders that are in contact.",
              key = "Contact:getColliders",
              module = "lovr.physics",
              related = {
                "Contact:getShapes"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "first",
                      type = "Collider",
                      description = "The first collider."
                    },
                    {
                      name = "second",
                      type = "Collider",
                      description = "The second collider."
                    }
                  }
                }
              }
            },
            {
              name = "getFriction",
              summary = "Get the friction of the Contact.",
              description = "Returns the friction of the Contact.  Lower friction makes it easier for the colliders to slide against each other.",
              key = "Contact:getFriction",
              module = "lovr.physics",
              related = {
                "Collider:getFriction",
                "Collider:setFriction",
                "Contact:getRestitution",
                "Contact:setRestitution"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The contact friction."
                    }
                  }
                }
              }
            },
            {
              name = "getNormal",
              summary = "Get the normal vector of the Contact.",
              description = "Returns the normal vector of the Contact.  This is a direction vector that represents which direction the second collider should move to resolve the collision.",
              key = "Contact:getNormal",
              module = "lovr.physics",
              related = {
                "Contact:getOverlap",
                "Contact:getPoints"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the normal vector."
                    }
                  }
                }
              }
            },
            {
              name = "getOverlap",
              summary = "Get the amount of overlap between the colliders.",
              description = "Returns the amount of overlap between the colliders.",
              key = "Contact:getOverlap",
              module = "lovr.physics",
              related = {
                "Contact:getNormal"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "overlap",
                      type = "number",
                      description = "The amount of overlap, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getPoints",
              summary = "Get the contact points of the Contact.",
              description = "Returns the contact points of the Contact.  These are the points where the colliders are intersecting.",
              key = "Contact:getPoints",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "...points",
                      type = "number",
                      description = "Triplets of x/y/z numbers, one for each contact point."
                    }
                  }
                }
              }
            },
            {
              name = "getRestitution",
              summary = "Get the bounciness of the Contact.",
              description = "Returns the restitution of the Contact.  Restitution makes the Colliders bounce off of each other.  A restitution value of zero results in an inelastic collision response, whereas 1.0 results in an elastic collision that preserves all of the velocity.  Restitution can be bigger than 1.0 to make the collision even more bouncy.",
              key = "Contact:getRestitution",
              module = "lovr.physics",
              notes = "The default restitution is the maximum restitution of either of the colliders.",
              related = {
                "Collider:getRestitution",
                "Collider:setRestitution",
                "Contact:getFriction",
                "Contact:setFriction"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "restitution",
                      type = "number",
                      description = "The contact restitution."
                    }
                  }
                }
              }
            },
            {
              name = "getShapes",
              summary = "Get the two Shapes that are in contact.",
              description = "Returns the two Shapes that are in contact.",
              key = "Contact:getShapes",
              module = "lovr.physics",
              related = {
                "Contact:getColliders"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "first",
                      type = "Shape",
                      description = "The first shape."
                    },
                    {
                      name = "second",
                      type = "Shape",
                      description = "The second shape."
                    }
                  }
                }
              }
            },
            {
              name = "getSurfaceVelocity",
              summary = "Get the surface velocity of the Contact.",
              description = "Returns the world space surface velocity of the Contact.  This can be used to achieve a conveyor belt effect.",
              key = "Contact:getSurfaceVelocity",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the surface velocity."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the surface velocity."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the surface velocity."
                    }
                  }
                }
              }
            },
            {
              name = "isEnabled",
              summary = "Check if the Contact is enabled.",
              description = "Returns whether the Contact is enabled.  Disabled contacts do not generate any collision response.  Use `Contact:setEnabled` to disable a contact to selectively ignore certain collisions.",
              key = "Contact:isEnabled",
              module = "lovr.physics",
              related = {
                "Collider:isEnabled",
                "Collider:setEnabled",
                "World:setCallbacks"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether the Contact is enabled."
                    }
                  }
                }
              }
            },
            {
              name = "setEnabled",
              summary = "Enable or disable the Contact.",
              description = "Enables or disables the Contact.  Disabled contacts do not generate any collision response.",
              key = "Contact:setEnabled",
              module = "lovr.physics",
              notes = "Note that this is the slowest way to ignore a collision.  Faster ways to disable collisions (in increasing order of speed) are:\n\n- The `filter` callback in `World:setCallbacks`\n- Disabling collision between tags with `World:disableCollisionBetween`\n- Removing the collider from the World completely with `Collider:setEnabled`",
              variants = {
                {
                  arguments = {
                    {
                      name = "enable",
                      type = "boolean",
                      description = "Whether the Contact should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setFriction",
              summary = "Set the friction of the Contact.",
              description = "Sets the friction of the Contact.  Lower friction makes it easier for the colliders to slide against each other.  This overrides the default friction computed by the friction of the two Colliders.",
              key = "Contact:setFriction",
              module = "lovr.physics",
              notes = "The default friction is computed from the geometric mean of the Colliders' friction:\n\n    friction = (frictionA * frictionB) ^ .5\n\nNegative frictions will be clamped to zero.",
              related = {
                "Collider:getFriction",
                "Collider:setFriction",
                "Contact:getRestitution",
                "Contact:setRestitution"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The contact friction."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setRestitution",
              summary = "Set the bounciness of the Contact.",
              description = "Sets the restitution of the Contact.  Restitution makes the Colliders bounce off of each other. A restitution value of zero results in an inelastic collision response, whereas 1.0 results in an elastic collision that preserves all of the velocity.  Restitution can be bigger than 1.0 to make the collision even more bouncy.",
              key = "Contact:setRestitution",
              module = "lovr.physics",
              notes = "The default restitution is the maximum restitution of either of the colliders.\n\nNegative restitution values will be clamped to zero.",
              related = {
                "Collider:getRestitution",
                "Collider:setRestitution",
                "Contact:getFriction",
                "Contact:setFriction"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "restitution",
                      type = "number",
                      description = "The contact restitution."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSurfaceVelocity",
              summary = "Set the surface velocity of the Contact.",
              description = "Sets the world space surface velocity of the Contact.  This can be used to achieve a conveyor belt effect.",
              key = "Contact:setSurfaceVelocity",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the surface velocity."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the surface velocity."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the surface velocity."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "velocity",
                      type = "Vec3",
                      description = "The surface velocity."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "ConvexShape",
          summary = "A convex hull shape.",
          description = "A type of `Shape` that is a convex hull of a collection of points, allowing for custom collision shapes.  It is similar to a `MeshShape`, but it is not required to be kinematic, and it will use the convex hull of the mesh instead of using the exact triangles of the object.\n\nConvex shapes can be created from a `Model`, `ModelData`, `Mesh`, or a table of point positions, similar to `MeshShape`.\n\nConvex shapes can be cloned by passing in an existing ConvexShape to clone:\n\n    model = lovr.data.newModelData('rock.glb')\n    parent = lovr.physics.newConvexShape(model)\n    clone = lovr.physics.newConvexShape(parent, scale)\n\nThe clone will reuse all of the data from the parent, which speeds things up a lot.\n\nConvex shapes can have a custom scale applied to their points, and clones can have their own scale.",
          key = "ConvexShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newConvexShape",
            "World:newConvexCollider"
          },
          examples = {
            {
              description = "Drawing a convex hull.",
              code = "function lovr.load()\n  model = lovr.graphics.newModel('eggplant.glb')\n  hull = lovr.physics.newConvexShape(model)\n\n  -- Each face will be a list of points to draw a line through\n  faces = {}\n\n  for f = 1, hull:getFaceCount() do\n    local face = {}\n\n    for _, pointindex in ipairs(hull:getFace(f)) do\n      local x, y, z = hull:getPoint(pointindex)\n      table.insert(face, x)\n      table.insert(face, y)\n      table.insert(face, z)\n    end\n\n    -- Connect the last point back to the first point\n    table.insert(face, face[1])\n    table.insert(face, face[2])\n    table.insert(face, face[3])\n\n    table.insert(faces, face)\n  end\nend\n\nfunction lovr.draw(pass)\n  pass:push()\n  pass:translate(0, 0, -5)\n  pass:draw(model)\n\n  pass:setColor(1, 0, 0)\n  for i, points in pairs(faces) do\n    pass:line(points)\n  end\n  pass:pop()\nend"
            }
          },
          extends = "Shape",
          methods = {
            {
              name = "getFace",
              summary = "Get the point indices of one of the faces of the convex hull.",
              description = "Returns the indices of points that make up one of the faces of the convex hull.",
              key = "ConvexShape:getFace",
              module = "lovr.physics",
              related = {
                "ConvexShape:getPoint",
                "ConvexShape:getFaceCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the face."
                    }
                  },
                  returns = {
                    {
                      name = "points",
                      type = "table",
                      description = "A table with point indices.  Use `ConvexShape:getPoint` to get the coordinates.  The points are given in counterclockwise order."
                    }
                  }
                }
              }
            },
            {
              name = "getFaceCount",
              summary = "Get the number of faces in the convex hull.",
              description = "Returns the number of faces in the convex hull.",
              key = "ConvexShape:getFaceCount",
              module = "lovr.physics",
              related = {
                "ConvexShape:getFace"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of faces."
                    }
                  }
                }
              }
            },
            {
              name = "getPoint",
              summary = "Get one of the points in the convex hull.",
              description = "Returns one of the points in the convex hull, in local space.",
              key = "ConvexShape:getPoint",
              module = "lovr.physics",
              notes = "The point positions will be scaled by the ConvexShape's scale, see `ConvexShape:getScale`.",
              related = {
                "ConvexShape:getPointCount"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "index",
                      type = "number",
                      description = "The index of the point."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate."
                    }
                  }
                }
              }
            },
            {
              name = "getPointCount",
              summary = "Get the number of points in the convex hull.",
              description = "Returns the number of points in the convex hull.",
              key = "ConvexShape:getPointCount",
              module = "lovr.physics",
              notes = "This isn't necessarily the same as the number of points or vertices that were used to create the shape, since points inside the hull will be discarded.",
              related = {
                "ConvexShape:getPoint"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of points."
                    }
                  }
                }
              }
            },
            {
              name = "getScale",
              summary = "Get the scale the ConvexShape was created with.",
              description = "Returns the scale the ConvexShape was created with.",
              key = "ConvexShape:getScale",
              module = "lovr.physics",
              related = {
                "lovr.physics.newConvexShape",
                "World:newConvexCollider"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "CylinderShape",
          summary = "A cylinder Shape.",
          description = "A type of `Shape` that can be used for cylinder-shaped things.",
          key = "CylinderShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newCylinderShape",
            "World:newCylinderCollider"
          },
          extends = "Shape",
          methods = {
            {
              name = "getLength",
              summary = "Get the length of the CylinderShape.",
              description = "Returns the length of the CylinderShape.",
              key = "CylinderShape:getLength",
              module = "lovr.physics",
              related = {
                "CylinderShape:getRadius",
                "CylinderShape:setRadius"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cylinder, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getRadius",
              summary = "Get the radius of the CylinderShape.",
              description = "Returns the radius of the CylinderShape.",
              key = "CylinderShape:getRadius",
              module = "lovr.physics",
              related = {
                "CylinderShape:getLength",
                "CylinderShape:setLength"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "setLength",
              summary = "Set the length of the CylinderShape.",
              description = "Sets the length of the CylinderShape.",
              key = "CylinderShape:setLength",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              related = {
                "CylinderShape:getRadius",
                "CylinderShape:setRadius"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "length",
                      type = "number",
                      description = "The new length, in meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setRadius",
              summary = "Set the radius of the CylinderShape.",
              description = "Sets the radius of the CylinderShape.",
              key = "CylinderShape:setRadius",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              related = {
                "CylinderShape:getLength",
                "CylinderShape:setLength"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The new radius, in meters."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "DistanceJoint",
          summary = "A fixed distance joint.",
          description = "A DistanceJoint is a type of `Joint` that tries to keep two colliders within a certain distance. The distance is determined by the initial distance between the anchor points.  The joint allows for rotation on the anchor points.",
          key = "DistanceJoint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newDistanceJoint"
          },
          extends = "Joint",
          methods = {
            {
              name = "getLimits",
              summary = "Get the minimum and maximum distance.",
              description = "Returns the minimum and maximum distance allowed between the Colliders.",
              key = "DistanceJoint:getLimits",
              module = "lovr.physics",
              notes = "The limits default to the distance between the Colliders when the Joint was created.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum distance, in meters.  The Colliders won't be able to get closer than this."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum distance, in meters.  The Colliders won't be able to get further than this."
                    }
                  }
                }
              }
            },
            {
              name = "getSpring",
              summary = "Get the spring parameters of the joint.",
              description = "Returns the DistanceJoint's spring parameters.  Use this to control how fast the joint pulls the colliders back together at the distance limits.",
              key = "DistanceJoint:getSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).\n\nThe default damping ratio is 1.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled."
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring."
                    }
                  }
                }
              }
            },
            {
              name = "setLimits",
              summary = "Set the minimum and maximum distance.",
              description = "Sets the minimum and maximum distance allowed between the Colliders.",
              key = "DistanceJoint:setLimits",
              module = "lovr.physics",
              notes = "The limits default to the distance between the Colliders when the Joint was created.",
              variants = {
                {
                  arguments = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum distance, in meters.  The Colliders won't be able to get closer than this.",
                      default = "0"
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum distance, in meters.  The Colliders won't be able to get further than this.",
                      default = "min"
                    }
                  },
                  returns = {}
                },
                {
                  description = "Remove the limits, setting the minimum distance to zero and the maximum distance to infinity.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setSpring",
              summary = "Set the spring parameters of the joint.",
              description = "Sets the DistanceJoint's spring parameters.  Use this to control how fast the joint pulls the colliders back together at the distance limits.",
              key = "DistanceJoint:setSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).",
              variants = {
                {
                  arguments = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled.",
                      default = "0.0"
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          related = {
            "Collider"
          }
        },
        {
          name = "HingeJoint",
          summary = "A hinge joint.",
          description = "A HingeJoint is a type of `Joint` that only allows colliders to rotate on a single axis.",
          key = "HingeJoint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newHingeJoint"
          },
          extends = "Joint",
          methods = {
            {
              name = "getAngle",
              summary = "Get the current angle of the HingeJoint.",
              description = "Returns the current angle of the HingeJoint, relative to the rest position.",
              key = "HingeJoint:getAngle",
              module = "lovr.physics",
              related = {
                "HingeJoint:getAxis",
                "HingeJoint:getLimits",
                "HingeJoint:setLimits"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The hinge angle, in radians."
                    }
                  }
                }
              }
            },
            {
              name = "getAxis",
              summary = "Get the rotation axis of the HingeJoint.",
              description = "Returns the axis of the hinge, in world space.",
              key = "HingeJoint:getAxis",
              module = "lovr.physics",
              related = {
                "HingeJoint:getAngle",
                "Joint:getAnchors"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the axis."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the axis."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the axis."
                    }
                  }
                }
              }
            },
            {
              name = "getFriction",
              summary = "Get the friction of the HingeJoint.",
              description = "Returns the friction of the HingeJoint.  This is a maximum torque force that will be applied, in newton meters.",
              key = "HingeJoint:getFriction",
              module = "lovr.physics",
              notes = "Friction is only applied when the motor is disabled.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The friction, in newton meters."
                    }
                  }
                }
              }
            },
            {
              name = "getLimits",
              summary = "Get the angle limits of the HingeJoint.",
              description = "Returns the angle limits of the HingeJoint.  The \"zero\" angle is determined by the relative position of the colliders at the time the joint was created.",
              key = "HingeJoint:getLimits",
              module = "lovr.physics",
              notes = "The default limits are -π and π.",
              related = {
                "HingeJoint:getAngle"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum angle, in radians.  Always between -π and 0."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum angle, in radians.  Always between 0 and π."
                    }
                  }
                }
              }
            },
            {
              name = "getMaxMotorTorque",
              summary = "Get the maximum amount of torque the motor can use.",
              description = "Returns the maximum amount of torque the motor can use to reach its target, in newton meters.\n\nThere are separate limits for each direction the hinge can move.  They're usually kept the same, but one of them can be set to zero to make a motor that can only push in one direction.  Note that both limits are positive.",
              key = "HingeJoint:getMaxMotorTorque",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorTorque"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "positive",
                      type = "number",
                      description = "The maximum amount of torque the motor can use to push the hinge in the \"positive\" direction, in newton meters."
                    },
                    {
                      name = "negative",
                      type = "number",
                      description = "The maximum amount of torque the motor can use to push the hinge in the \"negative\" direction, in newton meters."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorMode",
              summary = "Get the motor mode of the HingeJoint.",
              description = "Returns the motor mode of the HingeJoint.  When enabled, the motor will drive the hinge to a target angle (for the `position` mode) or a target speed (for the `velocity` mode), set by `HingeJoint:setMotorTarget`.",
              key = "HingeJoint:getMotorMode",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorTarget",
                "HingeJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mode",
                      type = "MotorMode",
                      description = "The mode of the motor, or `nil` if the motor is disabled."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorSpring",
              summary = "Get the spring parameters of the motor target.",
              description = "Returns the spring parameters of the motor target.  These are similar to the spring parameters set by `HingeJoint:setSpring`, but they apply to the motor when it reaches its target instead of the angle limits of the hinge joint.  Note that these only take effect when the motor mode is `position`.",
              key = "HingeJoint:getMotorSpring",
              module = "lovr.physics",
              notes = "See `HingeJoint:setSpring` for more detailed info on how the spring parameters work.",
              related = {
                "HingeJoint:getSpring",
                "HingeJoint:setSpring",
                "HingeJoint:getMotorTarget",
                "HingeJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled."
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorTarget",
              summary = "Get the target of the hinge motor.",
              description = "Returns the target value for the HingeJoint's motor.  This is either a target angle or a target velocity, based on the mode set by `HingeJoint:setMotorMode`.",
              key = "HingeJoint:getMotorTarget",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorMode",
                "HingeJoint:setMotorMode"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "target",
                      type = "number",
                      description = "The target value, in radians or radians per second, depending on the mode."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorTorque",
              summary = "Get the current motor torque.",
              description = "Returns the current torque the motor is using to reach its target, in newton meters.",
              key = "HingeJoint:getMotorTorque",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMaxMotorTorque",
                "HingeJoint:setMaxMotorTorque"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "torque",
                      type = "number",
                      description = "The current torque, in newton meters."
                    }
                  }
                }
              }
            },
            {
              name = "getSpring",
              summary = "Get the spring parameters of the HingeJoint limits.",
              description = "Returns the spring parameters of the HingeJoint.  Use this to make the angle limits of the hinge \"soft\".  When the motor is active, a separate set of spring parameters can be set on the motor, see `HingeJoint:setMotorSpring`.",
              key = "HingeJoint:getSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).\n\nThe default damping ratio is 1.",
              related = {
                "HingeJoint:getMotorSpring",
                "HingeJoint:setMotorSpring"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled."
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring."
                    }
                  }
                }
              }
            },
            {
              name = "setFriction",
              summary = "Set the friction of the HingeJoint.",
              description = "Sets the friction of the HingeJoint.  This is a maximum torque force that will be applied, in newton meters.",
              key = "HingeJoint:setFriction",
              module = "lovr.physics",
              notes = "Friction is only applied when the motor is disabled.",
              variants = {
                {
                  arguments = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The friction, in newton meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLimits",
              summary = "Set the angle limits of the HingeJoint.",
              description = "Sets the angle limits of the HingeJoint.  The \"zero\" angle is determined by the relative position of the colliders at the time the joint was created.",
              key = "HingeJoint:setLimits",
              module = "lovr.physics",
              notes = "The default limits are -π and π.",
              related = {
                "HingeJoint:getAngle"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum angle, in radians.  Should be between -π and 0."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum angle, in radians.  Should be between 0 and π."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the limits, setting them to -π and π.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMaxMotorTorque",
              summary = "Set the maximum amount of torque the motor can use.",
              description = "Sets the maximum amount of torque the motor can use to reach its target, in newton meters.\n\nThere are separate limits for each direction the hinge can move.  They're usually kept the same, but one of them can be set to zero to make a motor that can only push in one direction.  Note that both limits are positive.",
              key = "HingeJoint:setMaxMotorTorque",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorTorque"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "positive",
                      type = "number",
                      description = "The maximum amount of torque the motor can use to push the hinge in the \"positive\" direction, in newton meters.",
                      default = "math.huge"
                    },
                    {
                      name = "negative",
                      type = "number",
                      description = "The maximum amount of torque the motor can use to push the hinge in the \"negative\" direction, in newton meters.",
                      default = "positive"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMotorMode",
              summary = "Set the motor mode of the HingeJoint.",
              description = "Sets the motor mode of the HingeJoint.  When enabled, the motor will drive the hinge to a target angle (for the `position` mode) or a target speed (for the `velocity` mode), set by `HingeJoint:setMotorTarget`.",
              key = "HingeJoint:setMotorMode",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorTarget",
                "HingeJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "MotorMode",
                      description = "The mode of the motor."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disables the motor.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMotorSpring",
              summary = "Set the spring parameters of the motor target.",
              description = "Sets the spring parameters of the motor target.  These are similar to the spring parameters set by `HingeJoint:setSpring`, but they apply to the motor when it reaches its target instead of the angle limits of the hinge joint.  Note that these only take effect when the motor mode is `position`.",
              key = "HingeJoint:setMotorSpring",
              module = "lovr.physics",
              notes = "See `HingeJoint:setSpring` for more detailed info on how the spring parameters work.",
              related = {
                "HingeJoint:getSpring",
                "HingeJoint:setSpring",
                "HingeJoint:getMotorTarget",
                "HingeJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled.",
                      default = "0.0"
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMotorTarget",
              summary = "Set the target of the hinge motor.",
              description = "Sets the target value for the HingeJoint's motor.  This is either a target angle or a target velocity, based on the mode set by `HingeJoint:setMotorMode`.",
              key = "HingeJoint:setMotorTarget",
              module = "lovr.physics",
              related = {
                "HingeJoint:getMotorMode",
                "HingeJoint:setMotorMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "target",
                      type = "number",
                      description = "The target value, in radians or radians per second, depending on the mode."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSpring",
              summary = "Set the spring parameters of the HingeJoint limits.",
              description = "Sets the spring parameters of the HingeJoint.  Use this to make the angle limits of the hinge \"soft\".  When the motor is active, a separate set of spring parameters can be set on the motor, see `HingeJoint:setMotorSpring`.",
              key = "HingeJoint:setSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).",
              related = {
                "HingeJoint:getMotorSpring",
                "HingeJoint:setMotorSpring"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled.",
                      default = "0.0"
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          related = {
            "Collider"
          }
        },
        {
          name = "Joint",
          summary = "Joins two Colliders together.",
          description = "A Joint is a physics object that constrains the movement of two Colliders.",
          key = "Joint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newWeldJoint",
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint"
          },
          extends = "Object",
          methods = {
            {
              name = "destroy",
              summary = "Destroy the Joint.",
              description = "Destroys the Joint, removing it from the World and breaking the connection between its Colliders.  There is no way to get the Joint back after destroying it, and attempting to use it will throw an error.  To temporarily disable a Joint, use `Joint:setEnabled`.",
              key = "Joint:destroy",
              module = "lovr.physics",
              notes = "Joints are automatically destroyed if either of their Colliders are destroyed or if the World is destroyed or garbage collected.",
              related = {
                "Joint:isDestroyed",
                "Joint:setEnabled",
                "Collider:destroy",
                "Shape:destroy",
                "World:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getAnchors",
              summary = "Get the anchor points of the Joint.",
              description = "Returns the world space anchor points of the Joint.  Joints are attached to each collider at a single point, which is defined when the Joint is created.",
              key = "Joint:getAnchors",
              module = "lovr.physics",
              related = {
                "Joint:getColliders"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the anchor point on the first Collider, in world space."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the anchor point on the first Collider, in world space."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the anchor point on the first Collider, in world space."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the anchor point on the second Collider, in world space."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the anchor point on the second Collider, in world space."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the anchor point on the second Collider, in world space."
                    }
                  }
                }
              }
            },
            {
              name = "getColliders",
              summary = "Get the Colliders the Joint is attached to.",
              description = "Returns the Colliders the Joint is attached to.",
              key = "Joint:getColliders",
              module = "lovr.physics",
              related = {
                "Collider:getJoints"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "colliderA",
                      type = "Collider",
                      description = "The first Collider."
                    },
                    {
                      name = "colliderB",
                      type = "Collider",
                      description = "The second Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getForce",
              summary = "Get the force used to satisfy the Joint's constraint.",
              description = "Returns the magnitude of the force used to satisfy the Joint's constraint during the last physics update, in newtons.\n\nThis is useful for breakable joints.  Use `Joint:destroy` to break the joint if its force goes above a threshold.",
              key = "Joint:getForce",
              module = "lovr.physics",
              notes = "This does not include the motor force of a `SliderJoint`, see `SliderJoint:getMotorForce`. that.",
              related = {
                "Joint:getTorque",
                "SliderJoint:getMotorForce"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "force",
                      type = "number",
                      description = "The magnitude of the force used to satisfy the Joint's constraint."
                    }
                  }
                }
              }
            },
            {
              name = "getPriority",
              summary = "Get the priority of the Joint.",
              description = "Returns the priority of the Joint.  Joints with a higher priority are more likely to be solved correctly.  Priority values are non-negative integers.",
              key = "Joint:getPriority",
              module = "lovr.physics",
              notes = "The default priority is zero.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "priority",
                      type = "number",
                      description = "The integer priority value."
                    }
                  }
                }
              }
            },
            {
              name = "getTorque",
              summary = "Get the torque used to satisfy the Joint's constraint.",
              description = "Returns the magnitude of the torque used to satisfy the Joint's constraint during the last physics update, in newton meters.\n\nThis is useful for breakable joints.  Use `Joint:destroy` to break the joint if its torque goes above a threshold.",
              key = "Joint:getTorque",
              module = "lovr.physics",
              notes = "This does not include the motor force of a `HingeJoint`, see `HingeJoint:getMotorForce`.",
              related = {
                "Joint:getForce",
                "HingeJoint:getMotorTorque"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "torque",
                      type = "number",
                      description = "The magnitude of the torque used to satisfy the Joint's constraint."
                    }
                  }
                }
              }
            },
            {
              name = "getType",
              summary = "Get the type of the Joint.",
              description = "Returns the type of the Joint.",
              key = "Joint:getType",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "type",
                      type = "JointType",
                      description = "The type of the Joint."
                    }
                  }
                }
              }
            },
            {
              name = "getUserData",
              summary = "Get the Lua value associated with the Joint.",
              description = "Returns the Lua value associated with the Joint.",
              key = "Joint:getUserData",
              module = "lovr.physics",
              notes = "The user data is not shared between threads.  Each thread has its own user data for the Joint.",
              related = {
                "Collider:getUserData",
                "Collider:setUserData",
                "Shape:getUserData",
                "Shape:setUserData"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value associated with the Joint."
                    }
                  }
                }
              }
            },
            {
              name = "isDestroyed",
              summary = "Check if a Joint is destroyed.",
              description = "Returns whether a Joint has been destroyed.  This the only method that can be called on a destroyed Joint, using the Joint in any other way will error.",
              key = "Joint:isDestroyed",
              module = "lovr.physics",
              related = {
                "Joint:destroy",
                "Joint:isEnabled",
                "Joint:setEnabled",
                "Collider:destroy",
                "Shape:destroy",
                "World:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "destroyed",
                      type = "boolean",
                      description = "Whether the Joint has been destroyed."
                    }
                  }
                }
              }
            },
            {
              name = "isEnabled",
              summary = "Check if the Joint is enabled.",
              description = "Returns whether the Joint is enabled.  Disabled joints do not affect the simulation in any way. Use `Joint:setEnabled` to reactivate the Joint later.  If the Joint is no longer needed, `Joint:destroy` is a better option that completely removes the Joint from the simulation.",
              key = "Joint:isEnabled",
              module = "lovr.physics",
              related = {
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether the Joint is enabled."
                    }
                  }
                }
              }
            },
            {
              name = "setEnabled",
              summary = "Enable or disable the Joint.",
              description = "Enable or disable the Joint.  Disabled joints do not affect the simulation in any way.  If the Joint is no longer needed, `Joint:destroy` is a better option that completely removes the Joint from the simulation.",
              key = "Joint:setEnabled",
              module = "lovr.physics",
              related = {
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether the Joint should be enabled."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setPriority",
              summary = "Set the priority of the Joint.",
              description = "Sets the priority of the Joint.  Joints with a higher priority are more likely to be solved correctly.  Priority values are non-negative integers.",
              key = "Joint:setPriority",
              module = "lovr.physics",
              notes = "The default priority is zero.",
              variants = {
                {
                  arguments = {
                    {
                      name = "priority",
                      type = "number",
                      description = "The integer priority value."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setUserData",
              summary = "Associate a Lua value with the Joint.",
              description = "Associates a Lua value with the Joint.",
              key = "Joint:setUserData",
              module = "lovr.physics",
              notes = "Set the user data to `nil` to clear any existing reference.\n\nThe user data is not shared between threads.  Each thread has its own user data for the Joint.",
              related = {
                "Collider:getUserData",
                "Collider:setUserData",
                "Shape:getUserData",
                "Shape:setUserData"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value to associate with the Joint."
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          related = {
            "Collider"
          }
        },
        {
          name = "MeshShape",
          summary = "A mesh Shape.",
          description = "A type of `Shape` that can be used for triangle meshes.",
          key = "MeshShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newMeshShape",
            "World:newMeshCollider"
          },
          extends = "Shape",
          methods = {
            {
              name = "getScale",
              summary = "Get the scale the MeshShape was created with.",
              description = "Returns the scale the MeshShape was created with.",
              key = "MeshShape:getScale",
              module = "lovr.physics",
              related = {
                "lovr.physics.newMeshShape",
                "World:newMeshCollider"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The scale."
                    }
                  }
                }
              }
            }
          },
          notes = "If a `Collider` contains a MeshShape, it will be forced to become kinematic.  `ConvexShape` can be used instead for dynamic mesh colliders."
        },
        {
          name = "Shape",
          summary = "Defines the shape of Colliders.",
          description = "A Shape is a physics object that can be attached to colliders to define their shape.",
          key = "Shape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape",
            "World:newBoxCollider",
            "World:newSphereCollider",
            "World:newCapsuleCollider",
            "World:newCylinderCollider",
            "World:newConvexCollider",
            "World:newMeshCollider",
            "World:newTerrainCollider"
          },
          extends = "Object",
          methods = {
            {
              name = "containsPoint",
              summary = "Check if a point is inside the shape.",
              description = "Returns whether a point is inside the Shape.\n\nThis takes into account the pose of the Shape's collider (if any), as well as its local offset set with `Shape:setOffset`.",
              key = "Shape:containsPoint",
              module = "lovr.physics",
              related = {
                "Shape:raycast",
                "World:raycast",
                "World:shapecast",
                "World:overlapShape",
                "World:queryBox",
                "World:querySphere"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the point."
                    }
                  },
                  returns = {
                    {
                      name = "hit",
                      type = "boolean",
                      description = "Whether the point is inside the Shape."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "point",
                      type = "Vec3",
                      description = "The point, as a vector."
                    }
                  },
                  returns = {
                    {
                      name = "hit",
                      type = "boolean",
                      description = "Whether the point is inside the Shape."
                    }
                  }
                }
              }
            },
            {
              name = "destroy",
              summary = "Destroy the Shape.",
              description = "Destroys the Shape, removing it from the Collider it's attached to.",
              key = "Shape:destroy",
              module = "lovr.physics",
              notes = "Calling methods on the Shape after destroying it will error (except for `Shape:isDestroyed`).\n\nIf the Shape is attached to a Collider with automatic mass enabled, the collider's mass properties will update.",
              related = {
                "Shape:isDestroyed",
                "Collider:destroy",
                "Joint:destroy",
                "World:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getAABB",
              summary = "Get the Shape's axis aligned bounding box.",
              description = "Returns the axis aligned bounding box of the Shape.",
              key = "Shape:getAABB",
              module = "lovr.physics",
              related = {
                "Collider:getAABB"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "minx",
                      type = "number",
                      description = "The minimum x coordinate of the box."
                    },
                    {
                      name = "maxx",
                      type = "number",
                      description = "The maximum x coordinate of the box."
                    },
                    {
                      name = "miny",
                      type = "number",
                      description = "The minimum y coordinate of the box."
                    },
                    {
                      name = "maxy",
                      type = "number",
                      description = "The maximum y coordinate of the box."
                    },
                    {
                      name = "minz",
                      type = "number",
                      description = "The minimum z coordinate of the box."
                    },
                    {
                      name = "maxz",
                      type = "number",
                      description = "The maximum z coordinate of the box."
                    }
                  }
                }
              }
            },
            {
              name = "getCenterOfMass",
              summary = "Get the center of mass of the Shape.",
              description = "Returns the center of mass of the Shape.  Currently the only shape that can have a non-zero center of mass is `ConvexShape`.",
              key = "Shape:getCenterOfMass",
              module = "lovr.physics",
              notes = "`MeshShape` and `TerrainShape` do not have a well-defined mass, this function returns zero for those shapes.",
              related = {
                "Collider:getCenterOfMass",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the center of mass."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the center of mass."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the center of mass."
                    }
                  }
                }
              }
            },
            {
              name = "getCollider",
              summary = "Get the Collider the Shape is attached to.",
              description = "Returns the Collider the Shape is attached to.\n\nThis function will return `nil` if the Shape is not attached to a Collider.  When a Shape isn't attached to a Collider, the Shape can still be used for queries with `World:overlapShape` and `World:shapecast`.",
              key = "Shape:getCollider",
              module = "lovr.physics",
              notes = "A Shape can only be attached to one Collider at a time.",
              related = {
                "Collider",
                "Collider:getShape",
                "Collider:getShapes",
                "Collider:addShape",
                "Collider:removeShape"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The Collider the Shape is attached to, or nil if the Shape isn't attached to a Collider."
                    }
                  }
                }
              }
            },
            {
              name = "getDensity",
              summary = "Get the density of the Shape.",
              description = "Returns the density of the Shape, in kilograms per cubic meter.  The density, combined with the volume of the Shape, determines the Shape's overall mass.",
              key = "Shape:getDensity",
              module = "lovr.physics",
              notes = "The default density is 1,000, which is the density of water.\n\n`MeshShape` and `TerrainShape` do not have volume, and return 0.",
              related = {
                "Shape:getVolume",
                "Shape:getMass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "density",
                      type = "number",
                      description = "The density of the Shape, in kilograms per cubic meter."
                    }
                  }
                }
              }
            },
            {
              name = "getInertia",
              summary = "Get the inertia of the Shape.",
              description = "Returns the inertia of the Shape.\n\nInertia is kind of like \"angular mass\".  Regular mass determines how resistant a Collider is to linear forces (movement), whereas inertia determines how resistant the Collider is to torque (rotation).  Colliders with less inertia are more spinny.\n\nIn 3D, inertia is represented by a 3x3 matrix, called a tensor.  To make calculations easier, the physics engine stores the inertia using eigenvalue decomposition, splitting the matrix into a diagonal matrix and a rotation.  It's complicated!\n\nIn a realistic simulation, mass and inertia follow a linear relationship.  If the mass of an object increases, the diagonal part of its inertia should increase proportionally.",
              key = "Shape:getInertia",
              module = "lovr.physics",
              notes = "`MeshShape` and `TerrainShape` do not have mass or volue, and for those shapes this function returns zeroes.",
              related = {
                "Shape:getMass",
                "Shape:getCenterOfMass",
                "Collider:getInertia"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "dx",
                      type = "number",
                      description = "The x component of the diagonal matrix."
                    },
                    {
                      name = "dy",
                      type = "number",
                      description = "The y component of the diagonal matrix."
                    },
                    {
                      name = "dz",
                      type = "number",
                      description = "The z component of the diagonal matrix."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle of the inertia rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the inertia rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the inertia rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the inertia rotation axis."
                    }
                  }
                }
              }
            },
            {
              name = "getMass",
              summary = "Get the mass of the Shape.",
              description = "Returns the mass of the Shape, in kilograms.  The mass is the volume multiplied by the density.",
              key = "Shape:getMass",
              module = "lovr.physics",
              notes = "The mass of a Collider is the sum of the mass of all of its Shapes.  The center of a mass of a Collider is the average of all of its Shapes, weighted by their mass.\n\n`MeshShape` and `TerrainShape` do not have mass, and will return 0.",
              related = {
                "Collider:getMass",
                "Collider:setMass",
                "Collider:resetMassData",
                "Shape:getVolume",
                "Shape:getDensity",
                "Shape:setDensity",
                "Shape:getInertia",
                "Shape:getCenterOfMass"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mass",
                      type = "number",
                      description = "The mass of the Shape, in kilograms."
                    }
                  }
                }
              }
            },
            {
              name = "getOffset",
              summary = "Get the local offset of the Shape.",
              description = "Returns the local offset of the Shape.  When the Shape is attached to a Collider, it will have this offset relative to the Collider.",
              key = "Shape:getOffset",
              module = "lovr.physics",
              related = {
                "Shape:getPosition",
                "Shape:getOrientation",
                "Shape:getPose"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The local x offset of the Shape, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The local y offset of the Shape, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The local z offset of the Shape, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Shape is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getOrientation",
              summary = "Get the orientation of the Shape.",
              description = "Get the orientation of the Shape in world space, taking into account the position and orientation of the Collider it's attached to, if any.  Shapes that aren't attached to a Collider will return their local offset.",
              key = "Shape:getOrientation",
              module = "lovr.physics",
              related = {
                "Shape:getPosition",
                "Shape:getPose",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Shape is rotated."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the rotation axis."
                    }
                  }
                }
              }
            },
            {
              name = "getPose",
              summary = "Get the pose of the Shape.",
              description = "Returns the position and orientation of the Shape in world space, taking into the account the position and orientation of the Collider it's attached to, if any.  Shapes that aren't attached to a Collider will return their local offset.",
              key = "Shape:getPose",
              module = "lovr.physics",
              related = {
                "Shape:getPosition",
                "Shape:getOrientation",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Shape, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Shape, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Shape, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Shape is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              summary = "Get the position of the Shape.",
              description = "Returns the position of the Shape in world space, taking into the account the position and orientation of the Collider it's attached to, if any.  Shapes that aren't attached to a Collider will return their local offset.",
              key = "Shape:getPosition",
              module = "lovr.physics",
              related = {
                "Shape:getOrientation",
                "Shape:getPose",
                "Shape:getOffset",
                "Shape:setOffset"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position, in world space."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position, in world space."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position, in world space."
                    }
                  }
                }
              }
            },
            {
              name = "getType",
              summary = "Get the type of the Shape.",
              description = "Returns the type of the Shape.",
              key = "Shape:getType",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "type",
                      type = "ShapeType",
                      description = "The type of the Shape."
                    }
                  }
                }
              }
            },
            {
              name = "getUserData",
              summary = "Get the Lua value associated with the Shape.",
              description = "Returns the Lua value associated with the Shape.",
              key = "Shape:getUserData",
              module = "lovr.physics",
              notes = "The user data is not shared between threads.  Each thread has its own user data for the Shape.",
              related = {
                "Collider:getUserData",
                "Collider:setUserData",
                "Joint:getUserData",
                "Joint:setUserData"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value associated with the Shape."
                    }
                  }
                }
              }
            },
            {
              name = "getVolume",
              summary = "Get the volume of the Shape.",
              description = "Returns the volume of the Shape, in cubic meters.",
              key = "Shape:getVolume",
              module = "lovr.physics",
              notes = "`MeshShape` and `TerrainShape` do not have volume, and will return 0.",
              related = {
                "Shape:getDensity",
                "Shape:setDensity",
                "Shape:getMass",
                "Shape:getAABB"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "volume",
                      type = "number",
                      description = "The volume of the shape, in cubic meters."
                    }
                  }
                }
              }
            },
            {
              name = "isDestroyed",
              summary = "Check if the Shape is destroyed.",
              description = "Returns whether the Shape has been destroyed.  Destroyed shapes can not be used for anything.",
              key = "Shape:isDestroyed",
              module = "lovr.physics",
              related = {
                "Shape:destroy",
                "Collider:isDestroyed",
                "Joint:isDestroyed",
                "World:isDestroyed"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "destroyed",
                      type = "boolean",
                      description = "Whether the Shape has been destroyed."
                    }
                  }
                }
              }
            },
            {
              name = "raycast",
              summary = "Cast a ray against the shape.",
              description = "Casts a ray against the Shape and returns the first intersection.\n\nThis takes into account the pose of the Shape's collider (if any), as well as its local offset set with `Shape:setOffset`.",
              key = "Shape:raycast",
              module = "lovr.physics",
              related = {
                "World:raycast",
                "Shape:containsPoint",
                "World:shapecast",
                "World:overlapShape"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the origin of the ray."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the origin of the ray."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the origin of the ray."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the endpoint of the ray."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the endpoint of the ray."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the endpoint of the ray."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number | nil",
                      description = "The index of the triangle that was hit, or `nil` if this is not a MeshShape."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "origin",
                      type = "Vec3",
                      description = "The origin of the ray."
                    },
                    {
                      name = "endpoint",
                      type = "Vec3",
                      description = "The endpoint of the ray."
                    }
                  },
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number | nil",
                      description = "The index of the triangle that was hit, or `nil` if this is not a MeshShape."
                    }
                  }
                }
              }
            },
            {
              name = "setDensity",
              summary = "Set the density of the Shape.",
              description = "Sets the density of the Shape, in kilograms per cubic meter.  The density, combined with the volume of the Shape, determines the Shape's overall mass.",
              key = "Shape:setDensity",
              module = "lovr.physics",
              notes = "This changes the mass of the Shape.  If the Shape is attached to a Collider with automatic mass enabled, the Collider's mass properties will change as well.\n\nThe default density is 1,000, which is the density of water.\n\n`MeshShape` and `TerrainShape` do not have mass.",
              related = {
                "Shape:getVolume",
                "Shape:getMass"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "density",
                      type = "number",
                      description = "The density of the Shape, in kilograms per cubic meter."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setOffset",
              summary = "Set the local offset of the Shape.",
              description = "Sets the local offset of the Shape.  When the Shape is attached to a Collider, it will have this offset relative to the Collider.",
              key = "Shape:setOffset",
              module = "lovr.physics",
              related = {
                "Shape:getPosition",
                "Shape:getOrientation",
                "Shape:getPose"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The local x offset of the Shape, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The local y offset of the Shape, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The local z offset of the Shape, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The number of radians the Shape is rotated around its axis of rotation."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The local offset of the Shape, in meters."
                    },
                    {
                      name = "rotation",
                      type = "Quat",
                      description = "The local rotation of the Shape, in meters."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setUserData",
              summary = "Associate a Lua value with the Shape.",
              description = "Associates a Lua value with the Shape.",
              key = "Shape:setUserData",
              module = "lovr.physics",
              notes = "Set the user data to `nil` to clear any existing reference.\n\nThe user data is not shared between threads.  Each thread has its own user data for the Shape.",
              related = {
                "Collider:getUserData",
                "Collider:setUserData",
                "Joint:getUserData",
                "Joint:setUserData"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "data",
                      type = "*",
                      description = "The custom value to associate with the Shape."
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Basics",
              links = {
                "Shape:getType",
                "Shape:destroy",
                "Shape:isDestroyed",
                "Shape:getCollider",
                "Shape:getUserData",
                "Shape:setUserData"
              }
            },
            {
              name = "Position",
              links = {
                "Shape:getOffset",
                "Shape:setOffset",
                "Shape:getPosition",
                "Shape:getOrientation",
                "Shape:getPose",
                "Shape:getAABB"
              }
            },
            {
              name = "Mass",
              links = {
                "Shape:getVolume",
                "Shape:getDensity",
                "Shape:setDensity",
                "Shape:getMass",
                "Shape:getInertia",
                "Shape:getCenterOfMass"
              }
            },
            {
              name = "Queries",
              links = {
                "Shape:containsPoint",
                "Shape:raycast"
              }
            }
          }
        },
        {
          name = "SliderJoint",
          summary = "A slider joint.",
          description = "A SliderJoint is a type of `Joint` that only allows colliders to move on a single axis.",
          key = "SliderJoint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newSliderJoint"
          },
          extends = "Joint",
          methods = {
            {
              name = "getAxis",
              summary = "Get the axis of the SliderJoint.",
              description = "Returns the axis of the slider, in world space.",
              key = "SliderJoint:getAxis",
              module = "lovr.physics",
              related = {
                "SliderJoint:getPosition"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x component of the axis."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y component of the axis."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z component of the axis."
                    }
                  }
                }
              }
            },
            {
              name = "getFriction",
              summary = "Get the friction of the SliderJoint.",
              description = "Returns the friction of the SliderJoint.  This is a maximum friction force that will be applied, in newtons, opposing movement along the slider axis.",
              key = "SliderJoint:getFriction",
              module = "lovr.physics",
              notes = "Friction is only applied when the motor is disabled.",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The maximum friction force, in newtons."
                    }
                  }
                }
              }
            },
            {
              name = "getLimits",
              summary = "Get the position limits of the SliderJoint.",
              description = "Returns the position limits of the SliderJoint.  The \"zero\" position is determined by the relative position of the colliders at the time the joint was created, and positive positions are further apart along the slider axis.",
              key = "SliderJoint:getLimits",
              module = "lovr.physics",
              notes = "The default limits are -math.huge and math.huge (no limits).",
              related = {
                "SliderJoint:getPosition"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum position, in meters.  Must be less than or equal to zero."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum position, in meters.  Must be greater than or equal to zero."
                    }
                  }
                }
              }
            },
            {
              name = "getMaxMotorForce",
              summary = "Get the maximum amount of force the motor can use.",
              description = "Returns the maximum amount of force the motor can use to reach its target, in newtons.\n\nThere are separate limits for each direction the slider can move.  They're usually kept the same, but one of them can be set to zero to make a motor that can only push in one direction. Note that both limits are positive.",
              key = "SliderJoint:getMaxMotorForce",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorForce"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "positive",
                      type = "number",
                      description = "The maximum amount of force the motor can use to push the slider in the \"positive\" direction, in newtons."
                    },
                    {
                      name = "negative",
                      type = "number",
                      description = "The maximum amount of force the motor can use to push the slider in the \"negative\" direction, in newtons."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorForce",
              summary = "Get the current motor force.",
              description = "Returns the current force the motor is using to reach its target, in newtons.",
              key = "SliderJoint:getMotorForce",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMaxMotorForce",
                "SliderJoint:setMaxMotorForce"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "force",
                      type = "number",
                      description = "The current force, in newtons."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorMode",
              summary = "Get the motor mode of the SliderJoint.",
              description = "Returns the motor mode of the SliderJoint.  When enabled, the motor will drive the slider to a target position (for the `position` mode) or a target speed (for the `velocity` mode), set by `SliderJoint:setMotorTarget`.",
              key = "SliderJoint:getMotorMode",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorTarget",
                "SliderJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "mode",
                      type = "MotorMode",
                      description = "The mode of the motor, or `nil` if the motor is disabled."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorSpring",
              summary = "Get the spring parameters of the motor target.",
              description = "Returns the spring parameters of the motor target.  These are similar to the spring parameters set by `SliderJoint:setSpring`, but they apply to the motor when it reaches its target instead of the position limits of the slider joint.  Note that these only take effect when the motor mode is `position`.",
              key = "SliderJoint:getMotorSpring",
              module = "lovr.physics",
              notes = "See `SliderJoint:setSpring` for more detailed info on how the spring parameters work.",
              related = {
                "SliderJoint:getSpring",
                "SliderJoint:setSpring",
                "SliderJoint:getMotorTarget",
                "SliderJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled."
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring."
                    }
                  }
                }
              }
            },
            {
              name = "getMotorTarget",
              summary = "Get the target of the slider motor.",
              description = "Returns the target value for the SliderJoint's motor.  This is either a target position or a target velocity, based on the mode set by `SliderJoint:setMotorMode`.",
              key = "SliderJoint:getMotorTarget",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorMode",
                "SliderJoint:setMotorMode"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "target",
                      type = "number",
                      description = "The target value, in meters or meters per second, depending on the mode."
                    }
                  }
                }
              }
            },
            {
              name = "getPosition",
              summary = "Get how far the SliderJoint is extended.",
              description = "Returns the position of the slider joint.  The \"zero\" position is the relative distance the colliders were at when the joint is created, and positive positions are further apart along the slider's axis.",
              key = "SliderJoint:getPosition",
              module = "lovr.physics",
              related = {
                "SliderJoint:getAxis",
                "SliderJoint:setLimits"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "position",
                      type = "number",
                      description = "The position of the slider joint, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "getSpring",
              summary = "Get the spring parameters of the SliderJoint limits.",
              description = "Returns the spring parameters of the SliderJoint.  Use this to make the position limits of the slider \"soft\".  When the motor is active, a separate set of spring parameters can be set on the motor, see `SliderJoint:setMotorSpring`.",
              key = "SliderJoint:getSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).\n\nThe default damping ratio is 1.",
              related = {
                "SliderJoint:getMotorSpring",
                "SliderJoint:setMotorSpring"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled."
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring."
                    }
                  }
                }
              }
            },
            {
              name = "setFriction",
              summary = "Set the friction of the SliderJoint.",
              description = "Sets the friction of the SliderJoint.  This is a maximum friction force that will be applied, in newtons, opposing movement along the slider axis.",
              key = "SliderJoint:setFriction",
              module = "lovr.physics",
              notes = "Friction is only applied when the motor is disabled.",
              variants = {
                {
                  arguments = {
                    {
                      name = "friction",
                      type = "number",
                      description = "The maximum friction force, in newtons."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLimits",
              summary = "Set the position limits of the SliderJoint.",
              description = "Sets the position limits of the SliderJoint.  The \"zero\" position is determined by the relative position of the colliders at the time the joint was created, and positive distances are further apart on the slider axis.",
              key = "SliderJoint:setLimits",
              module = "lovr.physics",
              notes = "The default limits are -math.huge and math.huge.",
              related = {
                "SliderJoint:getPosition"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "min",
                      type = "number",
                      description = "The minimum position, in meters.  Must be less than or equal to zero."
                    },
                    {
                      name = "max",
                      type = "number",
                      description = "The maximum position, in meters.  Must be greater than or equal to zero."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disable the limits, setting them to -math.huge and math.huge.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMaxMotorForce",
              summary = "Set the maximum amount of force the motor can use.",
              description = "Sets the maximum amount of force the motor can use to reach its target, in newtons.\n\nThere are separate limits for each direction the slider can move.  They're usually kept the same, but one of them can be set to zero to make a motor that can only push in one direction. Note that both limits are positive.",
              key = "SliderJoint:setMaxMotorForce",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorForce"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "positive",
                      type = "number",
                      description = "The maximum amount of force the motor can use to push the slider in the \"positive\" direction, in newtons.",
                      default = "math.huge"
                    },
                    {
                      name = "negative",
                      type = "number",
                      description = "The maximum amount of force the motor can use to push the slider in the \"negative\" direction, in newtons.",
                      default = "positive"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMotorMode",
              summary = "Set the motor mode of the SliderJoint.",
              description = "Sets the motor mode of the SliderJoint.  When enabled, the motor will drive the slider to a target position (for the `position` mode) or a target speed (for the `velocity` mode), set by `SliderJoint:setMotorTarget`.",
              key = "SliderJoint:setMotorMode",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorTarget",
                "SliderJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "mode",
                      type = "MotorMode",
                      description = "The mode of the motor."
                    }
                  },
                  returns = {}
                },
                {
                  description = "Disables the motor.",
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "setMotorSpring",
              summary = "Set the spring parameters of the motor target.",
              description = "Sets the spring parameters of the motor target.  These are similar to the spring parameters set by `SldierJoint:setSpring`, but they apply to the motor when it reaches its target instead of the position limits of the slider joint.  Note that these only take effect when the motor mode is `position`.",
              key = "SliderJoint:setMotorSpring",
              module = "lovr.physics",
              notes = "See `SldierJoint:setSpring` for more detailed info on how the spring parameters work.",
              related = {
                "SliderJoint:getSpring",
                "SliderJoint:setSpring",
                "SliderJoint:getMotorTarget",
                "SliderJoint:setMotorTarget"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled.",
                      default = "0.0"
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setMotorTarget",
              summary = "Set the target of the slider motor.",
              description = "Sets the target value for the SliderJoint's motor.  This is either a target position or a target velocity, based on the mode set by `SliderJoint:setMotorMode`.",
              key = "SliderJoint:setMotorTarget",
              module = "lovr.physics",
              related = {
                "SliderJoint:getMotorMode",
                "SliderJoint:setMotorMode"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "target",
                      type = "number",
                      description = "The target value, in meters or meters per second, depending on the mode."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSpring",
              summary = "Set the spring parameters of the SliderJoint limits.",
              description = "Sets the spring parameters of the SliderJoint.  Use this to make the position limits of the slider \"soft\".  When the motor is active, a separate set of spring parameters can be set on the motor, see `SliderJoint:setMotorSpring`.",
              key = "SliderJoint:setSpring",
              module = "lovr.physics",
              notes = "Higher frequencies make the spring more stiff.  When zero (the default), the spring is disabled and the limits will be as stiff as possible.\n\nThe damping ratio controls how quickly the oscillation slows down:\n\n- Undamped: Zero damping will cause the spring to oscillate forever.  (Note that the spring may\n  still lose a small amount of energy over time).\n- Underdamped: Damping less than one results in a system that is underdamped.  The spring will\n  oscillate around the target, but the oscillations will decay over time, eventually stabilizing\n  at the target.\n- Overdamped: Damping greater than one will not have any oscillation, and the spring will take\n  extra time to reach the target.\n- Critical Damping: When the damping is exactly 1.0, there is no oscillation and the spring\n  takes the minimum amount of time to reach the target (based on the frequency).",
              related = {
                "SliderJoint:getMotorSpring",
                "SliderJoint:setMotorSpring"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "frequency",
                      type = "number",
                      description = "The frequency of the spring, in hertz.  Higher frequencies make the spring more stiff.  When zero, the spring is disabled.",
                      default = "0.0"
                    },
                    {
                      name = "damping",
                      type = "number",
                      description = "The damping ratio of the spring.",
                      default = "1.0"
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          related = {
            "Collider"
          }
        },
        {
          name = "SphereShape",
          summary = "A sphere Shape.",
          description = "A type of `Shape` that can be used for spheres.",
          key = "SphereShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newSphereShape",
            "World:newSphereCollider"
          },
          extends = "Shape",
          methods = {
            {
              name = "getRadius",
              summary = "Get the radius of the SphereShape.",
              description = "Returns the radius of the SphereShape.",
              key = "SphereShape:getRadius",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters."
                    }
                  }
                }
              }
            },
            {
              name = "setRadius",
              summary = "Set the radius of the SphereShape.",
              description = "Sets the radius of the SphereShape.",
              key = "SphereShape:setRadius",
              module = "lovr.physics",
              notes = "This changes the mass of the shape.  If the shape is attached to a collider with automatic mass enabled, the mass properties of the collider will update as well.\n\nChanging shapes can make the physics engine explode since it can cause objects to overlap in unnatural ways.",
              variants = {
                {
                  arguments = {
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters."
                    }
                  },
                  returns = {}
                }
              }
            }
          }
        },
        {
          name = "TerrainShape",
          summary = "A terrain Shape.",
          description = "A type of `Shape` that can be used for terrains and irregular surfaces.",
          key = "TerrainShape",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newTerrainShape",
            "World:newTerrainCollider"
          },
          extends = "Shape",
          methods = {}
        },
        {
          name = "WeldJoint",
          summary = "A joint that welds two colliders together.",
          description = "A WeldJoint is a `Joint` that restricts all relative motion between two colliders, as though they were welded together into a single object.  All six degrees of freedom are constrained.\n\nWeldJoints are useful for making breakable objects.  Several colliders can be welded together with joints, and if `Joint:getForce` reports a large enough value, the joints can be disabled or destroyed, allowing the pieces to move freely.",
          key = "WeldJoint",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newWeldJoint"
          },
          extends = "Joint",
          methods = {}
        },
        {
          name = "World",
          summary = "An object holding all the colliders and joints in a physics simulation.",
          description = "A World is an object that holds all of the colliders and joints in a physics simulation.\n\nBe sure to call `World:update` on the World every frame to advance the simulation.",
          key = "World",
          module = "lovr.physics",
          constructors = {
            "lovr.physics.newWorld"
          },
          extends = "Object",
          methods = {
            {
              name = "destroy",
              summary = "Destroy the World!!  Muahaha!",
              description = "Destroys the World.  This will destroy all colliders, shapes, and joints in the world.  After calling this function, the world can no longer be used.  Attempting to call a method on the World after destroying it will error, with the exception of `World:isDestroyed`.",
              key = "World:destroy",
              module = "lovr.physics",
              notes = "If a World gets garbage collected, it will be destroyed and, consequently, all of the colliders, shapes, and joints in the World will be destroyed as well, even if they can still be reached by Lua.  This is an exception to the way objects in LÖVR normally work, and is done to avoid issues with cycles in reference counting.",
              related = {
                "Collider:destroy",
                "Shape:destroy",
                "Joint:destroy"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "disableCollisionBetween",
              summary = "Disable collision between two tags.",
              description = "Disables collision between two tags.  Use `Collider:setTag` to set a Collider's tag.",
              key = "World:disableCollisionBetween",
              module = "lovr.physics",
              notes = "By default, collision is enabled between all tags.\n\nAnother way of disabling collisions is by using the `filter` callback in `World:setCallbacks`. However, using tags is much faster than using the callback, because the physics engine calls the callback later in the collision detection process.  With tags, the colliders are ignored much earlier and precise collision detection is never performed.\n\nTags can be marked as \"static\" when the world is created, as an optimization hint.  Static tags will never collide with other static tags, regardless of whether collision is enabled between them.",
              related = {
                "World:enableCollisionBetween",
                "World:isCollisionEnabledBetween",
                "lovr.physics.newWorld",
                "World:getTags",
                "Collider:setTag"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "tag1",
                      type = "string",
                      description = "The first tag."
                    },
                    {
                      name = "tag2",
                      type = "string",
                      description = "The second tag."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "enableCollisionBetween",
              summary = "Enable collision between two tags.",
              description = "Enables collision between two tags.  Use `Collider:setTag` to set a Collider's tag.",
              key = "World:enableCollisionBetween",
              module = "lovr.physics",
              notes = "By default, collision is enabled between all tags.\n\nTags can be marked as \"static\" when the world is created, as an optimization hint.  Static tags will never collide with other static tags, regardless of whether collision is enabled between them.",
              related = {
                "World:disableCollisionBetween",
                "World:isCollisionEnabledBetween",
                "lovr.physics.newWorld",
                "World:getTags",
                "Collider:setTag"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "tag1",
                      type = "string",
                      description = "The first tag."
                    },
                    {
                      name = "tag2",
                      type = "string",
                      description = "The second tag."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "getAngularDamping",
              summary = "Get the angular damping of the World.",
              description = "Returns the angular damping parameters of the World.  Angular damping makes things less \"spinny\", making them slow down their angular velocity over time.",
              key = "World:getAngularDamping",
              module = "lovr.physics",
              deprecated = true,
              notes = "This sets the default damping for newly-created colliders.  Damping can also be set on a per-collider basis using `Collider:setAngularDamping`.",
              related = {
                "Collider:getAngularDamping",
                "Collider:setAngularDamping"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The angular damping."
                    },
                    {
                      name = "threshold",
                      type = "number",
                      description = "Velocity limit below which the damping is not applied."
                    }
                  }
                }
              }
            },
            {
              name = "getCallbacks",
              summary = "Get the World's collision callbacks.",
              description = "- Returns the callbacks assigned to the World.\n- The callbacks are described in more detail on `World:setCallbacks`.",
              key = "World:getCallbacks",
              module = "lovr.physics",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "callbacks",
                      type = "table",
                      description = "The World collision callbacks.",
                      table = {
                        {
                          name = "filter",
                          type = "function | nil",
                          description = "The function used to filter collisions."
                        },
                        {
                          name = "enter",
                          type = "function | nil",
                          description = "The function called when 2 colliders start touching."
                        },
                        {
                          name = "exit",
                          type = "function | nil",
                          description = "The function called when 2 colliders stop touching."
                        },
                        {
                          name = "contact",
                          type = "function | nil",
                          description = "The function called every frame while 2 colliders are in contact."
                        }
                      }
                    }
                  }
                }
              }
            },
            {
              name = "getColliderCount",
              summary = "Get the number of colliders in the world.",
              description = "Returns the number of colliders in the world.  This includes sleeping and disabled colliders.",
              key = "World:getColliderCount",
              module = "lovr.physics",
              notes = "The world has a maximum number of colliders, configured when creating the world.  The default is 8192.  Trying to create more than this will error.",
              related = {
                "World:getColliders",
                "World:getJointCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of colliders in the World."
                    }
                  }
                }
              }
            },
            {
              name = "getColliders",
              summary = "Get a list of colliders in the World.",
              description = "Returns a list of colliders in the world.  This includes sleeping and disabled colliders.",
              key = "World:getColliders",
              module = "lovr.physics",
              related = {
                "World:getColliderCount",
                "World:getJoints"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "colliders",
                      type = "{Collider}",
                      description = "The list of `Collider` objects in the World."
                    }
                  }
                }
              }
            },
            {
              name = "getGravity",
              summary = "Get the gravity of the World.",
              description = "Returns the World's gravity.  Gravity is a constant acceleration applied to all colliders.  The default is `(0, -9.81, 0)` meters per second squared, causing colliders to fall downward.\n\nUse `Collider:setGravityScale` to change gravity strength for a single collider.",
              key = "World:getGravity",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore gravity, since they are not moved by forces.  Colliders with higher mass do not fall faster.",
              related = {
                "Collider:getGravityScale",
                "Collider:setGravityScale",
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "gx",
                      type = "number",
                      description = "The x component of the gravity force, in meters per second squared."
                    },
                    {
                      name = "gy",
                      type = "number",
                      description = "The y component of the gravity force, in meters per second squared."
                    },
                    {
                      name = "gz",
                      type = "number",
                      description = "The z component of the gravity force, in meters per second squared."
                    }
                  }
                }
              }
            },
            {
              name = "getJointCount",
              summary = "Get the number of joints in the world.",
              description = "Returns the number of joints in the world.  This includes disabled joints.",
              key = "World:getJointCount",
              module = "lovr.physics",
              related = {
                "World:getJoints",
                "World:getColliderCount"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of joints in the World."
                    }
                  }
                }
              }
            },
            {
              name = "getJoints",
              summary = "Get a list of joints in the World.",
              description = "Returns a table with all the joints in the World.  This includes disabled joints.",
              key = "World:getJoints",
              module = "lovr.physics",
              related = {
                "World:getJointCount",
                "World:getColliders"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "joints",
                      type = "{Joint}",
                      description = "The list of `Joint` objects in the World."
                    }
                  }
                }
              }
            },
            {
              name = "getLinearDamping",
              summary = "Get the linear damping of the World.",
              description = "Returns the linear damping parameters of the World.  Linear damping is similar to drag or air resistance, slowing down colliders over time as they move.",
              key = "World:getLinearDamping",
              module = "lovr.physics",
              deprecated = true,
              notes = "A linear damping of 0 means colliders won't slow down over time.  This is the default.\n\nThis sets the default damping for newly-created colliders.  Damping can also be set on a per-collider basis using `Collider:setLinearDamping`.",
              related = {
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The linear damping."
                    },
                    {
                      name = "threshold",
                      type = "number",
                      description = "Velocity limit below which the damping is not applied."
                    }
                  }
                }
              }
            },
            {
              name = "getResponseTime",
              summary = "Get the response time of the World.",
              description = "Returns the response time factor of the World.\n\nThe response time controls how relaxed collisions and joints are in the physics simulation, and functions similar to inertia.  A low response time means collisions are resolved quickly, and higher values make objects more spongy and soft.\n\nThe value can be any positive number.  It can be changed on a per-joint basis for `DistanceJoint` and `BallJoint` objects.",
              key = "World:getResponseTime",
              module = "lovr.physics",
              deprecated = true,
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "responseTime",
                      type = "number",
                      description = "The response time setting for the World."
                    }
                  }
                }
              }
            },
            {
              name = "getStepCount",
              summary = "Get the step count of the World.",
              description = "Returns the step count of the World.  The step count influences how many steps are taken during a call to `World:update`.  A higher number of steps will be slower, but more accurate.  The default step count is 20.",
              key = "World:getStepCount",
              module = "lovr.physics",
              deprecated = true,
              related = {
                "World:update"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "steps",
                      type = "number",
                      description = "The step count."
                    }
                  }
                }
              }
            },
            {
              name = "getTags",
              summary = "Get the World's list of collision tags.",
              description = "Returns the list of collision tags that were specified when the World was created.  Tags are assigned to colliders using `Collider:setTag`, and collision can be enabled/disabled for pairs of tags with `World:enableCollisionBetween` and `World:disableCollisionBetween`.",
              key = "World:getTags",
              module = "lovr.physics",
              related = {
                "lovr.physics.newWorld",
                "Collider:getTag",
                "Collider:setTag",
                "World:enableCollisionBetween",
                "World:disableCollisionBetween",
                "World:isCollisionEnabledBetween"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "tags",
                      type = "{string}",
                      description = "A table of collision tags (strings)."
                    }
                  }
                }
              }
            },
            {
              name = "getTightness",
              summary = "Get the tightness of joints in the World.",
              description = "Returns the tightness of joints in the World.\n\nThe tightness controls how much force is applied to colliders connected by joints.  With a value of 0, no force will be applied and joints won't have any effect.  With a tightness of 1, a strong force will be used to try to keep the Colliders constrained.  A tightness larger than 1 will overcorrect the joints, which can sometimes be desirable.  Negative tightness values are not supported.",
              key = "World:getTightness",
              module = "lovr.physics",
              deprecated = true,
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "tightness",
                      type = "number",
                      description = "The tightness of the World."
                    }
                  }
                }
              }
            },
            {
              name = "interpolate",
              summary = "Interpolate collider poses.",
              description = "Interpolates collider poses between their previous pose and their current pose.  Methods like `Collider:getPosition` and `Collider:getOrientation` will return the smoothed values.\n\nAfter `World:update` is called, any interpolation is reset and `World:interpolate` will need to be called again to recompute the interpolated poses.\n\nThis can be used to decouple the physics tick rate from the rendering rate.  For example, the physics simulation can be run at a fixed rate of 30Hz, and collider poses can be interpolated before rendering.  This leads to a more stable simulation, and allows the physics rate to be increased or decreased as desired, independent of the current display refresh rate.",
              key = "World:interpolate",
              module = "lovr.physics",
              examples = {
                {
                  description = "An example of a fixed timestep physics update.",
                  code = "function lovr.load()\n  world = lovr.physics.newWorld()\n  time = 0\n  timestep = 1 / 30 -- 30Hz\nend\n\nfunction lovr.update(dt)\n  time = time + dt\n\n  -- Update as many times as needed, if any\n  while time >= timestep do\n    world:update(timestep)\n    time = time - timestep\n\n    -- Potentially do per-tick gameplay logic here\n    -- like check for collisions or apply impulses\n  end\n\n  -- Interpolate the colliders\n  local alpha = time / timestep\n  world:interpolate(alpha)\nend\n\nfunction lovr.draw(pass)\n  -- Draw colliders as usual, using `Collider:getPose` etc.\nend"
                }
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "alpha",
                      type = "number",
                      description = "The interpolation parameter.  An alpha of zero will use the previous collider pose, an alpha of 1.0 will use the latest collider pose, etc.  Can be less than zero or greater than one."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "isCollisionEnabledBetween",
              summary = "Check if two tags can collide.",
              description = "Returns whether collisions are enabled between a pair of tags.",
              key = "World:isCollisionEnabledBetween",
              module = "lovr.physics",
              notes = "If either tag is nil, this function returns true, for convenience.  For example, the following function will still work if either of the colliders don't have a tag:\n\n    function willCollide(c1, c2)\n      return world:isCollisionEnabledBetween(c1:getTag(), c2:getTag())\n    end\n\nBy default, collision is enabled between all tags.\n\nTags can be marked as \"static\" when the world is created, as an optimization hint.  Static tags will never collide with other static tags, regardless of whether collision is enabled between them.",
              related = {
                "World:disableCollisionBetween",
                "World:enableCollisionBetween",
                "lovr.physics.newWorld",
                "World:getTags",
                "Collider:setTag"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "tag1",
                      type = "string",
                      description = "The first tag."
                    },
                    {
                      name = "tag2",
                      type = "string",
                      description = "The second tag."
                    }
                  },
                  returns = {
                    {
                      name = "enabled",
                      type = "boolean",
                      description = "Whether or not two colliders with the specified tags will collide."
                    }
                  }
                }
              }
            },
            {
              name = "isDestroyed",
              summary = "Check if the World has been destroyed.",
              description = "Returns whether the World has been destroyed.  Destroyed worlds can not be used for anything.",
              key = "World:isDestroyed",
              module = "lovr.physics",
              related = {
                "World:destroy",
                "Collider:isDestroyed",
                "Shape:isDestroyed",
                "Joint:isDestroyed"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "destroyed",
                      type = "boolean",
                      description = "Whether the World has been destroyed."
                    }
                  }
                }
              }
            },
            {
              name = "isSleepingAllowed",
              summary = "Check if colliders can go to sleep.",
              description = "Returns whether colliders can go to sleep in the World.",
              key = "World:isSleepingAllowed",
              module = "lovr.physics",
              deprecated = true,
              notes = "If sleeping is enabled, the World will try to detect colliders that haven't moved for a while and put them to sleep.  Sleeping colliders don't impact the physics simulation, which makes updates more efficient and improves physics performance.  However, the physics engine isn't perfect at waking up sleeping colliders and this can lead to bugs where colliders don't react to forces or collisions properly.\n\nThis can be set on individual colliders.\n\nColliders can be manually put to sleep or woken up using `Collider:setAwake`.",
              related = {
                "Collider:isSleepingAllowed",
                "Collider:setSleepingAllowed",
                "Collider:isAwake",
                "Collider:setAwake"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "allowed",
                      type = "boolean",
                      description = "Whether colliders can sleep."
                    }
                  }
                }
              }
            },
            {
              name = "newBoxCollider",
              summary = "Add a Collider with a BoxShape to the World.",
              description = "Adds a Collider to the world and attaches a `BoxShape`.",
              key = "World:newBoxCollider",
              module = "lovr.physics",
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.",
              related = {
                "BoxShape",
                "Collider",
                "World:newCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the box, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the box, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the box, in meters.",
                      default = "0"
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box, in meters.",
                      default = "1"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box, in meters.",
                      default = "width"
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box, in meters.",
                      default = "width"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the box, in meters."
                    },
                    {
                      name = "size",
                      type = "Vec3",
                      description = "The size of the box, in meters."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newCapsuleCollider",
              summary = "Add a Collider with a CapsuleShape to the World.",
              description = "Adds a Collider to the world and attaches a `CapsuleShape`.",
              key = "World:newCapsuleCollider",
              module = "lovr.physics",
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.\n\nThe length of the capsule goes along its local Z axis.",
              related = {
                "CapsuleShape",
                "Collider",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the capsule, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the capsule, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the capsule, in meters.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule, in meters.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the capsule, not including the caps, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the capsule, in meters.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the capsule, not including the caps, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newCollider",
              summary = "Add a Collider to the World.",
              description = "Adds a new Collider to the World, without attaching any Shapes to it.  Use `Collider:addShape` to add shapes.",
              key = "World:newCollider",
              module = "lovr.physics",
              examples = {
                {
                  code = "function lovr.load()\n  world = lovr.physics.newWorld()\n  collider = world:newCollider(0, 0, 0)\n  shape = lovr.physics.newSphereShape(.5)\n  collider:addShape(shape)\nend"
                }
              },
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.",
              related = {
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider",
                "Collider:addShape",
                "Collider",
                "Shape"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of the Collider."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of the Collider."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of the Collider."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the Collider."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newConvexCollider",
              summary = "Add a Collider with a ConvexShape to the World.",
              description = "Adds a Collider to the world and attaches a `ConvexShape`.  A `ConvexShape` is a convex hull of a set of points, kinda like if you wrapped them in wrapping paper.",
              key = "World:newConvexCollider",
              module = "lovr.physics",
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.",
              related = {
                "ConvexShape",
                "Collider",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "points",
                      type = "table",
                      description = "A list of vertices to compute a convex hull from.  Can be a table of tables (each with 3 numbers) or a table of numbers (every 3 numbers form a 3D point)."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "points",
                      type = "table",
                      description = "A list of vertices to compute a convex hull from.  Can be a table of tables (each with 3 numbers) or a table of numbers (every 3 numbers form a 3D point)."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "modelData",
                      type = "ModelData",
                      description = "The ModelData to compute a convex hull from."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "modelData",
                      type = "ModelData",
                      description = "The ModelData to compute a convex hull from."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "model",
                      type = "Model",
                      description = "The Model to compute a convex hull from."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "model",
                      type = "Model",
                      description = "The Model to compute a convex hull from."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "mesh",
                      type = "Mesh",
                      description = "The Mesh to compute a convex hull from.  It must use the `cpu` storage mode."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "mesh",
                      type = "Mesh",
                      description = "The Mesh to compute a convex hull from.  It must use the `cpu` storage mode."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  description = "Clones an existing ConvexShape, which is faster than passing the same points multiple times. Clones can have their own scale.  The clone's scale doesn't get multiplied with the scale of the template.",
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the collider, in meters.",
                      default = "0"
                    },
                    {
                      name = "template",
                      type = "ConvexShape",
                      description = "An existing ConvexShape to clone."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  description = "Clones an existing ConvexShape, which is faster than passing the same points multiple times. Clones can have their own scale.  The clone's scale doesn't get multiplied with the scale of the template.",
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the capsule, in meters."
                    },
                    {
                      name = "template",
                      type = "ConvexShape",
                      description = "An existing ConvexShape to clone."
                    },
                    {
                      name = "scale",
                      type = "number",
                      description = "A scale to apply to the points.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newCylinderCollider",
              summary = "Add a Collider with a CylinderShape to the World.",
              description = "Adds a Collider to the world and attaches a `CylinderShape`.",
              key = "World:newCylinderCollider",
              module = "lovr.physics",
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.\n\nThe length of the cylinder goes along its local Z axis.",
              related = {
                "CylinderShape",
                "Collider",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the cylinder, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the cylinder, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the cylinder, in meters.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder, in meters.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cylinder, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the cylinder, in meters."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the cylinder, in meters.",
                      default = "1"
                    },
                    {
                      name = "length",
                      type = "number",
                      description = "The length of the cylinder, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newMeshCollider",
              summary = "Add a Collider with a MeshShape to the World.",
              description = "Adds a Collider to the world and attaches a `MeshShape`.\n\nColliders with mesh shapes are immobile and can only be used for static environment objects. The collider will be kinematic and forces/velocities will not move it.  Also, these colliders will not detect collisions with other kinematic objects.\n\nMeshShapes are not treated as solid objects, but instead a collection of triangles.  They do not have mass or volume, and there is no concept of being \"inside\" a mesh.  `ConvexShape` is a good alternative for solid objects with an arbitrary shape.",
              key = "World:newMeshCollider",
              module = "lovr.physics",
              notes = "The triangles in a MeshShape should use counterclockwise winding.",
              related = {
                "Collider",
                "MeshShape",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newTerrainCollider",
                "Model:getTriangles"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "vertices",
                      type = "table",
                      description = "A table of vertices in the mesh.  Can be a table of tables (each with 3 numbers) or a table of numbers (every 3 numbers form a 3D vertex)."
                    },
                    {
                      name = "indices",
                      type = "table",
                      description = "A table of triangle indices representing how the vertices are connected together into triangles."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "modelData",
                      type = "ModelData",
                      description = "A ModelData to use for the mesh data."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "model",
                      type = "Model",
                      description = "A Model to use for the mesh data.  Similar to calling `Model:getTriangles` and passing it to this function, but has better performance."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "mesh",
                      type = "Mesh",
                      description = "A Mesh to use for the mesh data.  It must use the `cpu` storage mode."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  description = "Clones an existing MeshShape, which is faster than passing the same mesh multiple times. Clones can have their own scale.  The clone's scale doesn't get multiplied with the scale of the template.",
                  arguments = {
                    {
                      name = "template",
                      type = "MeshShape",
                      description = "An existing MeshShape to reuse."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newSphereCollider",
              summary = "Add a Collider with a SphereShape to the World.",
              description = "Adds a Collider to the world and attaches a `SphereShape`.",
              key = "World:newSphereCollider",
              module = "lovr.physics",
              notes = "This will throw an error if there are too many colliders in the world.  The limit defaults to 16384 and can be changed in `lovr.physics.newWorld`.",
              related = {
                "SphereShape",
                "Collider",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the sphere, in meters.",
                      default = "0"
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the sphere, in meters.",
                      default = "0"
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the sphere, in meters.",
                      default = "0"
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the sphere, in meters."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters.",
                      default = "1"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "newTerrainCollider",
              summary = "Add a Collider with a TerrainShape to the World.",
              description = "Adds a Collider to the world and attaches a `TerrainShape`.\n\nColliders with terrain shapes are immobile and can only be used for static environment objects. The collider will be kinematic and forces/velocities will not move it.  Also, these colliders will not detect collisions with other kinematic objects.\n\nTerrainShapes are not treated as solid objects, but instead a collection of triangles.  They do not have mass or volume, and there is no concept of being \"inside\" the terrain.",
              key = "World:newTerrainCollider",
              module = "lovr.physics",
              related = {
                "Collider",
                "TerrainShape",
                "World:newCollider",
                "World:newBoxCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newSphereCollider",
                "World:newMeshCollider",
                "lovr.data.newImage"
              },
              variants = {
                {
                  description = "Create a flat floor collider.",
                  arguments = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The width and depth of the terrain, in meters."
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  description = "Create terrain from a heightmap image.",
                  arguments = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The width and depth of the terrain, in meters."
                    },
                    {
                      name = "heightmap",
                      type = "Image",
                      description = "A heightmap image describing the terrain elevation at different points.  The red channel brightness of each pixel determines the elevation at corresponding coordinates.  The image must be square and must have one of the formats supported by `Image:getPixel`."
                    },
                    {
                      name = "stretch",
                      type = "number",
                      description = "A vertical multiplier for height values to obtain terrain height.  When the image format has pixel values only in the 0 to 1 range, this can be used to scale the height to meters.",
                      default = "1.0"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                },
                {
                  description = "Create terrain defined with a callback function.",
                  arguments = {
                    {
                      name = "scale",
                      type = "number",
                      description = "The width and depth of the terrain, in meters."
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "A function that returns terrain height from x and z coordinates.  The x and z inputs will range from `-scale / 2` to `scale / 2`.",
                      arguments = {
                        {
                          name = "x",
                          type = "number"
                        },
                        {
                          name = "z",
                          type = "number"
                        }
                      },
                      returns = {
                        name = "height",
                        type = "number"
                      }
                    },
                    {
                      name = "samples",
                      type = "number",
                      description = "The number of samples taken across the x and z dimensions.  More samples will result in higher terrain fidelity, but use more CPU and memory.",
                      default = "100"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The new Collider."
                    }
                  }
                }
              }
            },
            {
              name = "overlapShape",
              summary = "Find colliders that overlap a shape.",
              description = "Places a shape in the World, returning any shapes it intersects.\n\nA tag filter can be given to filter out shapes by their collider's tag:\n\n- Use nil to skip filtering.\n- Pass a tag name to only return shapes whose collider has that tag.\n- Pass a tag name with a ~ in front of it to exclude colliders with that tag.\n- Pass multiple tags separated by spaces to include multiple tags (works with ~ too).\n\nProvide an optional callback to call for each shape detected.  If the callbacks nil, this function returns the first shape detected.  In either case this function returns the shape, the hit position, and a penetration vector.  The penetration vector represents the direction and distance the shape would need to move so that it is no longer colliding with the input shape.",
              key = "World:overlapShape",
              module = "lovr.physics",
              related = {
                "World:shapecast",
                "World:raycast",
                "World:queryBox",
                "World:querySphere"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to test."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x position to place the shape at, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position to place the shape at, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position to place the shape at, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle the shape is rotated around its rotation axis, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    },
                    {
                      name = "maxDistance",
                      type = "number",
                      description = "The maximum distance at which a shape can be detected, in meters.  Zero will detect shapes touching the input shape, 1.0 will detect shapes within 1 meter of the input shape, etc.",
                      default = "0"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "Tags to filter by, or nil for no filter.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The callback to call for each intersection detected.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to test."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to place the shape at, in meters."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the shape."
                    },
                    {
                      name = "maxDistance",
                      type = "number",
                      description = "The maximum distance at which a shape can be detected, in meters.  Zero will detect shapes touching the input shape, 1.0 will detect shapes within 1 meter of the input shape, etc.",
                      default = "0"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "Tags to filter by, or nil for no filter.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The callback to call for each intersection detected.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to test."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x position to place the shape at, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position to place the shape at, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position to place the shape at, in meters."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The angle the shape is rotated around its rotation axis, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the axis of rotation."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the axis of rotation."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the axis of rotation."
                    },
                    {
                      name = "maxDistance",
                      type = "number",
                      description = "The maximum distance at which a shape can be detected, in meters.  Zero will detect shapes touching the input shape, 1.0 will detect shapes within 1 meter of the input shape, etc.",
                      default = "0"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "Tags to filter by, or nil for no filter.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the penetration vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the penetration vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the penetration vector."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to test."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to place the shape at, in meters."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the shape."
                    },
                    {
                      name = "maxDistance",
                      type = "number",
                      description = "The maximum distance at which a shape can be detected, in meters.  Zero will detect shapes touching the input shape, 1.0 will detect shapes within 1 meter of the input shape, etc.",
                      default = "0"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "Tags to filter by, or nil for no filter.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z position of a world space contact point on the surface of the shape."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the penetration vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the penetration vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the penetration vector."
                    }
                  }
                }
              }
            },
            {
              name = "queryBox",
              summary = "Find colliders that intersect an axis-aligned box.",
              description = "Find colliders within an axis-aligned bounding box.  This is a fast but imprecise query that only checks a rough box around colliders.  Use `World:overlapShape` for an exact collision test.\n\nRough queries like this are useful for doing a quick check before doing lots of more expensive collision testing.\n\nPass a callback function to call for each collider detected, or leave the callback off and this function will return the first collider found.",
              key = "World:queryBox",
              module = "lovr.physics",
              notes = "This will return sleeping colliders and sensors, but it will ignore disabled colliders.",
              related = {
                "World:querySphere",
                "World:overlapShape",
                "World:shapecast",
                "World:raycast"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the box, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the box, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the box, in meters."
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box, in meters"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box, in meters"
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box, in meters."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "A function to call when a collider is detected.  The function will be called with a single `Collider` argument.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the box, in meters."
                    },
                    {
                      name = "size",
                      type = "Vec3",
                      description = "The size of the box, in meters."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "A function to call when a collider is detected.  The function will be called with a single `Collider` argument.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the box, in meters."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the box, in meters."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the box, in meters."
                    },
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the box, in meters"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the box, in meters"
                    },
                    {
                      name = "depth",
                      type = "number",
                      description = "The depth of the box, in meters."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "A Collider that intersected the box."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the box, in meters."
                    },
                    {
                      name = "size",
                      type = "Vec3",
                      description = "The size of the box, in meters."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "A Collider that intersected the box."
                    }
                  }
                }
              }
            },
            {
              name = "querySphere",
              summary = "Find colliders that intersect a sphere.",
              description = "Find colliders within a sphere.  This is a fast but imprecise query that only checks a rough box around colliders.  Use `World:overlapShape` for an exact collision test.\n\nRough queries like this are useful for doing a quick check before doing lots of more expensive collision testing.\n\nPass a callback function to call for each collider detected, or leave the callback off and this function will return the first collider found.",
              key = "World:querySphere",
              module = "lovr.physics",
              related = {
                "World:queryBox",
                "World:overlapShape",
                "World:shapecast",
                "World:raycast"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the sphere."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the sphere."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "A function to call when an intersection is detected.  The function will be called with a single `Collider` argument.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "A function to call when an intersection is detected.  The function will be called with a single `Collider` argument.",
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the center of the sphere."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the center of the sphere."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the center of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "A Collider that intersected the sphere."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position of the center of the sphere."
                    },
                    {
                      name = "radius",
                      type = "number",
                      description = "The radius of the sphere, in meters"
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front of the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "A Collider that intersected the sphere."
                    }
                  }
                }
              }
            },
            {
              name = "raycast",
              summary = "Find colliders that intersect a line.",
              description = "Traces a ray through the world and calls a function for each collider that was hit.\n\nThe callback can be left off, in which case the closest hit will be returned.",
              key = "World:raycast",
              module = "lovr.physics",
              notes = "The callback function is passed a collider, a shape, a world-space point, a world-space normal, a triangle index, and a fraction:\n\n    function(collider, shape, x, y, z, nx, ny, nz, tri, fraction)\n      return fraction\n    end\n\nThe callback can return a fraction value used to limit the range of further hits.  For example:\n\n- Returning 0.0 will abort the raycast and ignore all other hits.\n- Returning 1.0 will call the callback for all hits.\n- Returning `fraction` will return successively closer hits.\n\nRaycasts will hit sensors and sleeping colliders, but will not hit disabled colliders.",
              related = {
                "Shape:raycast",
                "World:shapecast",
                "World:overlapShape",
                "World:queryBox",
                "World:querySphere"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the origin of the ray."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the origin of the ray."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the origin of the ray."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the endpoint of the ray."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the endpoint of the ray."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the endpoint of the ray."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The function to call when an intersection is detected (see notes).",
                      arguments = {
                        {
                          name = "collider",
                          type = "Collider"
                        },
                        {
                          name = "shape",
                          type = "Shape"
                        },
                        {
                          name = "x",
                          type = "number"
                        },
                        {
                          name = "y",
                          type = "number"
                        },
                        {
                          name = "z",
                          type = "number"
                        },
                        {
                          name = "nx",
                          type = "number"
                        },
                        {
                          name = "ny",
                          type = "number"
                        },
                        {
                          name = "nz",
                          type = "number"
                        },
                        {
                          name = "triangle",
                          type = "number"
                        },
                        {
                          name = "fraction",
                          type = "number"
                        }
                      },
                      returns = {
                        {
                          name = "limit",
                          type = "number",
                          default = "1.0"
                        }
                      },
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "origin",
                      type = "Vec3",
                      description = "The origin of the ray."
                    },
                    {
                      name = "endpoint",
                      type = "Vec3",
                      description = "The endpoint of the ray."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The function to call when an intersection is detected (see notes).",
                      arguments = {
                        {
                          name = "collider",
                          type = "Collider"
                        },
                        {
                          name = "shape",
                          type = "Shape"
                        },
                        {
                          name = "x",
                          type = "number"
                        },
                        {
                          name = "y",
                          type = "number"
                        },
                        {
                          name = "z",
                          type = "number"
                        },
                        {
                          name = "nx",
                          type = "number"
                        },
                        {
                          name = "ny",
                          type = "number"
                        },
                        {
                          name = "nz",
                          type = "number"
                        },
                        {
                          name = "triangle",
                          type = "number"
                        },
                        {
                          name = "fraction",
                          type = "number"
                        }
                      },
                      returns = {
                        {
                          name = "limit",
                          type = "number",
                          default = "1.0"
                        }
                      },
                      default = "nil"
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "x1",
                      type = "number",
                      description = "The x coordinate of the origin of the ray."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y coordinate of the origin of the ray."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z coordinate of the origin of the ray."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x coordinate of the endpoint of the ray."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y coordinate of the endpoint of the ray."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z coordinate of the endpoint of the ray."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The Collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point, in world space."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point, in world space."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point, in world space."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number | nil",
                      description = "The index of the triangle that was hit, or nil if a MeshShape was not hit."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "origin",
                      type = "Vec3",
                      description = "The origin of the ray."
                    },
                    {
                      name = "endpoint",
                      type = "Vec3",
                      description = "The endpoint of the ray."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The Collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point, in world space."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point, in world space."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point, in world space."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number | nil",
                      description = "The index of the triangle that was hit, or nil if a MeshShape was not hit."
                    }
                  }
                }
              }
            },
            {
              name = "setAngularDamping",
              summary = "Set the angular damping of the World.",
              description = "Sets the angular damping of the World.  Angular damping makes things less \"spinny\", making them slow down their angular velocity over time. Damping is only applied when angular velocity is over the threshold value.",
              key = "World:setAngularDamping",
              module = "lovr.physics",
              deprecated = true,
              notes = "This sets the default damping for newly-created colliders.  Damping can also be set on a per-collider basis using `Collider:setAngularDamping`.",
              related = {
                "Collider:getAngularDamping",
                "Collider:setAngularDamping"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The angular damping."
                    },
                    {
                      name = "threshold",
                      type = "number",
                      description = "Velocity limit below which the damping is not applied.",
                      default = "0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setCallbacks",
              summary = "Set the World's collision callbacks.",
              description = "Assigns collision callbacks to the world.  These callbacks are used to filter collisions or get notifications when colliders start or stop touching.  Callbacks are called during `World:update`.\n\n### Filter\n\nFilters collisions.  Receives two colliders and returns a boolean indicating if they should collide.  Note that it is much faster to use tags and `World:enableCollisionBetween` to control collision.  This should only be used when the logic for filtering the collision is highly dynamic.\n\n### Enter\n\nCalled when two colliders begin touching.  Receives two colliders and a `Contact` object with more information about the collision.  The `contact` callback will also be called for this collision.\n\n### Exit\n\nCalled when two colliders stop touching.  Receives two colliders.\n\n### Contact\n\nCalled continuously while two colliders are touching.  Receives two colliders and a `Contact` object with more information about the collision.  The contact can also be disabled to disable the collision response, and its friction/resitution/velocity can be changed.  There can be multiple active contact areas (called \"manifolds\") between a pair of colliders; this callback will be called for each one.",
              key = "World:setCallbacks",
              module = "lovr.physics",
              examples = {
                {
                  code = "world:setCallbacks({\n  filter = function(a, b)\n    return true\n  end,\n  enter = function(a, b, contact)\n    -- play sounds, spawn particles, etc.\n    -- the collision has not been resolved yet, so the velocity of a and b\n    -- is the velocity before the collision, and can be used to estimate the\n    -- collision force\n  end,\n  exit = function(a, b)\n    -- a and b have stopped touching!\n  end,\n  contact = function(a, b, contact)\n    -- a and b are touching this frame\n    -- use sparingly, as this may be called many times per frame\n    -- use Contact:setFriction and Contact:setResitution to update\n    -- the contact behavior, or Contact:setSurfaceVelocity, for a\n    -- conveyor belt effect, or Contact:setEnabled to disable the\n    -- collision completely.\n  end\n})"
                }
              },
              notes = "The `Thread` that last set these callbacks must also be the thread to call `World:update`.\n\nNote that when a collider goes to sleep, its active contacts will be removed and the `exit` callback will be called.",
              related = {
                "World:update",
                "Contact"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "callbacks",
                      type = "table",
                      description = "The World collision callbacks.  All of them are optional.",
                      table = {
                        {
                          name = "filter",
                          type = "function",
                          description = "The function to use to filter collisions."
                        },
                        {
                          name = "enter",
                          type = "function",
                          description = "The function to call when 2 colliders start touching."
                        },
                        {
                          name = "exit",
                          type = "function",
                          description = "The function to call when 2 colliders stop touching."
                        },
                        {
                          name = "contact",
                          type = "function",
                          description = "The function to call every frame while 2 colliders are in contact."
                        }
                      }
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setGravity",
              summary = "Set the gravity of the World.",
              description = "Sets the World's gravity.  Gravity is a constant acceleration applied to all colliders.  The default is `(0, -9.81, 0)` meters per second squared, causing colliders to fall downward.\n\nUse `Collider:setGravityScale` to change gravity strength for a single collider.",
              key = "World:setGravity",
              module = "lovr.physics",
              notes = "Kinematic colliders ignore gravity, since they are not moved by forces.  Colliders with higher mass do not fall faster.",
              related = {
                "Collider:getGravityScale",
                "Collider:setGravityScale",
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "xg",
                      type = "number",
                      description = "The x component of the gravity force."
                    },
                    {
                      name = "yg",
                      type = "number",
                      description = "The y component of the gravity force."
                    },
                    {
                      name = "zg",
                      type = "number",
                      description = "The z component of the gravity force."
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "gravity",
                      type = "Vec3",
                      description = "The gravity force."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setLinearDamping",
              summary = "Set the linear damping of the World.",
              description = "Sets the linear damping of the World.  Linear damping is similar to drag or air resistance, slowing down colliders over time as they move. Damping is only applied when linear velocity is over the threshold value.",
              key = "World:setLinearDamping",
              module = "lovr.physics",
              deprecated = true,
              notes = "A linear damping of 0 means colliders won't slow down over time.  This is the default.\n\nThis sets the default damping for newly-created colliders.  Damping can also be set on a per-collider basis using `Collider:setLinearDamping`.",
              related = {
                "Collider:getLinearDamping",
                "Collider:setLinearDamping"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "damping",
                      type = "number",
                      description = "The linear damping."
                    },
                    {
                      name = "threshold",
                      type = "number",
                      description = "Velocity limit below which the damping is not applied.",
                      default = "0"
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setResponseTime",
              summary = "Set the response time of the World.",
              description = "Sets the response time factor of the World.\n\nThe response time controls how relaxed collisions and joints are in the physics simulation, and functions similar to inertia.  A low response time means collisions are resolved quickly, and higher values make objects more spongy and soft.\n\nThe value can be any positive number.  It can be changed on a per-joint basis for `DistanceJoint` and `BallJoint` objects.",
              key = "World:setResponseTime",
              module = "lovr.physics",
              deprecated = true,
              variants = {
                {
                  arguments = {
                    {
                      name = "responseTime",
                      type = "number",
                      description = "The new response time setting for the World."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setSleepingAllowed",
              summary = "Set whether colliders can go to sleep.",
              description = "Sets whether colliders can go to sleep in the World.",
              key = "World:setSleepingAllowed",
              module = "lovr.physics",
              deprecated = true,
              notes = "If sleeping is enabled, the World will try to detect colliders that haven't moved for a while and put them to sleep.  Sleeping colliders don't impact the physics simulation, which makes updates more efficient and improves physics performance.  However, the physics engine isn't perfect at waking up sleeping colliders and this can lead to bugs where colliders don't react to forces or collisions properly.\n\nThis can be set on individual colliders.\n\nColliders can be manually put to sleep or woken up using `Collider:setAwake`.",
              related = {
                "Collider:isSleepingAllowed",
                "Collider:setSleepingAllowed",
                "Collider:isAwake",
                "Collider:setAwake"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "allowed",
                      type = "boolean",
                      description = "Whether colliders can sleep."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setStepCount",
              summary = "Set the step count of the World.",
              description = "Sets the step count of the World.  The step count influences how many steps are taken during a call to `World:update`.  A higher number of steps will be slower, but more accurate.  The default step count is 20.",
              key = "World:setStepCount",
              module = "lovr.physics",
              deprecated = true,
              related = {
                "World:update"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "steps",
                      type = "number",
                      description = "The new step count."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "setTightness",
              summary = "Set the tightness of joints in the World.",
              description = "Sets the tightness of joints in the World.\n\nThe tightness controls how much force is applied to colliders connected by joints.  With a value of 0, no force will be applied and joints won't have any effect.  With a tightness of 1, a strong force will be used to try to keep the Colliders constrained.  A tightness larger than 1 will overcorrect the joints, which can sometimes be desirable.  Negative tightness values are not supported.",
              key = "World:setTightness",
              module = "lovr.physics",
              deprecated = true,
              variants = {
                {
                  arguments = {
                    {
                      name = "tightness",
                      type = "number",
                      description = "The new tightness for the World."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "shapecast",
              summary = "Move a shape through the world and return any colliders it touches.",
              description = "Moves a shape from a starting point to an endpoint and returns any colliders it touches along its path.\n\nThis is similar to a raycast, but with a `Shape` instead of a point.",
              key = "World:shapecast",
              module = "lovr.physics",
              notes = "The callback function is passed a collider, a shape, a world-space point, a world-space normal, a triangle index (for mesh shapes), and a fraction:\n\n    function(collider, shape, x, y, z, nx, ny, nz, tri, fraction)\n      return fraction\n    end\n\nThe callback can return a fraction value used to limit the range of further hits.  For example:\n\n- Returning 0.0 will abort the shapecast and ignore all other hits.\n- Returning 1.0 will call the callback for all hits.\n- Returning `fraction` will return successively closer hits.\n\nShapecasts will hit sensors and sleeping colliders, but will not hit disabled colliders.",
              related = {
                "World:raycast",
                "World:overlapShape",
                "World:queryBox",
                "World:querySphere"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to cast."
                    },
                    {
                      name = "x1",
                      type = "number",
                      description = "The x position to start at."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y position to start at."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z position to start at."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x position to move the shape to."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y position to move the shape to."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z position to move the shape to."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the shape around its rotation axis, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the rotation axis."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The function to call when an intersection is detected (see notes).",
                      arguments = {
                        {
                          name = "collider",
                          type = "Collider"
                        },
                        {
                          name = "shape",
                          type = "Shape"
                        },
                        {
                          name = "x",
                          type = "number"
                        },
                        {
                          name = "y",
                          type = "number"
                        },
                        {
                          name = "z",
                          type = "number"
                        },
                        {
                          name = "nx",
                          type = "number"
                        },
                        {
                          name = "ny",
                          type = "number"
                        },
                        {
                          name = "nz",
                          type = "number"
                        },
                        {
                          name = "triangle",
                          type = "number"
                        },
                        {
                          name = "fraction",
                          type = "number"
                        }
                      },
                      returns = {
                        {
                          name = "limit",
                          type = "number",
                          default = "1.0"
                        }
                      }
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to cast."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to start at."
                    },
                    {
                      name = "destination",
                      type = "Vec3",
                      description = "The position to move the shape to."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the shape."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    },
                    {
                      name = "callback",
                      type = "function",
                      description = "The function to call when an intersection is detected (see notes).",
                      arguments = {
                        {
                          name = "collider",
                          type = "Collider"
                        },
                        {
                          name = "shape",
                          type = "Shape"
                        },
                        {
                          name = "x",
                          type = "number"
                        },
                        {
                          name = "y",
                          type = "number"
                        },
                        {
                          name = "z",
                          type = "number"
                        },
                        {
                          name = "nx",
                          type = "number"
                        },
                        {
                          name = "ny",
                          type = "number"
                        },
                        {
                          name = "nz",
                          type = "number"
                        },
                        {
                          name = "triangle",
                          type = "number"
                        },
                        {
                          name = "fraction",
                          type = "number"
                        }
                      },
                      returns = {
                        {
                          name = "limit",
                          type = "number",
                          default = "1.0"
                        }
                      }
                    }
                  },
                  returns = {}
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to cast."
                    },
                    {
                      name = "x1",
                      type = "number",
                      description = "The x position to start at."
                    },
                    {
                      name = "y1",
                      type = "number",
                      description = "The y position to start at."
                    },
                    {
                      name = "z1",
                      type = "number",
                      description = "The z position to start at."
                    },
                    {
                      name = "x2",
                      type = "number",
                      description = "The x position to move the shape to."
                    },
                    {
                      name = "y2",
                      type = "number",
                      description = "The y position to move the shape to."
                    },
                    {
                      name = "z2",
                      type = "number",
                      description = "The z position to move the shape to."
                    },
                    {
                      name = "angle",
                      type = "number",
                      description = "The rotation of the shape around its rotation axis, in radians."
                    },
                    {
                      name = "ax",
                      type = "number",
                      description = "The x component of the rotation axis."
                    },
                    {
                      name = "ay",
                      type = "number",
                      description = "The y component of the rotation axis."
                    },
                    {
                      name = "az",
                      type = "number",
                      description = "The z component of the rotation axis."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The Collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number",
                      description = "The triangle that was hit, or `nil` if a MeshShape was not hit."
                    },
                    {
                      name = "fraction",
                      type = "number",
                      description = "The fraction along the ray where the impact occurred."
                    }
                  }
                },
                {
                  arguments = {
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape to cast."
                    },
                    {
                      name = "position",
                      type = "Vec3",
                      description = "The position to start at."
                    },
                    {
                      name = "destination",
                      type = "Vec3",
                      description = "The position to move the shape to."
                    },
                    {
                      name = "orientation",
                      type = "Quat",
                      description = "The orientation of the shape."
                    },
                    {
                      name = "filter",
                      type = "string",
                      description = "An optional tag filter.  Pass one or more tags separated by spaces to only return colliders with those tags.  Or, put `~` in front the tags to exclude colliders with those tags.",
                      default = "nil"
                    }
                  },
                  returns = {
                    {
                      name = "collider",
                      type = "Collider",
                      description = "The Collider that was hit."
                    },
                    {
                      name = "shape",
                      type = "Shape",
                      description = "The Shape that was hit."
                    },
                    {
                      name = "x",
                      type = "number",
                      description = "The x coordinate of the impact point."
                    },
                    {
                      name = "y",
                      type = "number",
                      description = "The y coordinate of the impact point."
                    },
                    {
                      name = "z",
                      type = "number",
                      description = "The z coordinate of the impact point."
                    },
                    {
                      name = "nx",
                      type = "number",
                      description = "The x component of the normal vector."
                    },
                    {
                      name = "ny",
                      type = "number",
                      description = "The y component of the normal vector."
                    },
                    {
                      name = "nz",
                      type = "number",
                      description = "The z component of the normal vector."
                    },
                    {
                      name = "triangle",
                      type = "number",
                      description = "The triangle that was hit, or `nil` if a MeshShape was not hit."
                    },
                    {
                      name = "fraction",
                      type = "number",
                      description = "The fraction along the ray where the impact occurred."
                    }
                  }
                }
              }
            },
            {
              name = "update",
              summary = "Advance the physics simulation.",
              description = "Updates the World, advancing the physics simulation forward in time and moving all the colliders.",
              key = "World:update",
              module = "lovr.physics",
              examples = {
                {
                  code = "function lovr.update(dt)\n  world:update(dt)\nend"
                }
              },
              notes = "By default, the World updates at a fixed timestep.  This means that the physics simulation will always update with a constant rate, for example 60 \"ticks\" per second.  This improves stability of the simulation and decouples physics from rendering.  Collider poses are automatically interpolated between the two most recent ticks, ensuring smooth movement even if the tick rate is lower than the rendering rate.\n\nFixed timestep can be disabled by setting the `tickRate` option to 0 in `lovr.physics.newWorld`. This will use a variable timestep where the `dt` value passed to this function will be applied directly to the physics simulation.\n\nThis function must be called from the last thread that called `World:setCallbacks`.  If no callbacks are set, then this can be called from any thread.",
              related = {
                "lovr.physics.newWorld"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "dt",
                      type = "number",
                      description = "The amount of time to advance the simulation forward."
                    }
                  },
                  returns = {}
                }
              }
            }
          },
          sections = {
            {
              name = "Basics",
              links = {
                "World:update",
                "World:interpolate",
                "World:getGravity",
                "World:setGravity",
                "World:getCallbacks",
                "World:setCallbacks",
                "World:destroy",
                "World:isDestroyed"
              }
            },
            {
              name = "Queries",
              description = "Queries answer some question about the World, like \"do any colliders intersect this line?\" or \"are there any colliders inside this sphere?\".  There are 3 types of queries:\n\n- \"cast\" tests sweep a shape along a line and figure out which colliders are in its path.\n- \"overlap\" tests place a shape at a position and figure out which colliders it touches.\n- \"query\" tests are similar to overlap tests, but they are fast and inexact.  They only\n  check the bounding box of a collider, and only support testing against simple shapes.",
              links = {
                "World:raycast",
                "World:shapecast",
                "World:overlapShape",
                "World:queryBox",
                "World:querySphere"
              }
            },
            {
              name = "Collision Tags",
              description = "Collision tags are used to ignore collision between certain pairs of colliders.  The list of available tags is defined when creating the world, and colliders can be given a tag using `Collider:setTag`.",
              links = {
                "World:getTags",
                "World:disableCollisionBetween",
                "World:enableCollisionBetween",
                "World:isCollisionEnabledBetween"
              }
            },
            {
              name = "Colliders",
              links = {
                "World:newCollider",
                "World:newBoxCollider",
                "World:newSphereCollider",
                "World:newCapsuleCollider",
                "World:newCylinderCollider",
                "World:newConvexCollider",
                "World:newMeshCollider",
                "World:newTerrainCollider",
                "World:getColliderCount",
                "World:getColliders"
              }
            },
            {
              name = "Joints",
              links = {
                "World:getJointCount",
                "World:getJoints"
              }
            }
          }
        }
      },
      sections = {
        {
          name = "World",
          description = "A World holds all of the objects in a physics simulation.  Use methods like `World:newBoxCollider` to add objects to the world.  Call `World:update` each frame to advance the physics simulation and calculate new positions for all the colliders.",
          links = {
            "lovr.physics.newWorld"
          }
        },
        {
          name = "Colliders",
          description = "A Collider is a single \"object\" in the physics world.  A Collider has zero or more `Shape` objects attached to it, which determine its collision shape.  Colliders can be connected together with `Joint` objects.",
          links = {
            "World:newCollider",
            "World:newBoxCollider",
            "World:newSphereCollider",
            "World:newCapsuleCollider",
            "World:newCylinderCollider",
            "World:newConvexCollider",
            "World:newMeshCollider",
            "World:newTerrainCollider"
          }
        },
        {
          name = "Shapes",
          description = "Shapes define the collision shape of a collider.  Normally it isn't necessary to create shapes manually, instead convenience methods like `World:newSphereCollider` will create a collider with a shape attached.",
          links = {
            "lovr.physics.newBoxShape",
            "lovr.physics.newSphereShape",
            "lovr.physics.newCapsuleShape",
            "lovr.physics.newCylinderShape",
            "lovr.physics.newConvexShape",
            "lovr.physics.newMeshShape",
            "lovr.physics.newTerrainShape"
          }
        },
        {
          name = "Joints",
          description = "Joints connect colliders together and constrain their movement in various ways.",
          links = {
            "lovr.physics.newWeldJoint",
            "lovr.physics.newBallJoint",
            "lovr.physics.newConeJoint",
            "lovr.physics.newDistanceJoint",
            "lovr.physics.newHingeJoint",
            "lovr.physics.newSliderJoint"
          }
        }
      }
    },
    {
      name = "system",
      tag = "modules",
      summary = "Provides information about the current operating system and platform.",
      description = "The `lovr.system` provides information about the current platform and hardware.\n\nIt also interfaces with the desktop window and window input.",
      key = "lovr.system",
      enums = {
        {
          name = "Permission",
          summary = "Application permissions.",
          description = "These are the different permissions that need to be requested using `lovr.system.requestPermission` on some platforms.",
          key = "Permission",
          module = "lovr.system",
          related = {
            "lovr.system.requestPermission"
          },
          values = {
            {
              name = "audiocapture",
              description = "Requests microphone access."
            }
          }
        }
      },
      functions = {
        {
          name = "getClipboardText",
          tag = "system-clipboard",
          summary = "Get the clipboard text.",
          description = "Returns the clipboard text.",
          key = "lovr.system.getClipboardText",
          module = "lovr.system",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "text",
                  type = "string | nil",
                  description = "The clipboard text."
                }
              }
            }
          }
        },
        {
          name = "getCoreCount",
          tag = "system-info",
          summary = "Get the number of logical cores.",
          description = "Returns the number of logical cores on the system.",
          key = "lovr.system.getCoreCount",
          module = "lovr.system",
          related = {
            "lovr.thread"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "cores",
                  type = "number",
                  description = "The number of logical cores on the system."
                }
              }
            }
          }
        },
        {
          name = "getMousePosition",
          tag = "system-mouse",
          summary = "Get the position of the mouse.",
          description = "Returns the position of the mouse.",
          key = "lovr.system.getMousePosition",
          module = "lovr.system",
          related = {
            "lovr.system.getMouseX",
            "lovr.system.getMouseY",
            "lovr.mousemoved"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the mouse, relative to the top-left of the window."
                },
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the mouse, relative to the top-left of the window."
                }
              }
            }
          }
        },
        {
          name = "getMouseX",
          tag = "system-mouse",
          summary = "Get the x position of the mouse.",
          description = "Returns the x position of the mouse.",
          key = "lovr.system.getMouseX",
          module = "lovr.system",
          related = {
            "lovr.system.getMouseY",
            "lovr.system.getMousePosition",
            "lovr.mousemoved"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "x",
                  type = "number",
                  description = "The x position of the mouse, relative to the top-left of the window."
                }
              }
            }
          }
        },
        {
          name = "getMouseY",
          tag = "system-mouse",
          summary = "Get the y position of the mouse.",
          description = "Returns the y position of the mouse.",
          key = "lovr.system.getMouseY",
          module = "lovr.system",
          related = {
            "lovr.system.getMouseX",
            "lovr.system.getMousePosition",
            "lovr.mousemoved"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "y",
                  type = "number",
                  description = "The y position of the mouse, relative to the top-left of the window."
                }
              }
            }
          }
        },
        {
          name = "getOS",
          tag = "system-info",
          summary = "Get the current operating system.",
          description = "Returns the current operating system.",
          key = "lovr.system.getOS",
          module = "lovr.system",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "os",
                  type = "string",
                  description = "Either \"Windows\", \"macOS\", \"Linux\", \"Android\" or \"Web\"."
                }
              }
            }
          }
        },
        {
          name = "getWindowDensity",
          tag = "system-window",
          summary = "Get the window pixel density.",
          description = "Returns the window pixel density.  High DPI windows will usually return 2.0 to indicate that there are 2 pixels for every window coordinate in each axis.  On a normal display, 1.0 is returned, indicating that window coordinates match up with pixels 1:1.",
          key = "lovr.system.getWindowDensity",
          module = "lovr.system",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "density",
                  type = "number",
                  description = "The pixel density of the window."
                }
              }
            }
          }
        },
        {
          name = "getWindowDimensions",
          tag = "system-window",
          summary = "Get the dimensions of the window.",
          description = "Returns the dimensions of the desktop window.",
          key = "lovr.system.getWindowDimensions",
          module = "lovr.system",
          notes = "If the window is not open, this will return zeros.",
          related = {
            "lovr.system.getWindowWidth",
            "lovr.system.getWindowHeight",
            "lovr.system.isWindowOpen"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the desktop window."
                },
                {
                  name = "height",
                  type = "number",
                  description = "The height of the desktop window."
                }
              }
            }
          }
        },
        {
          name = "getWindowHeight",
          tag = "system-window",
          summary = "Get the height of the window.",
          description = "Returns the height of the desktop window.",
          key = "lovr.system.getWindowHeight",
          module = "lovr.system",
          notes = "If the window is not open, this will return zero.",
          related = {
            "lovr.system.getWindowWidth",
            "lovr.system.getWindowDimensions",
            "lovr.system.isWindowOpen"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The height of the desktop window."
                }
              }
            }
          }
        },
        {
          name = "getWindowWidth",
          tag = "system-window",
          summary = "Get the width of the window.",
          description = "Returns the width of the desktop window.",
          key = "lovr.system.getWindowWidth",
          module = "lovr.system",
          notes = "If the window is not open, this will return zero.",
          related = {
            "lovr.system.getWindowHeight",
            "lovr.system.getWindowDimensions",
            "lovr.system.isWindowOpen"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "width",
                  type = "number",
                  description = "The width of the desktop window."
                }
              }
            }
          }
        },
        {
          name = "hasKeyRepeat",
          tag = "system-keyboard",
          summary = "Check if key repeat is enabled.",
          description = "Returns whether key repeat is enabled.",
          key = "lovr.system.hasKeyRepeat",
          module = "lovr.system",
          notes = "Key repeat is disabled by default.",
          related = {
            "lovr.keypressed"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "enabled",
                  type = "boolean",
                  description = "Whether key repeat is enabled."
                }
              }
            }
          }
        },
        {
          name = "isKeyDown",
          tag = "system-keyboard",
          summary = "Get the state of a key.",
          description = "Returns whether a key on the keyboard is pressed.",
          key = "lovr.system.isKeyDown",
          module = "lovr.system",
          related = {
            "lovr.system.wasKeyPressed",
            "lovr.system.wasKeyReleased",
            "lovr.keypressed",
            "lovr.keyreleased"
          },
          variants = {
            {
              arguments = {
                {
                  name = "...",
                  type = "KeyCode",
                  description = "The set of keys to check."
                }
              },
              returns = {
                {
                  name = "down",
                  type = "boolean",
                  description = "Whether any of the keys are currently pressed."
                }
              }
            }
          }
        },
        {
          name = "isMouseDown",
          tag = "system-mouse",
          summary = "Check if a mouse button is pressed.",
          description = "Returns whether a mouse button is currently pressed.",
          key = "lovr.system.isMouseDown",
          module = "lovr.system",
          related = {
            "lovr.mousepressed",
            "lovr.mousereleased",
            "lovr.system.getMouseX",
            "lovr.system.getMouseY",
            "lovr.system.getMousePosition"
          },
          variants = {
            {
              arguments = {
                {
                  name = "button",
                  type = "number",
                  description = "The index of a button to check.  Use 1 for the primary mouse button, 2 for the secondary button, and 3 for the middle button.  Other indices can be used, but are hardware-specific."
                }
              },
              returns = {
                {
                  name = "down",
                  type = "boolean",
                  description = "Whether the mouse button is currently down."
                }
              }
            }
          }
        },
        {
          name = "isWindowFocused",
          tag = "system-window",
          summary = "Check if the desktop window is focused.",
          description = "Returns whether the desktop window is focused.",
          key = "lovr.system.isWindowFocused",
          module = "lovr.system",
          related = {
            "lovr.focus",
            "lovr.headset.isFocused",
            "lovr.system.openWindow",
            "lovr.system.isWindowOpen",
            "lovr.system.isWindowVisible"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "focused",
                  type = "boolean",
                  description = "Whether the desktop window is focused."
                }
              }
            }
          }
        },
        {
          name = "isWindowOpen",
          tag = "system-window",
          summary = "Check if the desktop window is open.",
          description = "Returns whether the desktop window is open.  `t.window` can be set to `nil` in `lovr.conf` to disable automatic opening of the window.  In this case, the window can be opened manually using `lovr.system.openWindow`.",
          key = "lovr.system.isWindowOpen",
          module = "lovr.system",
          related = {
            "lovr.system.openWindow",
            "lovr.system.isWindowVisible",
            "lovr.system.isWindowFocused"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "open",
                  type = "boolean",
                  description = "Whether the desktop window is open."
                }
              }
            }
          }
        },
        {
          name = "isWindowVisible",
          tag = "system-window",
          summary = "Check if the desktop window is visible.",
          description = "Returns whether the desktop window is visible (open and not minimized).",
          key = "lovr.system.isWindowVisible",
          module = "lovr.system",
          related = {
            "lovr.visible",
            "lovr.headset.isVisible",
            "lovr.system.openWindow",
            "lovr.system.isWindowOpen",
            "lovr.system.isWindowFocused"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "visible",
                  type = "boolean",
                  description = "Whether the desktop window is visible."
                }
              }
            }
          }
        },
        {
          name = "openWindow",
          tag = "system-window",
          summary = "Open the desktop window.",
          description = "Opens the desktop window.  If the window is already open, this function does nothing.",
          key = "lovr.system.openWindow",
          module = "lovr.system",
          notes = "By default, the window is opened automatically, but this can be disabled by setting `t.window` to `nil` in `conf.lua`.",
          related = {
            "lovr.system.isWindowOpen",
            "lovr.conf"
          },
          variants = {
            {
              arguments = {
                {
                  name = "options",
                  type = "table",
                  description = "Window options.",
                  table = {
                    {
                      name = "width",
                      type = "number",
                      description = "The width of the window, or 0 to use the width of the monitor.",
                      default = "720"
                    },
                    {
                      name = "height",
                      type = "number",
                      description = "The height of the window, or 0 to use the height of the monitor.",
                      default = "800"
                    },
                    {
                      name = "fullscreen",
                      type = "boolean",
                      description = "Whether the window should be fullscreen."
                    },
                    {
                      name = "resizable",
                      type = "boolean",
                      description = "Whether the window should be resizable."
                    },
                    {
                      name = "title",
                      type = "string",
                      description = "The window title."
                    },
                    {
                      name = "icon",
                      type = "string",
                      description = "An `Image` or path to an image file to use for the window icon."
                    }
                  }
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "pollEvents",
          tag = "system-window",
          summary = "Poll the OS for new window events.",
          description = "Fills the event queue with unprocessed events from the operating system.  This function should be called often, otherwise the operating system will consider the application unresponsive. This function is called in the default implementation of `lovr.run`, and the events are later processed by `lovr.event.poll`.",
          key = "lovr.system.pollEvents",
          module = "lovr.system",
          related = {
            "lovr.event.poll"
          },
          variants = {
            {
              arguments = {},
              returns = {}
            }
          }
        },
        {
          name = "requestPermission",
          tag = "system-info",
          summary = "Request permission to use a feature.",
          description = "Requests permission to use a feature.  Usually this will pop up a dialog box that the user needs to confirm.  Once the permission request has been acknowledged, the `lovr.permission` callback will be called with the result.  Currently, this is only used for requesting microphone access on Android devices.",
          key = "lovr.system.requestPermission",
          module = "lovr.system",
          related = {
            "lovr.permission"
          },
          variants = {
            {
              arguments = {
                {
                  name = "permission",
                  type = "Permission",
                  description = "The permission to request."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setClipboardText",
          tag = "system-clipboard",
          summary = "Set the clipboard text.",
          description = "Sets the clipboard text.",
          key = "lovr.system.setClipboardText",
          module = "lovr.system",
          variants = {
            {
              arguments = {
                {
                  name = "text",
                  type = "string",
                  description = "The string to set as the clipboard text."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "setKeyRepeat",
          tag = "system-keyboard",
          summary = "Enable or disable key repeat.",
          description = "Enables or disables key repeat.  Key repeat affects whether `lovr.keypressed` will be fired multiple times while a key is held down.  The `repeat` parameter of the callback can be used to detect whether a key press comes from a \"repeat\" or not.",
          key = "lovr.system.setKeyRepeat",
          module = "lovr.system",
          notes = "Key repeat is disabled by default.  `lovr.textinput` is not affected by key repeat.",
          related = {
            "lovr.keypressed"
          },
          variants = {
            {
              arguments = {
                {
                  name = "enable",
                  type = "boolean",
                  description = "Whether key repeat should be enabled."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "wasKeyPressed",
          tag = "system-keyboard",
          summary = "Check if a key was pressed this frame.",
          description = "Returns whether a key on the keyboard was pressed this frame.",
          key = "lovr.system.wasKeyPressed",
          module = "lovr.system",
          notes = "Technically this returns whether the key was pressed between the last 2 calls to `lovr.system.pollEvents`, but that function is called automatically at the beginning of each frame in `lovr.run`, so it all works out!",
          related = {
            "lovr.system.isKeyDown",
            "lovr.system.wasKeyReleased",
            "lovr.keypressed",
            "lovr.keyreleased"
          },
          variants = {
            {
              arguments = {
                {
                  name = "...",
                  type = "KeyCode",
                  description = "The set of keys to check."
                }
              },
              returns = {
                {
                  name = "pressed",
                  type = "boolean",
                  description = "Whether any of the specified keys were pressed this frame."
                }
              }
            }
          }
        },
        {
          name = "wasKeyReleased",
          tag = "system-keyboard",
          summary = "Check if a key was released this frame.",
          description = "Returns whether a key on the keyboard was released this frame.",
          key = "lovr.system.wasKeyReleased",
          module = "lovr.system",
          notes = "Technically this returns whether the key was released between the last 2 calls to `lovr.system.pollEvents`, but that function is called automatically at the beginning of each frame in `lovr.run`, so it all works out!",
          related = {
            "lovr.system.isKeyDown",
            "lovr.system.wasKeyPressed",
            "lovr.keypressed",
            "lovr.keyreleased"
          },
          variants = {
            {
              arguments = {
                {
                  name = "...",
                  type = "KeyCode",
                  description = "The set of keys to check."
                }
              },
              returns = {
                {
                  name = "released",
                  type = "boolean",
                  description = "Whether any of the specified keys were released this frame."
                }
              }
            }
          }
        },
        {
          name = "wasMousePressed",
          tag = "system-mouse",
          summary = "Check if a mouse button was pressed this frame.",
          description = "Returns whether a button on the mouse was pressed this frame.",
          key = "lovr.system.wasMousePressed",
          module = "lovr.system",
          notes = "Technically this returns whether the button was pressed between the last 2 calls to `lovr.system.pollEvents`, but that function is called automatically at the beginning of each frame in `lovr.run`, so it all works out!",
          related = {
            "lovr.system.isMouseDown",
            "lovr.system.wasMouseReleased",
            "lovr.mousepressed",
            "lovr.mousereleased"
          },
          variants = {
            {
              arguments = {
                {
                  name = "button",
                  type = "number",
                  description = "The index of a button to check.  Use 1 for the primary mouse button, 2 for the secondary button, and 3 for the middle button.  Other indices can be used, but are hardware-specific."
                }
              },
              returns = {
                {
                  name = "pressed",
                  type = "boolean",
                  description = "Whether the mouse button was pressed this frame."
                }
              }
            }
          }
        },
        {
          name = "wasMouseReleased",
          tag = "system-mouse",
          summary = "Check if a mouse button was released this frame.",
          description = "Returns whether a button on the mouse was released this frame.",
          key = "lovr.system.wasMouseReleased",
          module = "lovr.system",
          notes = "Technically this returns whether the button was released between the last 2 calls to `lovr.system.pollEvents`, but that function is called automatically at the beginning of each frame in `lovr.run`, so it all works out!",
          related = {
            "lovr.system.isMouseDown",
            "lovr.system.wasMousePressed",
            "lovr.mousepressed",
            "lovr.mousereleased"
          },
          variants = {
            {
              arguments = {
                {
                  name = "button",
                  type = "number",
                  description = "The index of a button to check.  Use 1 for the primary mouse button, 2 for the secondary button, and 3 for the middle button.  Other indices can be used, but are hardware-specific."
                }
              },
              returns = {
                {
                  name = "released",
                  type = "boolean",
                  description = "Whether the mouse button was released this frame."
                }
              }
            }
          }
        }
      },
      objects = {},
      sections = {
        {
          name = "System Information",
          tag = "system-info"
        },
        {
          name = "Keyboard",
          tag = "system-keyboard"
        },
        {
          name = "Mouse",
          tag = "system-mouse"
        },
        {
          name = "Clipboard",
          tag = "system-clipboard"
        },
        {
          name = "Window",
          tag = "system-window"
        }
      }
    },
    {
      name = "thread",
      tag = "modules",
      summary = "Allows the creation of background threads.",
      description = "The `lovr.thread` module provides functions for creating threads and communicating between them.\n\nThese are operating system level threads, which are different from Lua coroutines.\n\nThreads are useful for performing expensive background computation without affecting the framerate or performance of the main thread.  Some examples of this include asset loading, networking and network requests, and physics simulation.\n\nThreads come with some caveats:\n\n- Threads run in a bare Lua environment.  The `lovr` module (and any of lovr's modules) need to\n  be required before they can be used.\n  - To get `require` to work properly, add `require 'lovr.filesystem'` to the thread code.\n- Threads are completely isolated from other threads.  They do not have access to the variables\n  or functions of other threads, and communication between threads must be coordinated through\n  `Channel` objects.\n- The graphics module (or any functions that perform rendering) cannot be used in a thread.\n  Note that this includes creating graphics objects like Models and Textures.  There are \"data\"\n  equivalent `ModelData` and `Image` objects that can be used in threads though.\n- `lovr.system.pollEvents` cannot be called from a thread.\n- Crashes or problems can happen if two threads access the same object at the same time, so\n  special care must be taken to coordinate access to objects from multiple threads.",
      key = "lovr.thread",
      enums = {},
      functions = {
        {
          name = "getChannel",
          summary = "Get a Channel for communicating between threads.",
          description = "Returns a named Channel for communicating between threads.",
          key = "lovr.thread.getChannel",
          module = "lovr.thread",
          related = {
            "Channel",
            "lovr.thread.newChannel"
          },
          variants = {
            {
              arguments = {
                {
                  name = "name",
                  type = "string",
                  description = "The name of the Channel to get."
                }
              },
              returns = {
                {
                  name = "channel",
                  type = "Channel",
                  description = "The Channel with the specified name."
                }
              }
            }
          }
        },
        {
          name = "newChannel",
          summary = "Create a new, unnamed Channel.",
          description = "Creates a new unnamed `Channel` object.  Usually it's more convenient to use `lovr.thread.getChannel`, since other threads can use that function to query the channel by name.  Unnamed channels don't require a unique name, but they need to be sent to other threads somehow (e.g. on a different Channel or as an argument to `Thread:start`).",
          key = "lovr.thread.newChannel",
          module = "lovr.thread",
          related = {
            "lovr.thread.getChannel"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "channel",
                  type = "Channel",
                  description = "The new Channel."
                }
              }
            }
          }
        },
        {
          name = "newThread",
          summary = "Create a new Thread.",
          description = "Creates a new Thread from Lua code.",
          key = "lovr.thread.newThread",
          module = "lovr.thread",
          notes = "The Thread won\\'t start running immediately.  Use `Thread:start` to start it.\n\nThe string argument is assumed to be a filename if there isn't a newline in the first 1024 characters.  For really short thread code, an extra newline can be added to trick LÖVR into loading it properly.",
          related = {
            "Thread:start",
            "lovr.threaderror"
          },
          variants = {
            {
              arguments = {
                {
                  name = "code",
                  type = "string",
                  description = "The code to run in the Thread."
                }
              },
              returns = {
                {
                  name = "thread",
                  type = "Thread",
                  description = "The new Thread."
                }
              }
            },
            {
              arguments = {
                {
                  name = "file",
                  type = "string | Blob",
                  description = "A filename or Blob containing code to run in the Thread."
                }
              },
              returns = {
                {
                  name = "thread",
                  type = "Thread",
                  description = "The new Thread."
                }
              }
            }
          }
        }
      },
      objects = {
        {
          name = "Channel",
          summary = "A message channel for communicating between threads.",
          description = "A Channel is an object used to communicate between `Thread` objects.  Different threads can send messages on the same Channel to communicate with each other.  Messages can be sent and received on a Channel using `Channel:push` and `Channel:pop`, and are received in a first-in-first-out fashion. The following types of data can be passed through Channels: nil, boolean, number, string, lightuserdata, table, vector, and any LÖVR object.",
          key = "Channel",
          module = "lovr.thread",
          constructors = {
            "lovr.thread.newChannel",
            "lovr.thread.getChannel"
          },
          extends = "Object",
          methods = {
            {
              name = "clear",
              summary = "Clear all messages from the Channel.",
              description = "Removes all pending messages from the Channel.",
              key = "Channel:clear",
              module = "lovr.thread",
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            },
            {
              name = "getCount",
              summary = "Get the number of messages in the Channel.",
              description = "Returns the number of messages in the Channel.",
              key = "Channel:getCount",
              module = "lovr.thread",
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "count",
                      type = "number",
                      description = "The number of messages in the Channel."
                    }
                  }
                }
              }
            },
            {
              name = "hasRead",
              summary = "Get whether a message has been read.",
              description = "Returns whether or not the message with the given ID has been read.  Every call to `Channel:push` returns a message ID.",
              key = "Channel:hasRead",
              module = "lovr.thread",
              related = {
                "Channel:push"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "id",
                      type = "number",
                      description = "The ID of the message to check."
                    }
                  },
                  returns = {
                    {
                      name = "read",
                      type = "boolean",
                      description = "Whether the message has been read."
                    }
                  }
                }
              }
            },
            {
              name = "peek",
              summary = "Look at a message from the Channel without popping it.",
              description = "Returns a message from the Channel without popping it from the queue.  If the Channel is empty, `nil` is returned.  This can be useful to determine if the Channel is empty.",
              key = "Channel:peek",
              module = "lovr.thread",
              notes = "The second return value can be used to detect if a `nil` message is in the queue.",
              related = {
                "Channel:pop"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "message",
                      type = "*",
                      description = "The message, or `nil` if there is no message."
                    },
                    {
                      name = "present",
                      type = "boolean",
                      description = "Whether a message was returned (use to detect nil)."
                    }
                  }
                }
              }
            },
            {
              name = "pop",
              summary = "Pop a message from the Channel.",
              description = "Pops a message from the Channel.  If the Channel is empty, an optional timeout argument can be used to wait for a message, otherwise `nil` is returned.",
              key = "Channel:pop",
              module = "lovr.thread",
              notes = "Threads can get stuck forever waiting on Channel messages, so be careful.",
              related = {
                "Channel:peek",
                "Channel:push"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "wait",
                      type = "number | boolean",
                      description = "How long to wait for a message to be popped, in seconds.  `true` can be used to wait forever and `false` can be used to avoid waiting.",
                      default = "false"
                    }
                  },
                  returns = {
                    {
                      name = "message",
                      type = "*",
                      description = "The received message, or `nil` if nothing was received."
                    }
                  }
                }
              }
            },
            {
              name = "push",
              summary = "Push a message onto the Channel.",
              description = "Pushes a message onto the Channel.  The following types of data can be pushed: nil, boolean, number, string, table, lightuserdata, vectors, and userdata (LÖVR objects).",
              key = "Channel:push",
              module = "lovr.thread",
              notes = "Threads can get stuck forever waiting on Channel messages, so be careful.",
              related = {
                "Channel:pop",
                "Channel:hasRead"
              },
              variants = {
                {
                  arguments = {
                    {
                      name = "message",
                      type = "*",
                      description = "The message to push."
                    },
                    {
                      name = "wait",
                      type = "number | boolean",
                      description = "How long to wait for the message to be popped, in seconds.  `true` can be used to wait forever and `false` can be used to avoid waiting.",
                      default = "false"
                    }
                  },
                  returns = {
                    {
                      name = "id",
                      type = "number",
                      description = "The ID of the pushed message."
                    },
                    {
                      name = "read",
                      type = "boolean",
                      description = "Whether the message was read by another thread before the wait timeout."
                    }
                  }
                }
              }
            }
          }
        },
        {
          name = "Thread",
          summary = "A separate thread of execution that can run code in parallel with other threads.",
          description = "A Thread is an object that runs a chunk of Lua code in the background.  Threads are completely isolated from other threads, meaning they have their own Lua context and can't access the variables and functions of other threads.  Communication between threads is limited and is accomplished by using `Channel` objects.\n\nTo get `require` to work properly, add `require 'lovr.filesystem'` to the thread code.",
          key = "Thread",
          module = "lovr.thread",
          constructors = {
            "lovr.thread.newThread"
          },
          extends = "Object",
          methods = {
            {
              name = "getError",
              summary = "Get the Thread's error message.",
              description = "Returns the message for the error that occurred on the Thread, or nil if no error has occurred.",
              key = "Thread:getError",
              module = "lovr.thread",
              related = {
                "lovr.threaderror"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "error",
                      type = "string | nil",
                      description = "The error message, or `nil` if no error has occurred on the Thread."
                    }
                  }
                }
              }
            },
            {
              name = "isRunning",
              summary = "Check if the Thread is running.",
              description = "Returns whether or not the Thread is currently running.",
              key = "Thread:isRunning",
              module = "lovr.thread",
              related = {
                "Thread:start"
              },
              variants = {
                {
                  arguments = {},
                  returns = {
                    {
                      name = "running",
                      type = "boolean",
                      description = "Whether or not the Thread is running."
                    }
                  }
                }
              }
            },
            {
              name = "start",
              summary = "Start the Thread.",
              description = "Starts the Thread.",
              key = "Thread:start",
              module = "lovr.thread",
              examples = {
                {
                  code = "function lovr.load()\n  lovr.thread.newThread([[\n    print(...)\n  ]]):start(lovr.getVersion())\nend"
                }
              },
              notes = "The arguments can be nil, booleans, numbers, strings, lightuserdata, tables, vectors, or LÖVR objects.",
              variants = {
                {
                  arguments = {
                    {
                      name = "...arguments",
                      type = "*",
                      description = "Up to 4 arguments to pass to the Thread's function."
                    }
                  },
                  returns = {}
                }
              }
            },
            {
              name = "wait",
              summary = "Wait for the Thread to complete.",
              description = "Waits for the Thread to complete, then returns.",
              key = "Thread:wait",
              module = "lovr.thread",
              related = {
                "Thread:isRunning"
              },
              variants = {
                {
                  arguments = {},
                  returns = {}
                }
              }
            }
          },
          related = {
            "lovr.threaderror",
            "lovr.system.getCoreCount",
            "Channel"
          }
        }
      },
      related = {
        "lovr.system.getCoreCount"
      }
    },
    {
      name = "timer",
      tag = "modules",
      summary = "Exposes a high resolution timer.",
      description = "The `lovr.timer` module provides a few functions that deal with time.  All times are measured in seconds.",
      key = "lovr.timer",
      enums = {},
      functions = {
        {
          name = "getAverageDelta",
          summary = "Get the average delta over the last second.",
          description = "Returns the average delta over the last second.",
          key = "lovr.timer.getAverageDelta",
          module = "lovr.timer",
          related = {
            "lovr.timer.getDelta",
            "lovr.update"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "delta",
                  type = "number",
                  description = "The average delta, in seconds."
                }
              }
            }
          }
        },
        {
          name = "getDelta",
          summary = "Get the time elapsed since the last update.",
          description = "Returns the time between the last two frames.  This is the same value as the `dt` argument provided to `lovr.update` when VR is disabled.  When VR is enabled, the `dt` will instead be `lovr.headset.getDeltaTime`.",
          key = "lovr.timer.getDelta",
          module = "lovr.timer",
          notes = "The return value of this function will remain the same until `lovr.timer.step` is called.  This function should not be used to measure times for game behavior or benchmarking, use `lovr.timer.getTime` for that.",
          related = {
            "lovr.headset.getDeltaTime",
            "lovr.timer.getTime",
            "lovr.update"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "dt",
                  type = "number",
                  description = "The delta time, in seconds."
                }
              }
            }
          }
        },
        {
          name = "getFPS",
          summary = "Get the current frames per second.",
          description = "Returns the current frames per second, averaged over the last 90 frames.",
          key = "lovr.timer.getFPS",
          module = "lovr.timer",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "fps",
                  type = "number",
                  description = "The current FPS."
                }
              }
            }
          }
        },
        {
          name = "getTime",
          summary = "Get the current time.",
          description = "Returns the time since some time in the past.  This can be used to measure the difference between two points in time.",
          key = "lovr.timer.getTime",
          module = "lovr.timer",
          related = {
            "lovr.headset.getTime"
          },
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "time",
                  type = "number",
                  description = "The current time, in seconds."
                }
              }
            }
          }
        },
        {
          name = "sleep",
          summary = "Go to sleep.",
          description = "Sleeps the application for a specified number of seconds.  While the game is asleep, no code will be run, no graphics will be drawn, and the window will be unresponsive.",
          key = "lovr.timer.sleep",
          module = "lovr.timer",
          variants = {
            {
              arguments = {
                {
                  name = "duration",
                  type = "number",
                  description = "The number of seconds to sleep for."
                }
              },
              returns = {}
            }
          }
        },
        {
          name = "step",
          summary = "Steps the internal clock.",
          description = "Steps the timer, returning the new delta time.  This is called automatically in `lovr.run` and it's used to calculate the new `dt` to pass to `lovr.update`.",
          key = "lovr.timer.step",
          module = "lovr.timer",
          variants = {
            {
              arguments = {},
              returns = {
                {
                  name = "delta",
                  type = "number",
                  description = "The amount of time since the last call to this function, in seconds."
                }
              }
            }
          }
        }
      },
      objects = {}
    },
    {
      name = "utf8",
      tag = "libraries",
      summary = "UTF-8 string processing.",
      description = "LÖVR includes Lua 5.3's `utf8` library, even on Lua versions that don't support it.  Lua's regular strings aren't utf8-aware, so this library makes it easier to work with multi-byte characters that are outside the ASCII range.\n\nSee the [Lua reference manual](https://www.lua.org/manual/5.3/manual.html#6.5) for documentation.",
      key = "utf8",
      enums = {},
      examples = {
        {
          code = "local utf8 = require 'utf8'\n\nlocal str = 'LÖVR'\n\nprint(string.len(str)) --> prints 5, because Ö takes up 2 bytes\nprint(utf8.len(str))   --> prints 4"
        }
      },
      external = true,
      functions = {},
      objects = {}
    }
  }
}