Open Brush Docs
  • Home
  • How to get Open Brush
  • Differences between Open Brush and Tilt Brush
  • User Guide
    • Get started with Open Brush
    • Painting with Open Brush
    • The Open Brush UI
      • Admin Panel
        • Settings Panel
        • Labs Panel
      • Tools Panel
        • Selection Options
        • Repaint Options
      • Brushes Panel
      • Extras Panel
        • Environment Panel
        • Lights Panel
        • Backdrop Panel
        • Guides Panel
        • Media Library
        • Camera Paths Panel
        • Snap Settings Panel
        • Transform Panel
        • Layers Panel
      • Experimental Panel
      • UI Differences Between Basic Mode and Advanced Mode
    • Grid and Angle Snapping
    • Repaint Tool and Jitter
    • Selection/Erase Filter
    • Lazy Input
    • Bimanual Input and Revolver
    • World Axis Unlock
    • Saving and sharing your Open Brush sketches
    • Troubleshooting issues with Open Brush
    • Check out Labs features
    • Importing Images, Videos and 3D Models
    • Experimental Mode
    • Make moving creations using audio reactive brushes
    • Using Reference Images on Oculus Quest
    • Remixing and Creative Commons
    • Accessing Autosave Files
    • The Open Brush config file
    • Exporting Open Brush sketches to other apps
      • Exporting to Unreal Engine 5
      • Exporting to Snapchat Lens Studio
      • Configuring Export
    • Plugins
      • Example Plugins
        • Example Pointer Plugins
        • Example Symmetry Plugins
        • Example Tool Plugins
        • Example Background Plugins
      • Writing Plugins
        • Getting Started
        • Tweaking existing plugins
        • Writing a Pointer Plugin
        • Writing a Symmetry Plugin
        • Writing a Tool Plugin
        • Writing a Background Plugin
        • Defining and Drawing Brush Strokes
      • Plugin API Scripting Reference
    • Open Brush Unity SDK
    • Open Brush API
      • Retrieving a preview image
      • API Commands List
    • Cameras and Exporting Video
    • Brushes
      • Brush List
      • Memory limits and brush costs
      • Experimental Brushes
      • Hiding Brushes with Brush Tags
    • Using Open Brush without a VR headset
    • Command Line Arguments
    • Tilt Brush Version 23 Release Notes
  • Get Involved!
    • How to help with Testing
  • Pre-release and Experimental Builds
    • Installing the Beta Release
    • "Experimental Mode" Builds
    • Feature: 3D Shapes Tool
    • Feature: Animation Timeline
    • Feature: Icosa Gallery Support
    • Feature: Brush Editing
    • Feature: Plugin Scripting
    • Feature: Sculpting
    • Combined Testing Build
    • Old or Completed Feature Builds
      • Feature: Polyhedra
      • Feature: Snip Tool
      • Feature: Layers
      • Insominx's (michael-g) Experimental Build
      • XR Framework Beta
      • Feature: Transform Panel and Snap Enhancements
      • Feature: Improved GLTF Importer
      • Feature: Multi-Mirror
      • Feature: New Monoscopic Mode
      • Feature: Improved Import/Export
      • Feature: Multiplayer
  • Case Studies
  • Other Resources
  • Developer Notes
    • UI Elements
    • Unity shader examples
    • Setting up CI for Open Brush using Github Actions
    • Open Brush File Format
    • Previous Github Wiki
      • Brushes
      • BuildingOpenBrush
      • BurstCompiler
      • Comparison
      • MonoscopicMode
      • PseudoCode
      • UserInterface
    • Differences between Standard and Experimental Mode
    • Open Brush AsCanvas Notes
    • Unity Versions
  • Release History
    • v2.10 Multiplayer
    • v2.9 (Maintenance)
    • v2.8 Import/Export
    • v2.7 (Maintenance)
    • v2.6 (Maintenance)
    • v2.5 (Maintenance)
    • v2.4 "Prismatic"
    • v2.2: Settings and Sketches
    • v2.1 Hotfix
    • 🚀v2.0: XR Update
    • v1.0: Happy Birthday to Us!
    • Current Beta Release Notes
  • Docs TODO
  • Contacting Us
Powered by GitBook
On this page
Edit on GitHub
Export as PDF
  1. User Guide
  2. Plugins
  3. Writing Plugins

Defining and Drawing Brush Strokes

PreviousWriting a Background PluginNextOpen Brush Unity SDK

Last updated 5 months ago

When you paint freehand in Open Brush, the application is constantly recording your hand's position and orientation. Therefore internally a stroke is defined as a list of transforms. Scale isn't used but the position and rotation are key in defining the shape of the resulting stroke.

There are several situations when you might need to define a stroke when writing a plugin:

  1. The most common use-case is with Tool Plugins. The value you return from the Main() function in a Tool Plugin is drawn as a brush stroke

  2. You can paths explicitly using Path:Draw(), PathList:Draw() or the draw methods provided by classes such as SVG

In both these cases you must define the path as a list of transforms. Both the position and rotation are used to define the shape of the stroke. It matches what happens when you draw a stroke by hand - at each point in time you control both the position of the brush and it's orientation. Orientation doesn't matter for all brushes (a tube brush looks much the same whatever the rotation of the brush controller at each point is) but other brushes such as flat stroke brushes do make use of the rotation values you provide.

In the simple case where you are returning a value from the Main function of a Tool Plugin, you can return a normal lua array (or "table" as they are also called) containing two or more Transform instances:

origin = Transform:New(Vector3:New(0, 0, 0), Rotation.forwards)
return {origin, origin:TranslateBy(2, 2, 0)}

It's simple to use a lua list like this: {} but there is also a class specifically for definition a list of transforms and it's called . The advantage of using this class is that also has many useful methods for modifying paths.

origin = Transform:New(Vector3:New(0, 0, 0), Rotation.forwards)
path = Path:New({origin, origin:TranslateBy(2, 2, 0)})
path:RotateBy(0, 45, 0)
return path

(The various Draw() methods insist that you use a Path object - so you can't use a simple lua array when you use those.)

Open Brush usually assumes a brush stroke is drawn by hand. Some simplification is done depending on your settings but a stroke is still usually made up of a lot of points forming a smooth curve as the app samples your controller position and orientation many times a second.

When you draw paths via code in a plugin script, you often send only the exact points you want. For example if you were drawing a square then you'd simply define the four points that make up the corners of the square (although you usually repeat the first point at the end if you want a closed shape)

The problem is that by default Open Brush tries to smooth the path you give it so your nice precise square becomes a rounded squiggle. The end result actually varies depending on the brush you use - different brushes use different rules for how to smooth the input points.

But generally speaking - if you want to draw a precise geometric shape then you need to add extra points - and the Path object has some useful methods to do this.

Path